X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;ds=inline;f=src%2Fcompiler%2Fmain.lisp;h=efb342cfff936eabb1c1e8551388fdfc4639bb6f;hb=ea12c1295d511ba5242f3ce64c44e1e445f72cc8;hp=67ac1239581e530bc8be3bd955cc07f0d074028a;hpb=084168e1524a6493bc0f9d1697753d31239b158d;p=sbcl.git diff --git a/src/compiler/main.lisp b/src/compiler/main.lisp index 67ac123..efb342c 100644 --- a/src/compiler/main.lisp +++ b/src/compiler/main.lisp @@ -28,7 +28,8 @@ #!+sb-show *compiler-trace-output* *last-source-context* *last-original-source* *last-source-form* *last-format-string* *last-format-args* - *last-message-count* *lexenv* *fun-names-in-this-file*)) + *last-message-count* *lexenv* *fun-names-in-this-file* + *allow-instrumenting*)) ;;; Whether call of a function which cannot be defined causes a full ;;; warning. @@ -37,6 +38,9 @@ (defvar *check-consistency* nil) (defvar *all-components*) +;;; Set to NIL to disable loop analysis for register allocation. +(defvar *loop-analyze* t) + ;;; Bind this to a stream to capture various internal debugging output. (defvar *compiler-trace-output* nil) @@ -116,12 +120,12 @@ is intended to be wrapped around the compilation of all files in the same system. These keywords are defined: :OVERRIDE Boolean-Form - One of the effects of this form is to delay undefined warnings - until the end of the form, instead of giving them at the end of each - compilation. If OVERRIDE is NIL (the default), then the outermost - WITH-COMPILATION-UNIT form grabs the undefined warnings. Specifying - OVERRIDE true causes that form to grab any enclosed warnings, even if - it is enclosed by another WITH-COMPILATION-UNIT." + One of the effects of this form is to delay undefined warnings + until the end of the form, instead of giving them at the end of each + compilation. If OVERRIDE is NIL (the default), then the outermost + WITH-COMPILATION-UNIT form grabs the undefined warnings. Specifying + OVERRIDE true causes that form to grab any enclosed warnings, even if + it is enclosed by another WITH-COMPILATION-UNIT." `(%with-compilation-unit (lambda () ,@body) ,@options)) (defun %with-compilation-unit (fn &key override) @@ -196,7 +200,7 @@ (t (compiler-warn "~@" kind name))) @@ -221,12 +225,12 @@ (when summary (if (eq kind :variable) (compiler-warn - "~:[This ~(~A~) is~;These ~(~A~)s are~] undefined:~ - ~% ~{~<~% ~1:;~S~>~^ ~}" + "~:[This ~(~A~) is~;These ~(~A~)s are~] undefined:~ + ~% ~{~<~% ~1:;~S~>~^ ~}" (cdr summary) kind summary) (compiler-style-warn - "~:[This ~(~A~) is~;These ~(~A~)s are~] undefined:~ - ~% ~{~<~% ~1:;~S~>~^ ~}" + "~:[This ~(~A~) is~;These ~(~A~)s are~] undefined:~ + ~% ~{~<~% ~1:;~S~>~^ ~}" (cdr summary) kind summary)))))))) (unless (and (not abort-p) @@ -283,17 +287,20 @@ (maybe-mumble "opt") (event ir1-optimize-until-done) (let ((count 0) - (cleared-reanalyze nil)) + (cleared-reanalyze nil) + (fastp nil)) (loop (when (component-reanalyze component) (setq count 0) (setq cleared-reanalyze t) (setf (component-reanalyze component) nil)) (setf (component-reoptimize component) nil) - (ir1-optimize component) + (ir1-optimize component fastp) (cond ((component-reoptimize component) (incf count) - (when (= count *max-optimize-iterations*) + (when (and (>= count *max-optimize-iterations*) + (not (component-reanalyze component)) + (eq (component-reoptimize component) :maybe)) (maybe-mumble "*") (cond ((retry-delayed-ir1-transforms :optimize) (maybe-mumble "+") @@ -310,7 +317,8 @@ (t (maybe-mumble " ") (return))) - (maybe-mumble ".")) + (setq fastp (>= count *max-optimize-iterations*)) + (maybe-mumble (if fastp "-" "."))) (when cleared-reanalyze (setf (component-reanalyze component) t))) (values)) @@ -398,7 +406,8 @@ (maybe-mumble "control ") (control-analyze component #'make-ir2-block) - (when (ir2-component-values-receivers (component-info component)) + (when (or (ir2-component-values-receivers (component-info component)) + (component-dx-lvars component)) (maybe-mumble "stack ") (stack-analyze component) ;; Assign BLOCK-NUMBER for any cleanup blocks introduced by @@ -521,6 +530,25 @@ (ir1-phases component) + (when *loop-analyze* + (dfo-as-needed component) + (find-dominators component) + (loop-analyze component)) + + #| + (when (and *loop-analyze* *compiler-trace-output*) + (labels ((print-blocks (block) + (format *compiler-trace-output* " ~A~%" block) + (when (block-loop-next block) + (print-blocks (block-loop-next block)))) + (print-loop (loop) + (format *compiler-trace-output* "loop=~A~%" loop) + (print-blocks (loop-blocks loop)) + (dolist (l (loop-inferiors loop)) + (print-loop l)))) + (print-loop (component-outer-loop component)))) + |# + ;; FIXME: What is MAYBE-MUMBLE for? Do we need it any more? (maybe-mumble "env ") (physenv-analyze component) @@ -612,13 +640,7 @@ (setq *tn-id* 0) (clrhash *label-ids*) (clrhash *id-labels*) - (setq *label-id* 0) - - ;; Clear some PACK data structures (for GC purposes only). - (aver (not *in-pack*)) - (dolist (sb *backend-sb-list*) - (when (finite-sb-p sb) - (fill (finite-sb-live-tns sb) nil)))) + (setq *label-id* 0)) ;; (Note: The CMU CL code used to set CL::*GENSYM-COUNTER* to zero here. ;; Superficially, this seemed harmful -- the user could reasonably be @@ -667,7 +689,7 @@ ;;; A FILE-INFO structure holds all the source information for a ;;; given file. -(defstruct (file-info (:copier nil)) +(def!struct (file-info (:copier nil)) ;; If a file, the truename of the corresponding source file. If from ;; a Lisp form, :LISP. If from a stream, :STREAM. (name (missing-arg) :type (or pathname (member :lisp :stream))) @@ -690,11 +712,11 @@ ;;; The SOURCE-INFO structure provides a handle on all the source ;;; information for an entire compilation. -(defstruct (source-info - #-no-ansi-print-object - (:print-object (lambda (s stream) - (print-unreadable-object (s stream :type t)))) - (:copier nil)) +(def!struct (source-info + #-no-ansi-print-object + (:print-object (lambda (s stream) + (print-unreadable-object (s stream :type t)))) + (:copier nil)) ;; the UT that compilation started at (start-time (get-universal-time) :type unsigned-byte) ;; the FILE-INFO structure for this compilation @@ -733,7 +755,7 @@ (handler-case (read stream nil stream) (reader-error (condition) (error 'input-error-in-compile-file - :error condition + :condition condition ;; We don't need to supply :POSITION here because ;; READER-ERRORs already know their position in the file. )) @@ -742,7 +764,7 @@ ;; file in the middle of something it's trying to read. (end-of-file (condition) (error 'input-error-in-compile-file - :error condition + :condition condition ;; We need to supply :POSITION here because the END-OF-FILE ;; condition doesn't carry the position that the user ;; probably cares about, where the failed READ began. @@ -811,7 +833,9 @@ ;;; *TOPLEVEL-LAMBDAS* instead. (defun convert-and-maybe-compile (form path) (declare (list path)) - (let* ((*lexenv* (make-lexenv :policy *policy*)) + (let* ((*lexenv* (make-lexenv :policy *policy* + :handled-conditions *handled-conditions* + :disabled-package-locks *disabled-package-locks*)) (tll (ir1-toplevel form path nil))) (cond ((eq *block-compile* t) (push tll *toplevel-lambdas*)) (t (compile-toplevel (list tll) nil))))) @@ -856,7 +880,11 @@ ;; FIXME: Ideally, something should be done so that DECLAIM ;; inside LOCALLY works OK. Failing that, at least we could ;; issue a warning instead of silently screwing up. - (*policy* (lexenv-policy *lexenv*))) + (*policy* (lexenv-policy *lexenv*)) + ;; This is probably also a hack + (*handled-conditions* (lexenv-handled-conditions *lexenv*)) + ;; ditto + (*disabled-package-locks* (lexenv-disabled-package-locks *lexenv*))) (process-toplevel-progn forms path compile-time-too)))) ;;; Parse an EVAL-WHEN situations list, returning three flags, @@ -913,14 +941,11 @@ (setf (component-name component) (debug-namify "~S initial component" name)) (setf (component-kind component) :initial) - (let* ((locall-fun (ir1-convert-lambdalike - definition - :debug-name (debug-namify "top level local call ~S" - name) - ;; KLUDGE: we do this so that we get to have - ;; nice debug returnness in functions defined - ;; from the REPL - :allow-debug-catch-tag t)) + (let* ((locall-fun (let ((*allow-instrumenting* t)) + (ir1-convert-lambdalike + definition + :debug-name (debug-namify "top level local call " + name)))) (fun (ir1-convert-lambda (make-xep-lambda-expression locall-fun) :source-name (or name '.anonymous.) :debug-name (unless name @@ -954,7 +979,10 @@ '(original-source-start 0 0))) (when name (legal-fun-name-or-type-error name)) - (let* ((*lexenv* (make-lexenv :policy *policy*)) + (let* ( + (*lexenv* (make-lexenv :policy *policy* + :handled-conditions *handled-conditions* + :disabled-package-locks *disabled-package-locks*)) (fun (make-functional-from-toplevel-lambda lambda-expression :name name :path path))) @@ -1059,11 +1087,9 @@ (catch 'process-toplevel-form-error-abort (let* ((path (or (gethash form *source-paths*) (cons form path))) (*compiler-error-bailout* - (lambda () + (lambda (&optional condition) (convert-and-maybe-compile - `(error 'simple-program-error - :format-control "execution of a form compiled with errors:~% ~S" - :format-arguments (list ',form)) + (make-compiler-error-form condition form) path) (throw 'process-toplevel-form-error-abort nil)))) @@ -1177,8 +1203,9 @@ ((macrolet) (funcall-in-macrolet-lexenv magic - (lambda (&key funs) + (lambda (&key funs prepend) (declare (ignore funs)) + (aver (null prepend)) (process-toplevel-locally body path compile-time-too)) @@ -1186,7 +1213,8 @@ ((symbol-macrolet) (funcall-in-symbol-macrolet-lexenv magic - (lambda (&key vars) + (lambda (&key vars prepend) + (aver (null prepend)) (process-toplevel-locally body path compile-time-too @@ -1344,6 +1372,45 @@ (setq *block-compile* nil) (setq *entry-points* nil))) +(defun handle-condition-p (condition) + (let ((lexenv + (etypecase *compiler-error-context* + (node + (node-lexenv *compiler-error-context*)) + (compiler-error-context + (let ((lexenv (compiler-error-context-lexenv + *compiler-error-context*))) + (aver lexenv) + lexenv)) + (null *lexenv*)))) + (let ((muffles (lexenv-handled-conditions lexenv))) + (if (null muffles) ; common case + nil + (dolist (muffle muffles nil) + (destructuring-bind (typespec . restart-name) muffle + (when (and (typep condition typespec) + (find-restart restart-name condition)) + (return t)))))))) + +(defun handle-condition-handler (condition) + (let ((lexenv + (etypecase *compiler-error-context* + (node + (node-lexenv *compiler-error-context*)) + (compiler-error-context + (let ((lexenv (compiler-error-context-lexenv + *compiler-error-context*))) + (aver lexenv) + lexenv)) + (null *lexenv*)))) + (let ((muffles (lexenv-handled-conditions lexenv))) + (aver muffles) + (dolist (muffle muffles (bug "fell through")) + (destructuring-bind (typespec . restart-name) muffle + (when (typep condition typespec) + (awhen (find-restart restart-name condition) + (invoke-restart it)))))))) + ;;; Read all forms from INFO and compile them, with output to OBJECT. ;;; Return (VALUES NIL WARNINGS-P FAILURE-P). (defun sub-compile-file (info) @@ -1354,11 +1421,14 @@ (sb!xc:*compile-file-truename* nil) ; SUB-SUB-COMPILE-FILE (*policy* *policy*) + (*handled-conditions* *handled-conditions*) + (*disabled-package-locks* *disabled-package-locks*) (*lexenv* (make-null-lexenv)) (*block-compile* *block-compile-arg*) (*source-info* info) (*toplevel-lambdas* ()) (*fun-names-in-this-file* ()) + (*allow-instrumenting* nil) (*compiler-error-bailout* (lambda () (compiler-mumble "~2&; fatal error, aborting compilation~%") @@ -1378,25 +1448,27 @@ (*info-environment* *info-environment*) (*gensym-counter* 0)) (handler-case - (with-compilation-values - (sb!xc:with-compilation-unit () - (clear-stuff) - - (sub-sub-compile-file info) - - (finish-block-compilation) - (let ((object *compile-object*)) - (etypecase object - (fasl-output (fasl-dump-source-info info object)) - (core-object (fix-core-source-info info object)) - (null))) - nil)) + (handler-bind (((satisfies handle-condition-p) #'handle-condition-handler)) + (with-compilation-values + (sb!xc:with-compilation-unit () + (clear-stuff) + + (sub-sub-compile-file info) + + (finish-block-compilation) + (let ((object *compile-object*)) + (etypecase object + (fasl-output (fasl-dump-source-info info object)) + (core-object (fix-core-source-info info object)) + (null))) + nil))) ;; Some errors are sufficiently bewildering that we just fail ;; immediately, without trying to recover and compile more of ;; the input file. - (input-error-in-compile-file (condition) + (fatal-compiler-error (condition) + (signal condition) (format *error-output* - "~@" + "~@" condition) (values nil t t))))) @@ -1649,11 +1721,9 @@ (throw 'pending-init circular-ref))) (multiple-value-bind (creation-form init-form) (handler-case - (sb!xc:make-load-form constant (make-null-lexenv)) + (sb!xc:make-load-form constant (make-null-lexenv)) (error (condition) - (compiler-error "(while making load form for ~S)~%~A" - constant - condition))) + (compiler-error condition))) (case creation-form (:sb-just-dump-it-normally (fasl-validate-structure constant *compile-object*)