Changeset 5776
- Timestamp:
- Jan 23, 2007, 5:59:23 AM (18 years ago)
- File:
-
- 1 edited
-
trunk/ccl/compiler/X86/X8664/x8664-backend.lisp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ccl/compiler/X86/X8664/x8664-backend.lisp
r5752 r5776 296 296 (pushnew *x8664-backend* *known-backends* :key #'backend-name) 297 297 298 ;;; FFI stuff. Seems to be shared by Darwin/Linux/FreeBSD. 299 300 ;;; A returned structure is passed as an invisible first argument if 301 ;;; it's more than 2 doublewords long or if it contains unaligned fields. 302 ;;; Not clear how the latter case can happen, so this just checks for 303 ;;; the first. 304 (defun x8664::record-type-returns-structure-as-first-arg (rtype) 305 (when (and rtype 306 (not (typep rtype 'unsigned-byte)) 307 (not (member rtype *foreign-representation-type-keywords* 308 :test #'eq))) 309 (let* ((ftype (if (typep rtype 'foreign-type) 310 rtype 311 (parse-foreign-type rtype)))) 312 (> (ensure-foreign-type-bits ftype) 128)))) 313 314 ;;; On x8664, structures can be passed by value: 315 ;;; a) in memory, if they're more than 128 bits in size or if there aren't 316 ;;; enough of the right kind of register to pass them entirely in registers. 317 ;;; b) as a series of 64-bit chunks, passed in GPRs if any component of the 318 ;;; chunk is a non FLOAT or in FPRs otherwise. 319 ;;; Note that this means that a chunk consisting of two SINGLE-FLOATs would 320 ;;; be passed in the low 64 bit of an SSE (xmm) register. 321 322 (defun x8664::field-is-of-class-integer (field) 323 ;; Return true if field is of "class" integer or if it's a record 324 ;; type of class integer. (See the System V AMD64 ABI document for 325 ;; a convoluted definition of field "classes".) 326 (let* ((ftype (foreign-record-field-type field))) 327 (typecase ftype 328 ((or foreign-integer-type foreign-pointer-type) t) 329 (foreign-record-type (dolist (f (foreign-record-type-fields ftype)) 330 (when (x8664::field-is-of-class-integer f) 331 (return t)))) 332 (otherwise nil)))) 333 334 (defun x8664::classify-8byte (field-list bit-limit) 335 ;; CDR down the fields in FIELD-LIST until we find a field of class integer, 336 ;; hit the end of the list, or find a field whose offset is >= BIT-LIMIT. 337 ;; In the first case, return :INTEGER. In other cases, return :FLOAT. 338 (dolist (field field-list :float) 339 (if (<= bit-limit (foreign-record-field-offset field)) 340 (return :float) 341 (if (x8664::field-is-of-class-integer field) 342 (return :integer))))) 343 344 ;;; Return a first value :memory, :integer, or::float and a second 345 ;;; value of NIL, :integer, or :float according to how the structure 346 ;;; RTYPE should ideally be passed or returned. Note that the caller 347 ;;; may decide to turn this to :memory if there aren't enough 348 ;;; available registers of the right class when passing an instance of 349 ;;; this structure type. 350 (defun x8664::classify-record-type (rtype) 351 (let* ((nbits (ensure-foreign-type-bits rtype)) 352 (fields (foreign-record-type-fields rtype))) 353 (cond ((> nbits 128) (values :memory nil)) 354 ((<= nbits 64) (values (x8664::classify-8byte fields 64) nil)) 355 (t (values (x8664::classify-8byte fields 64) 356 (do* () 357 ((>= (foreign-record-field-offset (car fields)) 64) 358 (x8664::classify-8byte fields 128)) 359 (setq fields (cdr fields)))))))) 360 361 (defun x8664::struct-from-regbuf-values (r rtype regbuf) 362 (multiple-value-bind (first second) 363 (x8664::classify-record-type rtype) 364 (let* ((gpr-offset 0) 365 (fpr-offset 16)) 366 (collect ((forms)) 367 (case first 368 (:integer (forms `(setf (%%get-unsigned-longlong ,r 0) 369 (%%get-unsigned-longlong ,regbuf 0))) 370 (setq gpr-offset 8)) 371 (:float (forms `(setf (%%get-unsigned-longlong ,r 0) 372 (%%get-unsigned-longlong ,regbuf 16))) 373 (setf fpr-offset 24))) 374 (case second 375 (:integer (forms `(setf (%%get-unsigned-longlong ,r 8) 376 (%%get-unsigned-longlong ,regbuf ,gpr-offset)))) 377 (:float (forms `(setf (%%get-unsigned-longlong ,r 8) 378 (%%get-unsigned-longlong ,regbuf ,fpr-offset))))) 379 `(progn ,@(forms)))))) 380 381 (defun x8664::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result)) 382 (let* ((result-type-spec (or (car (last args)) :void)) 383 (regbuf nil) 384 (result-temp nil) 385 (result-form nil) 386 (struct-result-type nil) 387 (structure-arg-temp nil)) 388 (multiple-value-bind (result-type error) 389 (parse-foreign-type result-type-spec) 390 (if error 391 (setq result-type-spec :void result-type *void-foreign-type*) 392 (setq args (butlast args))) 393 (collect ((argforms)) 394 (when (eq (car args) :monitor-exception-ports) 395 (argforms (pop args))) 396 (when (typep result-type 'foreign-record-type) 397 (setq result-form (pop args) 398 struct-result-type result-type 399 result-type *void-foreign-type* 400 result-type-spec :void) 401 (if (x8664::record-type-returns-structure-as-first-arg struct-result-type) 402 (progn 403 (argforms :address) 404 (argforms result-form)) 405 (progn 406 (setq regbuf (gensym) 407 result-temp (gensym)) 408 (argforms :registers) 409 (argforms regbuf)))) 410 (let* ((valform nil)) 411 (unless (evenp (length args)) 412 (error "~s should be an even-length list of alternating foreign types and values" args)) 413 (do* ((args args (cddr args)) 414 (remaining-gprs 6) 415 (remaining-fprs 8)) 416 ((null args)) 417 (let* ((arg-type-spec (car args)) 418 (arg-value-form (cadr args))) 419 (if (or (member arg-type-spec *foreign-representation-type-keywords* 420 :test #'eq) 421 (typep arg-type-spec 'unsigned-byte)) 422 (progn 423 (argforms arg-type-spec) 424 (argforms arg-value-form)) 425 (let* ((ftype (parse-foreign-type arg-type-spec))) 426 (if (typep ftype 'foreign-record-type) 427 (multiple-value-bind (first8 second8) 428 (x8664::classify-record-type ftype) 429 (let* ((gprs remaining-gprs) 430 (fprs remaining-fprs)) 431 (case first8 432 (:integer (if (< (decf gprs) 0) (setq first8 :memory))) 433 (:float (if (< (decf fprs) 0) (setq first8 :memory)))) 434 (case second8 435 (:integer (if (< (decf gprs) 0) (setq first8 :memory))) 436 (:float (if (< (decf fprs) 0) (setq first8 :memory))))) 437 (if (eq first8 :memory) 438 (progn 439 (argforms (ceiling (foreign-record-type-bits ftype) 64)) 440 (argforms arg-value-form)) 441 (progn 442 (if second8 443 (progn 444 (unless structure-arg-temp 445 (setq structure-arg-temp (gensym))) 446 (setq valform `(%setf-macptr ,structure-arg-temp ,arg-value-form))) 447 (setq valform arg-value-form)) 448 (if (eq first8 :float) 449 (progn 450 (decf remaining-fprs) 451 (argforms :double-float) 452 (argforms `(%get-double-float ,valform 0))) 453 (progn 454 (decf remaining-gprs) 455 (argforms :unsigned-doubleword) 456 (argforms `(%%get-unsigned-longlong ,valform 0)))) 457 (when second8 458 (if (eq second8 :float) 459 (progn 460 (decf remaining-fprs) 461 (argforms :double-float) 462 (argforms `(%get-double-float ,valform 8))) 463 (progn 464 (decf remaining-gprs) 465 (argforms :unsigned-doubleword) 466 (argforms `(%%get-unsigned-longlong ,valform 8)))))))) 467 (let* ((rtype (foreign-type-to-representation-type ftype))) 468 (if (or (eq rtype :singlefloat) (eq rtype :double-float)) 469 (decf remaining-fprs) 470 (decf remaining-gprs)) 471 (argforms rtype) 472 (argforms (funcall arg-coerce arg-type-spec arg-value-form)))))))) 473 (argforms (foreign-type-to-representation-type result-type)) 474 (let* ((call (funcall result-coerce result-type-spec `(,@callform ,@(argforms))))) 475 (when structure-arg-temp 476 (setq call `(let* ((,structure-arg-temp (%null-ptr))) 477 (declare (dynamic-extent ,structure-arg-temp) 478 (type macptr ,structure-arg-temp)) 479 ,call))) 480 (if regbuf 481 `(let* ((,result-temp (%null-ptr))) 482 (declare (dynamic-extent ,result-temp) 483 (type macptr ,result-temp)) 484 (%setf-macptr ,result-temp ,result-form) 485 (%stack-block ((,regbuf (+ (* 2 8) (* 2 8)))) 486 ,call 487 ,(x8664::struct-from-regbuf-values result-temp struct-result-type regbuf))) 488 call))))))) 489 490 298 491 #+x8664-target 299 492 (require "X8664-VINSNS")
Note:
See TracChangeset
for help on using the changeset viewer.
