"UNION" "VALUES" "*")
:export ("ADDR"
"ALIEN"
- #!+win32 "ALIEN-FUNCALL-STDCALL"
"ALIEN-FUNCALL" "ALIEN-SAP" "ALIEN-SIZE"
"CAST" "C-STRING"
"DEFINE-ALIEN-ROUTINE" "DEFINE-ALIEN-TYPE" "DEFINE-ALIEN-VARIABLE"
"SB!KERNEL" "SB!SYS")
:reexport ("SLOT" "CODE-INSTRUCTIONS" "FLUSHABLE")
:export ("%ALIEN-FUNCALL"
- #!+win32 "%ALIEN-FUNCALL-STDCALL"
"%CATCH-BREAKUP" "%CONTINUE-UNWIND"
"%LISTIFY-REST-ARGS" "%MORE-ARG" "%MORE-ARG-VALUES"
"%UNWIND-PROTECT-BREAKUP"
"*SETF-ASSUMED-FBOUNDP*"
"*SUPPRESS-VALUES-DECLARATION*"
+ #!+x86 "SET-FPU-WORD-FOR-C"
+ #!+x86 "SET-FPU-WORD-FOR-LISP"
"ALLOC-ALIEN-STACK-SPACE" "ALLOC-NUMBER-STACK-SPACE"
"ALLOCATE-CODE-OBJECT" "ALLOCATE-FRAME"
"ALLOCATE-DYNAMIC-CODE-OBJECT" "ALLOCATE-FULL-CALL-FRAME"
(t
(error "~S is not an alien function." alien)))))
-(defun alien-funcall-stdcall (alien &rest args)
- #!+sb-doc
- "Call the foreign function ALIEN with the specified arguments. ALIEN's
- type specifies the argument and result types."
- (declare (type alien-value alien))
- (let ((type (alien-value-type alien)))
- (typecase type
- (alien-pointer-type
- (apply #'alien-funcall-stdcall (deref alien) args))
- (alien-fun-type
- (unless (= (length (alien-fun-type-arg-types type))
- (length args))
- (error "wrong number of arguments for ~S~%expected ~W, got ~W"
- type
- (length (alien-fun-type-arg-types type))
- (length args)))
- (let ((stub (alien-fun-type-stub type)))
- (unless stub
- (setf stub
- (let ((fun (gensym))
- (parms (make-gensym-list (length args))))
- (compile nil
- `(lambda (,fun ,@parms)
- (declare (optimize (sb!c::insert-step-conditions 0)))
- (declare (type (alien ,type) ,fun))
- (alien-funcall-stdcall ,fun ,@parms)))))
- (setf (alien-fun-type-stub type) stub))
- (apply stub alien args)))
- (t
- (error "~S is not an alien function." alien)))))
-
(defmacro define-alien-routine (name result-type
&rest args
&environment lexenv)
(defknown alien-funcall (alien-value &rest *) *
(any recursive))
-#!+win32
-(defknown alien-funcall-stdcall (alien-value &rest *) *
- (any recursive))
\f
;;;; cosmetic transforms
(dolist (arg args)
(annotate-ordinary-lvar arg)))
+;;; We support both the stdcall and cdecl calling conventions on win32 by
+;;; resetting ESP after the foreign function returns. This way it works
+;;; correctly whether the party that is supposed to pop arguments from
+;;; the stack is the caller (cdecl) or the callee (stdcall).
(defoptimizer (%alien-funcall ir2-convert)
((function type &rest args) call block)
(let ((type (if (constant-lvar-p type)
(lvar-value type)
(error "Something is broken.")))
(lvar (node-lvar call))
- (args args))
+ (args args)
+ #!+win32 (stack-pointer (make-stack-pointer-tn)))
(multiple-value-bind (nsp stack-frame-size arg-tns result-tns)
(make-call-out-tns type)
+ #!+x86 (vop set-fpu-word-for-c call block)
+ #!+win32 (vop current-stack-pointer call block stack-pointer)
(vop alloc-number-stack-space call block stack-frame-size nsp)
(dolist (tn arg-tns)
;; On PPC, TN might be a list. This is used to indicate
((lvar-tn call block function)
(reference-tn-list arg-tns nil))
((reference-tn-list result-tns t))))
- (vop dealloc-number-stack-space call block stack-frame-size)
- (move-lvar-result call block result-tns lvar))))
-\f
-;;;; ALIEN-FUNCALL-STDCALL support
-
-#!+win32
-(deftransform alien-funcall-stdcall ((function &rest args)
- ((alien (* t)) &rest *) *
- :important t)
- (let ((names (make-gensym-list (length args))))
- (/noshow "entering first DEFTRANSFORM ALIEN-FUNCALL-STDCALL" function args)
- `(lambda (function ,@names)
- (alien-funcall-stdcall (deref function) ,@names))))
-
-#!+win32
-(deftransform alien-funcall-stdcall ((function &rest args) * * :important t)
- (let ((type (lvar-type function)))
- (unless (alien-type-type-p type)
- (give-up-ir1-transform "can't tell function type at compile time"))
- (/noshow "entering second DEFTRANSFORM ALIEN-FUNCALL-STDCALL" function)
- (let ((alien-type (alien-type-type-alien-type type)))
- (unless (alien-fun-type-p alien-type)
- (give-up-ir1-transform))
- (let ((arg-types (alien-fun-type-arg-types alien-type)))
- (unless (= (length args) (length arg-types))
- (abort-ir1-transform
- "wrong number of arguments; expected ~W, got ~W"
- (length arg-types)
- (length args)))
- (collect ((params) (deports))
- (dolist (arg-type arg-types)
- (let ((param (gensym)))
- (params param)
- (deports `(deport ,param ',arg-type))))
- (let ((return-type (alien-fun-type-result-type alien-type))
- (body `(%alien-funcall-stdcall (deport function ',alien-type)
- ',alien-type
- ,@(deports))))
- (if (alien-values-type-p return-type)
- (collect ((temps) (results))
- (dolist (type (alien-values-type-values return-type))
- (let ((temp (gensym)))
- (temps temp)
- (results `(naturalize ,temp ',type))))
- (setf body
- `(multiple-value-bind ,(temps) ,body
- (values ,@(results)))))
- (setf body `(naturalize ,body ',return-type)))
- (/noshow "returning from DEFTRANSFORM ALIEN-FUNCALL-STDCALL" (params) body)
- `(lambda (function ,@(params))
- ,body)))))))
-
-#!+win32
-(defoptimizer (%alien-funcall-stdcall derive-type) ((function type &rest args))
- (declare (ignore function args))
- (unless (constant-lvar-p type)
- (error "Something is broken."))
- (let ((type (lvar-value type)))
- (unless (alien-fun-type-p type)
- (error "Something is broken."))
- (values-specifier-type
- (compute-alien-rep-type
- (alien-fun-type-result-type type)))))
-
-#!+win32
-(defoptimizer (%alien-funcall-stdcall ltn-annotate)
- ((function type &rest args) node ltn-policy)
- (setf (basic-combination-info node) :funny)
- (setf (node-tail-p node) nil)
- (annotate-ordinary-lvar function)
- (dolist (arg args)
- (annotate-ordinary-lvar arg)))
-
-#!+win32
-(defoptimizer (%alien-funcall-stdcall ir2-convert)
- ((function type &rest args) call block)
- (let ((type (if (constant-lvar-p type)
- (lvar-value type)
- (error "Something is broken.")))
- (lvar (node-lvar call))
- (args args))
- (multiple-value-bind (nsp stack-frame-size arg-tns result-tns)
- (make-call-out-tns type)
- (vop alloc-number-stack-space call block stack-frame-size nsp)
- (dolist (tn arg-tns)
- (let* ((arg (pop args))
- (sc (tn-sc tn))
- (scn (sc-number sc))
- #!-x86 (temp-tn (make-representation-tn (tn-primitive-type tn)
- scn))
- (move-arg-vops (svref (sc-move-arg-vops sc) scn)))
- (aver arg)
- (unless (= (length move-arg-vops) 1)
- (error "no unique move-arg-vop for moves in SC ~S" (sc-name sc)))
- #!+x86 (emit-move-arg-template call
- block
- (first move-arg-vops)
- (lvar-tn call block arg)
- nsp
- tn)
- #!-x86 (progn
- (emit-move call
- block
- (lvar-tn call block arg)
- temp-tn)
- (emit-move-arg-template call
- block
- (first move-arg-vops)
- temp-tn
- nsp
- tn))))
- (aver (null args))
- (unless (listp result-tns)
- (setf result-tns (list result-tns)))
- (vop* call-out call block
- ((lvar-tn call block function)
- (reference-tn-list arg-tns nil))
- ((reference-tn-list result-tns t)))
- ;; This is the stdcall magic: Callee clears args.
- #+nil (vop dealloc-number-stack-space call block stack-frame-size)
+ #!-win32 (vop dealloc-number-stack-space call block stack-frame-size)
+ #!+win32 (vop reset-stack-pointer call block stack-pointer)
+ #!+x86 (vop set-fpu-word-for-lisp call block)
(move-lvar-result call block result-tns lvar))))
(in-package "SB!C")
(defknown %alien-funcall (system-area-pointer alien-type &rest *) *)
-(defknown %alien-funcall-stdcall (system-area-pointer alien-type &rest *) *)
,@(new-args))))))
(sb!c::give-up-ir1-transform))))
-#!+win32
-(deftransform %alien-funcall-stdcall ((function type &rest args) * * :node node)
- (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)))
- (aver (= (length arg-types) (length args)))
- (if (or (some #'(lambda (type)
- (and (alien-integer-type-p type)
- (> (sb!alien::alien-integer-type-bits type) 32)))
- arg-types)
- (and (alien-integer-type-p result-type)
- (> (sb!alien::alien-integer-type-bits result-type) 32)))
- (collect ((new-args) (lambda-vars) (new-arg-types))
- (dolist (type arg-types)
- (let ((arg (gensym)))
- (lambda-vars arg)
- (cond ((and (alien-integer-type-p type)
- (> (sb!alien::alien-integer-type-bits type) 32))
- (new-args `(logand ,arg #xffffffff))
- (new-args `(ash ,arg -32))
- (new-arg-types (parse-alien-type '(unsigned 32) env))
- (if (alien-integer-type-signed type)
- (new-arg-types (parse-alien-type '(signed 32) env))
- (new-arg-types (parse-alien-type '(unsigned 32) env))))
- (t
- (new-args arg)
- (new-arg-types type)))))
- (cond ((and (alien-integer-type-p result-type)
- (> (sb!alien::alien-integer-type-bits result-type) 32))
- (let ((new-result-type
- (let ((sb!alien::*values-type-okay* t))
- (parse-alien-type
- (if (alien-integer-type-signed result-type)
- '(values (unsigned 32) (signed 32))
- '(values (unsigned 32) (unsigned 32)))
- env))))
- `(lambda (function type ,@(lambda-vars))
- (declare (ignore type))
- (multiple-value-bind (low high)
- (%alien-funcall function
- ',(make-alien-fun-type
- :arg-types (new-arg-types)
- :result-type new-result-type)
- ,@(new-args))
- (logior low (ash high 32))))))
- (t
- `(lambda (function type ,@(lambda-vars))
- (declare (ignore type))
- (%alien-funcall function
- ',(make-alien-fun-type
- :arg-types (new-arg-types)
- :result-type result-type)
- ,@(new-args))))))
- (sb!c::give-up-ir1-transform))))
-
(define-vop (foreign-symbol-sap)
(:translate foreign-symbol-sap)
(:policy :fast-safe)
(inst fldz)) ; insure no regs are empty
))))
-(define-vop (alloc-number-stack-space)
- (:info amount)
- (:results (result :scs (sap-reg any-reg)))
+;;; 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
- (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)))
- (move result esp-tn)))
+ (inst wait))))
-(define-vop (dealloc-number-stack-space)
- (:info amount)
+(define-vop (set-fpu-word-for-lisp)
(:node-var node)
(:generator 0
- (unless (zerop amount)
- (let ((delta (logandc2 (+ amount 3) 3)))
- (inst add esp-tn delta)))
(when (policy node (= sb!c::float-accuracy 3))
(inst fnstcw (make-ea :word :base esp-tn))
(inst wait)
(inst wait)
(inst add esp-tn 4))))
+(define-vop (alloc-number-stack-space)
+ (:info amount)
+ (:results (result :scs (sap-reg any-reg)))
+ (:generator 0
+ (aver (location= result esp-tn))
+ (unless (zerop amount)
+ (let ((delta (logandc2 (+ amount 3) 3)))
+ (inst sub esp-tn delta)))
+ (move result esp-tn)))
+
+(define-vop (dealloc-number-stack-space)
+ (:info amount)
+ (:generator 0
+ (unless (zerop amount)
+ (let ((delta (logandc2 (+ amount 3) 3)))
+ (inst add esp-tn delta)))))
+
(define-vop (alloc-alien-stack-space)
(:info amount)
#!+sb-thread (:temporary (:sc unsigned-reg) temp)
;;; checkins which aren't released. (And occasionally for internal
;;; versions, especially for internal versions off the main CVS
;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.9.8.39"
+"0.9.8.40"