;;; -*- Mode:LISP; Package:COMPILER; Base:8; Readtable:ZL -*- (defun (:property list p1cross) (form) (let ((fn (case (length (cdr form)) (0 'nil) (1 'li:ncons) (2 'li:list2) (3 'li:list3) (4 'li:list4) (t 'li:listn)))) (p1 `(,fn . ,(cdr form))))) (defun (:property list* p1cross) (form) (let ((fn (case (length (cdr form)) (t 'li:list*)))) (p1 `(,fn . ,(cdr form))))) (defprop list-in-area p2list-cross p2-for-k) (defprop list*-in-area p2list-cross p2-for-k) (defun p2list-cross (argl dest &aux area) (declare (ignore dest)) (when (memq *p2fn* '(list-in-area list*-in-area)) (setq area (pop argl))) (fsignal "convert this")) (DEFUN (:PROPERTY ATOM P2-FOR-K) (ARGL DEST) ;just treat ATOM normally. This effectively overrides the normal P2. (P2MISC-FOR-K 'ATOM ARGL DEST 1)) ;;; NOT compiles into a misc insn normally, ;;; but with a branch destination, it optimizes away by inverting the condition. (DEFUN (:PROPERTY NOT P2-FOR-K) (ARGL DEST) (IF (OR (EQ (CADR *BDEST*) 'NILIND) (EQ (CADR *BDEST*) 'ATOMIND)) (LET ((SENSE (OTHER (CADDR *BDEST*)))) (P2BRANCH-for-k (CAR ARGL) DEST `(BRANCH ,(CADR *BDEST*) ,SENSE . ,(CDDDR *BDEST*))) (SETQ *BDEST* NIL)) (P2MISC-for-k 'NOT ARGL DEST 1))) (DEFUN (:PROPERTY SETQ P2-for-k) (ARGL DEST) (PROG () (OR ARGL (RETURN (p2-for-k '(quote nil) dest))) LOOP (P2SETQ-1-for-k (CAR ARGL) (CADR ARGL) (COND ((NULL (CDDR ARGL)) DEST) (T 'D-IGNORE))) (SETQ ARGL (CDDR ARGL)) (AND ARGL (GO LOOP)))) ;;; Compile code to set VAR to the result of computing VALUE, ;;; and also move that value to DEST. (DEFUN P2SETQ-1-for-k (VAR VALUE DEST) (COND ((MEMQ VAR '(NIL T)) NIL) ;; The next case appear identical to the default. ;;((AND (CONSP VAR) (EQ (CAR VAR) 'LEXICAL-REF)) ;; (movem-and-move-to-dest-for-k value var dest)) (T (movem-and-move-to-dest-for-k value var dest))) NIL) (defun movem-and-move-to-dest-for-k (value var dest) ;;compile VALUE, storing the result in VAR, and also in DEST. ;; VAR is a REF type construct. ;; DEST is any dest acceptable to P2-FOR-K. NOTE: that means its an INTERNAL dest!! ;;** idea for special hack.. Change these k:r0 s to k:r15. Then peephole optimizer ;; could assume the contents on any k:r(n) is used at most once and do some optimizations ;; (particularily wrt MD). Cheap flow analysis. (let ((inter-var (when (listp var) (case (car var) ((local-ref) (intermediate-dest-for-store (var-lap-address (cadr var)))))))) (multiple-value-bind (inter-dest inter-reg) (compute-temporary-destination var inter-var) ;;salt it in var, if necessary. (cond ((and (symbolp var) ;; @#$@#$ This should be NC::REGISTER or COMPILER::REGISTER (get var :register)) (p2-for-k value inter-dest) (outi-for-k `(k:move ,var ,inter-reg k:boxed-right) :single-value)) ((atom var) ;; Store from inter-reg into special variable ;; Let POST-PROCESS make OPEN-CALL, otherwise it gets faked out. (p2-for-k value inter-dest) (let ((tail-p (tail-call-p dest 'symbol:%%set))) (tail-call-open 'symbol:%%set tail-p #'discard-temporary-frame :single-value) (outi-for-k `(k:movei k:o0 (quote ,var) k:boxed)) (outi-for-k `(k:move k:o1 ,inter-reg k:boxed-right)) (return-from movem-and-move-to-dest-for-k (maybe-tail-call `(symbol:%%set 2) dest :single-value tail-p))) ;;calling subroutine anyway, and %%set returns as value the right thing. ;;so putting dest in subroutine call solves whole problem and avoids any ;;possibility of K:R0 bashage. ) ((eq (car var) 'local-ref) (p2-for-k value inter-dest) (let ((lap-address (var-lap-address (cadr var)))) (finish-store inter-reg lap-address dest))) ((eq (car var) 'self-ref) ;; We delay computing value until after new frame gets opened. (iv-ref-for-k var 'li:instance-var-write inter-reg)) ((eq (car var) 'lexical-ref) (p2-for-k value inter-dest) (let* ((tail-p (tail-call-p dest)) (ref-spec (second var)) (level (ldb (byte 12. 12.) ref-spec)) (offset (ldb (byte 12. 0.) ref-spec))) (tail-call-open 'li:closure-set tail-p #'discard-temporary-frame :single-value) (closure-set-call level offset inter-reg dest tail-p))) (t (ferror nil "Compiler internal error -- can't finish store"))) ;;salt it in dest, if necessary. (cond ((eq dest 'd-ignore) nil) ((eq dest inter-reg) nil) ;already in place ((k-destination-p dest) (outi-for-k `(k:move ,dest ,inter-reg k:boxed-right))) (t (outi-for-k `(k:move ,dest ,inter-reg k:boxed-right))))))) (DEFUN (:PROPERTY PROGN-WITH-DECLARATIONS P2-for-k) (ARGL DEST) (LET ((*VARS* (CAR ARGL))) (progn-for-k DEST (CDR ARGL)))) (defun (:property progn p2-for-k) (argl dest) (progn-for-k dest argl)) (defun progn-for-k (dest argl) (loop for argx on argl for arg = (first argx) while (rest argx) do (p2-for-k arg 'd-ignore) finally (p2-for-k arg dest))) (defun (:property prog2 p2-for-k) (argl dest) (p2prog12mv-for-k 2 dest argl nil))