Update of /project/movitz/cvsroot/movitz
In directory common-lisp.net:/tmp/cvs-serv20257
Modified Files:
compiler.lisp
Log Message:
Added defvar *compiler-do-type-inference*. Also added code to restore
the host's *features* when doing host-side stuff.
Date: Fri Feb 13 17:05:04 2004
Author: ffjeld
Index: movitz/compiler.lisp
diff -u movitz/compiler.lisp:1.24 movitz/compiler.lisp:1.25
--- movitz/compiler.lisp:1.24 Fri Feb 13 05:40:14 2004
+++ movitz/compiler.lisp Fri Feb 13 17:05:04 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.24 2004/02/13 10:40:14 ffjeld Exp $
+;;;; $Id: compiler.lisp,v 1.25 2004/02/13 22:05:04 ffjeld Exp $
;;;;
;;;;------------------------------------------------------------------
@@ -51,6 +51,9 @@
(defvar *compiler-compile-macro-expanders* t
"For macros of any kind, compile the macro-expanders using the host compiler.")
+(defvar *compiler-do-type-inference* t
+ "Spend time and effort performing type inference and optimization.")
+
(defvar *compiling-function-name*)
(defvar muerte.cl:*compile-file-pathname* nil)
@@ -142,7 +145,8 @@
Gensym a name whose symbol-function is set to the macro-expander, and return that symbol."
(let ((function-name (gensym (format nil "~A-expander-~@[~A-~]" type name))))
(if *compiler-compile-macro-expanders*
- (compile function-name lambda-form)
+ (with-host-environment ()
+ (compile function-name lambda-form))
(setf (symbol-function function-name)
(coerce lambda-form 'function)))
function-name))
@@ -331,113 +335,115 @@
(multiple-value-list (type-specifier-encode nil))))
(defun analyze-bindings (toplevel-funobj)
- "Figure out usage of bindings in a toplevel funobj."
- (let ((more-binding-references-p nil)
- (binding-usage (make-hash-table :test 'eq)))
- (labels ((type-is-t (type-specifier)
- (or (eq type-specifier t)
- (and (listp type-specifier)
- (eq 'or (car type-specifier))
- (some #'type-is-t (cdr type-specifier)))))
- (analyze-store (binding type)
- (assert (not (null type)) ()
- "store-lexical with empty type.")
- (assert (or (typep type 'binding)
- (eql 1 (type-specifier-num-values type))) ()
- "store-lexical with multiple-valued type: ~S for ~S" type binding)
- (let ((analysis (or (gethash binding binding-usage)
- (setf (gethash binding binding-usage)
- (make-type-analysis)))))
- (cond
- ((typep binding 'function-argument)
- (setf (type-analysis-encoded-type analysis)
- (multiple-value-list (type-specifier-encode t))))
- ((and (consp type) (eq 'binding-type (car type)))
- (let ((target-binding (binding-target (cadr type))))
- (cond
- ((eq binding target-binding))
- ((typep binding 'constant-object-binding)
- (setf (type-analysis-encoded-type analysis)
+ "Figure out usage of bindings in a toplevel funobj.
+Side-effects each binding's binding-store-type."
+ (when *compiler-do-type-inference*
+ (let ((more-binding-references-p nil)
+ (binding-usage (make-hash-table :test 'eq)))
+ (labels ((type-is-t (type-specifier)
+ (or (eq type-specifier t)
+ (and (listp type-specifier)
+ (eq 'or (car type-specifier))
+ (some #'type-is-t (cdr type-specifier)))))
+ (analyze-store (binding type)
+ (assert (not (null type)) ()
+ "store-lexical with empty type.")
+ (assert (or (typep type 'binding)
+ (eql 1 (type-specifier-num-values type))) ()
+ "store-lexical with multiple-valued type: ~S for ~S" type binding)
+ (let ((analysis (or (gethash binding binding-usage)
+ (setf (gethash binding binding-usage)
+ (make-type-analysis)))))
+ (cond
+ ((typep binding 'function-argument)
+ (setf (type-analysis-encoded-type analysis)
+ (multiple-value-list (type-specifier-encode t))))
+ ((and (consp type) (eq 'binding-type (car type)))
+ (let ((target-binding (binding-target (cadr type))))
+ (cond
+ ((eq binding target-binding))
+ ((typep binding 'constant-object-binding)
+ (setf (type-analysis-encoded-type analysis)
+ (multiple-value-list
+ (multiple-value-call
+ #'encoded-types-or
+ (values-list (type-analysis-encoded-type analysis))
+ (member-type-encode (constant-object target-binding))))))
+ (t (pushnew target-binding (type-analysis-binding-types analysis))
+ (setf more-binding-references-p t)))))
+ (t (setf (type-analysis-encoded-type analysis)
(multiple-value-list
(multiple-value-call
#'encoded-types-or
(values-list (type-analysis-encoded-type analysis))
- (member-type-encode (constant-object target-binding))))))
- (t (pushnew target-binding (type-analysis-binding-types analysis))
- (setf more-binding-references-p t)))))
- (t (setf (type-analysis-encoded-type analysis)
- (multiple-value-list
- (multiple-value-call
- #'encoded-types-or
- (values-list (type-analysis-encoded-type analysis))
- (type-specifier-encode type))))))))
- (analyze-code (code)
- (dolist (instruction code)
- (when (listp instruction)
- (multiple-value-bind (store-binding store-type)
- (find-written-binding-and-type instruction)
- (when store-binding
- (analyze-store (binding-target store-binding) store-type)))
- (analyze-code (instruction-sub-program instruction)))))
- (analyze-funobj (funobj)
- (loop for (nil . function-env) in (function-envs funobj)
- do (analyze-code (extended-code function-env)))
- (loop for function-binding in (sub-function-binding-usage funobj) by #'cddr
- do (analyze-funobj (function-binding-funobj function-binding)))
- funobj))
- ;; 1. Examine each store to lexical bindings.
- (analyze-funobj toplevel-funobj)
- ;; 2.
- (loop repeat 10 while more-binding-references-p
- doing
- (setf more-binding-references-p nil)
- (maphash (lambda (binding analysis)
- (dolist (target-binding (type-analysis-binding-types analysis))
- (let* ((target-analysis
- (or (gethash target-binding binding-usage)
- (and (typep target-binding 'function-argument)
- (make-type-analysis
- :encoded-type (multiple-value-list
- (type-specifier-encode t))))
- (error "Type-reference by ~S to unknown binding ~S"
- binding target-binding)))
- (new-type (setf (type-analysis-encoded-type analysis)
- (multiple-value-list
- (multiple-value-call
- #'encoded-types-or
- (values-list
- (type-analysis-encoded-type analysis))
- (values-list
- (type-analysis-encoded-type target-analysis)))))))
- (cond
- ((apply #'encoded-allp new-type)
- ;; If the type is already T, no need to look further.
- (setf (type-analysis-binding-types analysis) nil))
- ((setf (type-analysis-binding-types analysis)
- (remove target-binding
- (remove binding
- (union (type-analysis-binding-types analysis)
- (type-analysis-binding-types target-analysis)))))
- (setf more-binding-references-p t))))))
- binding-usage))
- (when more-binding-references-p
- (warn "Unable to remove all binding-references duding lexical type analysis."))
- ;; 3.
- (maphash (lambda (binding analysis)
- (assert (null (type-analysis-binding-types analysis)) ()
- "binding ~S type ~S still refers to ~S"
- binding
- (apply #'encoded-type-decode (type-analysis-encoded-type analysis))
- (type-analysis-binding-types analysis))
- (setf (binding-store-type binding)
- (type-analysis-encoded-type analysis))
- #+ignore
- (unless (apply #'encoded-allp (type-analysis-encoded-type analysis))
- (warn "Type: ~A => ~A"
- (binding-name binding)
- (apply #'encoded-type-decode (type-analysis-encoded-type analysis)))))
- binding-usage)
- toplevel-funobj)))
+ (type-specifier-encode type))))))))
+ (analyze-code (code)
+ (dolist (instruction code)
+ (when (listp instruction)
+ (multiple-value-bind (store-binding store-type)
+ (find-written-binding-and-type instruction)
+ (when store-binding
+ (analyze-store (binding-target store-binding) store-type)))
+ (analyze-code (instruction-sub-program instruction)))))
+ (analyze-funobj (funobj)
+ (loop for (nil . function-env) in (function-envs funobj)
+ do (analyze-code (extended-code function-env)))
+ (loop for function-binding in (sub-function-binding-usage funobj) by #'cddr
+ do (analyze-funobj (function-binding-funobj function-binding)))
+ funobj))
+ ;; 1. Examine each store to lexical bindings.
+ (analyze-funobj toplevel-funobj)
+ ;; 2.
+ (loop repeat 10 while more-binding-references-p
+ doing
+ (setf more-binding-references-p nil)
+ (maphash (lambda (binding analysis)
+ (dolist (target-binding (type-analysis-binding-types analysis))
+ (let* ((target-analysis
+ (or (gethash target-binding binding-usage)
+ (and (typep target-binding 'function-argument)
+ (make-type-analysis
+ :encoded-type (multiple-value-list
+ (type-specifier-encode t))))
+ (error "Type-reference by ~S to unknown binding ~S"
+ binding target-binding)))
+ (new-type (setf (type-analysis-encoded-type analysis)
+ (multiple-value-list
+ (multiple-value-call
+ #'encoded-types-or
+ (values-list
+ (type-analysis-encoded-type analysis))
+ (values-list
+ (type-analysis-encoded-type target-analysis)))))))
+ (cond
+ ((apply #'encoded-allp new-type)
+ ;; If the type is already T, no need to look further.
+ (setf (type-analysis-binding-types analysis) nil))
+ ((setf (type-analysis-binding-types analysis)
+ (remove target-binding
+ (remove binding
+ (union (type-analysis-binding-types analysis)
+ (type-analysis-binding-types target-analysis)))))
+ (setf more-binding-references-p t))))))
+ binding-usage))
+ (when more-binding-references-p
+ (warn "Unable to remove all binding-references duding lexical type analysis."))
+ ;; 3.
+ (maphash (lambda (binding analysis)
+ (assert (null (type-analysis-binding-types analysis)) ()
+ "binding ~S type ~S still refers to ~S"
+ binding
+ (apply #'encoded-type-decode (type-analysis-encoded-type analysis))
+ (type-analysis-binding-types analysis))
+ (setf (binding-store-type binding)
+ (type-analysis-encoded-type analysis))
+ #+ignore
+ (unless (apply #'encoded-allp (type-analysis-encoded-type analysis))
+ (warn "Type: ~A => ~A"
+ (binding-name binding)
+ (apply #'encoded-type-decode (type-analysis-encoded-type analysis)))))
+ binding-usage))))
+ toplevel-funobj)
(defun resolve-borrowed-bindings (toplevel-funobj)
"For <funobj>'s code, for every non-local binding used we create
@@ -1128,11 +1134,18 @@
(delete-file-p nil))
(handler-bind
(#+sbcl (sb-ext:defconstant-uneql #'continue)
+ #+lispworks-personal-edition
+ (conditions:stack-overflow (lambda (&optional c)
+ (declare (ignore c))
+ (warn "Stack overflow. Skipping function ~S.~%"
+ *compiling-function-name*)
+ (invoke-restart 'skip-toplevel-form)))
#+ignore ((or error warning) (lambda (c)
(declare (ignore c))
(format *error-output* "~&;; In file ~S:" path))))
(unwind-protect
- (let ((*features* (image-movitz-features *image*)))
+ (let ((*movitz-host-features* *features*)
+ (*features* (image-movitz-features *image*)))
(multiple-value-prog1
(movitz-compile-file-internal path load-priority)
(unless (equalp *features* (image-movitz-features *image*))
@@ -1152,45 +1165,51 @@
(symbol-value '*default-load-priority*)
(1+ (symbol-value '*default-load-priority*)))))
(declare (special *default-load-priority*))
- (with-retries-until-true (retry "Restart Movitz compilation of ~S." path)
- (let* ((muerte.cl::*compile-file-pathname* path)
- (*package* (find-package :muerte))
- (funobj (make-instance 'movitz-funobj-pass1
- :name (intern (format nil "file-~A" path) :muerte)
- :lambda-list (movitz-read nil)))
- (funobj-env (make-local-movitz-environment nil funobj
- :type 'funobj-env
- :declaration-context :funobj))
- (function-env (make-local-movitz-environment funobj-env funobj
- :type 'function-env
+ (with-simple-restart (continue "Skip Movitz compilation of ~S." path)
+ (with-retries-until-true (retry "Restart Movitz compilation of ~S." path)
+ (warn "Compiling ~A.." path)
+ (let* ((muerte.cl::*compile-file-pathname* path)
+ (*package* (find-package :muerte))
+ (funobj (make-instance 'movitz-funobj-pass1
+ :name (intern (format nil "file-~A" path) :muerte)
+ :lambda-list (movitz-read nil)))
+ (funobj-env (make-local-movitz-environment nil funobj
+ :type 'funobj-env
:declaration-context :funobj))
- (file-code
- (with-compilation-unit ()
- (add-bindings-from-lambda-list () function-env)
- (with-open-file (stream path :direction :input)
- (setf (funobj-env funobj) funobj-env)
- (loop for form = (with-movitz-syntax ()
- (read stream nil '#0=#:eof))
- until (eq form '#0#)
- appending
- (with-simple-restart (skip-toplevel-form
- "Skip the compilation of this top-level form.")
- (compiler-call #'compile-form
- :form form
- :funobj funobj
- :env function-env
- :top-level-p t
- :result-mode :ignore)))))))
- (cond
- ((null file-code)
- (setf (image-load-time-funobjs *image*)
- (delete funobj (image-load-time-funobjs *image*) :key #'first)))
- (t (setf (extended-code function-env) file-code
- (need-normalized-ecx-p function-env) nil
- (function-envs funobj) (list (cons 'muerte.cl::t function-env))
- (funobj-env funobj) funobj-env)
- (make-compiled-funobj-pass2 funobj)))
- t)))
+ (function-env (make-local-movitz-environment funobj-env funobj
+ :type 'function-env
+ :declaration-context :funobj))
+ (file-code
+ (with-compilation-unit ()
+ (add-bindings-from-lambda-list () function-env)
+ (with-open-file (stream path :direction :input)
+ (setf (funobj-env funobj) funobj-env)
+ (loop for form = (with-movitz-syntax ()
+ (read stream nil '#0=#:eof))
+ until (eq form '#0#)
+ appending
+ (with-simple-restart (skip-toplevel-form
+ "Skip the compilation of top-level form~@[ ~A~]."
+ (cond
+ ((symbolp form) form)
+ ((symbolp (car form)) (car form))))
+ #+lispworks-personal-edition (hcl:mark-and-sweep 2)
+ (compiler-call #'compile-form
+ :form form
+ :funobj funobj
+ :env function-env
+ :top-level-p t
+ :result-mode :ignore)))))))
+ (cond
+ ((null file-code)
+ (setf (image-load-time-funobjs *image*)
+ (delete funobj (image-load-time-funobjs *image*) :key #'first)))
+ (t (setf (extended-code function-env) file-code
+ (need-normalized-ecx-p function-env) nil
+ (function-envs funobj) (list (cons 'muerte.cl::t function-env))
+ (funobj-env funobj) funobj-env)
+ (make-compiled-funobj-pass2 funobj)))
+ t))))
;;;;
@@ -5352,7 +5371,7 @@
(define-find-read-bindings :incf-lexvar (binding delta &key protect-registers)
(declare (ignore delta protect-registers))
- binding)
+ nil #+ignore binding)
(define-extended-code-expander :incf-lexvar (instruction funobj frame-map)
(destructuring-bind (binding delta &key protect-registers)
@@ -5360,11 +5379,11 @@
(check-type binding binding)
(check-type delta integer)
(let* ((binding (binding-target binding))
- (location (new-binding-location binding frame-map :default nil)))
- (assert (= 5 (length (binding-store-type binding))) ()
- "Weird encoded-type: ~S" (binding-store-type binding))
+ (location (new-binding-location binding frame-map :default nil))
+ (binding-type (binding-store-type binding)))
(cond
- ((and location
+ ((and binding-type
+ location
(not (binding-lended-p binding))
(multiple-value-call #'encoded-subtypep
(values-list (binding-store-type binding))
@@ -5374,9 +5393,10 @@
`((:addl ,(* delta +movitz-fixnum-factor+)
(:ebp ,(stack-frame-offset location)))
(:into)))
- ((multiple-value-call #'encoded-subtypep
- (values-list (binding-store-type binding))
- (type-specifier-encode 'integer))
+ ((and binding-type
+ (multiple-value-call #'encoded-subtypep
+ (values-list (binding-store-type binding))
+ (type-specifier-encode 'integer)))
(let ((register (chose-free-register protect-registers)))
`(,@(make-load-lexical (ensure-local-binding binding funobj)
register funobj nil frame-map