0.pre7.117:
[sbcl.git] / src / compiler / ir1tran.lisp
index 7a10dc1..0c0c700 100644 (file)
@@ -33,7 +33,7 @@
 ;;; FIXME: It's confusing having one variable named *CURRENT-COMPONENT*
 ;;; and another named *COMPONENT-BEING-COMPILED*. (In CMU CL they
 ;;; were called *CURRENT-COMPONENT* and *COMPILE-COMPONENT* respectively,
-;;; which also confusing.)
+;;; which was also confusing.)
 (declaim (type (or component null) *current-component*))
 (defvar *current-component*)
 
 
 ;;; This function sets up the back link between the node and the
 ;;; continuation which continues at it.
-#!-sb-fluid (declaim (inline prev-link))
-(defun prev-link (node cont)
+(defun link-node-to-previous-continuation (node cont)
   (declare (type node node) (type continuation cont))
   (aver (not (continuation-next cont)))
   (setf (continuation-next cont) node)
 ;;; the continuation has no block, then we make it be in the block
 ;;; that the node is in. If the continuation heads its block, we end
 ;;; our block and link it to that block. If the continuation is not
-;;; currently used, then we set the derived-type for the continuation
+;;; currently used, then we set the DERIVED-TYPE for the continuation
 ;;; to that of the node, so that a little type propagation gets done.
 ;;;
 ;;; We also deal with a bit of THE's semantics here: we weaken the
 ;;; otherwise NIL is returned.
 ;;;
 ;;; This function may have arbitrary effects on the global environment
-;;; due to processing of PROCLAIMs and EVAL-WHENs. All syntax error
-;;; checking is done, with erroneous forms being replaced by a proxy
-;;; which signals an error if it is evaluated. Warnings about possibly
-;;; inconsistent or illegal changes to the global environment will
-;;; also be given.
+;;; due to processing of EVAL-WHENs. All syntax error checking is
+;;; done, with erroneous forms being replaced by a proxy which signals
+;;; an error if it is evaluated. Warnings about possibly inconsistent
+;;; or illegal changes to the global environment will also be given.
 ;;;
 ;;; We make the initial component and convert the form in a PROGN (and
 ;;; an optional NIL tacked on the end.) We then return the lambda. We
           (res (ir1-convert-lambda-body
                 forms ()
                 :debug-name (debug-namify "top level form ~S" form))))
-      (setf (functional-entry-function res) res
+      (setf (functional-entry-fun res) res
            (functional-arg-documentation res) ()
            (functional-kind res) :toplevel)
       res)))
      (let* ((leaf (find-constant value))
            (res (make-ref (leaf-type leaf) leaf)))
        (push res (leaf-refs leaf))
-       (prev-link res start)
+       (link-node-to-previous-continuation res start)
        (use-continuation res cont)))
     (values)))
 
-;;; Add FUN to the COMPONENT-REANALYZE-FUNS. FUN is returned.
+;;; Add FUN to the COMPONENT-REANALYZE-FUNS, unless it's some
+;;; trivial type for which reanalysis is a trivial no-op. FUN is returned.
 (defun maybe-reanalyze-fun (fun)
   (declare (type functional fun))
+
+  (aver-live-component *current-component*)
+  (when (lambda-p fun) ; when it's easy to ask FUN its COMPONENT
+    ;; general sanity check, specifically related to bug 138
+    (aver (eql (lambda-component fun) *current-component*)))
+
+  ;; I *think* this means "unless FUN is of some type for which
+  ;; reanalysis is a no-op". -- WHN 2001-01-06
   (when (typep fun '(or optional-dispatch clambda))
     (pushnew fun (component-reanalyze-funs *current-component*)))
+
   fun)
 
 ;;; Generate a REF node for LEAF, frobbing the LEAF structure as
                        leaf)))
     (push res (leaf-refs leaf))
     (setf (leaf-ever-used leaf) t)
-    (prev-link res start)
+    (link-node-to-previous-continuation res start)
     (use-continuation res cont)))
 
 ;;; Convert a reference to a symbolic constant or variable. If the
 ;;; symbol is entered in the LEXENV-VARIABLES we use that definition,
 ;;; otherwise we find the current global definition. This is also
