Update of /project/movitz/cvsroot/movitz
In directory common-lisp.net:/tmp/cvs-serv6248
Modified Files:
compiler.lisp
Log Message:
Many fixes to the compiler. Basic change is that LET init-forms are
compiled with compile-form-unprotected, and that
compile-lexical-variable and compile-self-evaluating return binding
only as "returns", not in the form of "code".
Date: Sun Aug 28 23:03:43 2005
Author: ffjeld
Index: movitz/compiler.lisp
diff -u movitz/compiler.lisp:1.160 movitz/compiler.lisp:1.161
--- movitz/compiler.lisp:1.160 Fri Aug 26 23:42:08 2005
+++ movitz/compiler.lisp Sun Aug 28 23:03:41 2005
@@ -8,7 +8,7 @@
;;;; Created at: Wed Oct 25 12:30:49 2000
;;;; Distribution: See the accompanying file COPYING.
;;;;
-;;;; $Id: compiler.lisp,v 1.160 2005/08/26 21:42:08 ffjeld Exp $
+;;;; $Id: compiler.lisp,v 1.161 2005/08/28 21:03:41 ffjeld Exp $
;;;;
;;;;------------------------------------------------------------------
@@ -1510,6 +1510,7 @@
(defun optimize-code (unoptimized-code &rest args)
+ #+ignore (print-code 'to-optimize unoptimized-code)
(if (not *compiler-do-optimize*)
unoptimized-code
(apply #'optimize-code-internal
@@ -2883,7 +2884,7 @@
(let* ((count-init-pc (gethash binding var-counts))
(count (car count-init-pc))
(init-pc (second count-init-pc)))
- ;; (warn "b ~S: count: ~D, init-pc: ~{~&~A~}" binding count init-pc)
+ #+ignore (warn "b ~S: count: ~D, init-pc: ~{~&~A~}" binding count init-pc)
(cond
((and (not *compiler-allow-transients*)
(typep binding 'function-argument))
@@ -2972,7 +2973,7 @@
(take-note-of-binding (binding &optional storep init-pc)
(let ((count-init-pc (or (gethash binding var-counter)
(setf (gethash binding var-counter)
- (list 0 nil t)))))
+ (list 0 nil (not storep))))))
(when init-pc
(assert (not (second count-init-pc)))
(setf (second count-init-pc) init-pc))
@@ -2980,10 +2981,17 @@
(unless (eq binding (binding-target binding))
;; (break "ewfew: ~S" (gethash (binding-target binding) var-counter))
(take-note-of-binding (binding-target binding)))
+ (setf (third count-init-pc) t)
(incf (car count-init-pc))))
#+ignore
(when (typep binding 'forwarding-binding)
(take-note-of-binding (forwarding-binding-target binding) storep)))
+ (take-note-of-init (binding init-pc)
+ (let ((count-init-pc (or (gethash binding var-counter)
+ (setf (gethash binding var-counter)
+ (list 0 nil nil)))))
+ (assert (not (second count-init-pc)))
+ (setf (second count-init-pc) init-pc)))
(do-discover-variables (code env)
(loop for pc on code as instruction in code
when (listp instruction)
@@ -3028,11 +3036,14 @@
protect-registers protect-carry)
(cdr instruction)
(declare (ignore protect-registers protect-carry init-with-type))
- (when init-with-register
+ (cond
+ ((not init-with-register)
+ (take-note-of-init binding pc))
+ (init-with-register
(take-note-of-binding binding t pc)
(when (and (typep init-with-register 'binding)
(not (typep binding 'forwarding-binding))) ; XXX
- (take-note-of-binding init-with-register)))))
+ (take-note-of-binding init-with-register))))))
(t (mapcar #'take-note-of-binding
(find-read-bindings instruction))
(mapcar #'record-binding-used ; This is just concerning "unused variable"
@@ -3072,34 +3083,35 @@
(let* ((stack-frame-position (env-floor env))
(bindings-to-locate
(loop for binding being the hash-keys of var-counts
- when (eq env (binding-extent-env binding))
- unless (let ((variable (binding-name binding)))
- (cond
- ((not (typep binding 'lexical-binding)))
- ((typep binding 'lambda-binding))
- ((typep binding 'constant-object-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)
- (plusp (or (car (gethash binding var-counts)) 0)))
- (prog1 nil ; may need lending-cons
- (setf (new-binding-location binding frame-map)
- `(:argument-stack ,(function-argument-argnum binding)))))
- ((unless (or (movitz-env-get variable 'ignore nil
- (binding-env binding) nil)
- (movitz-env-get variable 'ignorable nil
- (binding-env binding) nil)
- (typep binding 'hidden-rest-function-argument)
- (third (gethash binding var-counts)))
- (warn "Unused variable: ~S"
- (binding-name binding))))
- ((not (plusp (or (car (gethash binding var-counts)) 0))))))
+ when
+ (and (eq env (binding-extent-env binding))
+ (not (let ((variable (binding-name binding)))
+ (cond
+ ((not (typep binding 'lexical-binding)))
+ ((typep binding 'lambda-binding))
+ ((typep binding 'constant-object-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)
+ (plusp (or (car (gethash binding var-counts)) 0)))
+ (prog1 nil ; may need lending-cons
+ (setf (new-binding-location binding frame-map)
+ `(:argument-stack ,(function-argument-argnum binding)))))
+ ((unless (or (movitz-env-get variable 'ignore nil
+ (binding-env binding) nil)
+ (movitz-env-get variable 'ignorable nil
+ (binding-env binding) nil)
+ (typep binding 'hidden-rest-function-argument)
+ (third (gethash binding var-counts)))
+ (warn "Unused variable: ~S"
+ (binding-name binding))))
+ ((not (plusp (or (car (gethash binding var-counts)) 0))))))))
collect binding))
(bindings-fun-arg-sorted
(when (eq env function-env)
@@ -3371,6 +3383,7 @@
(etypecase x
(symbol x)
(cons (car x))
+ (constant-object-binding :constant-binding)
(lexical-binding :lexical-binding)
(dynamic-binding :dynamic-binding)))
@@ -3512,7 +3525,8 @@
(when (movitz-env-get (binding-name binding) 'ignore nil (binding-env binding))
(warn "The variable ~S is used even if it was declared ignored."
(binding-name binding)))
- (let ((protect-registers (cons :edx protect-registers)))
+ (let ((binding (ensure-local-binding binding funobj))
+ (protect-registers (cons :edx protect-registers)))
(labels ((chose-tmp-register (&optional preferred)
(or tmp-register
(unless (member preferred protect-registers)
@@ -3673,7 +3687,9 @@
(t (make-result-and-returns-glue
result-mode :eax
(install-for-single-value binding binding-location :eax t)))))
- (t (case (result-mode-type result-mode)
+ (t (when (integerp result-mode)
+ (break "result-mode: ~S" result-mode))
+ (case (result-mode-type result-mode)
((:single-value :eax :ebx :ecx :edx :esi :esp :ebp)
(install-for-single-value binding binding-location
(single-value-register result-mode) nil))
@@ -3816,6 +3832,14 @@
(t `((:movl ,source :eax)
(,*compiler-global-segment-prefix*
:call (:edi ,(global-constant-offset 'unbox-u32))))))))))
+ ((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))
+ (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)
@@ -4803,8 +4827,9 @@
`((:init-lexvar ,binding)
,@(when supplied-p-var
`((:init-lexvar ,supplied-p-binding)))
- ,@(compiler-call #'compile-self-evaluating
- :form (eval-form (optional-function-argument-init-form binding) env nil)
+ ,@(compiler-call #'compile-form
+ :form (list 'muerte.cl:quote
+ (eval-form (optional-function-argument-init-form binding) env nil))
:funobj funobj
:env env
:result-mode :ebx)
@@ -4912,8 +4937,10 @@
`((:init-lexvar ,supplied-p-binding
:init-with-register :edi
:init-with-type null)))
- (compiler-call #'compile-self-evaluating
- :form (eval-form (optional-function-argument-init-form binding) env)
+ (compiler-call #'compile-form
+ :form (list 'muerte.cl:quote
+ (eval-form (optional-function-argument-init-form binding)
+ env))
:env env
:funobj funobj
:result-mode :eax)
@@ -5115,6 +5142,11 @@
(lexical-binding
(values (append code
`((:load-lexical ,returns-provided ,desired-result)))
+ desired-result))
+ (constant-object-binding
+ (values (if (eq *movitz-nil* (constant-object returns-provided))
+ nil
+ `((:jmp ',(operands desired-result))))
desired-result))))
(:boolean-branch-on-false
(etypecase (operator returns-provided)
@@ -5144,9 +5176,14 @@
(lexical-binding
(values (append code
`((:load-lexical ,returns-provided ,desired-result)))
+ desired-result))
+ (constant-object-binding
+ (values (if (not (eq *movitz-nil* (constant-object returns-provided)))
+ nil
+ `((:jmp ',(operands desired-result))))
desired-result))))
(:untagged-fixnum-ecx
- (case returns-provided
+ (case (result-mode-type returns-provided)
(:untagged-fixnum-ecx
(values code :untagged-fixnum-ecx))
((:eax :single-value :multiple-values :function)
@@ -5155,10 +5192,19 @@
:call (:edi ,(global-constant-offset 'unbox-u32)))))
:untagged-fixnum-ecx))
(:ecx
+ ;; In theory (at least..) ECX can only hold non-pointers, so don't check.
(values (append code
- `((:testb ,+movitz-fixnum-zmask+ :cl)
- (:jnz '(:sub-program (not-an-integer) (:int 107))) ;
- (:sarl ,+movitz-fixnum-shift+ :ecx)))
+ `((:shrl ,+movitz-fixnum-shift+ :ecx)))
+ :untagged-fixnum-ecx))
+ ((:ebx :edx)
+ (values (append code
+ `((:movl ,returns-provided :eax)
+ (,*compiler-global-segment-prefix*
+ :call (:edi ,(global-constant-offset 'unbox-u32)))))
+ :untagged-fixnum-ecx))
+ (:lexical-binding
+ (values (append code
+ `((:load-lexical ,returns-provided :untagged-fixnum-ecx)))
:untagged-fixnum-ecx))))
((:single-value :eax)
(cond
@@ -5226,11 +5272,6 @@
(values (append code `((:load-lexical ,returns-provided ,desired-result)))
desired-result))
(t (case (operator returns-provided)
- #+ignore
- (:untagged-fixnum-eax
- (values (append code
- `((:leal ((:eax 4)) ,desired-result)))
- desired-result))
(:nothing
(values (append code
`((:movl :edi ,desired-result)))
@@ -5337,7 +5378,14 @@
:multiple-values)))))
(unless new-returns-provided
(multiple-value-setq (new-code new-returns-provided glue-side-effects-p)
- (ecase (operator returns-provided)
+ (ecase (result-mode-type returns-provided)
+ (:constant-binding
+ (case (result-mode-type desired-result)
+ ((:eax :ebx :ecx :edx :push :lexical-binding)
+ (values (append code
+ `((:load-constant ,(constant-object returns-provided)
+ ,desired-result)))
+ desired-result))))
(#.+boolean-modes+
(make-result-and-returns-glue desired-result :eax
(make-result-and-returns-glue :eax returns-provided code
@@ -5900,6 +5948,12 @@
(:ignore
(compiler-values ()
:final-form binding))
+ (t (compiler-values ()
+ :code nil
+ :final-form binding
+ :returns binding
+ :functional-p t))
+ #+ignore
(t (let ((returns (ecase (result-mode-type result-mode)
((:function :multiple-values :eax)
:eax)
@@ -6037,13 +6091,15 @@
(compiler-values (self-eval)
:returns :nothing
:type nil))
- ((:eax :single-value :multiple-values :function)
- (compiler-values (self-eval)
- :code `((:load-lexical ,binding :eax))
- :returns :eax))
(t (compiler-values (self-eval)
- :code `((:load-lexical ,binding ,result-mode))
- :returns result-mode))))))
+ :returns binding))))))
+;;; ((:eax :single-value :multiple-values :function)
+;;; (compiler-values (self-eval)
+;;; :code `((:load-lexical ,binding :eax))
+;;; :returns :eax))
+;;; (t (compiler-values (self-eval)
+;;; :code `((:load-lexical ,binding ,result-mode))
+;;; :returns result-mode))))))
(define-compiler compile-implicit-progn (&all all &form forms &top-level-p top-level-p
&result-mode result-mode)
@@ -6738,7 +6794,7 @@
(destructuring-bind (object result-mode &key (op :movl))
(cdr instruction)
(when (and (eq op :movl) (typep result-mode 'binding))
- (check-type result-mode 'lexical-binding)
+ (check-type result-mode lexical-binding)
(values result-mode `(eql ,object)))))
(define-extended-code-expander :load-constant (instruction funobj frame-map)
@@ -6795,330 +6851,333 @@
(destination-location (if (or (not (bindingp destination))
(typep destination 'borrowed-binding))
destination
- (new-binding-location (binding-target destination) frame-map)))
+ (new-binding-location (binding-target destination)
+ frame-map
+ :default nil)))
(type0 (apply #'encoded-type-decode (binding-store-type term0)))
(type1 (apply #'encoded-type-decode (binding-store-type term1)))
(result-type (multiple-value-call #'encoded-integer-types-add
(values-list (binding-store-type term0))
(values-list (binding-store-type term1)))))
-;;; (warn "dest: ~S ~S"
-;;; (apply #'encoded-type-decode (binding-store-type destination))
-;;; result-type)
-;;; (when (binding-lended-p term0)
-;;; (warn "Add from lend0: ~S" term0))
-;;; (when (binding-lended-p term1)
-;;; (warn "Add from lend1: ~S" term1))
-;;; (when (and (bindingp destination)
-;;; (binding-lended-p destination))
-;;; (warn "Add for lended dest: ~S" destination))
-;;; (when (typep destination 'borrowed-binding)
-;;; (warn "Add for borrowed ~S" destination))
- (let ((loc0 (new-binding-location (binding-target term0) frame-map :default nil))
- (loc1 (new-binding-location (binding-target term1) frame-map :default nil)))
- #+ignore
- (warn "add: ~A for ~A" instruction result-type)
- #+ignore
- (warn "add for: ~S is ~A, from ~A/~A and ~A/~A."
- destination result-type
- term0 loc0
- term1 loc1)
- #+ignore
- (when (eql destination-location 9)
- (warn "add for: ~S/~S~%= ~A/~A in ~S~&~A/~A in ~S."
- destination destination-location
- term0 loc0 (binding-extent-env (binding-target term0))
- term1 loc1 (binding-extent-env (binding-target term1)))
- (print-code 'load-term1 (make-load-lexical term1 :eax funobj nil frame-map))
- (print-code 'load-dest (make-load-lexical destination :eax funobj nil frame-map)))
- (flet ((make-store (source destination)
- (cond
- ((eq source destination)
- nil)
- ((member destination '(:eax :ebx :ecx :edx))
- `((:movl ,source ,destination)))
- (t (make-store-lexical destination source nil funobj frame-map))))
- (make-default-add ()
- (when (movitz-subtypep result-type '(unsigned-byte 32))
- (warn "Defaulting u32 ADD: ~A/~S = ~A/~S + ~A/~S"
- destination-location
- destination
- loc0 term0
- loc1 term1))
- (append (cond
- ((type-specifier-singleton type0)
- (append (make-load-lexical term1 :eax funobj nil frame-map)
- (make-load-constant (car (type-specifier-singleton type0))
- :ebx funobj frame-map)))
- ((type-specifier-singleton type1)
- (append (make-load-lexical term0 :eax funobj nil frame-map)
- (make-load-constant (car (type-specifier-singleton type1))
- :ebx funobj frame-map)))
- ((and (eq :eax loc0) (eq :ebx loc1))
- nil)
- ((and (eq :ebx loc0) (eq :eax loc1))
- nil) ; terms order isn't important
- ((eq :eax loc1)
- (append
- (make-load-lexical term0 :ebx funobj nil frame-map)))
- (t (append
- (make-load-lexical term0 :eax funobj nil frame-map)
- (make-load-lexical term1 :ebx funobj nil frame-map))))
- `((:movl (:edi ,(global-constant-offset '+)) :esi))
- (make-compiled-funcall-by-esi 2)
- (etypecase destination
- (symbol
- (unless (eq destination :eax)
- `((:movl :eax ,destination))))
- (binding
- (make-store-lexical destination :eax nil funobj frame-map))))))
- (let ((constant0 (let ((x (type-specifier-singleton type0)))
- (when (and x (typep (car x) 'movitz-fixnum))
- (movitz-immediate-value (car x)))))
- (constant1 (let ((x (type-specifier-singleton type1)))
- (when (and x (typep (car x) 'movitz-fixnum))
- (movitz-immediate-value (car x))))))
- (cond
- ((type-specifier-singleton result-type)
- ;; (break "constant add: ~S" instruction)
- (make-load-constant (car (type-specifier-singleton result-type))
- destination funobj frame-map))
- ((movitz-subtypep type0 '(integer 0 0))
- (cond
- ((eql destination loc1)
- #+ignore (break "NOP add: ~S" instruction)
- nil)
- ((and (member destination-location '(:eax :ebx :ecx :edx))
- (member loc1 '(:eax :ebx :ecx :edx)))
- `((:movl ,loc1 ,destination-location)))
- ((integerp loc1)
- (make-load-lexical term1 destination-location funobj nil frame-map))
- #+ignore
- ((integerp destination-location)
- (make-store-lexical destination-location loc1 nil funobj frame-map))
- (t (break "Unknown X zero-add: ~S" instruction))))
- ((movitz-subtypep type1 '(integer 0 0))
- ;; (warn "zero-add ~S => ~S [~S]" loc0 destination-location result-type)
- (cond
- ((eql destination loc0)
- #+ignore (break "NOP add: ~S" instruction)
- nil)
- ((and (member destination-location '(:eax :ebx :ecx :edx))
- (member loc0 '(:eax :ebx :ecx :edx)))
- `((:movl ,loc0 ,destination-location)))
- ((integerp loc0)
- (make-load-lexical term0 destination-location funobj nil frame-map))
- #+ignore
- ((integerp destination-location)
- (make-store-lexical destination-location loc0 nil funobj frame-map))
- (t (break "Unknown Y zero-add: ~S" instruction))))
- ((and (movitz-subtypep type0 'fixnum)
- (movitz-subtypep type1 'fixnum)
- (movitz-subtypep result-type 'fixnum))
- (assert (not (and constant0 (zerop constant0))))
- (assert (not (and constant1 (zerop constant1))))
+ ;; A null location means the binding is unused, in which
+ ;; case there's no need to perform the addition.
+ (when destination-location
+ (let ((loc0 (new-binding-location (binding-target term0) frame-map :default nil))
+ (loc1 (new-binding-location (binding-target term1) frame-map :default nil)))
+ #+ignore
+ (warn "add: ~A for ~A" instruction result-type)
+ #+ignore
+ (warn "add for: ~S is ~A, from ~A/~A and ~A/~A."
+ destination result-type
+ term0 loc0
+ term1 loc1)
+ #+ignore
+ (when (eql destination-location 9)
+ (warn "add for: ~S/~S~%= ~A/~A in ~S~&~A/~A in ~S."
+ destination destination-location
+ term0 loc0 (binding-extent-env (binding-target term0))
+ term1 loc1 (binding-extent-env (binding-target term1)))
+ (print-code 'load-term1 (make-load-lexical term1 :eax funobj nil frame-map))
+ (print-code 'load-dest (make-load-lexical destination :eax funobj nil frame-map)))
+ (flet ((make-store (source destination)
+ (cond
+ ((eq source destination)
+ nil)
+ ((member destination '(:eax :ebx :ecx :edx))
+ `((:movl ,source ,destination)))
+ (t (make-store-lexical destination source nil funobj frame-map))))
+ (make-default-add ()
+ (when (movitz-subtypep result-type '(unsigned-byte 32))
+ (warn "Defaulting u32 ADD: ~A/~S = ~A/~S + ~A/~S"
+ destination-location
+ destination
+ loc0 term0
+ loc1 term1))
+ (append (cond
+ ((type-specifier-singleton type0)
+ (append (make-load-lexical term1 :eax funobj nil frame-map)
+ (make-load-constant (car (type-specifier-singleton type0))
+ :ebx funobj frame-map)))
+ ((type-specifier-singleton type1)
+ (append (make-load-lexical term0 :eax funobj nil frame-map)
+ (make-load-constant (car (type-specifier-singleton type1))
+ :ebx funobj frame-map)))
+ ((and (eq :eax loc0) (eq :ebx loc1))
+ nil)
+ ((and (eq :ebx loc0) (eq :eax loc1))
+ nil) ; terms order isn't important
+ ((eq :eax loc1)
+ (append
+ (make-load-lexical term0 :ebx funobj nil frame-map)))
+ (t (append
+ (make-load-lexical term0 :eax funobj nil frame-map)
+ (make-load-lexical term1 :ebx funobj nil frame-map))))
+ `((:movl (:edi ,(global-constant-offset '+)) :esi))
+ (make-compiled-funcall-by-esi 2)
+ (etypecase destination
+ (symbol
+ (unless (eq destination :eax)
+ `((:movl :eax ,destination))))
+ (binding
+ (make-store-lexical destination :eax nil funobj frame-map))))))
+ (let ((constant0 (let ((x (type-specifier-singleton type0)))
+ (when (and x (typep (car x) 'movitz-fixnum))
+ (movitz-immediate-value (car x)))))
+ (constant1 (let ((x (type-specifier-singleton type1)))
+ (when (and x (typep (car x) 'movitz-fixnum))
+ (movitz-immediate-value (car x))))))
(cond
- ((and (not (binding-lended-p (binding-target term0)))
- (not (binding-lended-p (binding-target term1)))
- (not (and (bindingp destination)
- (binding-lended-p (binding-target destination)))))
+ ((type-specifier-singleton result-type)
+ ;; (break "constant add: ~S" instruction)
+ (make-load-constant (car (type-specifier-singleton result-type))
+ destination funobj frame-map))
+ ((movitz-subtypep type0 '(integer 0 0))
(cond
- ((and constant0
- (equal loc1 destination-location))
- (cond
- ((member destination-location '(:eax :ebx :ecx :edx))
- `((:addl ,constant0 ,destination-location)))
- ((integerp loc1)
- `((:addl ,constant0 (:ebp ,(stack-frame-offset loc1)))))
- ((eq :argument-stack (operator loc1))
- `((:addl ,constant0
- (:ebp ,(argument-stack-offset (binding-target term1))))))
- (t (error "Don't know how to add this for loc1 ~S" loc1))))
- ((and constant0
- (integerp destination-location)
- (eql term1 destination-location))
- (break "untested")
- `((:addl ,constant0 (:ebp ,(stack-frame-offset destination-location)))))
- ((and constant0
- (integerp destination-location)
- (member loc1 '(:eax :ebx :ecx :edx)))
- (break "check this!")
- `((:addl ,constant0 ,loc1)
- (:movl ,loc1 (:ebp ,(stack-frame-offset destination-location)))))
- ((and (integerp loc0)
- (integerp loc1)
- (member destination-location '(:eax :ebx :ecx :edx)))
- (append `((:movl (:ebp ,(stack-frame-offset loc0)) ,destination-location)
- (:addl (:ebp ,(stack-frame-offset loc1)) ,destination-location))))
- ((and (integerp destination-location)
- (eql loc0 destination-location)
- constant1)
- `((:addl ,constant1 (:ebp ,(stack-frame-offset destination-location)))))
- ((and (integerp destination-location)
- (eql loc1 destination-location)
- constant0)
- `((:addl ,constant0 (:ebp ,(stack-frame-offset destination-location)))))
- ((and (member destination-location '(:eax :ebx :ecx :edx))
- (eq loc0 :untagged-fixnum-ecx)
- constant1)
- `((:leal ((:ecx ,+movitz-fixnum-factor+) ,constant1)
- ,destination-location)))
- ((and (member destination-location '(:eax :ebx :ecx :edx))
- (integerp loc1)
- constant0)
- `((:movl (:ebp ,(stack-frame-offset loc1)) ,destination-location)
- (:addl ,constant0 ,destination-location)))
+ ((eql destination loc1)
+ #+ignore (break "NOP add: ~S" instruction)
+ nil)
((and (member destination-location '(:eax :ebx :ecx :edx))
- (integerp loc0)
- constant1)
- `((:movl (:ebp ,(stack-frame-offset loc0)) ,destination-location)
- (:addl ,constant1 ,destination-location)))
- ((and (member destination-location '(:eax :ebx :ecx :edx))
- (integerp loc0)
- (member loc1 '(:eax :ebx :ecx :edx))
- (not (eq destination-location loc1)))
- `((:movl (:ebp ,(stack-frame-offset loc0)) ,destination-location)
- (:addl ,loc1 ,destination-location)))
- ((and (member destination-location '(:eax :ebx :ecx :edx))
- constant0
(member loc1 '(:eax :ebx :ecx :edx)))
- `((:leal (,loc1 ,constant0) ,destination-location)))
+ `((:movl ,loc1 ,destination-location)))
+ ((integerp loc1)
+ (make-load-lexical term1 destination funobj nil frame-map))
+ #+ignore
+ ((integerp destination-location)
+ (make-store-lexical destination-location loc1 nil funobj frame-map))
+ (t (break "Unknown X zero-add: ~S" instruction))))
+ ((movitz-subtypep type1 '(integer 0 0))
+ ;; (warn "zero-add ~S => ~S [~S]" loc0 destination-location result-type)
+ (cond
+ ((eql destination-location loc0)
+ #+ignore (break "NOP add: ~S" instruction)
+ nil)
((and (member destination-location '(:eax :ebx :ecx :edx))
- constant1
(member loc0 '(:eax :ebx :ecx :edx)))
- `((:leal (,loc0 ,constant1) ,destination-location)))
- ((and (member destination-location '(:eax :ebx :ecx :edx))
- constant0
- (eq :argument-stack (operator loc1)))
- `((:movl (:ebp ,(argument-stack-offset (binding-target term1)))
- ,destination-location)
- (:addl ,constant0 ,destination-location)))
- ((and (member destination-location '(:eax :ebx :ecx :edx))
- constant1
- (eq :argument-stack (operator loc0)))
- `((:movl (:ebp ,(argument-stack-offset (binding-target term0)))
- ,destination-location)
- (:addl ,constant1 ,destination-location)))
- (t (warn "Unknown fixnum ADD: ~A/~S = ~A/~S + ~A/~S"
- destination-location
- destination
- loc0 term0
- loc1 term1)
- #+ignore (warn "map: ~A" frame-map)
-;;; (warn "ADDI: ~S" instruction)
- (append (cond
- ((type-specifier-singleton type0)
- (append (make-load-lexical term1 :eax funobj nil frame-map)
- (make-load-constant (car (type-specifier-singleton type0))
- :ebx funobj frame-map)))
- ((type-specifier-singleton type1)
- (append (make-load-lexical term0 :eax funobj nil frame-map)
- (make-load-constant (car (type-specifier-singleton type1))
- :ebx funobj frame-map)))
- ((and (eq :eax loc0) (eq :ebx loc1))
- nil)
- ((and (eq :ebx loc0) (eq :eax loc1))
- nil) ; terms order isn't important
- ((eq :eax loc1)
- (append
- (make-load-lexical term0 :ebx funobj nil frame-map)))
- (t (append
- (make-load-lexical term0 :eax funobj nil frame-map)
- (make-load-lexical term1 :ebx funobj nil frame-map))))
- `((:movl (:edi ,(global-constant-offset '+)) :esi))
- (make-compiled-funcall-by-esi 2)
- (etypecase destination
- (symbol
- (unless (eq destination :eax)
- `((:movl :eax ,destination))))
- (binding
- (make-store-lexical destination :eax nil funobj frame-map)))))))
- ((and constant0
- (integerp destination-location)
- (eql loc1 destination-location)
- (binding-lended-p (binding-target destination)))
- (assert (binding-lended-p (binding-target term1)))
- (append (make-load-lexical destination :eax funobj t frame-map)
- `((:addl ,constant0 (-1 :eax)))))
- ((warn "~S" (list (and (bindingp destination)
- (binding-lended-p (binding-target destination)))
- (binding-lended-p (binding-target term0))
- (binding-lended-p (binding-target term1)))))
- (t (warn "Unknown fixnum add: ~S" instruction)
- (make-default-add))))
- ((and (movitz-subtypep type0 'fixnum)
- (movitz-subtypep type1 'fixnum))
- (flet ((mkadd-into (src destreg)
- (assert (eq destreg :eax) (destreg)
- "Movitz' INTO protocol says the overflowed value must be in EAX, ~
-but it's requested to be in ~S."
- destreg)
- (let ((srcloc (new-binding-location (binding-target src) frame-map)))
- (unless (eql srcloc loc1) (break))
- (if (integerp srcloc)
- `((:addl (:ebp ,(stack-frame-offset srcloc))
- ,destreg)
- (:into))
- (ecase (operator srcloc)
- ((:eax :ebx :ecx :edx)
- `((:addl ,srcloc ,destreg)
- (:into)))
- ((:argument-stack)
- `((:addl (:ebx ,(argument-stack-offset src))
- ,destreg)
- (:into)))
- )))))
+ `((:movl ,loc0 ,destination-location)))
+ ((member loc0 '(:eax :ebx :ecx :edx))
+ (make-store-lexical destination loc0 nil funobj frame-map))
+ ((integerp loc0)
+ (make-load-lexical term0 destination funobj nil frame-map))
+ (t (break "Unknown Y zero-add: ~S" instruction))))
+ ((and (movitz-subtypep type0 'fixnum)
+ (movitz-subtypep type1 'fixnum)
+ (movitz-subtypep result-type 'fixnum))
+ (assert (not (and constant0 (zerop constant0))))
+ (assert (not (and constant1 (zerop constant1))))
(cond
- ((and (not constant0)
- (not constant1)
- (not (binding-lended-p (binding-target term0)))
+ ((and (not (binding-lended-p (binding-target term0)))
(not (binding-lended-p (binding-target term1)))
(not (and (bindingp destination)
(binding-lended-p (binding-target destination)))))
(cond
- ((and (not (eq loc0 :untagged-fixnum-ecx))
- (not (eq loc1 :untagged-fixnum-ecx))
- (not (eq destination-location :untagged-fixnum-ecx)))
- (append (cond
- ((and (eq loc0 :eax) (eq loc1 :eax))
- `((:addl :eax :eax)
- (:into)))
- ((eq loc0 :eax)
- (mkadd-into term1 :eax))
- ((eq loc1 :eax)
- (mkadd-into term0 :eax))
- (t (append (make-load-lexical term0 :eax funobj nil frame-map
- :protect-registers (list loc1))
- (mkadd-into term1 :eax))))
+ ((and constant0
+ (equal loc1 destination-location))
+ (cond
+ ((member destination-location '(:eax :ebx :ecx :edx))
+ `((:addl ,constant0 ,destination-location)))
+ ((integerp loc1)
+ `((:addl ,constant0 (:ebp ,(stack-frame-offset loc1)))))
+ ((eq :argument-stack (operator loc1))
+ `((:addl ,constant0
+ (:ebp ,(argument-stack-offset (binding-target term1))))))
+ (t (error "Don't know how to add this for loc1 ~S" loc1))))
+ ((and constant0
+ (integerp destination-location)
+ (eql term1 destination-location))
+ (break "untested")
+ `((:addl ,constant0 (:ebp ,(stack-frame-offset destination-location)))))
+ ((and constant0
+ (integerp destination-location)
+ (member loc1 '(:eax :ebx :ecx :edx)))
+ `((:addl ,constant0 ,loc1)
+ (:movl ,loc1 (:ebp ,(stack-frame-offset destination-location)))))
+ ((and (integerp loc0)
+ (integerp loc1)
+ (member destination-location '(:eax :ebx :ecx :edx)))
+ (append `((:movl (:ebp ,(stack-frame-offset loc0)) ,destination-location)
+ (:addl (:ebp ,(stack-frame-offset loc1)) ,destination-location))))
+ ((and (integerp destination-location)
+ (eql loc0 destination-location)
+ constant1)
+ `((:addl ,constant1 (:ebp ,(stack-frame-offset destination-location)))))
+ ((and (integerp destination-location)
+ (eql loc1 destination-location)
+ constant0)
+ `((:addl ,constant0 (:ebp ,(stack-frame-offset destination-location)))))
+ ((and (member destination-location '(:eax :ebx :ecx :edx))
+ (eq loc0 :untagged-fixnum-ecx)
+ constant1)
+ `((:leal ((:ecx ,+movitz-fixnum-factor+) ,constant1)
+ ,destination-location)))
+ ((and (member destination-location '(:eax :ebx :ecx :edx))
+ (integerp loc1)
+ constant0)
+ `((:movl (:ebp ,(stack-frame-offset loc1)) ,destination-location)
+ (:addl ,constant0 ,destination-location)))
+ ((and (member destination-location '(:eax :ebx :ecx :edx))
+ (integerp loc0)
+ constant1)
+ `((:movl (:ebp ,(stack-frame-offset loc0)) ,destination-location)
+ (:addl ,constant1 ,destination-location)))
+ ((and (member destination-location '(:eax :ebx :ecx :edx))
+ (integerp loc0)
+ (member loc1 '(:eax :ebx :ecx :edx))
+ (not (eq destination-location loc1)))
+ `((:movl (:ebp ,(stack-frame-offset loc0)) ,destination-location)
+ (:addl ,loc1 ,destination-location)))
+ ((and (member destination-location '(:eax :ebx :ecx :edx))
+ constant0
+ (member loc1 '(:eax :ebx :ecx :edx)))
+ `((:leal (,loc1 ,constant0) ,destination-location)))
+ ((and (member destination-location '(:eax :ebx :ecx :edx))
+ constant1
+ (member loc0 '(:eax :ebx :ecx :edx)))
+ `((:leal (,loc0 ,constant1) ,destination-location)))
+ ((and (member destination-location '(:eax :ebx :ecx :edx))
+ constant0
+ (eq :argument-stack (operator loc1)))
+ `((:movl (:ebp ,(argument-stack-offset (binding-target term1)))
+ ,destination-location)
+ (:addl ,constant0 ,destination-location)))
+ ((and (member destination-location '(:eax :ebx :ecx :edx))
+ constant1
+ (eq :argument-stack (operator loc0)))
+ `((:movl (:ebp ,(argument-stack-offset (binding-target term0)))
+ ,destination-location)
+ (:addl ,constant1 ,destination-location)))
+ (constant0
+ (append (make-load-lexical term1 :eax funobj nil frame-map)
+ `((:addl ,constant0 :eax))
(make-store :eax destination)))
- (t (make-default-add)
- #+ignore
- (append (make-load-lexical term0 :untagged-fixnum-ecx funobj nil frame-map)
- `((,*compiler-local-segment-prefix*
- :movl :ecx (:edi ,(global-constant-offset 'raw-scratch0))))
- (make-load-lexical term1 :untagged-fixnum-ecx funobj nil frame-map)
- `((,*compiler-local-segment-prefix*
- :addl (:edi ,(global-constant-offset 'raw-scratch0)) :ecx))
- (if (integerp destination-location)
- `((,*compiler-local-segment-prefix*
- :call (:edi ,(global-constant-offset 'box-u32-ecx)))
- (:movl :eax (:ebp ,(stack-frame-offset destination-location))))
- (ecase (operator destination-location)
- ((:untagged-fixnum-ecx)
- nil)
- ((:eax)
- `((,*compiler-local-segment-prefix*
- :call (:edi ,(global-constant-offset 'box-u32-ecx)))))
- ((:ebx :ecx :edx)
- `((,*compiler-local-segment-prefix*
- :call (:edi ,(global-constant-offset 'box-u32-ecx)))
- (:movl :eax ,destination-location)))
- ((:argument-stack)
- `((,*compiler-local-segment-prefix*
- :call (:edi ,(global-constant-offset 'box-u32-ecx)))
- (:movl :eax (:ebp ,(argument-stack-offset
- (binding-target destination))))))))))))
- (t (make-default-add)))))
- (t (make-default-add)))))))))
+ (constant1
+ (append (make-load-lexical term0 :eax funobj nil frame-map)
+ `((:addl ,constant1 :eax))
+ (make-store :eax destination)))
+ ((eql loc0 loc1)
+ (append (make-load-lexical term0 :eax funobj nil frame-map)
+ `((:addl :eax :eax))
+ (make-store :eax destination)))
+ (t (warn "Unknown fixnum ADD: ~A/~S = ~A/~S + ~A/~S"
+ destination-location
+ destination
+ loc0 term0
+ loc1 term1)
+ #+ignore (warn "map: ~A" frame-map)
+;;; (warn "ADDI: ~S" instruction)
+ (append (cond
+ ((type-specifier-singleton type0)
+ (append (make-load-lexical term1 :eax funobj nil frame-map)
+ (make-load-constant (car (type-specifier-singleton type0))
+ :ebx funobj frame-map)))
+ ((type-specifier-singleton type1)
+ (append (make-load-lexical term0 :eax funobj nil frame-map)
+ (make-load-constant (car (type-specifier-singleton type1))
+ :ebx funobj frame-map)))
+ ((and (eq :eax loc0) (eq :ebx loc1))
+ nil)
+ ((and (eq :ebx loc0) (eq :eax loc1))
+ nil) ; terms order isn't important
+ ((eq :eax loc1)
+ (append
+ (make-load-lexical term0 :ebx funobj nil frame-map)))
+ (t (append
+ (make-load-lexical term0 :eax funobj nil frame-map)
+ (make-load-lexical term1 :ebx funobj nil frame-map))))
+ `((:movl (:edi ,(global-constant-offset '+)) :esi))
+ (make-compiled-funcall-by-esi 2)
+ (etypecase destination
+ (symbol
+ (unless (eq destination :eax)
+ `((:movl :eax ,destination))))
+ (binding
+ (make-store-lexical destination :eax nil funobj frame-map)))))))
+ ((and constant0
+ (integerp destination-location)
+ (eql loc1 destination-location)
+ (binding-lended-p (binding-target destination)))
+ (assert (binding-lended-p (binding-target term1)))
+ (append (make-load-lexical destination :eax funobj t frame-map)
+ `((:addl ,constant0 (-1 :eax)))))
+ ((warn "~S" (list (and (bindingp destination)
+ (binding-lended-p (binding-target destination)))
+ (binding-lended-p (binding-target term0))
+ (binding-lended-p (binding-target term1)))))
+ (t (warn "Unknown fixnum add: ~S" instruction)
+ (make-default-add))))
+ ((and (movitz-subtypep type0 'fixnum)
+ (movitz-subtypep type1 'fixnum))
+ (flet ((mkadd-into (src destreg)
+ (assert (eq destreg :eax) (destreg)
+ "Movitz' INTO protocol says the overflowed value must be in EAX, ~
+but it's requested to be in ~S."
+ destreg)
+ (let ((srcloc (new-binding-location (binding-target src) frame-map)))
+ (unless (eql srcloc loc1) (break))
+ (if (integerp srcloc)
+ `((:addl (:ebp ,(stack-frame-offset srcloc))
+ ,destreg)
+ (:into))
+ (ecase (operator srcloc)
+ ((:eax :ebx :ecx :edx)
+ `((:addl ,srcloc ,destreg)
+ (:into)))
+ ((:argument-stack)
+ `((:addl (:ebx ,(argument-stack-offset src))
+ ,destreg)
+ (:into)))
+ )))))
+ (cond
+ ((and (not constant0)
+ (not constant1)
+ (not (binding-lended-p (binding-target term0)))
+ (not (binding-lended-p (binding-target term1)))
+ (not (and (bindingp destination)
+ (binding-lended-p (binding-target destination)))))
+ (cond
+ ((and (not (eq loc0 :untagged-fixnum-ecx))
+ (not (eq loc1 :untagged-fixnum-ecx))
+ (not (eq destination-location :untagged-fixnum-ecx)))
+ (append (cond
+ ((and (eq loc0 :eax) (eq loc1 :eax))
+ `((:addl :eax :eax)
+ (:into)))
+ ((eq loc0 :eax)
+ (mkadd-into term1 :eax))
+ ((eq loc1 :eax)
+ (mkadd-into term0 :eax))
+ (t (append (make-load-lexical term0 :eax funobj nil frame-map
+ :protect-registers (list loc1))
+ (mkadd-into term1 :eax))))
+ (make-store :eax destination)))
+ (t (make-default-add)
+ #+ignore
+ (append (make-load-lexical term0 :untagged-fixnum-ecx funobj nil frame-map)
+ `((,*compiler-local-segment-prefix*
+ :movl :ecx (:edi ,(global-constant-offset 'raw-scratch0))))
+ (make-load-lexical term1 :untagged-fixnum-ecx funobj nil frame-map)
+ `((,*compiler-local-segment-prefix*
+ :addl (:edi ,(global-constant-offset 'raw-scratch0)) :ecx))
+ (if (integerp destination-location)
+ `((,*compiler-local-segment-prefix*
+ :call (:edi ,(global-constant-offset 'box-u32-ecx)))
+ (:movl :eax (:ebp ,(stack-frame-offset destination-location))))
+ (ecase (operator destination-location)
+ ((:untagged-fixnum-ecx)
+ nil)
+ ((:eax)
+ `((,*compiler-local-segment-prefix*
+ :call (:edi ,(global-constant-offset 'box-u32-ecx)))))
+ ((:ebx :ecx :edx)
+ `((,*compiler-local-segment-prefix*
+ :call (:edi ,(global-constant-offset 'box-u32-ecx)))
+ (:movl :eax ,destination-location)))
+ ((:argument-stack)
+ `((,*compiler-local-segment-prefix*
+ :call (:edi ,(global-constant-offset 'box-u32-ecx)))
+ (:movl :eax (:ebp ,(argument-stack-offset
+ (binding-target destination))))))))))))
+ (t (make-default-add)))))
+ (t (make-default-add))))))))))
;;;;;;;