📄 c-call.lisp
字号:
(:generator 2 (inst mov res (make-fixup foreign-symbol :foreign-dataref))))(define-vop (call-out) (:args (function :scs (sap-reg)) (args :more t)) (:results (results :more t)) (:temporary (:sc unsigned-reg :offset eax-offset :from :eval :to :result) eax) (:temporary (:sc unsigned-reg :offset ecx-offset :from :eval :to :result) ecx) (:temporary (:sc unsigned-reg :offset edx-offset :from :eval :to :result) edx) (:node-var node) (:vop-var vop) (:save-p t) (:ignore args ecx edx) (:generator 0 ;; FIXME & OAOOM: This is brittle and error-prone to maintain two ;; instances of the same logic, on in arch-assem.S, and one in ;; c-call.lisp. If you modify this, modify that one too... (cond ((policy node (> space speed)) (move eax function) (inst call (make-fixup "call_into_c" :foreign))) (t ;; Setup the NPX for C; all the FP registers need to be ;; empty; pop them all. (dotimes (i 8) (inst fstp fr0-tn)) ;; Clear out DF: Darwin, Windows, and Solaris at least require ;; this, and it should not hurt others either. (inst cld) (inst call function) ;; To give the debugger a clue. FIXME: not really internal-error? (note-this-location vop :internal-error) ;; Restore the NPX for lisp; ensure no regs are empty (dotimes (i 7) (inst fldz)) (if (and results (location= (tn-ref-tn results) fr0-tn)) ;; The return result is in fr0. (inst fxch fr7-tn) ; move the result back to fr0 (inst fldz)) ; insure no regs are empty ))));;; While SBCL uses the FPU in 53-bit mode, most C libraries assume that;;; the FPU is in 64-bit mode. So we change the FPU mode to 64-bit with;;; the SET-FPU-WORD-FOR-C VOP before calling out to C and set it back;;; to 53-bit mode after coming back using the SET-FPU-WORD-FOR-LISP VOP.(define-vop (set-fpu-word-for-c) (:node-var node) (:generator 0 (when (policy node (= sb!c::float-accuracy 3)) (inst sub esp-tn 4) (inst fnstcw (make-ea :word :base esp-tn)) (inst wait) (inst or (make-ea :word :base esp-tn) #x300) (inst fldcw (make-ea :word :base esp-tn)) (inst wait))))(define-vop (set-fpu-word-for-lisp) (:node-var node) (:generator 0 (when (policy node (= sb!c::float-accuracy 3)) (inst fnstcw (make-ea :word :base esp-tn)) (inst wait) (inst and (make-ea :word :base esp-tn) #xfeff) (inst fldcw (make-ea :word :base esp-tn)) (inst wait) (inst add esp-tn 4))))(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 esp-tn)) (unless (zerop amount) (let ((delta (logandc2 (+ amount 3) 3))) (inst sub esp-tn delta))) (align-stack-pointer esp-tn) (move result esp-tn)))(define-vop (alloc-alien-stack-space) (: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 esp-tn))) (unless (zerop amount) (let ((delta (logandc2 (+ amount 3) 3))) (inst mov temp (make-ea-for-symbol-tls-index *alien-stack*)) (inst sub (make-ea :dword :base temp) delta :fs))) (load-tl-symbol-value result *alien-stack*)) #!-sb-thread (:generator 0 (aver (not (location= result esp-tn))) (unless (zerop amount) (let ((delta (logandc2 (+ amount 3) 3))) (inst sub (make-ea-for-symbol-value *alien-stack*) delta))) (load-symbol-value result *alien-stack*)))(define-vop (dealloc-alien-stack-space) (:info amount) #!+sb-thread (:temporary (:sc unsigned-reg) temp) #!+sb-thread (:generator 0 (unless (zerop amount) (let ((delta (logandc2 (+ amount 3) 3))) (inst mov temp (make-ea-for-symbol-tls-index *alien-stack*)) (inst add (make-ea :dword :base temp) delta :fs)))) #!-sb-thread (:generator 0 (unless (zerop amount) (let ((delta (logandc2 (+ amount 3) 3))) (inst add (make-ea-for-symbol-value *alien-stack*) delta)))));;; 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 t) (:generator 0))#-sb-xc-host(defun alien-callback-accessor-form (type sp offset) `(deref (sap-alien (sap+ ,sp ,offset) (* ,type))))#-sb-xc-host(defun alien-callback-assembler-wrapper (index return-type arg-types) "Cons up a piece of code which calls call-callback with INDEX and apointer to the arguments." (declare (ignore arg-types)) (let* ((segment (make-segment)) (eax eax-tn) (edx edx-tn) (ebp ebp-tn) (esp esp-tn) ([ebp-8] (make-ea :dword :base ebp :disp -8)) ([ebp-4] (make-ea :dword :base ebp :disp -4))) (assemble (segment) (inst push ebp) ; save old frame pointer (inst mov ebp esp) ; establish new frame (inst mov eax esp) ; (inst sub eax 8) ; place for result (inst push eax) ; arg2 (inst add eax 16) ; arguments (inst push eax) ; arg1 (inst push (ash index 2)) ; arg0 ;; 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 expecte anyone ;; to rebind the variable. -- JES, 2006-01-01 (load-symbol-value eax sb!alien::*enter-alien-callback*) (inst push eax) ; function (inst mov eax (foreign-symbol-address "funcall3")) (inst call eax) ;; now put the result into the right register (cond ((and (alien-integer-type-p return-type) (eql (alien-type-bits return-type) 64)) (inst mov eax [ebp-8]) (inst mov edx [ebp-4])) ((or (alien-integer-type-p return-type) (alien-pointer-type-p return-type) (alien-type-= #.(parse-alien-type 'system-area-pointer nil) return-type)) (inst mov eax [ebp-8])) ((alien-single-float-type-p return-type) (inst fld [ebp-8])) ((alien-double-float-type-p return-type) (inst fldd [ebp-8])) ((alien-void-type-p return-type)) (t (error "unrecognized alien type: ~A" return-type))) (inst mov esp ebp) ; discard frame (inst pop ebp) ; restore frame pointer (inst ret)) (finalize-segment segment) ;; Now that the segment is done, convert it to a static ;; vector we can point foreign code to. (let ((buffer (sb!assem::segment-buffer segment))) (make-static-vector (length buffer) :element-type '(unsigned-byte 8) :initial-contents buffer))))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -