Update of /project/movitz/cvsroot/movitz In directory clnet:/tmp/cvs-serv8001
Modified Files: compiler.lisp Log Message: Fix a rather nasty compiler bug that would cause :store-lexical to generate GC-unsafe code (i.e. store pointers in ECX).
--- /project/movitz/cvsroot/movitz/compiler.lisp 2008/04/14 20:39:42 1.201 +++ /project/movitz/cvsroot/movitz/compiler.lisp 2008/04/15 23:04:39 1.202 @@ -8,7 +8,7 @@ ;;;; Created at: Wed Oct 25 12:30:49 2000 ;;;; Distribution: See the accompanying file COPYING. ;;;; -;;;; $Id: compiler.lisp,v 1.201 2008/04/14 20:39:42 ffjeld Exp $ +;;;; $Id: compiler.lisp,v 1.202 2008/04/15 23:04:39 ffjeld Exp $ ;;;; ;;;;------------------------------------------------------------------
@@ -3639,168 +3639,171 @@ (install-for-single-value binding binding-location :eax nil))) )))))))))
+ (defun make-store-lexical (binding source shared-reference-p funobj frame-map &key protect-registers) (let ((binding (ensure-local-binding binding funobj))) (assert (not (and shared-reference-p (not (binding-lended-p binding)))) - (binding) - "funny binding: ~W" binding) + (binding) + "funny binding: ~W" binding) (if (and nil (typep source 'constant-object-binding)) (make-load-constant (constant-object source) binding funobj frame-map) - (let ((protect-registers (cons source protect-registers))) - (cond - ((eq :untagged-fixnum-ecx source) - (if (eq :untagged-fixnum-ecx - (new-binding-location binding frame-map)) - nil - (append (make-result-and-returns-glue :ecx :untagged-fixnum-ecx) - (make-store-lexical binding :ecx shared-reference-p funobj frame-map - :protect-registers protect-registers)))) - ((typep binding 'borrowed-binding) - (let ((slot (borrowed-binding-reference-slot binding))) - (if (not shared-reference-p) - (let ((tmp-reg (chose-free-register protect-registers) - #+ignore(if (eq source :eax) :ebx :eax))) - (when (eq :ecx source) - (break "loading a word from ECX?")) - `((:movl (:esi ,(+ (slot-offset 'movitz-funobj 'constant0) (* 4 slot))) - ,tmp-reg) - (:movl ,source (-1 ,tmp-reg)))) - `((:movl ,source (:esi ,(+ (slot-offset 'movitz-funobj 'constant0) (* 4 slot)))))))) - ((typep binding 'forwarding-binding) - (assert (not (binding-lended-p binding)) (binding)) - (make-store-lexical (forwarding-binding-target binding) - source shared-reference-p funobj frame-map)) - ((not (new-binding-located-p binding frame-map)) - ;; (warn "Can't store to unlocated binding ~S." binding) - nil) - ((and (binding-lended-p binding) - (not shared-reference-p)) - (let ((tmp-reg (chose-free-register protect-registers) - #+ignore (if (eq source :eax) :ebx :eax)) - (location (new-binding-location binding frame-map))) - (if (integerp location) - `((:movl (:ebp ,(stack-frame-offset location)) ,tmp-reg) - (:movl ,source (,tmp-reg -1))) - (ecase (operator location) - (:argument-stack - (assert (<= 2 (function-argument-argnum binding)) () - "store-lexical argnum can't be ~A." (function-argument-argnum binding)) - `((:movl (:ebp ,(argument-stack-offset binding)) ,tmp-reg) - (:movl ,source (,tmp-reg -1)))))))) - (t (let ((location (new-binding-location binding frame-map))) - (cond - ((member source '(:eax :ebx :ecx :edx :edi :esp)) - (if (integerp location) - `((:movl ,source (:ebp ,(stack-frame-offset location)))) - (ecase (operator location) - ((:push) - `((:pushl ,source))) - ((:eax :ebx :ecx :edx) - (unless (eq source location) - `((:movl ,source ,location)))) - (:argument-stack - (assert (<= 2 (function-argument-argnum binding)) () - "store-lexical argnum can't be ~A." (function-argument-argnum binding)) - `((:movl ,source (:ebp ,(argument-stack-offset binding))))) - (:untagged-fixnum-ecx - (assert (not (eq source :edi))) - (cond - ((eq source :untagged-fixnum-ecx) - nil) - ((eq source :eax) - `((,*compiler-global-segment-prefix* - :call (:edi ,(global-constant-offset 'unbox-u32))))) - (t `((:movl ,source :eax) - (,*compiler-global-segment-prefix* - :call (:edi ,(global-constant-offset 'unbox-u32)))))))))) - ((eq source :boolean-cf=1) - (let ((tmp (chose-free-register protect-registers))) - `((:sbbl :ecx :ecx) - (,*compiler-local-segment-prefix* - :movl (:edi (:ecx 4) ,(global-constant-offset 'not-not-nil)) ,tmp) - ,@(make-store-lexical binding tmp shared-reference-p funobj frame-map - :protect-registers protect-registers)))) - ((eq source :boolean-cf=0) - (let ((tmp (chose-free-register protect-registers))) - `((:sbbl :ecx :ecx) - (,*compiler-local-segment-prefix* - :movl (:edi (:ecx 4) ,(global-constant-offset 'boolean-zero)) ,tmp) - ,@(make-store-lexical binding tmp shared-reference-p funobj frame-map - :protect-registers protect-registers)))) - ((and *compiler-use-cmov-p* - (member source +boolean-modes+)) - (let ((tmp (chose-free-register protect-registers))) - (append `((:movl :edi ,tmp)) - (list (cons *compiler-local-segment-prefix* - (make-cmov-on-boolean source - `(:edi ,(global-constant-offset 't-symbol)) - tmp))) - (make-store-lexical binding tmp shared-reference-p funobj frame-map + (let ((protect-registers (list* source protect-registers))) + (unless (or (eq source :untagged-fixnum-ecx)) ; test binding type! + (push :ecx protect-registers)) + (cond + ((eq :untagged-fixnum-ecx source) + (if (eq :untagged-fixnum-ecx + (new-binding-location binding frame-map)) + nil + (append (make-result-and-returns-glue :ecx :untagged-fixnum-ecx) + (make-store-lexical binding :ecx shared-reference-p funobj frame-map + :protect-registers protect-registers)))) + ((typep binding 'borrowed-binding) + (let ((slot (borrowed-binding-reference-slot binding))) + (if (not shared-reference-p) + (let ((tmp-reg (chose-free-register protect-registers) + #+ignore(if (eq source :eax) :ebx :eax))) + (when (eq :ecx source) + (break "loading a word from ECX?")) + `((:movl (:esi ,(+ (slot-offset 'movitz-funobj 'constant0) (* 4 slot))) + ,tmp-reg) + (:movl ,source (-1 ,tmp-reg)))) + `((:movl ,source (:esi ,(+ (slot-offset 'movitz-funobj 'constant0) (* 4 slot)))))))) + ((typep binding 'forwarding-binding) + (assert (not (binding-lended-p binding)) (binding)) + (make-store-lexical (forwarding-binding-target binding) + source shared-reference-p funobj frame-map)) + ((not (new-binding-located-p binding frame-map)) + ;; (warn "Can't store to unlocated binding ~S." binding) + nil) + ((and (binding-lended-p binding) + (not shared-reference-p)) + (let ((tmp-reg (chose-free-register protect-registers) + #+ignore (if (eq source :eax) :ebx :eax)) + (location (new-binding-location binding frame-map))) + (if (integerp location) + `((:movl (:ebp ,(stack-frame-offset location)) ,tmp-reg) + (:movl ,source (,tmp-reg -1))) + (ecase (operator location) + (:argument-stack + (assert (<= 2 (function-argument-argnum binding)) () + "store-lexical argnum can't be ~A." (function-argument-argnum binding)) + `((:movl (:ebp ,(argument-stack-offset binding)) ,tmp-reg) + (:movl ,source (,tmp-reg -1)))))))) + (t (let ((location (new-binding-location binding frame-map))) + (cond + ((member source '(:eax :ebx :ecx :edx :edi :esp)) + (if (integerp location) + `((:movl ,source (:ebp ,(stack-frame-offset location)))) + (ecase (operator location) + ((:push) + `((:pushl ,source))) + ((:eax :ebx :ecx :edx) + (unless (eq source location) + `((:movl ,source ,location)))) + (:argument-stack + (assert (<= 2 (function-argument-argnum binding)) () + "store-lexical argnum can't be ~A." (function-argument-argnum binding)) + `((:movl ,source (:ebp ,(argument-stack-offset binding))))) + (:untagged-fixnum-ecx + (assert (not (eq source :edi))) + (cond + ((eq source :untagged-fixnum-ecx) + nil) + ((eq source :eax) + `((,*compiler-global-segment-prefix* + :call (:edi ,(global-constant-offset 'unbox-u32))))) + (t `((:movl ,source :eax) + (,*compiler-global-segment-prefix* + :call (:edi ,(global-constant-offset 'unbox-u32)))))))))) + ((eq source :boolean-cf=1) + (let ((tmp (chose-free-register protect-registers))) + `((:sbbl :ecx :ecx) + (,*compiler-local-segment-prefix* + :movl (:edi (:ecx 4) ,(global-constant-offset 'not-not-nil)) ,tmp) + ,@(make-store-lexical binding tmp shared-reference-p funobj frame-map :protect-registers protect-registers)))) - ((member source +boolean-modes+) - (let ((tmp (chose-free-register protect-registers)) - (label (gensym "store-lexical-bool-"))) - (append `((:movl :edi ,tmp)) - (list (make-branch-on-boolean source label :invert t)) - `((,*compiler-local-segment-prefix* - :movl (:edi ,(global-constant-offset 't-symbol)) ,tmp)) - (list label) - (make-store-lexical binding tmp shared-reference-p funobj frame-map + ((eq source :boolean-cf=0) + (let ((tmp (chose-free-register protect-registers))) + `((:sbbl :ecx :ecx) + (,*compiler-local-segment-prefix* + :movl (:edi (:ecx 4) ,(global-constant-offset 'boolean-zero)) ,tmp) + ,@(make-store-lexical binding tmp shared-reference-p funobj frame-map :protect-registers protect-registers)))) - ((not (bindingp source)) - (error "Unknown source for store-lexical: ~S" source)) - ((binding-singleton source) - (assert (not shared-reference-p)) - (let ((value (car (binding-singleton source)))) - (etypecase value - (movitz-fixnum - (let ((immediate (movitz-immediate-value value))) - (if (integerp location) - (let ((tmp (chose-free-register protect-registers))) - (append (make-immediate-move immediate tmp) - `((:movl ,tmp (:ebp ,(stack-frame-offset location)))))) - #+ignore (if (= 0 immediate) - (let ((tmp (chose-free-register protect-registers))) - `((:xorl ,tmp ,tmp) - (:movl ,tmp (:ebp ,(stack-frame-offset location))))) - `((:movl ,immediate (:ebp ,(stack-frame-offset location))))) - (ecase (operator location) - ((:argument-stack) - `((:movl ,immediate (:ebp ,(argument-stack-offset binding))))) - ((:eax :ebx :ecx :edx) - (make-immediate-move immediate location)) - ((:untagged-fixnum-ecx) - (make-immediate-move (movitz-fixnum-value value) :ecx)))))) - (movitz-character - (let ((immediate (movitz-immediate-value value))) - (if (integerp location) - (let ((tmp (chose-free-register protect-registers))) - (append (make-immediate-move immediate tmp) - `((:movl ,tmp (:ebp ,(stack-frame-offset location)))))) - (ecase (operator location) - ((:argument-stack) - `((:movl ,immediate (:ebp ,(argument-stack-offset binding))))) - ((:eax :ebx :ecx :edx) - (make-immediate-move immediate location)))))) - (movitz-heap-object - (etypecase location - ((member :eax :ebx :edx) - (make-load-constant value location funobj frame-map)) - (integer - (let ((tmp (chose-free-register protect-registers))) - (append (make-load-constant value tmp funobj frame-map) - (make-store-lexical binding tmp shared-reference-p - funobj frame-map - :protect-registers protect-registers)))) - ((eql :untagged-fixnum-ecx) - (check-type value movitz-bignum) - (let ((immediate (movitz-bignum-value value))) - (check-type immediate (unsigned-byte 32)) - (make-immediate-move immediate :ecx))) - ))))) - (t (error "Generalized lexb source for store-lexical not implemented: ~S" source)))))))))) + ((and *compiler-use-cmov-p* + (member source +boolean-modes+)) + (let ((tmp (chose-free-register protect-registers))) + (append `((:movl :edi ,tmp)) + (list (cons *compiler-local-segment-prefix* + (make-cmov-on-boolean source + `(:edi ,(global-constant-offset 't-symbol)) + tmp))) + (make-store-lexical binding tmp shared-reference-p funobj frame-map + :protect-registers protect-registers)))) + ((member source +boolean-modes+) + (let ((tmp (chose-free-register protect-registers)) + (label (gensym "store-lexical-bool-"))) + (append `((:movl :edi ,tmp)) + (list (make-branch-on-boolean source label :invert t)) + `((,*compiler-local-segment-prefix* + :movl (:edi ,(global-constant-offset 't-symbol)) ,tmp)) + (list label) + (make-store-lexical binding tmp shared-reference-p funobj frame-map + :protect-registers protect-registers)))) + ((not (bindingp source)) + (error "Unknown source for store-lexical: ~S" source)) + ((binding-singleton source) + (assert (not shared-reference-p)) + (let ((value (car (binding-singleton source)))) + (etypecase value + (movitz-fixnum + (let ((immediate (movitz-immediate-value value))) + (if (integerp location) + (let ((tmp (chose-free-register protect-registers))) + (append (make-immediate-move immediate tmp) + `((:movl ,tmp (:ebp ,(stack-frame-offset location)))))) + #+ignore (if (= 0 immediate) + (let ((tmp (chose-free-register protect-registers))) + `((:xorl ,tmp ,tmp) + (:movl ,tmp (:ebp ,(stack-frame-offset location))))) + `((:movl ,immediate (:ebp ,(stack-frame-offset location))))) + (ecase (operator location) + ((:argument-stack) + `((:movl ,immediate (:ebp ,(argument-stack-offset binding))))) + ((:eax :ebx :ecx :edx) + (make-immediate-move immediate location)) + ((:untagged-fixnum-ecx) + (make-immediate-move (movitz-fixnum-value value) :ecx)))))) + (movitz-character + (let ((immediate (movitz-immediate-value value))) + (if (integerp location) + (let ((tmp (chose-free-register protect-registers))) + (append (make-immediate-move immediate tmp) + `((:movl ,tmp (:ebp ,(stack-frame-offset location)))))) + (ecase (operator location) + ((:argument-stack) + `((:movl ,immediate (:ebp ,(argument-stack-offset binding))))) + ((:eax :ebx :ecx :edx) + (make-immediate-move immediate location)))))) + (movitz-heap-object + (etypecase location + ((member :eax :ebx :edx) + (make-load-constant value location funobj frame-map)) + (integer + (let ((tmp (chose-free-register protect-registers))) + (append (make-load-constant value tmp funobj frame-map) + (make-store-lexical binding tmp shared-reference-p + funobj frame-map + :protect-registers protect-registers)))) + ((eql :untagged-fixnum-ecx) + (check-type value movitz-bignum) + (let ((immediate (movitz-bignum-value value))) + (check-type immediate (unsigned-byte 32)) + (make-immediate-move immediate :ecx))) + ))))) + (t (error "Generalized lexb source for store-lexical not implemented: ~S" source))))))))))
(defun finalize-code (code funobj frame-map) ;; (print-code 'to-be-finalized code)