-;;; where we pick off symbol macro and Alien variable references.
+;;; where we pick off symbol macro and alien variable references.
 (defun ir1-convert-variable (start cont name)
   (declare (type continuation start cont) (symbol name))
   (let ((var (or (lexenv-find name variables) (find-free-variable name))))
     (etypecase var
       (leaf
-       (when (and (lambda-var-p var) (lambda-var-ignorep var))
-        ;; (ANSI's specification for the IGNORE declaration requires
-        ;; that this be a STYLE-WARNING, not a full WARNING.)
-        (compiler-style-warning "reading an ignored variable: ~S" name))
+       (when (lambda-var-p var)
+        (let ((home (continuation-home-lambda-or-null start)))
+          (when home
+            (pushnew var (lambda-calls-or-closes home))))
+        (when (lambda-var-ignorep var)
+          ;; (ANSI's specification for the IGNORE declaration requires
+          ;; that this be a STYLE-WARNING, not a full WARNING.)
+          (compiler-style-warning "reading an ignored variable: ~S" name)))
        (reference-leaf start cont var))
       (cons
        (aver (eq (car var) 'MACRO))
          (t
           (ir1-convert-global-functoid-no-cmacro start cont form fun)))))
 
-;;; Handle the case of where the call was not a compiler macro, or was a
-;;; compiler macro and passed.
+;;; Handle the case of where the call was not a compiler macro, or was
+;;; a compiler macro and passed.
 (defun ir1-convert-global-functoid-no-cmacro (start cont form fun)
   (declare (type continuation start cont) (list form))
   ;; FIXME: Couldn't all the INFO calls here be converted into
              (return))
            (let ((this-cont (make-continuation)))
              (ir1-convert this-start this-cont form)
-             (setq this-start this-cont  forms (cdr forms)))))))
+             (setq this-start this-cont
+                   forms (cdr forms)))))))
   (values))
 \f
 ;;;; converting combinations
 
 ;;; Convert a function call where the function (i.e. the FUN argument)
-;;; is a LEAF. We return the COMBINATION node so that we can poke at
-;;; it if we want to.
+;;; is a LEAF. We return the COMBINATION node so that the caller can
+;;; poke at it if it wants to.
 (declaim (ftype (function (continuation continuation list leaf) combination)
                ir1-convert-combination))
 (defun ir1-convert-combination (start cont form fun)
            (ir1-convert this-start this-cont arg)
            (setq this-start this-cont)
            (arg-conts this-cont)))
-       (prev-link node this-start)
+       (link-node-to-previous-continuation node this-start)
        (use-continuation node cont)
        (setf (combination-args node) (arg-conts))))
     node))
   (values))
 
 ;;; Convert a call to a local function. If the function has already
-;;; been let converted, then throw FUN to LOCAL-CALL-LOSSAGE. This
+;;; been LET converted, then throw FUN to LOCAL-CALL-LOSSAGE. This
 ;;; should only happen when we are converting inline expansions for
 ;;; local functions during optimization.
 (defun ir1-convert-local-combination (start cont form fun)
           key))))
     key))
 
