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

📄 call.lisp

📁 开源跨平台Lisp编译器
💻 LISP
📖 第 1 页 / 共 3 页
字号:
;;; Non-TR local call for a fixed number of values passed according to the;;; unknown values convention.;;;;;; Args are the argument passing locations, which are specified only to;;; terminate their lifetimes in the caller.;;;;;; Values are the return value locations (wired to the standard passing;;; locations).;;;;;; Save is the save info, which we can ignore since saving has been done.;;; Return-PC is the TN that the return PC should be passed in.;;; Target is a continuation pointing to the start of the called function.;;; Nvals is the number of values received.;;;;;; Note: we can't use normal load-tn allocation for the fixed args, since all;;; registers may be tied up by the more operand.  Instead, we use;;; MAYBE-LOAD-STACK-TN.;;;(define-vop (call-local)  (:args (cfp)         (nfp)         (args :more t))  (:results (values :more t))  (:save-p t)  (:move-args :local-call)  (:info arg-locs callee target nvals)  (:vop-var vop)  (:temporary (:scs (descriptor-reg) :from :eval) move-temp)  (:temporary (:scs (non-descriptor-reg)) temp)  (:temporary (:sc control-stack :offset nfp-save-offset) nfp-save)  (:temporary (:sc any-reg :offset ocfp-offset :from :eval) ocfp)  (:ignore arg-locs args ocfp)  (:generator 5    (trace-table-entry trace-table-call-site)    (let ((label (gen-label))          (cur-nfp (current-nfp-tn vop)))      (when cur-nfp        (store-stack-tn nfp-save cur-nfp))      (let ((callee-nfp (callee-nfp-tn callee)))        (when callee-nfp          (maybe-load-stack-tn callee-nfp nfp)))      (maybe-load-stack-tn cfp-tn cfp)      (inst compute-lra-from-code code-tn label temp            (callee-return-pc-tn callee))      (note-this-location vop :call-site)      (inst b target :nullify t)      (emit-return-pc label)      (default-unknown-values vop values nvals move-temp temp label)      (when cur-nfp        (load-stack-tn cur-nfp nfp-save)))    (trace-table-entry trace-table-normal)));;; Non-TR local call for a variable number of return values passed according;;; to the unknown values convention.  The results are the start of the values;;; glob and the number of values received.;;;;;; Note: we can't use normal load-tn allocation for the fixed args, since all;;; registers may be tied up by the more operand.  Instead, we use;;; MAYBE-LOAD-STACK-TN.;;;(define-vop (multiple-call-local unknown-values-receiver)  (:args (cfp)         (nfp)         (args :more t))  (:save-p t)  (:move-args :local-call)  (:info save callee target)  (:ignore args save)  (:vop-var vop)  (:temporary (:sc control-stack :offset nfp-save-offset) nfp-save)  (:generator 20    (trace-table-entry trace-table-call-site)    (let ((label (gen-label))          (cur-nfp (current-nfp-tn vop)))      (when cur-nfp        (store-stack-tn nfp-save cur-nfp))      (let ((callee-nfp (callee-nfp-tn callee)))        (when callee-nfp          (maybe-load-stack-tn callee-nfp nfp)))      (maybe-load-stack-tn cfp-tn cfp)      (inst compute-lra-from-code code-tn label temp            (callee-return-pc-tn callee))      (note-this-location vop :call-site)      (inst b target :nullify t)      (emit-return-pc label)      (note-this-location vop :unknown-return)      (receive-unknown-values values-start nvals start count label temp)      (when cur-nfp        (load-stack-tn cur-nfp nfp-save)))    (trace-table-entry trace-table-normal)));;;; Local call with known values return:;;; Non-TR local call with known return locations.  Known-value return works;;; just like argument passing in local call.;;;;;; Note: we can't use normal load-tn allocation for the fixed args, since all;;; registers may be tied up by the more operand.  Instead, we use;;; MAYBE-LOAD-STACK-TN.;;;(define-vop (known-call-local)  (:args (cfp)         (nfp)         (args :more t))  (:results (res :more t))  (:move-args :local-call)  (:save-p t)  (:info save callee target)  (:ignore args res save)  (:vop-var vop)  (:temporary (:sc control-stack :offset nfp-save-offset) nfp-save)  (:temporary (:scs (non-descriptor-reg)) temp)  (:generator 5    (trace-table-entry trace-table-call-site)    (let ((label (gen-label))          (cur-nfp (current-nfp-tn vop)))      (when cur-nfp        (store-stack-tn nfp-save cur-nfp))      (let ((callee-nfp (callee-nfp-tn callee)))        (when callee-nfp          (maybe-load-stack-tn callee-nfp nfp)))      (maybe-load-stack-tn cfp-tn cfp)      (inst compute-lra-from-code code-tn label temp            (callee-return-pc-tn callee))      (note-this-location vop :call-site)      (inst b target :nullify t)      (emit-return-pc label)      (note-this-location vop :known-return)      (when cur-nfp        (load-stack-tn cur-nfp nfp-save)))    (trace-table-entry trace-table-normal)));;; Return from known values call.  We receive the return locations as;;; arguments to terminate their lifetimes in the returning function.  We;;; restore FP and CSP and jump to the Return-PC.;;;;;; Note: we can't use normal load-tn allocation for the fixed args, since all;;; registers may be tied up by the more operand.  Instead, we use;;; MAYBE-LOAD-STACK-TN.;;;(define-vop (known-return)  (:args (old-fp :target old-fp-temp)         (return-pc :target return-pc-temp)         (vals :more t))  (:temporary (:sc any-reg :from (:argument 0)) old-fp-temp)  (:temporary (:sc descriptor-reg :from (:argument 1)) return-pc-temp)  (:temporary (:scs (interior-reg)) lip)  (:move-args :known-return)  (:info val-locs)  (:ignore val-locs vals)  (:vop-var vop)  (:generator 6    (trace-table-entry trace-table-fun-epilogue)    (maybe-load-stack-tn old-fp-temp old-fp)    (maybe-load-stack-tn return-pc-temp return-pc)    (move cfp-tn csp-tn)    (let ((cur-nfp (current-nfp-tn vop)))      (when cur-nfp        (move cur-nfp nsp-tn)))    (inst addi (- n-word-bytes other-pointer-lowtag) return-pc-temp lip)    (inst bv lip)    (move old-fp-temp cfp-tn)    (trace-table-entry trace-table-normal)));;;; Full call:;;;;;;    There is something of a cross-product effect with full calls.  Different;;; versions are used depending on whether we know the number of arguments or;;; the name of the called function, and whether we want fixed values, unknown;;; values, or a tail call.;;;;;; In full call, the arguments are passed creating a partial frame on the;;; stack top and storing stack arguments into that frame.  On entry to the;;; callee, this partial frame is pointed to by FP.  If there are no stack;;; arguments, we don't bother allocating a partial frame, and instead set FP;;; to SP just before the call.;;;    This macro helps in the definition of full call VOPs by avoiding code;;; replication in defining the cross-product VOPs.;;;;;; Name is the name of the VOP to define.;;;;;; Named is true if the first argument is a symbol whose global function;;; definition is to be called.;;;;;; Return is either :Fixed, :Unknown or :Tail:;;; -- If :Fixed, then the call is for a fixed number of values, returned in;;;    the standard passing locations (passed as result operands).;;; -- If :Unknown, then the result values are pushed on the stack, and the;;;    result values are specified by the Start and Count as in the;;;    unknown-values continuation representation.;;; -- If :Tail, then do a tail-recursive call.  No values are returned.;;;    The Old-Fp and Return-PC are passed as the second and third arguments.;;;;;; In non-tail calls, the pointer to the stack arguments is passed as the last;;; fixed argument.  If Variable is false, then the passing locations are;;; passed as a more arg.  Variable is true if there are a variable number of;;; arguments passed on the stack.  Variable cannot be specified with :Tail;;; return.  TR variable argument call is implemented separately.;;;;;; In tail call with fixed arguments, the passing locations are passed as a;;; more arg, but there is no new-FP, since the arguments have been set up in;;; the current frame.;;;(macrolet ((define-full-call (name named return variable)  (aver (not (and variable (eq return :tail))))  `(define-vop (,name                ,@(when (eq return :unknown)                    '(unknown-values-receiver)))     (:args      ,@(unless (eq return :tail)          '((new-fp :scs (any-reg) :to :eval)))      ,(if named           '(fdefn :target fdefn-pass)           '(arg-fun :target lexenv))      ,@(when (eq return :tail)          '((ocfp :target ocfp-pass)            (lra :target lra-pass)))      ,@(unless variable '((args :more t :scs (descriptor-reg)))))     ,@(when (eq return :fixed)         '((:results (values :more t))))     (:save-p ,(if (eq return :tail) :compute-only t))     ,@(unless (or (eq return :tail) variable)         '((:move-args :full-call)))     (:vop-var vop)     (:info ,@(unless (or variable (eq return :tail)) '(arg-locs))            ,@(unless variable '(nargs))            ,@(when (eq return :fixed) '(nvals)))     (:ignore      ,@(unless (or variable (eq return :tail)) '(arg-locs))      ,@(unless variable '(args)))     (:temporary (:sc descriptor-reg                  :offset ocfp-offset                  ,@(when (eq return :tail)                      '(:from (:argument 1)))                  ,@(unless (eq return :fixed)                      '(:to :eval)))                 ocfp-pass)     (:temporary (:sc descriptor-reg                  :offset lra-offset                  ,@(when (eq return :tail)                      '(:from (:argument 2)))                  :to :eval)                 lra-pass)     ,@(if named         `((:temporary (:sc descriptor-reg :offset fdefn-offset                        :from (:argument ,(if (eq return :tail) 0 1))                        :to :eval)                       fdefn-pass))         `((:temporary (:sc descriptor-reg :offset lexenv-offset                        :from (:argument ,(if (eq return :tail) 0 1))                        :to :eval)                       lexenv)           (:temporary (:scs (descriptor-reg)                             :from (:argument ,(if (eq return :tail) 2 1))                             :to :eval)                       function)))     (:temporary (:sc any-reg :offset nargs-offset :to :eval)                 nargs-pass)     ,@(when variable         (mapcar #'(lambda (name offset)                     `(:temporary (:sc descriptor-reg                                   :offset ,offset                                   :to :eval)                         ,name))                 register-arg-names *register-arg-offsets*))     ,@(when (eq return :fixed)         '((:temporary (:scs (descriptor-reg) :from :eval) move-temp)))     ,@(unless (eq return :tail)         '((:temporary (:scs (non-descriptor-reg)) temp)           (:temporary (:sc control-stack :offset nfp-save-offset) nfp-save)))     (:temporary (:scs (interior-reg) :type interior) lip)     (:generator ,(+ (if named 5 0)                     (if variable 19 1)                     (if (eq return :tail) 0 10)                     15                     (if (eq return :unknown) 25 0))       (trace-table-entry trace-table-call-site)       (let* ((cur-nfp (current-nfp-tn vop))              ,@(unless (eq return :tail)                  '((lra-label (gen-label))))              (filler               (list :load-nargs                     ,@(if (eq return :tail)                           '((unless (location= ocfp ocfp-pass)                               :load-ocfp)                             (unless (location= lra lra-pass)                               :load-lra)                             (when cur-nfp                               :frob-nfp))                           '((when cur-nfp                               :frob-nfp)                             :comp-lra                             :save-fp                             :load-fp)))))         (labels             ((do-next-filler ()                (when filler                  (ecase (pop filler)                    ((nil) (do-next-filler))                    (:load-nargs                     ,@(if variable                           `((inst sub csp-tn new-fp nargs-pass)                             ,@(let ((index -1))                                 (mapcar #'(lambda (name)                                             `(loadw ,name new-fp                                                     ,(incf index)))                                         register-arg-names)))                           '((inst li (fixnumize nargs) nargs-pass))))                    ,@(if (eq return :tail)                          '((:load-ocfp                             (sc-case ocfp                               (any-reg                                (inst move ocfp ocfp-pass))                               (control-stack                                (loadw ocfp-pass cfp-tn (tn-offset ocfp)))))                            (:load-lra                             (sc-case lra                               (descriptor-reg                                (inst move lra lra-pass))                               (control-stack                                (loadw lra-pass cfp-tn (tn-offset lra)))))                            (:frob-nfp                             (inst move cur-nfp nsp-tn)))                          `((:frob-nfp                             (store-stack-tn nfp-save cur-nfp))                            (:comp-lra                             (inst compute-lra-from-code                                   code-tn lra-label temp lra-pass))                            (:save-fp                             (inst move cfp-tn ocfp-pass))                            (:load-fp                             ,(if variable                                  '(move new-fp cfp-tn)                                  '(if (> nargs register-arg-count)                                       (move new-fp cfp-tn)                                       (move csp-tn cfp-tn))))))))))           ,@(if named                 `((sc-case fdefn                     (descriptor-reg (move fdefn fdefn-pass))                     (control-stack                      (loadw fdefn-pass cfp-tn (tn-offset fdefn))                      (do-next-filler))                     (constant                      (loadw fdefn-pass code-tn (tn-offset fdefn)                             other-pointer-lowtag)                      (do-next-filler)))                   (loadw lip fdefn-pass fdefn-raw-addr-slot                          other-pointer-lowtag)                   (do-next-filler))                 `((sc-case arg-fun                     (descriptor-reg (move arg-fun lexenv))                     (control-stack                      (loadw lexenv cfp-tn (tn-offset arg-fun))                      (do-next-filler))                     (constant                      (loadw lexenv code-tn (tn-offset arg-fun)                             other-pointer-lowtag)                      (do-next-filler)))                   (loadw function lexenv closure-fun-slot                          fun-pointer-lowtag)                   (do-next-filler)                   (inst addi (- (ash simple-fun-code-offset word-shift)                                 fun-pointer-lowtag)                         function lip)))           (loop             (cond ((null filler)                    (return))                   ((null (car filler))                    (pop filler))                   ((null (cdr filler))                    (return))                   (t                    (do-next-filler))))           (note-this-location vop :call-site)           (inst bv lip :nullify (null filler))

⌨️ 快捷键说明

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