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

📄 c-call.lisp

📁 开源跨平台Lisp编译器
💻 LISP
📖 第 1 页 / 共 2 页
字号:
;;;; VOPs and other 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")(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  (stack-frame-size 0)  (did-int-arg nil)  (float-args 0))(define-alien-type-method (integer :arg-tn) (type state)  (let ((stack-frame-size (arg-state-stack-frame-size state)))    (setf (arg-state-stack-frame-size state) (1+ stack-frame-size))    (setf (arg-state-did-int-arg state) t)    (multiple-value-bind        (ptype reg-sc stack-sc)        (if (alien-integer-type-signed type)            (values 'signed-byte-32 'signed-reg 'signed-stack)            (values 'unsigned-byte-32 'unsigned-reg 'unsigned-stack))      (if (< stack-frame-size 4)          (my-make-wired-tn ptype reg-sc (+ stack-frame-size 4))          (my-make-wired-tn ptype stack-sc stack-frame-size)))))(define-alien-type-method (system-area-pointer :arg-tn) (type state)  (declare (ignore type))  (let ((stack-frame-size (arg-state-stack-frame-size state)))    (setf (arg-state-stack-frame-size state) (1+ stack-frame-size))    (setf (arg-state-did-int-arg state) t)    (if (< stack-frame-size 4)        (my-make-wired-tn 'system-area-pointer                          'sap-reg                          (+ stack-frame-size 4))        (my-make-wired-tn 'system-area-pointer                          'sap-stack                          stack-frame-size))))(define-alien-type-method (double-float :arg-tn) (type state)  (declare (ignore type))  (let ((stack-frame-size (logandc2 (1+ (arg-state-stack-frame-size state)) 1))        (float-args (arg-state-float-args state)))    (setf (arg-state-stack-frame-size state) (+ stack-frame-size 2))    (setf (arg-state-float-args state) (1+ float-args))    (cond ((>= stack-frame-size 4)           (my-make-wired-tn 'double-float                             'double-stack                             stack-frame-size))          ((and (not (arg-state-did-int-arg state))                (< float-args 2))           (my-make-wired-tn 'double-float                             'double-reg                             (+ (* float-args 2) 12)))          (t           (my-make-wired-tn 'double-float                             'double-int-carg-reg                             (+ stack-frame-size 4))))))(define-alien-type-method (single-float :arg-tn) (type state)  (declare (ignore type))  (let ((stack-frame-size (arg-state-stack-frame-size state))        (float-args (arg-state-float-args state)))    (setf (arg-state-stack-frame-size state) (1+ stack-frame-size))    (setf (arg-state-float-args state) (1+ float-args))    (cond ((>= stack-frame-size 4)           (my-make-wired-tn 'single-float                             'single-stack                             stack-frame-size))          ((and (not (arg-state-did-int-arg state))                (< float-args 2))           (my-make-wired-tn 'single-float                             'single-reg                             (+ (* float-args 2) 12)))          (t           (my-make-wired-tn 'single-float                             'single-int-carg-reg                             (+ stack-frame-size 4))))))(defstruct result-state  (num-results 0))(defun result-reg-offset (slot)  (ecase slot    (0 nl0-offset)    (1 nl1-offset)))(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-32 'signed-reg)            (values 'unsigned-byte-32 'unsigned-reg))      (my-make-wired-tn ptype reg-sc (result-reg-offset num-results)))))(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))));;; FIXME: do these still work? -- CSR, 2002-08-28(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 2))))(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 2))))(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 nsp-offset)              (* (max (arg-state-stack-frame-size arg-state) 4) 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))  (aver (sb!c::constant-lvar-p type))  (let* ((type (sb!c::lvar-value type))         (env (sb!kernel:make-null-lexenv))         (arg-types (alien-fun-type-arg-types type))         (result-type (alien-fun-type-result-type type)))    (aver (= (length arg-types) (length args)))    ;; We need to do something special for 64-bit integer arguments    ;; and results.    (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))                            ;; 64-bit long long types are stored in                            ;; consecutive locations, endian word order,                            ;; aligned to 8 bytes.                            (when (oddp (length (new-args)))                              (new-args nil))                            #!-little-endian                            (progn (new-args `(ash ,arg -32))                                   (new-args `(logand ,arg #xffffffff))                                   (if (oddp (length (new-arg-types)))                                       (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)))                                   (new-arg-types (parse-alien-type '(unsigned 32) env)))                            #!+little-endian                            (progn (new-args `(logand ,arg #xffffffff))                                   (new-args `(ash ,arg -32))                                   (if (oddp (length (new-arg-types)))                                       (new-arg-types (parse-alien-type '(unsigned 32) env)))                                   (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)                                      #!-little-endian                                      '(values (signed 32) (unsigned 32))                                      #!+little-endian                                      '(values (unsigned 32) (signed 32))                                      '(values (unsigned 32) (unsigned 32)))                                  env))))                          `(lambda (function type ,@(lambda-vars))                            (declare (ignore type))                             (multiple-value-bind                               #!-little-endian                               (high low)                               #!+little-endian                               (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)  (:args)  (:arg-types (:constant simple-string))  (:info foreign-symbol)  (:results (res :scs (sap-reg)))

⌨️ 快捷键说明

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