-;;; Parse a lambda-list into a list of VAR structures, stripping off
-;;; any aux bindings. Each arg name is checked for legality, and
+;;; Parse a lambda list into a list of VAR structures, stripping off
+;;; any &AUX bindings. Each arg name is checked for legality, and
 ;;; duplicate names are checked for. If an arg is globally special,
 ;;; the var is marked as :SPECIAL instead of :LEXICAL. &KEY,
 ;;; &OPTIONAL and &REST args are annotated with an ARG-INFO structure
 ;;;  4. a list of the &AUX variables; and
 ;;;  5. a list of the &AUX values.
 (declaim (ftype (function (list) (values list boolean boolean list list))
-               find-lambda-vars))
-(defun find-lambda-vars (list)
+               make-lambda-vars))
+(defun make-lambda-vars (list)
   (multiple-value-bind (required optional restp rest keyp keys allowp aux
                        morep more-context more-count)
       (parse-lambda-list list)
 ;;; sequentially bind each AUX-VAR to the corresponding AUX-VAL before
 ;;; converting the body. If there are no bindings, just convert the
 ;;; body, otherwise do one binding and recurse on the rest.
+;;;
+;;; FIXME: This could and probably should be converted to use
+;;; SOURCE-NAME and DEBUG-NAME. But I (WHN) don't use &AUX bindings,
+;;; so I'm not motivated. Patches will be accepted...
 (defun ir1-convert-aux-bindings (start cont body aux-vars aux-vals)
   (declare (type continuation start cont) (list body aux-vars aux-vals))
   (if (null aux-vars)
                                debug-name)
   (declare (list body vars aux-vars aux-vals)
           (type (or continuation null) result))
+
+  ;; We're about to try to put new blocks into *CURRENT-COMPONENT*.
+  (aver-live-component *current-component*)
+
   (let* ((bind (make-bind))
         (lambda (make-lambda :vars vars
                              :bind bind
                              :%debug-name debug-name))
         (result (or result (make-continuation))))
 
-    ;; This function should fail internal assertions if we didn't set
-    ;; up a valid debug name above.
+    ;; just to check: This function should fail internal assertions if
+    ;; we didn't set up a valid debug name above.
     ;;
     ;; (In SBCL we try to make everything have a debug name, since we
     ;; lack the omniscient perspective the original implementors used
        (let ((cont1 (make-continuation))
              (cont2 (make-continuation)))
          (continuation-starts-block cont1)
-         (prev-link bind cont1)
+         (link-node-to-previous-continuation bind cont1)
          (use-continuation bind cont2)
          (ir1-convert-special-bindings cont2 result body aux-vars aux-vals
                                        (svars)))
        (let ((block (continuation-block result)))
          (when block
            (let ((return (make-return :result result :lambda lambda))
-                 (tail-set (make-tail-set :functions (list lambda)))
+                 (tail-set (make-tail-set :funs (list lambda)))
                  (dummy (make-continuation)))
              (setf (lambda-tail-set lambda) tail-set)
              (setf (lambda-return lambda) return)
              (setf (continuation-dest result) return)
              (setf (block-last block) return)
-             (prev-link return result)
+             (link-node-to-previous-continuation return result)
              (use-continuation return dummy))
            (link-blocks block (component-tail *current-component*))))))
 
     (link-blocks (component-head *current-component*) (node-block bind))
     (push lambda (component-new-funs *current-component*))
+
     lambda))
 
 ;;; Create the actual entry-point function for an optional entry
 (defun generate-optional-default-entry (res default-vars default-vals
                                            entry-vars entry-vals
                                            vars supplied-p-p body
-                                           aux-vars aux-vals cont)
+                                           aux-vars aux-vals cont
+                                           source-name debug-name)
   (declare (type optional-dispatch res)
           (list default-vars default-vals entry-vars entry-vals vars body
                 aux-vars aux-vals)
                  (list* (leaf-source-name supplied-p) arg-name default-vals)
                  (cons arg entry-vars)
                  (list* t arg-name entry-vals)
-                 (rest vars) t body aux-vars aux-vals cont)
+                 (rest vars) t body aux-vars aux-vals cont
+                 source-name debug-name)
                 (ir1-convert-hairy-args
                  res
                  (cons arg default-vars)
                  (cons arg-name default-vals)
                  (cons arg entry-vars)
                  (cons arg-name entry-vals)
-                 (rest vars) supplied-p-p body aux-vars aux-vals cont))))
+                 (rest vars) supplied-p-p body aux-vars aux-vals cont
+                 source-name debug-name))))
 
     (convert-optional-entry ep default-vars default-vals
                            (if supplied-p
 ;;; type when computing the type for the main entry's argument.
 (defun ir1-convert-more (res default-vars default-vals entry-vars entry-vals
                             rest more-context more-count keys supplied-p-p
-                            body aux-vars aux-vals cont)
+                            body aux-vars aux-vals cont
+                            source-name debug-name)
   (declare (type optional-dispatch res)
           (list default-vars default-vals entry-vars entry-vals keys body
                 aux-vars aux-vals)
                        :aux-vars (append (bind-vars) aux-vars)
                        :aux-vals (append (bind-vals) aux-vals)
                        :result cont
-                       :debug-name (debug-namify "~S processor" '&more)))
+                       :debug-name (debug-namify "varargs entry point for ~A"
+                                                 (as-debug-name source-name
+                                                                debug-name))))
           (last-entry (convert-optional-entry main-entry default-vars
                                               (main-vals) ())))
       (setf (optional-dispatch-main-entry res) main-entry)
 (defun ir1-convert-hairy-args (res default-vars default-vals
                                    entry-vars entry-vals
                                    vars supplied-p-p body aux-vars
-                                   aux-vals cont)
+                                   aux-vals cont
+                                  source-name debug-name)
   (declare (type optional-dispatch res)
            (list default-vars default-vals entry-vars entry-vals vars body
                  aux-vars aux-vals)
              (ir1-convert-more res default-vars default-vals
                                entry-vars entry-vals
                                nil nil nil vars supplied-p-p body aux-vars
-                               aux-vals cont)
+                               aux-vals cont source-name debug-name)
              (let ((fun (ir1-convert-lambda-body
                         body (reverse default-vars)
                         :aux-vars aux-vars
                         :aux-vals aux-vals
                         :result cont
-                        :debug-name "hairy arg processor")))
+                        :debug-name (debug-namify
+                                     "hairy arg processor for ~A"
+                                     (as-debug-name source-name
+                                                    debug-name)))))
                (setf (optional-dispatch-main-entry res) fun)
                (push (if supplied-p-p
                          (convert-optional-entry fun entry-vars entry-vals ())
                 (nvals (cons (leaf-source-name arg) default-vals)))
            (ir1-convert-hairy-args res nvars nvals nvars nvals
                                    (rest vars) nil body aux-vars aux-vals
-                                   cont)))
+                                   cont
+                                  source-name debug-name)))
         (t
          (let* ((arg (first vars))
                 (info (lambda-var-arg-info arg))
               (let ((ep (generate-optional-default-entry
                          res default-vars default-vals
                          entry-vars entry-vals vars supplied-p-p body
-                         aux-vars aux-vals cont)))
+                         aux-vars aux-vals cont
+                        source-name debug-name)))
                 (push (if supplied-p-p
                           (convert-optional-entry ep entry-vars entry-vals ())
                           ep)
               (ir1-convert-more res default-vars default-vals
                                 entry-vars entry-vals
                                 arg nil nil (rest vars) supplied-p-p body
-                                aux-vars aux-vals cont))
+                                aux-vars aux-vals cont
+                               source-name debug-name))
              (:more-context
               (ir1-convert-more res default-vars default-vals
                                 entry-vars entry-vals
                                 nil arg (second vars) (cddr vars) supplied-p-p
-                                body aux-vars aux-vals cont))
+                                body aux-vars aux-vals cont
+                               source-name debug-name))
              (:keyword
               (ir1-convert-more res default-vars default-vals
                                 entry-vars entry-vals
                                 nil nil nil vars supplied-p-p body aux-vars
-                                aux-vals cont)))))))
+                                aux-vals cont source-name debug-name)))))))
 
 ;;; This function deals with the case where we have to make an
 ;;; OPTIONAL-DISPATCH to represent a LAMBDA. We cons up the result and
                                     :%source-name source-name
                                     :%debug-name debug-name))
        (min (or (position-if #'lambda-var-arg-info vars) (length vars))))
+    (aver-live-component *current-component*)
     (push res (component-new-funs *current-component*))
     (ir1-convert-hairy-args res () () () () vars nil body aux-vars aux-vals
-                           cont)
+                           cont source-name debug-name)
     (setf (optional-dispatch-min-args res) min)
     (setf (optional-dispatch-max-args res)
          (+ (1- (length (optional-dispatch-entry-points res))) min))
 
 ;;; Convert a LAMBDA form into a LAMBDA leaf or an OPTIONAL-DISPATCH leaf.
 (defun ir1-convert-lambda (form &key (source-name '.anonymous.) debug-name)
+
   (unless (consp form)
     (compiler-error "A ~S was found when expecting a lambda expression:~%  ~S"
                    (type-of form)
                    form))
   (unless (and (consp (cdr form)) (listp (cadr form)))
     (compiler-error
-     "The lambda expression has a missing or non-list lambda-list:~%  ~S"
+     "The lambda expression has a missing or non-list lambda list:~%  ~S"
      form))
 
   (multiple-value-bind (vars keyp allow-other-keys aux-vars aux-vals)
-      (find-lambda-vars (cadr form))
+      (make-lambda-vars (cadr form))
     (multiple-value-bind (forms decls) (sb!sys:parse-body (cddr form))
-      (let* ((cont (make-continuation))
+      (let* ((result-cont (make-continuation))
             (*lexenv* (process-decls decls
                                      (append aux-vars vars)
-                                     nil cont))
+                                     nil result-cont))
             (res (if (or (find-if #'lambda-var-arg-info vars) keyp)
                      (ir1-convert-hairy-lambda forms vars keyp
                                                allow-other-keys
-                                               aux-vars aux-vals cont
+                                               aux-vars aux-vals result-cont
                                                :source-name source-name
                                                :debug-name debug-name)
                      (ir1-convert-lambda-body forms vars
                                               :aux-vars aux-vars
                                               :aux-vals aux-vals
-                                              :result cont
+                                              :result result-cont
                                               :source-name source-name
                                               :debug-name debug-name))))
        (setf (functional-inline-expansion res) form)
            (specifier-type 'function))))
 
   (values))
-\f
-;;;; hacking function names
-
-;;; This is like LAMBDA, except the result is tweaked so that FUN-NAME
-;;; can extract a name. (Also possibly the name could also be used at
-;;; compile time to emit more-informative name-based compiler
-;;; diagnostic messages as well.)
-(defmacro-mundanely named-lambda (name args &body body)
-
-  ;; FIXME: For now, in this stub version, we just discard the name. A
-  ;; non-stub version might use either macro-level LOAD-TIME-VALUE
-  ;; hackery or customized IR1-transform level magic to actually put
-  ;; the name in place.
-  (aver (legal-fun-name-p name))
-  `(lambda ,args ,@body))