Changeset 5747


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

Two down, 5 to go.

File:
1 edited

Legend:

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

    r5737 r5747  
    1515;;;   http://opensource.franz.com/preamble.html
    1616
     17(in-package "CCL")
     18
     19;;; On DarwinPPC64:
     20;;; Structures whose size is exactly 16 bytes are passed in 2 GPRs,
     21;;; regardless of the types of their elements, when they are passed
     22;;; by value.
     23;;; Structures which contain unions are passed in N GPRs when passed
     24;;; by value
     25;;; All other structures passed by value are passed by passing their
     26;;; constituent elements as scalars.  (For bitfields, the containing
     27;;; integer counts as a constituent element.)
     28;;; Structures whose size is exactly 16 bytes are returned in GPR3
     29;;; and GPR4.
     30;;; Structures which contain unions are "returned" by passing a pointer
     31;;; to a structure instance in the first argument.
     32;;; All other structures are returned by returning their constituent
     33;;; elements as scalars.  (Note that - in some cases - we may need
     34;;; to reserve space in the foreign stack frame to handle scalar
     35;;; return values that don't fit in registers.  Need a way to tell
     36;;; %ff-call about this, as well as runtime support.)
     37
     38
     39(defun darwin64::record-type-contains-union (rtype)
     40  ;;; RTYPE is a FOREIGN-RECORD-TYPE object.
     41  ;;; If it, any of its fields, or any fields in an
     42  ;;; embedded structure or array field is a union,
     43  ;;; return true.
     44  ;;; (If this function returns true, we can't
     45  ;;; pass a structure of type RTYPE - or return one -
     46  ;;; by passing or returning the values of all of
     47  ;;; its fields, since some fields are aliased.
     48  ;;; However, if the record's size is exactly 128
     49  ;;; bits, we can pass/return  it in two GPRs.)
     50  (ensure-foreign-type-bits rtype)
     51  (or (eq (foreign-record-type-kind rtype) :union)
     52      (dolist (f (foreign-record-type-fields rtype))
     53        (let* ((fieldtype (foreign-record-field-type f)))
     54          (if (and (typep fieldtype 'foreign-record-type)
     55                   (darwin64::record-type-contains-union fieldtype))
     56            (return t))
     57          (if (typep fieldtype 'foreign-array-type)
     58            (let* ((atype (foreign-array-type-element-type fieldtype)))
     59              (if (and (typep atype 'foreign-record-type)
     60                       (darwin64::record-type-contains-union atype))
     61                (return t))))))))
     62
     63;;; On DarwinPPC64, we only have to pass a structure as a first
     64;;; argument if the type contains a union
     65(defun darwin64::record-type-returns-structure-as-first-arg (rtype)
     66  (when (and rtype
     67             (not (typep rtype 'unsigned-byte))
     68             (not (member rtype *foreign-representation-type-keywords*
     69                          :test #'eq)))
     70    (let* ((ftype (if (typep rtype 'foreign-type)
     71                    rtype
     72                    (parse-foreign-type rtype))))
     73      (and (typep ftype 'foreign-record-type)
     74           (not (= (ensure-foreign-type-bits ftype) 128))
     75           (darwin64::record-type-contains-union ftype)))))
     76
     77;;; Generate code to set the fields in a structure R of record-type
     78;;; RTYPE, based on the register values in REGBUF (8 64-bit GPRs,
     79;;; followed by 13 64-bit GPRs.)
     80;;; This also handles the 16-byte structure case.
     81;;; (It doesn't yet handle embedded arrays or bitfields.)
     82(defun darwin64::struct-from-regbuf-values (r rtype regbuf)
     83  (let* ((bits (ccl::ensure-foreign-type-bits rtype)))
     84    (collect ((forms))
     85      (cond ((= bits 128)               ;(and (eql day 'tuesday) ...)
     86             (forms `(setf (ccl::%%get-signed-longlong ,r 0)
     87                      (ccl::%%get-signed-longlong ,regbuf 0)
     88                      (ccl::%%get-signed-longlong ,r 8)
     89                      (ccl::%%get-signed-longlong ,regbuf 8))))
     90            (t
     91             (let* ((gpr-offset 0)
     92                    (fpr-offset (* 8 8)))
     93               (flet ((next-gpr-offset ()
     94                        (prog1 gpr-offset
     95                          (incf gpr-offset 8)))
     96                      (next-fpr-offset ()
     97                        (prog1 fpr-offset
     98                          (incf gpr-offset 8)
     99                          (incf fpr-offset 8))))
     100                 (labels ((do-fields (fields accessors)
     101                            (dolist (field fields)
     102                              (let* ((field-type (foreign-record-field-type field))
     103                                     (field-accessor-list (append accessors (list (foreign-record-field-name field))))
     104                                     (valform ()))
     105                                (etypecase field-type
     106                                  (foreign-record-type
     107                                   (do-fields (foreign-record-type-fields field-type)
     108                                     field-accessor-list))
     109                                  (foreign-pointer-type
     110                                   (setq valform
     111                                         `(%get-ptr ,regbuf ,(next-gpr-offset))))
     112                                  (foreign-double-float-type
     113                                   (setq valform
     114                                         `(%get-double-float  ,regbuf ,(next-fpr-offset))))
     115                                  (foreign-single-float-type
     116                                   (setq valform
     117                                         `(%get-single-float-from-double-ptr
     118                                           ,regbuf ,(next-fpr-offset))))
     119                                  (foreign-integer-type
     120                                   (let* ((bits (foreign-integer-type-bits field-type))
     121                                          (signed (foreign-integer-type-signed field-type)))
     122                                     (case bits
     123                                       (64
     124                                        (setq valform
     125                                              `(,(if signed
     126                                                     '%%get-signed-longlong
     127                                                     '%%get-unsigned-longlong)
     128                                                ,regbuf
     129                                                ,(next-gpr-offset))))
     130                                       (32
     131                                        (setq valform
     132                                              `(,(if signed
     133                                                     '%get-signed-long
     134                                                     '%get-unsigned-long)
     135                                                ,regbuf
     136                                                (+ 4 ,(next-gpr-offset)))))
     137                                       (16
     138                                        (setq valform
     139                                              `(,(if signed
     140                                                     '%get-signed-word
     141                                                     '%get-unsigned-word)
     142                                                ,regbuf
     143                                                (+ 6 ,(next-gpr-offset)))))
     144                                       (8
     145                                        (setq valform
     146                                              `(,(if signed
     147                                                     '%get-signed-byte
     148                                                     '%get-unsigned-byte)
     149                                                ,regbuf
     150                                                (+ 7 ,(next-gpr-offset))))))))
     151                                  (foreign-array-type
     152                                   (error "Embedded array-type."))
     153                                  )
     154                                (when valform
     155                                  (forms `(setf ,(%foreign-access-form
     156                                                  r
     157                                                  rtype
     158                                                  0
     159                                                  field-accessor-list)
     160                                           ,valform)))))))
     161                   (do-fields (foreign-record-type-fields rtype) nil ))
     162                 `(progn ,@(forms) nil))))))))
     163                                 
     164
     165(defun darwin64::expand-ff-call (callform args)
     166  (let* ((result-type-spec (or (car (last args)) :void))
     167         (regbuf nil)
     168         (result-temp nil)
     169         (result-form nil)
     170         (struct-result-type nil)
     171         (structure-arg-temp nil))
     172    (multiple-value-bind (result-type error)
     173        (parse-foreign-type result-type-spec)
     174      (if error
     175        (setq result-type-spec :void result-type *void-foreign-type*)
     176        (setq args (butlast args)))
     177      (collect ((argforms))
     178        (when (eq (car args) :monitor-exception-ports)
     179          (argforms (pop args)))
     180        (when (typep result-type 'foreign-record-type)
     181          (setq result-form (pop args)
     182                struct-result-type result-type
     183                result-type *void-foreign-type*
     184                result-type-spec :void)
     185          (if (darwin64::record-type-returns-structure-as-first-arg struct-result-type)
     186            (progn
     187              (argforms :address)
     188              (argforms result-form))
     189            (progn
     190              (setq regbuf (gensym)
     191                    result-temp (gensym))
     192              (argforms :registers)
     193              (argforms regbuf))))
     194        (let* ((valform nil))
     195          (labels ((do-fields (rtype fields accessors)
     196                     (dolist (field fields)
     197                       (let* ((field-type (foreign-record-field-type field))
     198                              (field-accessor-list (append accessors (list (foreign-record-field-name field))))
     199                              (access-form ()))
     200                         (typecase field-type
     201                           (foreign-record-type
     202                            (do-fields rtype (foreign-record-type-fields field-type) field-accessor-list))
     203                           ((or foreign-pointer-type foreign-integer-type
     204                                foreign-single-float-type foreign-double-float-type)
     205                            (setq access-form
     206                                  (%foreign-access-form valform rtype 0 field-accessor-list))))
     207                         (when access-form
     208                           (argforms (foreign-type-to-representation-type field-type))
     209                           (argforms access-form)
     210                           (setq valform structure-arg-temp))))))
     211            (unless (evenp (length args))
     212              (error "~s should be an even-length list of alternating foreign types and values" args))
     213            (do* ((args args (cddr args)))
     214                 ((null args))
     215              (let* ((arg-type-spec (car args))
     216                     (arg-value-form (cadr args)))
     217                (if (or (member arg-type-spec *foreign-representation-type-keywords*
     218                                :test #'eq)
     219                        (typep arg-type-spec 'unsigned-byte))
     220                  (progn
     221                    (argforms arg-type-spec)
     222                    (argforms arg-value-form))
     223                  (let* ((ftype (parse-foreign-type arg-type-spec)))
     224                    (if (typep ftype 'foreign-record-type)
     225                      (if (darwin64::record-type-contains-union ftype)
     226                        (progn
     227                          (argforms (ceiling (foreign-record-type-bits ftype) 64))
     228                          (argforms arg-value-form))
     229                        (progn
     230                          (unless structure-arg-temp
     231                            (setq structure-arg-temp (gensym)))
     232                          (setq valform `(%setf-macptr ,structure-arg-temp ,arg-value-form))
     233                          (do-fields ftype (foreign-record-type-fields ftype) nil)))
     234                      (progn
     235                        (argforms (foreign-type-to-representation-type ftype))
     236                        (argforms arg-value-form)))))))
     237            (argforms (foreign-type-to-representation-type result-type))
     238            (let* ((call `(,@callform ,@(argforms))))
     239              (when structure-arg-temp
     240                (setq call `(let* ((,structure-arg-temp (%null-ptr)))
     241                             (declare (dynamic-extent ,structure-arg-temp)
     242                                      (type macptr ,structure-arg-temp))
     243                             ,call)))
     244              (if regbuf
     245                `(let* ((,result-temp (%null-ptr)))
     246                  (declare (dynamic-extent ,result-temp)
     247                           (type macptr ,result-temp))
     248                  (%setf-macptr ,result-temp ,result-form)
     249                  (%stack-block ((,regbuf (+ (* 8 8) (* 8 13))))
     250                    ,call
     251                    ,(darwin64::struct-from-regbuf-values result-temp struct-result-type regbuf)))
     252                call))))))))
Note: See TracChangeset for help on using the changeset viewer.