Changeset 5746


Ignore:
Timestamp:
Jan 20, 2007, 6:21:48 PM (18 years ago)
Author:
Gary Byers
Message:

Looks mostly right; might need to be extended to handle coercions at
the Cocoa level, and probably needs some cooperation from
%EXTERNAL-CALL-EXPANDER (e.g., what's installed by #_).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ccl/lib/ffi-darwinppc32.lisp

    r5737 r5746  
    1515;;;   http://opensource.franz.com/preamble.html
    1616
     17(in-package "CCL")
     18
     19;;; If a record type has a single scalar field, return the type
     20;;; of that field.
     21(defun darwin32::record-type-has-single-scalar-field (record-type)
     22  (when (typep record-type 'foreign-structure-type)
     23    (ensure-foreign-type-bits record-type)
     24    (let* ((fields (foreign-record-type-fields record-type)))
     25      (when (null (cdr fields))
     26        (let* ((f0 (car fields))
     27               (type (foreign-record-field-type f0)))
     28          (typecase type
     29            ((or foreign-record-type foreign-array-type) nil)
     30            (otherwise type)))))))
     31
     32;;; If type denotes a foreign record type, return T if it would
     33;;; be "returned" by passing it as the first argument to the callee.
     34;;; On DarwinPPC32, this is true of all record types except for
     35;;; those for which RECORD-TYPE-HAS-SINGLE-SCALAR-FIELD returns
     36;;; true.
     37(defun darwin32::record-type-returns-structure-as-first-arg (rtype)
     38  (when (and rtype
     39             (not (typep rtype 'unsigned-byte))
     40             (not (member rtype *foreign-representation-type-keywords*
     41                          :test #'eq)))
     42    (let* ((ftype (if (typep rtype 'foreign-type)
     43                    rtype
     44                    (parse-foreign-type rtype))))
     45      (and (typep ftype 'foreign-record-type)
     46           (not (darwin32::record-type-has-single-scalar-field ftype))))))
     47
     48
     49;;; Structures that contain a single scalar field are "returned"
     50;;; as a value with that field's type.
     51;;; Other structures are "returned" by passing a pointer to a structure
     52;;; of the appropriate type as the first argument.
     53;;; Structures that contain a single scalar field are passed by value
     54;;; by passing the value of that field as a scalar.
     55;;; Structures that contain more than one field are passed by value
     56;;; as a sequence of N 32-bit words; %ff-call understands an unsigned
     57;;; integer argument "type" specifier to denote this.
     58
     59(defun darwin32::expand-ff-call (callform args)
     60  (let* ((result-type-spec (or (car (last args)) :void))
     61         (enclosing-form nil))
     62    (multiple-value-bind (result-type error)
     63        (parse-foreign-type result-type-spec)
     64      (if error
     65        (setq result-type-spec :void result-type *void-foreign-type*)
     66        (setq args (butlast args)))
     67      (collect ((argforms))
     68        (when (eq (car args) :monitor-exception-ports)
     69          (argforms (pop args)))
     70        (when (typep result-type 'foreign-record-type)
     71          (let* ((single-scalar (darwin32::record-type-has-single-scalar-field result-type))
     72                 (result-form (pop args)))
     73            (if single-scalar
     74              (progn
     75                (setq enclosing-form `(setf ,(%foreign-access-form result-form single-scalar 0 nil))
     76                      result-type single-scalar
     77                      result-type-spec (foreign-type-to-representation-type result-type)))
     78                     
     79              (progn
     80                (argforms :address)
     81                (argforms result-form)
     82                (setq result-type *void-foreign-type*
     83                      result-type-spec :void)))))
     84        (unless (evenp (length args))
     85          (error "~s should be an even-length list of alternating foreign types and values" args))
     86        (do* ((args args (cddr args)))
     87             ((null args))
     88          (let* ((arg-type-spec (car args))
     89                 (arg-value-form (cadr args)))
     90            (if (or (member arg-type-spec *foreign-representation-type-keywords*
     91                           :test #'eq)
     92                    (typep arg-type-spec 'unsigned-byte))
     93              (progn
     94                (argforms arg-type-spec)
     95                (argforms arg-value-form))
     96              (let* ((ftype (parse-foreign-type arg-type-spec)))
     97                (if (typep ftype 'foreign-record-type)
     98                  (let* ((single-scalar (darwin32::record-type-has-single-scalar-field ftype)))
     99                    (if single-scalar
     100                      (progn
     101                        (argforms (foreign-type-to-representation-type single-scalar))
     102                        (argforms (%foreign-access-form arg-value-form single-scalar 0 nil)))
     103                      (let* ((bits (ensure-foreign-type-bits ftype)))
     104                        (argforms (ceiling bits 32))
     105                        (argforms arg-value-form))))
     106                  (progn
     107                    (argforms (foreign-type-to-representation-type ftype))
     108                    (argforms arg-value-form)))))))
     109        (argforms (foreign-type-to-representation-type result-type))
     110        (let* ((call `(,@callform ,@(argforms))))
     111          (if enclosing-form
     112            `(,@enclosing-form ,call)
     113            call))))))
     114                 
     115           
     116           
     117                         
Note: See TracChangeset for help on using the changeset viewer.