0.8.16.34:
[sbcl.git] / src / compiler / main.lisp
index ff1bcce..efb342c 100644 (file)
@@ -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)
 
   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)
                    (t
                     (compiler-warn
                      "~@<The ~(~A~) ~S is undefined, and its name is ~
-                       reserved by ANSI CL so that even if it it were ~
+                       reserved by ANSI CL so that even if it were ~
                        defined later, the code doing so would not be ~
                        portable.~:@>"
                      kind name)))
            (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)
   (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 "+")
            (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))
     (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
 
     (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)
 
 ;;; 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)))
 
 ;;; 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
   (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.
            ))
     ;; 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.
     (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 "
-                                                 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
                  '(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
   (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))))
 
         (*source-info* info)
         (*toplevel-lambdas* ())
         (*fun-names-in-this-file* ())
+        (*allow-instrumenting* nil)
         (*compiler-error-bailout*
          (lambda ()
            (compiler-mumble "~2&; fatal error, aborting compilation~%")
       ;; 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*
-              "~@<compilation aborted because of input error: ~2I~_~A~:>"
+              "~@<compilation aborted because of fatal error: ~2I~_~A~:>"
               condition)
        (values nil t t)))))
 
        (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*)