Changeset 5747
- Timestamp:
- Jan 20, 2007, 6:22:15 PM (18 years ago)
- File:
-
- 1 edited
-
trunk/ccl/lib/ffi-darwinppc64.lisp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ccl/lib/ffi-darwinppc64.lisp
r5737 r5747 15 15 ;;; http://opensource.franz.com/preamble.html 16 16 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.
