0.9.1.52:
[sbcl.git] / src / compiler / x86 / c-call.lisp
index d626ede..479c9f1 100644 (file)
 
 
 (deftransform %alien-funcall ((function type &rest args) * * :node node)
-  (aver (sb!c::constant-continuation-p type))
-  (let* ((type (sb!c::continuation-value type))
+  (aver (sb!c::constant-lvar-p type))
+  (let* ((type (sb!c::lvar-value type))
         (env (sb!c::node-lexenv node))
          (arg-types (alien-fun-type-arg-types type))
          (result-type (alien-fun-type-result-type type)))
                                     ,@(new-args))))))
         (sb!c::give-up-ir1-transform))))
 
-
-
-
 (define-vop (foreign-symbol-address)
   (:translate foreign-symbol-address)
   (:policy :fast-safe)
   (:args)
-  (:arg-types (:constant simple-base-string))
+  (:arg-types (:constant simple-string))
+  (:info foreign-symbol)
+  (:results (res :scs (sap-reg)))
+  (:result-types system-area-pointer)
+  (:generator 2
+   (inst lea res (make-fixup foreign-symbol :foreign))))
+
+#!+linkage-table
+(define-vop (foreign-symbol-dataref-address)
+  (:translate foreign-symbol-dataref-address)
+  (:policy :fast-safe)
+  (:args)
+  (:arg-types (:constant simple-string))
   (:info foreign-symbol)
   (:results (res :scs (sap-reg)))
   (:result-types system-area-pointer)
   (:generator 2
-   (inst lea res (make-fixup (extern-alien-name foreign-symbol) :foreign))))
+   (inst mov res (make-fixup foreign-symbol :foreign-dataref))))
 
 (define-vop (call-out)
   (:args (function :scs (sap-reg))
   (:generator 0
     (cond ((policy node (> space speed))
           (move eax function)
-          (inst call (make-fixup (extern-alien-name "call_into_c") :foreign)))
+          (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.
 (define-vop (alloc-number-stack-space)
   (:info amount)
   (:results (result :scs (sap-reg any-reg)))
+  (:node-var node)
   (:generator 0
     (aver (location= result esp-tn))
+    (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))
     (unless (zerop amount)
       (let ((delta (logandc2 (+ amount 3) 3)))
        (inst sub esp-tn delta)))
 
 (define-vop (dealloc-number-stack-space)
   (:info amount)
+  (:node-var node)
   (:generator 0
     (unless (zerop amount)
       (let ((delta (logandc2 (+ amount 3) 3)))
-       (inst add esp-tn delta)))))
+       (inst add esp-tn delta)))
+    (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-alien-stack-space)
   (:info amount)
                                     (ash symbol-value-slot word-shift)
                                     (- 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)))
+  (: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 29)))
+  (:info number)
+  (:policy :fast-safe)
+  (:generator 2
+    (inst add esp-tn (fixnumize number))))
+
+#-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 a
+pointer 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
+             (inst push (get-lisp-obj-address #'enter-alien-callback)) ; function
+             (inst mov  eax (foreign-symbol-address-as-integer "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))))