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

📄 call.lisp

📁 开源跨平台Lisp编译器
💻 LISP
📖 第 1 页 / 共 3 页
字号:
           (do-next-filler))         ,@(ecase return             (:fixed              '((emit-return-pc lra-label)                (default-unknown-values vop values nvals                                        move-temp temp lra-label)                (when cur-nfp                  (load-stack-tn cur-nfp nfp-save))))             (:unknown              '((emit-return-pc lra-label)                (note-this-location vop :unknown-return)                (receive-unknown-values values-start nvals start count                                        lra-label temp)                (when cur-nfp                  (load-stack-tn cur-nfp nfp-save))))             (:tail)))       (trace-table-entry trace-table-normal)))))  (define-full-call call nil :fixed nil)  (define-full-call call-named t :fixed nil)  (define-full-call multiple-call nil :unknown nil)  (define-full-call multiple-call-named t :unknown nil)  (define-full-call tail-call nil :tail nil)  (define-full-call tail-call-named t :tail nil)  (define-full-call call-variable nil :fixed t)  (define-full-call multiple-call-variable nil :unknown t));;; Defined separately, since needs special code that BLT's the arguments;;; down.;;;(define-vop (tail-call-variable)  (:args (args-arg :scs (any-reg) :target args)         (function-arg :scs (descriptor-reg) :target lexenv)         (old-fp-arg :scs (any-reg) :target old-fp)         (lra-arg :scs (descriptor-reg) :target lra))  (:temporary (:sc any-reg :offset nl0-offset :from (:argument 0)) args)  (:temporary (:sc any-reg :offset lexenv-offset :from (:argument 1)) lexenv)  (:temporary (:sc any-reg :offset ocfp-offset :from (:argument 2)) old-fp)  (:temporary (:sc any-reg :offset lra-offset :from (:argument 3)) lra)  (:temporary (:scs (any-reg) :from (:argument 3)) tmp)  (:vop-var vop)  (:generator 75    ;; Move these into the passing locations if they are not already there.    (move args-arg args)    (move function-arg lexenv)    (move old-fp-arg old-fp)    (move lra-arg lra)    ;; Clear the number stack if anything is there.    (let ((cur-nfp (current-nfp-tn vop)))      (when cur-nfp        (inst move cur-nfp nsp-tn)))    ;; And jump to the assembly-routine that does the bliting.    (let ((fixup (make-fixup 'tail-call-variable :assembly-routine)))      (inst ldil fixup tmp)      (inst be fixup lisp-heap-space tmp :nullify t))));;;; Unknown values return:;;; Return a single value using the unknown-values convention.;;;(define-vop (return-single)  (:args (old-fp :scs (any-reg))         (return-pc :scs (descriptor-reg))         (value))  (:ignore value)  (:vop-var vop)  (:generator 6    ;; Clear the number stack.    (trace-table-entry trace-table-fun-epilogue)    (let ((cur-nfp (current-nfp-tn vop)))      (when cur-nfp        (inst move cur-nfp nsp-tn)))    ;; Clear the control stack, and restore the frame pointer.    (move cfp-tn csp-tn)    (move old-fp cfp-tn)    ;; Out of here.    (lisp-return return-pc :offset 1)    (trace-table-entry trace-table-normal)));;; Do unknown-values return of a fixed number of values.  The Values are;;; required to be set up in the standard passing locations.  Nvals is the;;; number of values returned.;;;;;; If returning a single value, then deallocate the current frame, restore;;; FP and jump to the single-value entry at Return-PC + 8.;;;;;; If returning other than one value, then load the number of values returned,;;; NIL out unsupplied values registers, restore FP and return at Return-PC.;;; When there are stack values, we must initialize the argument pointer to;;; point to the beginning of the values block (which is the beginning of the;;; current frame.);;;(define-vop (return)  (:args   (old-fp :scs (any-reg))   (return-pc :scs (descriptor-reg) :to (:eval 1))   (values :more t))  (:ignore values)  (:info nvals)  (:temporary (:sc descriptor-reg :offset a0-offset :from (:eval 0)) a0)  (:temporary (:sc descriptor-reg :offset a1-offset :from (:eval 0)) a1)  (:temporary (:sc descriptor-reg :offset a2-offset :from (:eval 0)) a2)  (:temporary (:sc descriptor-reg :offset a3-offset :from (:eval 0)) a3)  (:temporary (:sc descriptor-reg :offset a4-offset :from (:eval 0)) a4)  (:temporary (:sc descriptor-reg :offset a5-offset :from (:eval 0)) a5)  (:temporary (:sc any-reg :offset nargs-offset) nargs)  (:temporary (:sc any-reg :offset ocfp-offset) val-ptr)  (:vop-var vop)  (:generator 6    ;; Clear the number stack.    (trace-table-entry trace-table-fun-epilogue)    (let ((cur-nfp (current-nfp-tn vop)))      (when cur-nfp        (inst move cur-nfp nsp-tn)))    ;; Establish the values pointer and values count.    (move cfp-tn val-ptr)    (inst li (fixnumize nvals) nargs)    ;; restore the frame pointer and clear as much of the control    ;; stack as possible.    (move old-fp cfp-tn)    (inst addi (* nvals n-word-bytes) val-ptr csp-tn)    ;; pre-default any argument register that need it.    (when (< nvals register-arg-count)      (dolist (reg (subseq (list a0 a1 a2 a3 a4 a5) nvals))        (move null-tn reg)))    ;; And away we go.    (lisp-return return-pc)    (trace-table-entry trace-table-normal)));;; Do unknown-values return of an arbitrary number of values (passed on the;;; stack.)  We check for the common case of a single return value, and do that;;; inline using the normal single value return convention.  Otherwise, we;;; branch off to code that calls an assembly-routine.;;;(define-vop (return-multiple)  (:args   (old-fp-arg :scs (any-reg) :to (:eval 1))   (lra-arg :scs (descriptor-reg) :to (:eval 1))   (vals-arg :scs (any-reg) :target vals)   (nvals-arg :scs (any-reg) :target nvals))  (:temporary (:sc any-reg :offset nl1-offset :from (:argument 0)) old-fp)  (:temporary (:sc descriptor-reg :offset lra-offset :from (:argument 1)) lra)  (:temporary (:sc any-reg :offset nl0-offset :from (:argument 2)) vals)  (:temporary (:sc any-reg :offset nargs-offset :from (:argument 3)) nvals)  (:temporary (:sc descriptor-reg :offset a0-offset) a0)  (:temporary (:scs (any-reg) :from (:eval 0)) tmp)  (:vop-var vop)  (:node-var node)  (:generator 13    (trace-table-entry trace-table-fun-epilogue)    ;; Clear the number stack.    (let ((cur-nfp (current-nfp-tn vop)))      (when cur-nfp        (inst move cur-nfp nsp-tn)))    (unless (policy node (> space speed))      ;; Check for the single case.      (inst comib :<> (fixnumize 1) nvals-arg not-single)      (loadw a0 vals-arg)      ;; Return with one value.      (move cfp-tn csp-tn)      (move old-fp-arg cfp-tn)      (lisp-return lra-arg :offset 1))    ;; Nope, not the single case.    NOT-SINGLE    (move old-fp-arg old-fp)    (move lra-arg lra)    (move vals-arg vals)    (move nvals-arg nvals)    (let ((fixup (make-fixup 'return-multiple :assembly-routine)))      (inst ldil fixup tmp)      (inst be fixup lisp-heap-space tmp :nullify t))    (trace-table-entry trace-table-normal)));;;; XEP hackery:;;; We don't need to do anything special for regular functions.;;;(define-vop (setup-environment)  (:info label)  (:ignore label)  (:generator 0    ;; Don't bother doing anything.    ));;; Get the lexical environment from it's passing location.;;;(define-vop (setup-closure-environment)  (:temporary (:sc descriptor-reg :offset lexenv-offset :target closure               :to (:result 0))              lexenv)  (:results (closure :scs (descriptor-reg)))  (:info label)  (:ignore label)  (:generator 6    ;; Get result.    (move lexenv closure)));;; Copy a more arg from the argument area to the end of the current frame.;;; Fixed is the number of non-more arguments.;;;(define-vop (copy-more-arg)  (:temporary (:sc any-reg :offset nl0-offset) result)  (:temporary (:sc any-reg :offset nl1-offset) count)  (:temporary (:sc any-reg :offset nl2-offset) src)  (:temporary (:sc any-reg :offset nl3-offset) dst)  (:temporary (:sc descriptor-reg :offset l0-offset) temp)  (:info fixed)  (:generator 20    ;; Figure out how many things we are going to copy.    (unless (zerop fixed)      (inst addi (- (fixnumize fixed)) nargs-tn count))    ;; Blow out of here if is nothing to copy.    (inst comb :<= (if (zerop fixed) nargs-tn count) zero-tn done :nullify t)    (when (< fixed register-arg-count)      ;; Save a pointer to the results so we can fill in register args.      ;; We don't need this if there are more fixed args than reg args.      (move csp-tn result))    ;; Allocate the space on the stack.    (inst add csp-tn (if (zerop fixed) nargs-tn count) csp-tn)    (when (< fixed register-arg-count)      ;; We must stop when we run out of stack args, not when we run out of      ;; args in general.      (inst addi (fixnumize (- register-arg-count)) nargs-tn count)      ;; Everything of interest in registers.      (inst comb :<= count zero-tn do-regs))    ;; Initialize dst to be end of stack.    (move csp-tn dst)    ;; Initialize src to be end of args.    (inst add cfp-tn nargs-tn src)    LOOP    ;; *--dst = *--src, --count    (inst ldwm (- n-word-bytes) src temp)    (inst addib :> (fixnumize -1) count loop)    (inst stwm temp (- n-word-bytes) dst)    DO-REGS    (when (< fixed register-arg-count)      ;; Now we have to deposit any more args that showed up in registers.      ;; We know there is at least one more arg, otherwise we would have      ;; branched to done up at the top.      (inst addi (fixnumize (- fixed)) nargs-tn count)      (do ((i fixed (1+ i)))          ((>= i register-arg-count))        ;; Is this the last one?        (inst addib :<= (fixnumize -1) count done)        ;; Store it relative to the pointer saved at the start.        (storew (nth i register-arg-tns) result (- i fixed))))    DONE));;; More args are stored consequtively on the stack, starting immediately at;;; the context pointer.  The context pointer is not typed, so the lowtag is 0.;;;(define-full-reffer more-arg * 0 0 (descriptor-reg any-reg) * %more-arg);;; Turn more arg (context, count) into a list.;;;(define-vop (listify-rest-args)  (:args (context-arg :target context :scs (descriptor-reg))         (count-arg :target count :scs (any-reg)))  (:arg-types * tagged-num)  (:temporary (:scs (any-reg) :from (:argument 0)) context)  (:temporary (:scs (any-reg) :from (:argument 1)) count)  (:temporary (:scs (descriptor-reg) :from :eval) temp)  (:temporary (:scs (non-descriptor-reg) :from :eval) dst)  (:results (result :scs (descriptor-reg)))  (:translate %listify-rest-args)  (:policy :safe)  (:generator 20    (move context-arg context)    (move count-arg count)    ;; Check to see if there are any arguments.    (inst comb := count zero-tn done)    (move null-tn result)    ;; We need to do this atomically.    (pseudo-atomic ()      (assemble ()        ;; Allocate a cons (2 words) for each item.        (inst move alloc-tn result)        (inst dep list-pointer-lowtag 31 3 result)        (move result dst)        (inst sll count 1 temp)        (inst add alloc-tn temp alloc-tn)        LOOP        ;; Grab one value and stash it in the car of this cons.        (inst ldwm n-word-bytes context temp)        (storew temp dst 0 list-pointer-lowtag)        ;; Dec count, and if != zero, go back for more.        (inst addi (* 2 n-word-bytes) dst dst)        (inst addib :> (fixnumize -1) count loop :nullify t)        (storew dst dst -1 list-pointer-lowtag)        ;; NIL out the last cons.        (storew null-tn dst -1 list-pointer-lowtag)        ;; Clear out dst, because it points past the last cons.        (move null-tn dst)))    DONE));;; Return the location and size of the more arg glob created by Copy-More-Arg.;;; Supplied is the total number of arguments supplied (originally passed in;;; NARGS.)  Fixed is the number of non-rest arguments.;;;;;; We must duplicate some of the work done by Copy-More-Arg, since at that;;; time the environment is in a pretty brain-damaged state, preventing this;;; info from being returned as values.  What we do is compute;;; supplied - fixed, and return a pointer that many words below the current;;; stack top.;;;;;; WTF? FIXME -- CSR;;;(setf (info function source-transform 'c::%more-arg-context) nil);;;(define-vop (more-arg-context)  (:policy :fast-safe)  (:translate sb!c::%more-arg-context)  (:args (supplied :scs (any-reg)))  (:arg-types tagged-num (:constant fixnum))  (:info fixed)  (:results (context :scs (descriptor-reg))            (count :scs (any-reg)))  (:result-types t tagged-num)  (:note "more-arg-context")  (:generator 5    (inst addi (fixnumize (- fixed)) supplied count)    (inst sub csp-tn count context)));;; Signal wrong argument count error if Nargs isn't = to Count.;;;(define-vop (verify-arg-count)  (:policy :fast-safe)  (:translate sb!c::%verify-arg-count)  (:args (nargs :scs (any-reg)))  (:arg-types positive-fixnum (:constant t))  (:info count)  (:vop-var vop)  (:save-p :compute-only)  (:generator 3    (let ((err-lab           (generate-error-code vop invalid-arg-count-error nargs)))      (cond ((zerop count)             (inst bc :<> nil nargs zero-tn err-lab))            (t             (inst bci :<> nil (fixnumize count) nargs err-lab))))));;; Signal an argument count error.;;;(macrolet ((frob (name error translate &rest args)             `(define-vop (,name)                ,@(when translate                    `((:policy :fast-safe)                      (:translate ,translate)))                (:args ,@(mapcar #'(lambda (arg)                                     `(,arg :scs (any-reg descriptor-reg)))                                 args))                (:vop-var vop)                (:save-p :compute-only)                (:generator 1000                  (error-call vop ,error ,@args)))))  (frob arg-count-error invalid-arg-count-error    sb!c::%arg-count-error nargs)  (frob type-check-error object-not-type-error sb!c::%type-check-error    object type)  (frob layout-invalid-error layout-invalid-error sb!c::%layout-invalid-error    object layout)  (frob odd-key-args-error odd-key-args-error    sb!c::%odd-key-args-error)  (frob unknown-key-arg-error unknown-key-arg-error    sb!c::%unknown-key-arg-error key)  (frob nil-fun-returned-error nil-fun-returned-error nil fun))

⌨️ 快捷键说明

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