Permalink
Browse files

Some notes about Allegro's internals.

  • Loading branch information...
1 parent b8347d6 commit a998acd224ab8cc9d02aef05193b478ea589d65d @luismbo luismbo committed Jul 11, 2005
Showing with 132 additions and 0 deletions.
  1. +132 −0 doc/allegro-internals.txt
@@ -0,0 +1,132 @@
+July 2005
+These details were kindly provided by Duane Rettig of Franz.
+
+Regarding the following snippet of the macro expansion of
+FF:DEF-FOREIGN-CALL:
+
+ (SYSTEM::FF-FUNCALL
+ (LOAD-TIME-VALUE (EXCL::DETERMINE-FOREIGN-ADDRESS
+ '("foo" :LANGUAGE :C) 2 NIL))
+ '(:INT (INTEGER * *)) ARG1
+ '(:DOUBLE (DOUBLE-FLOAT * *)) ARG2
+ '(:INT (INTEGER * *)))
+
+"
+... in Allegro CL, if you define a foreign call FOO with C entry point
+"foo" and with :call-direct t in the arguments, and if other things are
+satisfied, then if a lisp function BAR is compiled which has a call to
+FOO, that call will not go through ff-funcall (and thus a large amount
+of argument manipulation and processing) but will instead set up its
+arguments directly on the stack, and will then perform the "call" more
+or less directly, through the "entry vec" (a small structure which
+keeps track of a foreign entry's address and status)."
+
+This is the code that generates what the compiler expects to see:
+
+(setq call-direct-form
+ (if* call-direct
+ then `(setf (get ',lispname 'sys::direct-ff-call)
+ (list ',external-name
+ ,callback
+ ,convention
+ ',returning
+ ',arg-types
+ ,arg-checking
+ ,entry-vec-flags))
+ else `(remprop ',lispname 'sys::direct-ff-call)))
+
+Thus generating something like:
+
+ (EVAL-WHEN (COMPILE LOAD EVAL)
+ (SETF (GET 'FOO 'SYSTEM::DIRECT-FF-CALL)
+ (LIST '("foo" :LANGUAGE :C) T :C
+ '(:INT (INTEGER * *))
+ '((:INT (INTEGER * *))
+ (:FLOAT (SINGLE-FLOAT * *)))
+ T
+ 2 ; this magic value is explained later
+ )))
+
+"
+(defun determine-foreign-address (name &optional (flags 0) method-index)
+ ;; return an entry-vec struct suitable for the foreign-call of name.
+ ;;
+ ;; name is either a string, which is taken without conversion, or
+ ;; a list consisting of a string to convert or a conversion function
+ ;; call.
+ ;; flags is an integer representing the flags to place into the entry-vec.
+ ;; method-index, if non-nil, is a word-index into a vtbl (virtual table).
+ ;; If method-index is true, then the name must be a string uniquely
+ ;; represented by the index and by the flags field.
+
+Note that not all architectures implement the :method-index argument
+to def-foreign-call, but your interface likely won't support it
+anyway, so just leave it nil. As for the flags, they are constants
+stored into the entry-vec returned by d-f-a and are given here:
+
+(defconstant ep-flag-call-semidirect 1) ; Real address stored in alt-address slot
+(defconstant ep-flag-never-release 2) ; Never release the heap
+(defconstant ep-flag-always-release 4) ; Always release the heap
+(defconstant ep-flag-release-when-ok 8) ; Release the heap unless without-interrupts
+
+(defconstant ep-flag-tramp-calls #x70) ; Make calls through special trampolines
+(defconstant ep-flag-tramp-shift 4)
+
+(defconstant ep-flag-variable-address #x100) ; Entry-point contains address of C var
+(defconstant ep-flag-strings-convert #x200) ; Convert strings automatically
+
+(defconstant ep-flag-get-errno #x1000) ;; [rfe5060]: Get errno value after call
+(defconstant ep-flag-get-last-error #x2000) ;; [rfe5060]: call GetLastError after call
+;; Leave #x4000 and #x8000 open for expansion
+
+Mostly, you'll give the value 2 (never release the heap), but if you
+give 4 or 8, then d-f-a will automatically set the 1 bit as well,
+which takes the call through a heap-release/reacquire process.
+
+Some docs for entry-vec are:
+
+;; -- entry vec --
+;; An entry-vec is an entry-point descriptor, usually a pointer into
+;; a shared-library. It is represented as a 5-element struct of type
+;; foreign-vector. The reason for this represntation is
+;; that it allows the entry point to be stored in a table, called
+;; the .saved-entry-points. table, and to be used by a foreign
+;; function. When the location of the foreign function to which the entry
+;; point refers changes, it is simply a matter of changing the value in entry
+;; point vector and the foreign call code sees it immediately. There is
+;; even an address that can be put in the entry point vector that denotes
+;; a missing foreign function, thus lookup can happen dynamically.
+
+(defstruct (entry-vec
+ (:type (vector excl::foreign (*)))
+ (:constructor make-entry-vec-boa ()))
+ name ; entry point name
+ (address 0) ; jump address for foreign code
+ (handle 0) ; shared-lib handle
+ (flags 0) ; ep-* flags
+ (alt-address 0) ; sometimes holds the real func addr
+ )
+
+[...]
+"
+
+Regarding the arguments to SYSTEM::FF-FUNCALL:
+ '(:int (integer * *)) argN
+
+"The type-spec is as it is given in the def-foreign-call
+syntax, with a C type optionally followed by a lisp type,
+followed optionally by a user-conversion function name[...]"
+
+
+Getting the alignment:
+
+CL-USER(2): (ff:get-foreign-type :int)
+#S(FOREIGN-FUNCTIONS::IFOREIGN-TYPE
+ :ATTRIBUTES NIL
+ :SFTYPE
+ #S(FOREIGN-FUNCTIONS::SIZED-FTYPE-PRIM
+ :KIND :INT
+ :WIDTH 4
+ :OFFSET 0
+ :ALIGN 4)
+ ...)

0 comments on commit a998acd

Please sign in to comment.