⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c-call.lisp

📁 开源跨平台Lisp编译器
💻 LISP
📖 第 1 页 / 共 2 页
字号:
;;;; the VOPs and other necessary machine specific support;;;; routines for call-out to C;;;; This software is part of the SBCL system. See the README file for;;;; more information.;;;;;;;; This software is derived from the CMU CL system, which was;;;; written at Carnegie Mellon University and released into the;;;; public domain. The software is in the public domain and is;;;; provided with absolutely no warranty. See the COPYING and CREDITS;;;; files for more information.(in-package "SB!VM");; The MOVE-ARG vop is going to store args on the stack for;; call-out. These tn's will be used for that. move-arg is normally;; used for things going down the stack but C wants to have args;; indexed in the positive direction.(defun my-make-wired-tn (prim-type-name sc-name offset)  (make-wired-tn (primitive-type-or-lose prim-type-name)                 (sc-number-or-lose sc-name)                 offset))(defstruct (arg-state (:copier nil))  (register-args 0)  (xmm-args 0)  (stack-frame-size 0))(defun int-arg (state prim-type reg-sc stack-sc)  (let ((reg-args (arg-state-register-args state)))    (cond ((< reg-args 6)           (setf (arg-state-register-args state) (1+ reg-args))           (my-make-wired-tn prim-type reg-sc                             (nth reg-args *c-call-register-arg-offsets*)))          (t           (let ((frame-size (arg-state-stack-frame-size state)))             (setf (arg-state-stack-frame-size state) (1+ frame-size))             (my-make-wired-tn prim-type stack-sc frame-size))))))(define-alien-type-method (integer :arg-tn) (type state)  (if (alien-integer-type-signed type)      (int-arg state 'signed-byte-64 'signed-reg 'signed-stack)      (int-arg state 'unsigned-byte-64 'unsigned-reg 'unsigned-stack)))(define-alien-type-method (system-area-pointer :arg-tn) (type state)  (declare (ignore type))  (int-arg state 'system-area-pointer 'sap-reg 'sap-stack))(defun float-arg (state prim-type reg-sc stack-sc)  (let ((xmm-args (arg-state-xmm-args state)))    (cond ((< xmm-args 8)           (setf (arg-state-xmm-args state) (1+ xmm-args))           (my-make-wired-tn prim-type reg-sc                             (nth xmm-args *float-regs*)))          (t           (let ((frame-size (arg-state-stack-frame-size state)))             (setf (arg-state-stack-frame-size state) (1+ frame-size))             (my-make-wired-tn prim-type stack-sc frame-size))))))(define-alien-type-method (double-float :arg-tn) (type state)  (declare (ignore type))  (float-arg state 'double-float 'double-reg 'double-stack))(define-alien-type-method (single-float :arg-tn) (type state)  (declare (ignore type))  (float-arg state 'single-float 'single-reg 'single-stack))(defstruct (result-state (:copier nil))  (num-results 0))(defun result-reg-offset (slot)  (ecase slot    (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))    (multiple-value-bind (ptype reg-sc)        (if (alien-integer-type-signed type)            (values 'signed-byte-64 'signed-reg)            (values 'unsigned-byte-64 'unsigned-reg))      (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)      alien))(define-alien-type-method (system-area-pointer :result-tn) (type state)  (declare (ignore type))  (let ((num-results (result-state-num-results state)))    (setf (result-state-num-results state) (1+ num-results))    (my-make-wired-tn 'system-area-pointer 'sap-reg                      (result-reg-offset num-results))))(define-alien-type-method (double-float :result-tn) (type state)  (declare (ignore type))  (let ((num-results (result-state-num-results state)))    (setf (result-state-num-results state) (1+ num-results))    (my-make-wired-tn 'double-float 'double-reg num-results)))(define-alien-type-method (single-float :result-tn) (type state)  (declare (ignore type))  (let ((num-results (result-state-num-results state)))    (setf (result-state-num-results state) (1+ num-results))    (my-make-wired-tn 'single-float 'single-reg num-results)))(define-alien-type-method (values :result-tn) (type state)  (let ((values (alien-values-type-values type)))    (when (> (length values) 2)      (error "Too many result values from c-call."))    (mapcar (lambda (type)              (invoke-alien-type-method :result-tn type state))            values)))(!def-vm-support-routine make-call-out-tns (type)  (let ((arg-state (make-arg-state)))    (collect ((arg-tns))      (dolist (arg-type (alien-fun-type-arg-types type))        (arg-tns (invoke-alien-type-method :arg-tn arg-type arg-state)))      (values (my-make-wired-tn 'positive-fixnum 'any-reg esp-offset)              (* (arg-state-stack-frame-size arg-state) n-word-bytes)              (arg-tns)              (invoke-alien-type-method :result-tn                                        (alien-fun-type-result-type type)                                        (make-result-state))))))(deftransform %alien-funcall ((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) 64)))                  arg-types)            (and (alien-integer-type-p result-type)                 (> (sb!alien::alien-integer-type-bits result-type) 64)))        (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) 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))                     (if (alien-integer-type-signed type)                         (new-arg-types (parse-alien-type '(signed 64) env))                         (new-arg-types (parse-alien-type '(unsigned 64) 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) 64))                 (let ((new-result-type                        (let ((sb!alien::*values-type-okay* t))                          (parse-alien-type                           (if (alien-integer-type-signed result-type)                               '(values (unsigned 64) (signed 64))                               '(values (unsigned 64) (unsigned 64)))                           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 64))))))                (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))));;; 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))(define-vop (sign-extend)  (:translate sign-extend)  (:policy :fast-safe)  (:args (val :scs (signed-reg)))  (:arg-types fixnum)  (:results (res :scs (signed-reg)))  (:result-types fixnum)  (:generator 1   (inst movsxd res         (make-random-tn :kind :normal                         :sc (sc-or-lose 'dword-reg)                         :offset (tn-offset val)))))#-sb-xc-host(defun sign-extend (x)  (declare (type (signed-byte 32) x))  (sign-extend x))#+sb-xc-host(defun sign-extend (x)  (if (logbitp 31 x)      (dpb x (byte 32 0) -1)      x))(define-vop (foreign-symbol-sap)  (:translate foreign-symbol-sap)  (: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 foreign-symbol :foreign))))#!+linkage-table(define-vop (foreign-symbol-dataref-sap)  (:translate foreign-symbol-dataref-sap)  (: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 mov res (make-fixup foreign-symbol :foreign-dataref))))(define-vop (call-out)  (:args (function :scs (sap-reg))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -