Update of /project/movitz/cvsroot/movitz
In directory common-lisp.net:/tmp/cvs-serv7611
Modified Files:
compiler.lisp
Log Message:
Quite a bit of cruft regarding register allocation etc. Still more
work to do here, but I don't have time for it right now..
Date: Wed Jun 9 10:26:00 2004
Author: ffjeld
Index: movitz/compiler.lisp
diff -u movitz/compiler.lisp:1.63 movitz/compiler.lisp:1.64
--- movitz/compiler.lisp:1.63 Tue Jun 8 01:14:15 2004
+++ movitz/compiler.lisp Wed Jun 9 10:26:00 2004
@@ -8,7 +8,7 @@
;;;; Created at: Wed Oct 25 12:30:49 2000
;;;; Distribution: See the accompanying file COPYING.
;;;;
-;;;; $Id: compiler.lisp,v 1.63 2004/06/08 08:14:15 ffjeld Exp $
+;;;; $Id: compiler.lisp,v 1.64 2004/06/09 17:26:00 ffjeld Exp $
;;;;
;;;;------------------------------------------------------------------
@@ -471,6 +471,9 @@
binding-usage))))
toplevel-funobj)
+(defmethod (setf borrowed-bindings) :before (x y)
+ (break "About to set borroweds for ~S to ~S." y x))
+
(defun resolve-borrowed-bindings (toplevel-funobj)
"For <funobj>'s code, for every non-local binding used we create
a borrowing-binding in the funobj-env. This process must be done
@@ -479,23 +482,7 @@
(check-type toplevel-funobj movitz-funobj)
(let ((function-binding-usage ()))
(labels ((process-binding (funobj binding usages)
- (typecase binding
- (forwarding-binding
- (setf (forwarding-binding-target binding)
- (process-binding funobj (forwarding-binding-target binding) usages)))
- (function-binding
- (dolist (usage usages)
- (pushnew usage
- (getf (sub-function-binding-usage (function-binding-parent binding))
- binding))
- (pushnew usage (getf function-binding-usage binding)))))
- (cond
- ((typep binding 'constant-object-binding)
- binding)
- ((eq funobj (binding-funobj binding))
- binding)
- (t #+ignore (warn "binding ~S is not local to ~S [~S])) .." binding funobj
- (mapcar #'borrowed-binding-target (borrowed-bindings funobj)))
+ (if (not (eq funobj (binding-funobj binding)))
(let ((borrowing-binding
(or (find binding (borrowed-bindings funobj)
:key #'borrowed-binding-target)
@@ -504,13 +491,39 @@
:name (binding-name binding)
:target-binding binding))
(borrowed-bindings funobj))))))
+ ;; We don't want to borrow a forwarding-binding..
+ (when (typep (borrowed-binding-target borrowing-binding)
+ 'forwarding-binding)
+ (change-class (borrowed-binding-target borrowing-binding)
+ 'located-binding))
+ #+ignore
+ (warn "binding ~S of ~S is not local to ~S, replacing with ~S of ~S."
+ binding (binding-env binding) funobj
+ borrowing-binding (binding-env borrowing-binding))
(pushnew borrowing-binding
(getf (binding-lended-p binding) :lended-to))
(dolist (usage usages)
(pushnew usage (borrowed-binding-usage borrowing-binding)))
- borrowing-binding))))
+ borrowing-binding)
+ ;; Binding is local to this funobj
+ (typecase binding
+ (forwarding-binding
+ (setf (forwarding-binding-target binding)
+ (process-binding funobj (forwarding-binding-target binding) usages)))
+ (function-binding
+ (dolist (usage usages)
+ (pushnew usage
+ (getf (sub-function-binding-usage (function-binding-parent binding))
+ binding))
+ (pushnew usage (getf function-binding-usage binding))))
+ (t binding))))
(resolve-sub-funobj (funobj sub-funobj)
(dolist (binding-we-lend (borrowed-bindings (resolve-funobj-borrowing sub-funobj)))
+ #+ignore
+ (warn "Lending from ~S to ~S: ~S <= ~S"
+ funobj sub-funobj
+ (borrowed-binding-target binding-we-lend)
+ binding-we-lend)
(process-binding funobj
(borrowed-binding-target binding-we-lend)
(borrowed-binding-usage binding-we-lend))))
@@ -562,7 +575,8 @@
;;; (multiple-value-bind (toplevel-funobj function-binding-usage)
;;; (resolve-borrowed-bindings toplevel-funobj)
(assert (null (borrowed-bindings toplevel-funobj)) ()
- "Can't deal with toplevel closures yet.")
+ "Can't deal with toplevel closures yet. Borrowed: ~S"
+ (borrowed-bindings toplevel-funobj))
(setf (movitz-funobj-extent toplevel-funobj) :indefinite-extent)
(let ((sub-funobj-index 0))
(loop for (function-binding usage) on function-binding-usage by #'cddr
@@ -2371,7 +2385,7 @@
(list new-value)
`(let ((,(car stores) (progn
(assert (not (new-binding-located-p ,binding-var ,getter)))
- (check-type ,new-value (or keyword (integer 0 *)))
+ (check-type ,new-value (or keyword binding (integer 0 *)))
(acons ,binding-var ,new-value ,getter))))
,setter
,new-value)
@@ -2573,27 +2587,31 @@
free-so-far)))
((:load-constant :load-lexical :store-lexical :cons-get :endp :incf-lexvar :init-lexvar)
(assert (gethash (instruction-is i) *extended-code-expanders*))
- (unless (can-expand-extended-p i frame-map)
- (return (values nil t)))
- (let ((exp (expand-extended-code i funobj frame-map)))
- (when (tree-search exp '(:call :local-function-init))
- (setf free-so-far
- (remove-if (lambda (r)
- (not (eq r :push)))
- free-so-far)))
- (setf free-so-far
- (remove-if (lambda (r)
- (and (not (eq r :push))
- (or (tree-search exp r)
- (tree-search exp (register32-to-low8 r)))))
- free-so-far))))
+ (cond
+ ((and (instruction-is i :init-lexvar) ; special case..
+ (typep (second i) 'forwarding-binding)))
+ (t (unless (can-expand-extended-p i frame-map)
+ ;; (warn "can't expand ~A from ~A" i frame-map)
+ (return (values nil t)))
+ (let ((exp (expand-extended-code i funobj frame-map)))
+ (when (tree-search exp '(:call :local-function-init))
+ (setf free-so-far
+ (remove-if (lambda (r)
+ (not (eq r :push)))
+ free-so-far)))
+ (setf free-so-far
+ (remove-if (lambda (r)
+ (and (not (eq r :push))
+ (or (tree-search exp r)
+ (tree-search exp (register32-to-low8 r)))))
+ free-so-far))))))
((:local-function-init)
(destructuring-bind (binding)
(cdr i)
(unless (typep binding 'funobj-binding)
(return nil))))
- (t (warn "Dist ~D stopped by ~A"
- distance i)
+ (t #+ignore (warn "Dist ~D stopped by ~A"
+ distance i)
(return nil)))))
;; do (warn "after ~A: ~A" i free-so-far)
finally (return free-so-far)))
@@ -2605,13 +2623,13 @@
(let* ((count-init-pc (gethash binding var-counts))
(count (car count-init-pc))
(init-pc (cdr count-init-pc)))
- ;; (warn "b ~S: count: ~D, init-pc: ~{~&~A~}" binding count init-pc)
(cond
((binding-lended-p binding)
;; We can't lend a register.
(values nil :never))
((and (= 1 count)
init-pc)
+ ;; (warn "b ~S: count: ~D, init-pc: ~{~&~A~}" binding count init-pc)
(assert (instruction-is (first init-pc) :init-lexvar))
(destructuring-bind (init-binding &key init-with-register init-with-type
protect-registers protect-carry)
@@ -2620,8 +2638,9 @@
(assert (eq binding init-binding))
(let* ((load-instruction
(find-if (lambda (i)
- (member binding (find-read-bindings i)
- :test #'binding-eql))
+ (and (not (instruction-is i :init-lexvar))
+ (member binding (find-read-bindings i)
+ :test #'eq)))
(cdr init-pc)
:end 15))
(binding-destination (third load-instruction))
@@ -2674,7 +2693,7 @@
"Iterate over CODE, and take note in the hash-table VAR-COUNTER which ~
variables CODE references that are lexically bound in ENV."
(check-type function-env function-env)
- ;; (format t "~{~&~S~}" code)
+ ;; (print-code 'discover code)
(let ((var-counter (make-hash-table :test #'eq :size 40)))
(labels ((take-note-of-binding (binding &optional storep init-pc)
(let ((count-init-pc (or (gethash binding var-counter)
@@ -2685,17 +2704,17 @@
(setf (cdr count-init-pc) init-pc))
(unless storep
(incf (car count-init-pc))))
+ #+ignore
(when (typep binding 'forwarding-binding)
- (take-note-of-binding (forwarding-binding-target binding))))
+ (take-note-of-binding (forwarding-binding-target binding) storep)))
(do-discover-variables (code env)
(loop for pc on code as instruction in code
when (listp instruction)
do (flet ((lend-lexical (borrowing-binding dynamic-extent-p)
(let ((lended-binding
(borrowed-binding-target borrowing-binding)))
- (when (typep lended-binding 'forwarding-binding)
- (setf lended-binding
- (change-class lended-binding 'located-binding)))
+ (assert (not (typep lended-binding 'forwarding-binding)) ()
+ "Can't lend a forwarding-binding.")
(pushnew lended-binding
(potentially-lended-bindings function-env))
(take-note-of-binding lended-binding)
@@ -2724,7 +2743,10 @@
(cdr instruction)
(declare (ignore protect-registers protect-carry init-with-type))
(when init-with-register
- (take-note-of-binding binding t pc))))
+ (take-note-of-binding binding t pc)
+ (when (and (typep init-with-register 'binding)
+ #+ignore (not (typep binding 'forwarding-binding)))
+ (take-note-of-binding init-with-register)))))
(t (mapcar #'take-note-of-binding
(find-read-bindings instruction))
(let ((store-binding (find-written-binding-and-type instruction)))
@@ -2765,7 +2787,12 @@
((not (typep binding 'lexical-binding)))
((typep binding 'lambda-binding))
((typep binding 'constant-object-binding))
- ((typep binding 'forwarding-binding))
+ ((typep binding 'forwarding-binding)
+ ;; Immediately "assign" to target.
+ (when (plusp (or (car (gethash binding var-counts)) 0))
+ (setf (new-binding-location binding frame-map)
+ (forwarding-binding-target binding)))
+ t)
((typep binding 'borrowed-binding))
((typep binding 'funobj-binding))
((and (typep binding 'fixed-required-function-argument)
@@ -2778,7 +2805,7 @@
(unless (or (movitz-env-get variable 'ignore nil env nil)
(movitz-env-get variable 'ignorable nil env nil)
(typep binding 'hidden-rest-function-argument))
- (warn "Unused variable: ~S" variable)))))
+ (warn "Unused variable: ~S" binding)))))
collect binding))
(bindings-fun-arg-sorted
(when (eq env function-env)
@@ -2919,7 +2946,7 @@
;; do (warn "bind: ~S: ~S" binding (eq function-env (find-function-env env funobj)))
when (sub-env-p env function-env)
do (assign-env-bindings (binding-env binding)))
- ;; (warn "Frame-map:~{ ~A~}" frame-map)
+ ;; (warn "Frame-map:~{ ~A~}" frame-map)
frame-map)))
@@ -3418,6 +3445,7 @@
(defun finalize-code (code funobj frame-map)
;; (print-code 'to-be-finalized code)
+ ;; (warn "frame-map: ~A" frame-map)
(labels ((actual-binding (b)
(if (typep b 'borrowed-binding)
(borrowed-binding-target b)
@@ -3481,92 +3509,92 @@
funobj frame-map)))))
(t ;; (warn "finalizing ~S" instruction)
- (case (first instruction)
- ((:locally :globally)
- (destructuring-bind (sub-instr)
- (cdr instruction)
- (let ((pf (ecase (first instruction)
- (:locally *compiler-local-segment-prefix*)
- (:globally *compiler-global-segment-prefix*))))
- (list (fix-edi-offset
- (cond
- ((atom sub-instr)
- sub-instr)
- ((consp (car sub-instr))
- (list* (append pf (car sub-instr))
- (cdr sub-instr)))
- (t (list* pf sub-instr))))))))
- (:declare-label-set nil)
- (:local-function-init
- (destructuring-bind (function-binding)
- (operands instruction)
- #+ignore (warn "local-function-init: init ~S at ~S"
- function-binding
- (new-binding-location function-binding frame-map))
- (finalize-code
- (let* ((sub-funobj (function-binding-funobj function-binding))
- (lend-code (loop for bb in (borrowed-bindings sub-funobj)
- append (make-lend-lexical bb :edx nil))))
- (cond
- ((typep function-binding 'funobj-binding)
- nil)
- ((null lend-code)
- (warn "null lending")
- (append (make-load-constant sub-funobj :eax funobj frame-map)
- (make-store-lexical function-binding :eax nil frame-map)))
- (t (append (make-load-constant sub-funobj :eax funobj frame-map)
- `((:movl (:edi ,(global-constant-offset 'copy-funobj)) :esi)
- (:call (:esi ,(bt:slot-offset 'movitz-funobj 'code-vector%1op)))
- (:movl :eax :edx))
- (make-store-lexical function-binding :eax nil frame-map)
- lend-code))))
- funobj frame-map)))
- (:load-lambda
- (destructuring-bind (function-binding register)
- (operands instruction)
- ;; (warn "load-lambda not completed for ~S" function-binding)
- (finalize-code
- (let* ((sub-funobj (function-binding-funobj function-binding))
- (lend-code (loop for bb in (borrowed-bindings sub-funobj)
- appending
- (make-lend-lexical bb :edx nil))))
- (cond
- ((null lend-code)
- ;; (warn "null lambda lending")
- (append (make-load-constant sub-funobj register funobj frame-map)))
- (t (append (make-load-constant sub-funobj :eax funobj frame-map)
- `((:movl (:edi ,(global-constant-offset 'copy-funobj)) :esi)
- (:call (:esi ,(bt:slot-offset 'movitz-funobj 'code-vector%1op)))
- (:movl :eax :edx))
- lend-code
- `((:movl :edx ,register))))))
- funobj frame-map)))
- (:load-constant
- (destructuring-bind (object result-mode &key (op :movl))
- (cdr instruction)
- (make-load-constant object result-mode funobj frame-map :op op)))
- (:lexical-control-transfer
- (destructuring-bind (return-code return-mode from-env to-env &optional to-label)
- (cdr instruction)
- (declare (ignore return-code))
- (let ((x (apply #'make-compiled-lexical-control-transfer
- nil
- return-mode from-env to-env
- (when to-label (list to-label)))))
- (finalize-code x funobj frame-map))))
- (:call-lexical
- (destructuring-bind (binding num-args)
- (operands instruction)
- (append (etypecase binding
- (closure-binding
- (make-load-lexical (ensure-local-binding binding)
- :esi funobj nil frame-map
- :tmp-register :edx))
- (funobj-binding
- (make-load-constant (function-binding-funobj binding)
- :esi funobj frame-map)))
- (make-compiled-funcall-by-esi num-args))))
- (t (expand-extended-code instruction funobj frame-map)))))))))
+ (case (first instruction)
+ ((:locally :globally)
+ (destructuring-bind (sub-instr)
+ (cdr instruction)
+ (let ((pf (ecase (first instruction)
+ (:locally *compiler-local-segment-prefix*)
+ (:globally *compiler-global-segment-prefix*))))
+ (list (fix-edi-offset
+ (cond
+ ((atom sub-instr)
+ sub-instr)
+ ((consp (car sub-instr))
+ (list* (append pf (car sub-instr))
+ (cdr sub-instr)))
+ (t (list* pf sub-instr))))))))
+ (:declare-label-set nil)
+ (:local-function-init
+ (destructuring-bind (function-binding)
+ (operands instruction)
+ #+ignore (warn "local-function-init: init ~S at ~S"
+ function-binding
+ (new-binding-location function-binding frame-map))
+ (finalize-code
+ (let* ((sub-funobj (function-binding-funobj function-binding))
+ (lend-code (loop for bb in (borrowed-bindings sub-funobj)
+ append (make-lend-lexical bb :edx nil))))
+ (cond
+ ((typep function-binding 'funobj-binding)
+ nil)
+ ((null lend-code)
+ (warn "null lending")
+ (append (make-load-constant sub-funobj :eax funobj frame-map)
+ (make-store-lexical function-binding :eax nil frame-map)))
+ (t (append (make-load-constant sub-funobj :eax funobj frame-map)
+ `((:movl (:edi ,(global-constant-offset 'copy-funobj)) :esi)
+ (:call (:esi ,(bt:slot-offset 'movitz-funobj 'code-vector%1op)))
+ (:movl :eax :edx))
+ (make-store-lexical function-binding :eax nil frame-map)
+ lend-code))))
+ funobj frame-map)))
+ (:load-lambda
+ (destructuring-bind (function-binding register)
+ (operands instruction)
+ ;; (warn "load-lambda not completed for ~S" function-binding)
+ (finalize-code
+ (let* ((sub-funobj (function-binding-funobj function-binding))
+ (lend-code (loop for bb in (borrowed-bindings sub-funobj)
+ appending
+ (make-lend-lexical bb :edx nil))))
+ (cond
+ ((null lend-code)
+ ;; (warn "null lambda lending")
+ (append (make-load-constant sub-funobj register funobj frame-map)))
+ (t (append (make-load-constant sub-funobj :eax funobj frame-map)
+ `((:movl (:edi ,(global-constant-offset 'copy-funobj)) :esi)
+ (:call (:esi ,(bt:slot-offset 'movitz-funobj 'code-vector%1op)))
+ (:movl :eax :edx))
+ lend-code
+ `((:movl :edx ,register))))))
+ funobj frame-map)))
+ (:load-constant
+ (destructuring-bind (object result-mode &key (op :movl))
+ (cdr instruction)
+ (make-load-constant object result-mode funobj frame-map :op op)))
+ (:lexical-control-transfer
+ (destructuring-bind (return-code return-mode from-env to-env &optional to-label)
+ (cdr instruction)
+ (declare (ignore return-code))
+ (let ((x (apply #'make-compiled-lexical-control-transfer
+ nil
+ return-mode from-env to-env
+ (when to-label (list to-label)))))
+ (finalize-code x funobj frame-map))))
+ (:call-lexical
+ (destructuring-bind (binding num-args)
+ (operands instruction)
+ (append (etypecase binding
+ (closure-binding
+ (make-load-lexical (ensure-local-binding binding)
+ :esi funobj nil frame-map
+ :tmp-register :edx))
+ (funobj-binding
+ (make-load-constant (function-binding-funobj binding)
+ :esi funobj frame-map)))
+ (make-compiled-funcall-by-esi num-args))))
+ (t (expand-extended-code instruction funobj frame-map)))))))))
(defun image-t-symbol-p (x)
@@ -5801,17 +5829,32 @@
(assert init-with-type)
(values binding init-with-type))))
+(define-find-read-bindings :init-lexvar (binding &key init-with-register &allow-other-keys)
+ (declare (ignore binding))
+ (when (typep init-with-register 'binding)
+ (list init-with-register)))
+
(define-extended-code-expander :init-lexvar (instruction funobj frame-map)
(destructuring-bind (binding &key protect-registers protect-carry
init-with-register init-with-type)
(cdr instruction)
(declare (ignore protect-carry)) ; nothing modifies carry anyway.
- (assert (eq binding (ensure-local-binding binding funobj)))
+ ;; (assert (eq binding (ensure-local-binding binding funobj)))
+ (assert (eq funobj (binding-funobj binding)))
(cond
((not (new-binding-located-p binding frame-map))
(unless (or (movitz-env-get (binding-name binding) 'ignore nil (binding-env binding))
- (movitz-env-get (binding-name binding) 'ignorable nil (binding-env binding)))
- (warn "Unused variable: ~S." (binding-name binding))))
+ (movitz-env-get (binding-name binding) 'ignorable nil (binding-env binding))
+ #+ignore
+ (labels ((recursive-located-p (b)
+ (or (new-binding-located-p b frame-map)
+ (and (typep binding 'forwarding-binding)
+ (recursive-located-p (forwarding-binding-target b))))))
+ (recursive-located-p binding)))
+ (warn "Unused variable: ~S." binding)))
+ ((typep binding 'forwarding-binding)
+ ;; No need to do any initialization because the target will be initialized.
+ nil)
(t (when (movitz-env-get (binding-name binding) 'ignore nil (binding-env binding))
(warn "Variable ~S used while declared ignored." (binding-name binding)))
(append
@@ -5835,24 +5878,34 @@
(make-compiled-funcall-by-symbol 'muerte.cl:copy-list 1 funobj)))))
(cond
((binding-lended-p binding)
- (let ((cons-position (getf (binding-lended-p binding)
- :stack-cons-location))
- (tmp-register (find-if (lambda (r)
- (and (not (member r protect-registers))
- (not (eq r init-with-register))))
- '(:edx :ecx :ebx :eax)))
- (init-register (or init-with-register :edi)))
+ (let* ((cons-position (getf (binding-lended-p binding)
+ :stack-cons-location))
+ (init-register (etypecase init-with-register
+ (lexical-binding
+ (or (find-if (lambda (r)
+ (not (member r protect-registers)))
+ '(:edx :ebx :eax))
+ (error "Unable to get a register.")))
+ (keyword init-with-register)
+ (null :edi)))
+ (tmp-register (find-if (lambda (r)
+ (and (not (member r protect-registers))
+ (not (eq r init-register))))
+ '(:edx :ebx :eax))))
(when init-with-register
(assert (not (null init-with-type))))
(assert tmp-register () ; solve this with push eax .. pop eax if ever needed.
"Unable to find a tmp-register for ~S." instruction)
- `((:leal (:ebp ,(1+ (stack-frame-offset (1+ cons-position))))
- ,tmp-register)
- (:movl :edi (,tmp-register 3)) ; cdr
- (:movl ,init-register (,tmp-register -1)) ; car
- (:movl ,tmp-register
- (:ebp ,(stack-frame-offset
- (new-binding-location binding frame-map)))))))
+ (append (when (typep init-with-register 'binding)
+ (make-load-lexical init-with-register init-register funobj nil frame-map
+ :protect-registers protect-registers))
+ `((:leal (:ebp ,(1+ (stack-frame-offset (1+ cons-position))))
+ ,tmp-register)
+ (:movl :edi (,tmp-register 3)) ; cdr
+ (:movl ,init-register (,tmp-register -1)) ; car
+ (:movl ,tmp-register
+ (:ebp ,(stack-frame-offset
+ (new-binding-location binding frame-map))))))))
(init-with-register
(make-store-lexical binding init-with-register nil frame-map))))))))