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

📄 c-call.lisp

📁 开源跨平台Lisp编译器
💻 LISP
📖 第 1 页 / 共 3 页
字号:
                                    ;; broken.                                    (if (/= 0                                            (rem in-words-processed                                                 words))                                        (progn                                          (incf in-words-processed)                                          (incf in-offset                                                n-word-bytes)))                                    (dotimes (k words)                                      ;; Copy from memory to memory.                                      (inst lwz r0 stack-pointer                                            in-offset)                                      (inst stw r0 stack-pointer                                            out-offset)                                      (incf out-words-processed)                                      (incf out-offset n-word-bytes)                                      (incf in-words-processed)                                      (incf in-offset n-word-bytes)))))                             ;; The handling of floats is a little ugly                             ;; because we hard-code the number of words                             ;; for single- and double-floats.                             ((alien-single-float-type-p type)                              (let ((fpr (pop fprs)))                                (if fpr                                    (inst stfs fpr stack-pointer out-offset)                                    (progn                                      ;; The ABI says that floats                                      ;; stored on the stack are                                      ;; promoted to doubles.  gcc                                      ;; stores them as floats.                                      ;; Follow gcc here.                                      ;;  => no alignment needed either.                                      (inst lfs f0                                            stack-pointer in-offset)                                      (inst stfs f0                                            stack-pointer out-offset)                                      (incf in-words-processed))))                              (incf out-words-processed))                             ((alien-double-float-type-p type)                              (let ((fpr (pop fprs)))                                (if fpr                                    (inst stfd fpr stack-pointer out-offset)                                    (progn                                      ;; Ensure alignment.                                      (if (oddp in-words-processed)                                          (progn                                            (incf in-words-processed)                                            (incf in-offset n-word-bytes)))                                      (inst lfd f0                                            stack-pointer in-offset)                                      (inst stfd f0                                            stack-pointer out-offset)                                      (incf in-words-processed 2))))                              (incf out-words-processed 2))                             (t                              (bug "Unknown alien floating point type: ~S" type))))))              (mapc #'save-arg                    argument-types                    (mapcar (lambda (arg)                              (ceiling (alien-type-bits arg) n-word-bits))                            argument-types))              ;; Arranged the args, allocated the return area.  Now              ;; actuall call funcall3:  funcall3 (call-alien-function,              ;; index, args, return-area)              (destructuring-bind (arg1 arg2 arg3 arg4)                  (mapcar #'make-gpr '(3 4 5 6))                (load-address-into arg1 (+ nil-value (static-symbol-offset                                                      'sb!alien::*enter-alien-callback*)))                (loadw arg1 arg1 symbol-value-slot other-pointer-lowtag)                (inst li arg2 (fixnumize index))                (inst addi arg3 stack-pointer (- arg-store-pos))                (inst addi arg4 stack-pointer (- return-area-pos)))              ;; Setup everything.  Now save sp, setup the frame.              (inst mflr r0)              (inst stw r0 stack-pointer (* 2 n-word-bytes)) ; FIXME: magic                                        ; constant, copied from Darwin.              (inst stwu stack-pointer stack-pointer (- frame-size))              ;; And make the call.              (load-address-into r0 (foreign-symbol-address "funcall3"))              (inst mtlr r0)              (inst blrl)              ;; We're back!  Restore sp and lr, load the              ;; return value from just under sp, and return.              (inst lwz stack-pointer stack-pointer 0)              (inst lwz r0 stack-pointer (* 2 n-word-bytes))              (inst mtlr r0)              (cond                ((sb!alien::alien-single-float-type-p result-type)                 (let ((f1 (make-fpr 1)))                   (inst lfs f1 stack-pointer (- return-area-pos))))                ((sb!alien::alien-double-float-type-p result-type)                 (let ((f1 (make-fpr 1)))                   (inst lfd f1 stack-pointer (- return-area-pos))))                ((sb!alien::alien-void-type-p result-type)                 ;; Nothing to do                 )                (t                 (loop with gprs = (mapcar #'make-gpr '(3 4))                       repeat n-return-area-words                       for gpr = (pop gprs)                       for offset from (- return-area-pos)                       by n-word-bytes                       do                       (unless gpr                         (bug "Out of return registers in alien-callback trampoline."))                       (inst lwz gpr stack-pointer offset))))              (inst blr))))        (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))               (vector (make-static-vector (length buffer)                                           :element-type '(unsigned-byte 8)                                           :initial-contents buffer))               (sap (sb!sys:vector-sap vector)))          (sb!alien:alien-funcall           (sb!alien:extern-alien "ppc_flush_icache"                                  (function void                                            system-area-pointer                                            unsigned-long))           sap (length buffer))          vector))))  ;;; Returns a vector in static space containing machine code for the  ;;; callback wrapper  #!+darwin  (defun alien-callback-assembler-wrapper (index result-type argument-types)    (flet ((make-gpr (n)             (make-random-tn :kind :normal :sc (sc-or-lose 'any-reg) :offset n))           (make-fpr (n)             (make-random-tn :kind :normal :sc (sc-or-lose 'double-reg) :offset n)))      (let* ((segment (make-segment)))        (assemble (segment)          ;; To save our arguments, we follow the algorithm sketched in the          ;; "PowerPC Calling Conventions" section of that document.          ;;          ;; CLH: There are a couple problems here. First, we bail if          ;; we run out of registers. AIUI, we can just ignore the extra          ;; args here and we will be ok...          (let ((words-processed 0)                (gprs (mapcar #'make-gpr '(3 4 5 6 7 8 9 10)))                (fprs (mapcar #'make-fpr '(1 2 3 4 5 6 7 8 9 10 11 12 13)))                (stack-pointer (make-gpr 1)))            (labels ((save-arg (type words)                       (let ((integerp (not (alien-float-type-p type)))                             (offset (+ (* words-processed n-word-bytes)                                        n-foreign-linkage-area-bytes)))                         (cond (integerp                                (dotimes (k words)                                  (let ((gpr (pop gprs)))                                    (when gpr                                      (inst stw gpr stack-pointer offset))                                    (incf words-processed)                                    (incf offset n-word-bytes))))                               ;; The handling of floats is a little ugly                               ;; because we hard-code the number of words                               ;; for single- and double-floats.                               ((alien-single-float-type-p type)                                (pop gprs)                                (let ((fpr (pop fprs)))                                  (when fpr                                    (inst stfs fpr stack-pointer offset)))                                (incf words-processed))                               ((alien-double-float-type-p type)                                (setf gprs (cddr gprs))                                (let ((fpr (pop fprs)))                                  (when fpr                                    (inst stfd fpr stack-pointer offset)))                                (incf words-processed 2))                               (t                                (bug "Unknown alien floating point type: ~S" type))))))              (mapc #'save-arg                    argument-types                    (mapcar (lambda (arg)                              (ceiling (alien-type-bits arg) n-word-bits))                            argument-types))))          ;; Set aside room for the return area just below sp, then          ;; actually call funcall3: funcall3 (call-alien-function,          ;; index, args, return-area)          ;;          ;; INDEX is fixnumized, ARGS and RETURN-AREA don't need to be          ;; because they're word-aligned. Kinda gross, but hey ...          (let* ((n-return-area-words                  (ceiling (or (alien-type-bits result-type) 0) n-word-bits))                 (n-return-area-bytes (* n-return-area-words n-word-bytes))                 ;; FIXME: magic constant, and probably n-args-bytes                 (args-size (* 3 n-word-bytes))                 ;; FIXME: n-frame-bytes?                 (frame-size (logandc2 (+ n-foreign-linkage-area-bytes                                          n-return-area-bytes                                          args-size                                          +stack-alignment-bytes+)                                       +stack-alignment-bytes+)))            (destructuring-bind (sp r0 arg1 arg2 arg3 arg4)                (mapcar #'make-gpr '(1 0 3 4 5 6))              ;; FIXME: This is essentially the same code as LR in              ;; insts.lisp, but attempting to use (INST LR ...) instead              ;; of this function results in callbacks not working.  Why?              ;;   --njf, 2006-01-04              (flet ((load-address-into (reg addr)                       (let ((high (ldb (byte 16 16) addr))                             (low (ldb (byte 16 0) addr)))                         (inst lis reg high)                         (inst ori reg reg low))))                ;; Setup the args                ;; CLH 2006/02/10 -Following JES' logic in                ;; x86-64/c-call.lisp, we need to access                ;; ENTER-ALIEN-CALLBACK through the symbol-value slot                ;; of SB-ALIEN::*ENTER-ALIEN-CALLBACK* to ensure that                ;; it works if GC moves ENTER-ALIEN-CALLBACK.                ;;                ;; old way:                ;; (load-address-into arg1 (get-lisp-obj-address #'enter-alien-callback))                ;; new way:                ;; (load-symbol arg1 'sb!alien::*enter-alien-callback*)                ;;                ;; whoops: can't use load-symbol here as null-tn might                ;; not be loaded with the proper value as we are                ;; coming in from C code. Use nil-value constant                ;; instead, following the logic in x86-64/c-call.lisp.                (load-address-into arg1 (+ nil-value (static-symbol-offset                                                      'sb!alien::*enter-alien-callback*)))                (loadw arg1 arg1 symbol-value-slot other-pointer-lowtag)                (inst li arg2 (fixnumize index))                (inst addi arg3 sp n-foreign-linkage-area-bytes)                ;; FIXME: This was (- (* RETURN-AREA-SIZE N-WORD-BYTES)), while                ;; RETURN-AREA-SIZE was (* N-RETURN-AREA-WORDS N-WORD-BYTES):                ;; I assume the intention was (- N-RETURN-AREA-BYTES), but who knows?                ;; --NS 2005-06-11                (inst addi arg4 sp (- n-return-area-bytes))                ;; FIXME! FIXME FIXME: What does this FIXME refer to?                ;; Save sp, setup the frame                (inst mflr r0)                (inst stw r0 sp (* 2 n-word-bytes)) ; FIXME: magic constant                (inst stwu sp sp (- frame-size))                ;; Make the call                (load-address-into r0 (foreign-symbol-address "funcall3"))                (inst mtlr r0)                (inst blrl))              ;; We're back!  Restore sp and lr, load the return value from just              ;; under sp, and return.              (inst lwz sp sp 0)              (inst lwz r0 sp (* 2 n-word-bytes))              (inst mtlr r0)              (cond                ((sb!alien::alien-single-float-type-p result-type)                 (let ((f1 (make-fpr 1)))                   (inst lfs f1 sp (- (* n-return-area-words n-word-bytes)))))                ((sb!alien::alien-double-float-type-p result-type)                 (let ((f1 (make-fpr 1)))                   (inst lfd f1 sp (- (* n-return-area-words n-word-bytes)))))                ((sb!alien::alien-void-type-p result-type)                 ;; Nothing to do                 )                (t                 (loop with gprs = (mapcar #'make-gpr '(3 4))                    repeat n-return-area-words                    for gpr = (pop gprs)                    for offset from (- (* n-return-area-words n-word-bytes))                    by n-word-bytes                    do                      (unless gpr                        (bug "Out of return registers in alien-callback trampoline."))                      (inst lwz gpr sp offset))))              (inst blr))))        (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))               (vector (make-static-vector (length buffer)                                           :element-type '(unsigned-byte 8)                                           :initial-contents buffer))               (sap (sb!sys:vector-sap vector)))          (sb!alien:alien-funcall           (sb!alien:extern-alien "ppc_flush_icache"                                  (function void                                            system-area-pointer                                            unsigned-long))           sap (length buffer))          vector)))))

⌨️ 快捷键说明

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