(0 eax-offset)
(1 edx-offset)))
-;; XXX The return handling probably doesn't conform to the ABI
-
(define-alien-type-method (integer :result-tn) (type state)
(let ((num-results (result-state-num-results state)))
(setf (result-state-num-results state) (1+ num-results))
(my-make-wired-tn ptype reg-sc (result-reg-offset num-results)))))
(define-alien-type-method (integer :naturalize-gen) (type alien)
- (if (and (alien-integer-type-signed type)
- (<= (alien-type-bits type) 32))
- `(sign-extend ,alien)
+ (if (<= (alien-type-bits type) 32)
+ (if (alien-integer-type-signed type)
+ `(sign-extend ,alien ,(alien-type-bits type))
+ `(logand ,alien ,(1- (ash 1 (alien-type-bits type)))))
alien))
(define-alien-type-method (system-area-pointer :result-tn) (type state)
(lambda-vars arg)
(cond ((and (alien-integer-type-p type)
(> (sb!alien::alien-integer-type-bits type) 64))
+ ;; CLH: FIXME! This should really be
+ ;; #xffffffffffffffff. nyef says: "Passing
+ ;; 128-bit integers to ALIEN functions on x86-64
+ ;; believed to be broken."
(new-args `(logand ,arg #xffffffff))
(new-args `(ash ,arg -64))
(new-arg-types (parse-alien-type '(unsigned 64) env))
,@(new-args))))))
(sb!c::give-up-ir1-transform))))
-;;; The ABI specifies that signed short/int's are returned as 32-bit
-;;; values. Negative values need to be sign-extended to 64-bits (done
-;;; in a :NATURALIZE-GEN alien-type-method).
-(defknown sign-extend ((signed-byte 32)) fixnum
- (foldable flushable movable))
+;;; The ABI is vague about how signed sub-word integer return values
+;;; are handled, but since gcc versions >=4.3 no longer do sign
+;;; extension in the callee, we need to do it in the caller. FIXME:
+;;; If the value to be extended is known to already be of the target
+;;; type at compile time, we can (and should) elide the extension.
+(defknown sign-extend ((signed-byte 64) t) fixnum
+ (foldable flushable movable))
(define-vop (sign-extend)
(:translate sign-extend)
(:policy :fast-safe)
(:args (val :scs (signed-reg)))
- (:arg-types fixnum)
+ (:arg-types signed-num (:constant fixnum))
+ (:info size)
(:results (res :scs (signed-reg)))
(:result-types fixnum)
(:generator 1
(inst movsxd res
(make-random-tn :kind :normal
- :sc (sc-or-lose 'dword-reg)
+ :sc (sc-or-lose (ecase size
+ (8 'byte-reg)
+ (16 'word-reg)
+ (32 'dword-reg)))
:offset (tn-offset val)))))
-(defun sign-extend (x)
- (declare (type (signed-byte 32) x))
- (sign-extend x))
+#-sb-xc-host
+(defun sign-extend (x size)
+ (declare (type (signed-byte 64) x))
+ (ecase size
+ (8 (sign-extend x size))
+ (16 (sign-extend x size))
+ (32 (sign-extend x size))))
+
+#+sb-xc-host
+(defun sign-extend (x size)
+ (if (logbitp (1- size) x)
+ (dpb x (byte size 0) -1)
+ x))
(define-vop (foreign-symbol-sap)
(:translate foreign-symbol-sap)
(args :more t))
(:results (results :more t))
(:temporary (:sc unsigned-reg :offset rax-offset :to :result) rax)
- (:ignore results)
+ ;; For safepoint builds: Force values of non-volatiles to the stack.
+ ;; These are the callee-saved registers in the native ABI, but
+ ;; safepoint-based GC needs to see all Lisp values on the stack. Note
+ ;; that R12-R15 are non-volatile registers, but there is no need to
+ ;; spill R12 because it is our thread-base-tn. RDI and RSI are
+ ;; non-volatile on Windows, but argument passing registers on other
+ ;; platforms.
+ #!+sb-safepoint (:temporary (:sc unsigned-reg :offset r13-offset) r13)
+ #!+sb-safepoint (:temporary (:sc unsigned-reg :offset r14-offset) r14)
+ #!+sb-safepoint (:temporary (:sc unsigned-reg :offset r15-offset) r15)
+ #!+(and sb-safepoint win32) (:temporary
+ (:sc unsigned-reg :offset rdi-offset) rdi)
+ #!+(and sb-safepoint win32) (:temporary
+ (:sc unsigned-reg :offset rsi-offset) rsi)
+ (:ignore results
+ #!+(and sb-safepoint win32) rdi
+ #!+(and sb-safepoint win32) rsi
+ #!+sb-safepoint r15
+ #!+sb-safepoint r13)
(:vop-var vop)
(:save-p t)
(:generator 0
+ ;; ABI: Direction flag must be clear on function entry. -- JES, 2006-01-20
+ (inst cld)
+ #!+sb-safepoint
+ (progn
+ ;; Current PC - don't rely on function to keep it in a form that
+ ;; GC understands
+ (let ((label (gen-label)))
+ (inst lea r14 (make-fixup nil :code-object label))
+ (emit-label label)))
;; ABI: AL contains amount of arguments passed in XMM registers
;; for vararg calls.
(move-immediate rax
while tn-ref
count (eq (sb-name (sc-sb (tn-sc (tn-ref-tn tn-ref))))
'float-registers)))
+ #!+sb-safepoint
+ (progn ;Store SP and PC in thread struct
+ (storew rsp-tn thread-base-tn thread-saved-csp-offset)
+ (storew r14 thread-base-tn thread-pc-around-foreign-call-slot))
(inst call function)
+ #!+sb-safepoint
+ (progn
+ ;; Zeroing out
+ (inst xor r14 r14)
+ ;; Zero PC storage place. NB. CSP-then-PC: same sequence on
+ ;; entry/exit, is actually corrent.
+ (storew r14 thread-base-tn thread-saved-csp-offset)
+ (storew r14 thread-base-tn thread-pc-around-foreign-call-slot))
;; To give the debugger a clue. XX not really internal-error?
(note-this-location vop :internal-error)))
(define-vop (alloc-number-stack-space)
(:info amount)
(:results (result :scs (sap-reg any-reg)))
+ (:result-types system-area-pointer)
(:generator 0
(aver (location= result rsp-tn))
(unless (zerop amount)
(:info amount)
#!+sb-thread (:temporary (:sc unsigned-reg) temp)
(:results (result :scs (sap-reg any-reg)))
+ (:result-types system-area-pointer)
#!+sb-thread
(:generator 0
(aver (not (location= result rsp-tn)))
(- other-pointer-lowtag)))
delta)))))
-;;; these are not strictly part of the c-call convention, but are
-;;; needed for the WITH-PRESERVED-POINTERS macro used for "locking
-;;; down" lisp objects so that GC won't move them while foreign
-;;; functions go to work.
-
-(define-vop (push-word-on-c-stack)
- (:translate push-word-on-c-stack)
- (:args (val :scs (sap-reg)))
+;;; not strictly part of the c-call convention, but needed for the
+;;; WITH-PINNED-OBJECTS macro used for "locking down" lisp objects so
+;;; that GC won't move them while foreign functions go to work.
+(define-vop (touch-object)
+ (:translate touch-object)
+ (:args (object))
+ (:ignore object)
(:policy :fast-safe)
- (:arg-types system-area-pointer)
- (:generator 2
- (inst push val)))
-
-(define-vop (pop-words-from-c-stack)
- (:translate pop-words-from-c-stack)
- (:args)
- (:arg-types (:constant (unsigned-byte 60)))
- (:info number)
- (:policy :fast-safe)
- (:generator 2
- (inst add rsp-tn (fixnumize number))))
+ (:arg-types t)
+ (:generator 0))
;;; Callbacks
(error "Too many arguments in callback")))
(let* ((segment (make-segment))
(rax rax-tn)
- (rcx rcx-tn)
+ #!+(not sb-safepoint) (rcx rcx-tn)
(rdi rdi-tn)
(rsi rsi-tn)
(rdx rdx-tn)
(t
(bug "Unknown alien floating point type: ~S" type)))))
- ;; arg0 to FUNCALL3 (function)
- ;;
- ;; Indirect the access to ENTER-ALIEN-CALLBACK through
- ;; the symbol-value slot of SB-ALIEN::*ENTER-ALIEN-CALLBACK*
- ;; to ensure it'll work even if the GC moves ENTER-ALIEN-CALLBACK.
- ;; Skip any SB-THREAD TLS magic, since we don't expect anyone
- ;; to rebind the variable. -- JES, 2006-01-01
- (inst mov rdi (+ nil-value (static-symbol-offset
- 'sb!alien::*enter-alien-callback*)))
- (loadw rdi rdi symbol-value-slot other-pointer-lowtag)
- ;; arg0 to ENTER-ALIEN-CALLBACK (trampoline index)
- (inst mov rsi (fixnumize index))
- ;; arg1 to ENTER-ALIEN-CALLBACK (pointer to argument vector)
- (inst mov rdx rsp)
- ;; add room on stack for return value
- (inst sub rsp 8)
- ;; arg2 to ENTER-ALIEN-CALLBACK (pointer to return value)
- (inst mov rcx rsp)
-
- ;; Make new frame
- (inst push rbp)
- (inst mov rbp rsp)
-
- ;; Call
- (inst mov rax (foreign-symbol-address "funcall3"))
- (inst call rax)
-
- ;; Back! Restore frame
- (inst mov rsp rbp)
- (inst pop rbp)
+ #!-sb-safepoint
+ (progn
+ ;; arg0 to FUNCALL3 (function)
+ ;;
+ ;; Indirect the access to ENTER-ALIEN-CALLBACK through
+ ;; the symbol-value slot of SB-ALIEN::*ENTER-ALIEN-CALLBACK*
+ ;; to ensure it'll work even if the GC moves ENTER-ALIEN-CALLBACK.
+ ;; Skip any SB-THREAD TLS magic, since we don't expect anyone
+ ;; to rebind the variable. -- JES, 2006-01-01
+ (inst mov rdi (+ nil-value (static-symbol-offset
+ 'sb!alien::*enter-alien-callback*)))
+ (loadw rdi rdi symbol-value-slot other-pointer-lowtag)
+ ;; arg0 to ENTER-ALIEN-CALLBACK (trampoline index)
+ (inst mov rsi (fixnumize index))
+ ;; arg1 to ENTER-ALIEN-CALLBACK (pointer to argument vector)
+ (inst mov rdx rsp)
+ ;; add room on stack for return value
+ (inst sub rsp 8)
+ ;; arg2 to ENTER-ALIEN-CALLBACK (pointer to return value)
+ (inst mov rcx rsp)
+
+ ;; Make new frame
+ (inst push rbp)
+ (inst mov rbp rsp)
+
+ ;; Call
+ (inst mov rax (foreign-symbol-address "funcall3"))
+ (inst call rax)
+
+ ;; Back! Restore frame
+ (inst mov rsp rbp)
+ (inst pop rbp))
+
+ #!+sb-safepoint
+ (progn
+ ;; arg0 to ENTER-ALIEN-CALLBACK (trampoline index)
+ (inst mov rdi (fixnumize index))
+ ;; arg1 to ENTER-ALIEN-CALLBACK (pointer to argument vector)
+ (inst mov rsi rsp)
+ ;; add room on stack for return value
+ (inst sub rsp 8)
+ ;; arg2 to ENTER-ALIEN-CALLBACK (pointer to return value)
+ (inst mov rdx rsp)
+ ;; Make new frame
+ (inst push rbp)
+ (inst mov rbp rsp)
+ ;; Call
+ (inst mov rax (foreign-symbol-address "callback_wrapper_trampoline"))
+ (inst call rax)
+ ;; Back! Restore frame
+ (inst mov rsp rbp)
+ (inst pop rbp))
;; Result now on top of stack, put it in the right register
(cond