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

📄 call.lisp

📁 开源跨平台Lisp编译器
💻 LISP
📖 第 1 页 / 共 4 页
字号:
                    ((null remaining))                  (let ((def (car remaining)))                    (emit-label (car def))                    (when (null (cdr remaining))                      (inst b defaulting-done))                    (store-stack-tn (cdr def) null-tn)))                (trace-table-entry trace-table-normal)))))        (when lra-label          (inst compute-code-from-lra code-tn code-tn lra-label temp))))  (values));;;; Unknown values receiving:;;;    Emit code needed at the return point for an unknown-values call for an;;; arbitrary number of values.;;;;;;    We do the single and non-single cases with no shared code: there doesn't;;; seem to be any potential overlap, and receiving a single value is more;;; important efficiency-wise.;;;;;;    When there is a single value, we just push it on the stack, returning;;; the old SP and 1.;;;;;;    When there is a variable number of values, we move all of the argument;;; registers onto the stack, and return Args and Nargs.;;;;;;    Args and Nargs are TNs wired to the named locations.  We must;;; explicitly allocate these TNs, since their lifetimes overlap with the;;; results Start and Count (also, it's nice to be able to target them).;;;(defun receive-unknown-values (args nargs start count lra-label temp)  (declare (type tn args nargs start count temp))  (let ((variable-values (gen-label))        (done (gen-label)))    (without-scheduling ()      (inst b variable-values)      (inst nop))    (when lra-label      (inst compute-code-from-lra code-tn code-tn lra-label temp))    (inst addu csp-tn csp-tn n-word-bytes)    (storew (first *register-arg-tns*) csp-tn -1)    (inst addu start csp-tn (- n-word-bytes))    (inst li count (fixnumize 1))    (emit-label done)    (assemble (*elsewhere*)      (trace-table-entry trace-table-fun-prologue)      (emit-label variable-values)      (when lra-label        (inst compute-code-from-lra code-tn code-tn lra-label temp))      (do ((arg *register-arg-tns* (rest arg))           (i 0 (1+ i)))          ((null arg))        (storew (first arg) args i))      (move start args)      (inst b done)      (move count nargs t)      (trace-table-entry trace-table-normal)))  (values));;; VOP that can be inherited by unknown values receivers.  The main thing this;;; handles is allocation of the result temporaries.;;;(define-vop (unknown-values-receiver)  (:results   (start :scs (any-reg))   (count :scs (any-reg)))  (:temporary (:sc descriptor-reg :offset ocfp-offset                   :from :eval :to (:result 0))              values-start)  (:temporary (:sc any-reg :offset nargs-offset               :from :eval :to (:result 1))              nvals)  (:temporary (:scs (non-descriptor-reg)) temp));;;; Local call with unknown values convention return:;;; 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 (fp)         (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    (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 fp)      (trace-table-entry trace-table-call-site)      (inst compute-lra-from-code            (callee-return-pc-tn callee) code-tn label temp)      (note-this-location vop :call-site)      (inst b target)      (inst nop)      (trace-table-entry trace-table-normal)      (emit-return-pc label)      (default-unknown-values vop values nvals move-temp temp label)      (when cur-nfp        (load-stack-tn cur-nfp nfp-save)))));;; 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 (fp)         (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)  (:temporary (:scs (non-descriptor-reg)) temp)  (:generator 20    (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 fp)      (trace-table-entry trace-table-call-site)      (inst compute-lra-from-code            (callee-return-pc-tn callee) code-tn label temp)      (note-this-location vop :call-site)      (inst b target)      (inst nop)      (trace-table-entry trace-table-normal)      (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)))));;;; 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 (fp)         (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    (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 fp)      (trace-table-entry trace-table-call-site)      (inst compute-lra-from-code            (callee-return-pc-tn callee) code-tn label temp)      (note-this-location vop :call-site)      (inst b target)      (inst nop)      (trace-table-entry trace-table-normal)      (emit-return-pc label)      (note-this-location vop :known-return)      (when cur-nfp        (load-stack-tn cur-nfp nfp-save)))));;; 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 (ocfp :target ocfp-temp)         (return-pc :target return-pc-temp)         (vals :more t))  (:temporary (:sc any-reg :from (:argument 0)) ocfp-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 ocfp-temp ocfp)    (maybe-load-stack-tn return-pc-temp return-pc)    (move csp-tn cfp-tn)    (let ((cur-nfp (current-nfp-tn vop)))      (when cur-nfp        (inst addu nsp-tn cur-nfp              (bytes-needed-for-non-descriptor-stack-frame))))    (inst addu lip return-pc-temp (- n-word-bytes other-pointer-lowtag))    (inst j lip)    (move cfp-tn ocfp-temp t)    (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 Ocfp 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.;;;(defmacro 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           '(name :target name-pass)           '(arg-fun :target lexenv))      ,@(when (eq return :tail)          '((ocfp :target ocfp-pass)            (return-pc :target return-pc-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))

⌨️ 快捷键说明

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