(defknown alien-funcall (alien-value &rest *) *
(any recursive))
+#!+win32
+(defknown alien-funcall-stdcall (alien-value &rest *) *
+ (any recursive))
\f
;;;; cosmetic transforms
((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)
+ (move-lvar-result call block result-tns lvar))))