0.pre7.114:
[sbcl.git] / src / compiler / ir2tran.lisp
index 9d96c87..db462db 100644 (file)
 ;;;; leaf reference
 
 ;;; Return the TN that holds the value of THING in the environment ENV.
+(declaim (ftype (function ((or nlx-info lambda-var) physenv) tn)
+               find-in-physenv))
 (defun find-in-physenv (thing physenv)
-  (declare (type (or nlx-info lambda-var) thing) (type physenv physenv)
-          (values tn))
-  (or (cdr (assoc thing (ir2-physenv-environment (physenv-info physenv))))
+  (or (cdr (assoc thing (ir2-physenv-closure (physenv-info physenv))))
       (etypecase thing
        (lambda-var
         ;; I think that a failure of this assertion means that we're
   (declare (type ref node) (type ir2-block block))
   (let* ((cont (node-cont node))
         (leaf (ref-leaf node))
-        (name (leaf-name leaf))
         (locs (continuation-result-tns
                cont (list (primitive-type (leaf-type leaf)))))
         (res (first locs)))
       (constant
        (if (legal-immediate-constant-p leaf)
           (emit-move node block (constant-tn leaf) res)
-          (let ((name-tn (emit-constant name)))
+          (let* ((name (leaf-source-name leaf))
+                 (name-tn (emit-constant name)))
             (if (policy node (zerop safety))
                 (vop fast-symbol-value node block name-tn res)
                 (vop symbol-value node block name-tn res)))))
       (functional
        (ir2-convert-closure node block leaf res))
       (global-var
-       (let ((unsafe (policy node (zerop safety))))
+       (let ((unsafe (policy node (zerop safety)))
+            (name (leaf-source-name leaf)))
         (ecase (global-var-kind leaf)
-          ((:special :global :constant)
+          ((:special :global)
            (aver (symbolp name))
            (let ((name-tn (emit-constant name)))
              (if unsafe
     (move-continuation-result node block locs cont))
   (values))
 
-;;; Emit code to load a function object representing LEAF into RES.
-;;; This gets interesting when the referenced function is a closure:
-;;; we must make the closure and move the closed over values into it.
+;;; Emit code to load a function object implementing FUN into
+;;; RES. This gets interesting when the referenced function is a
+;;; closure: we must make the closure and move the closed-over values
+;;; into it.
 ;;;
-;;; LEAF is either a :TOP-LEVEL-XEP functional or the XEP lambda for
-;;; the called function, since local call analysis converts all
-;;; closure references. If a TL-XEP, we know it is not a closure.
+;;; FUN is either a :TOPLEVEL-XEP functional or the XEP lambda for the
+;;; called function, since local call analysis converts all closure
+;;; references. If a :TOPLEVEL-XEP, we know it is not a closure.
 ;;;
 ;;; If a closed-over LAMBDA-VAR has no refs (is deleted), then we
 ;;; don't initialize that slot. This can happen with closures over
-;;; top-level variables, where optimization of the closure deleted the
+;;; top level variables, where optimization of the closure deleted the
 ;;; variable. Since we committed to the closure format when we
-;;; pre-analyzed the top-level code, we just leave an empty slot.
-(defun ir2-convert-closure (node block leaf res)
-  (declare (type ref node) (type ir2-block block)
-          (type functional leaf) (type tn res))
-  (unless (leaf-info leaf)
-    (setf (leaf-info leaf) (make-entry-info)))
-  (let ((entry (make-load-time-constant-tn :entry leaf))
-       (closure (etypecase leaf
+;;; pre-analyzed the top level code, we just leave an empty slot.
+(defun ir2-convert-closure (ref ir2-block fun res)
+  (declare (type ref ref) (type ir2-block ir2-block)
+          (type functional fun) (type tn res))
+
+  (unless (leaf-info fun)
+    (setf (leaf-info fun)
+         (make-entry-info :name (functional-debug-name fun))))
+  (let ((entry (make-load-time-constant-tn :entry fun))
+       (closure (etypecase fun
                   (clambda
-                   (physenv-closure (get-lambda-physenv leaf)))
+
+                   ;; This assertion was sort of an experiment. It
+                   ;; would be nice and sane and easier to understand
+                   ;; things if it were *always* true, but
+                   ;; experimentally I observe that it's only
+                   ;; *almost* always true. -- WHN 2001-01-02
+                   #+nil 
+                   (aver (eql (lambda-component fun)
+                              (block-component (ir2-block-block ir2-block))))
+
+                   ;; Check for some weirdness which came up in bug
+                   ;; 138, 2002-01-02.
+                   ;;
+                   ;; The MAKE-LOAD-TIME-CONSTANT-TN call above puts
+                   ;; an :ENTRY record into the
+                   ;; IR2-COMPONENT-CONSTANTS table. The
+                   ;; dump-a-COMPONENT code
+                   ;;   * treats every HANDLEless :ENTRY record into a
+                   ;;     patch, and
+                   ;;   * expects every patch to correspond to an
+                   ;;     IR2-COMPONENT-ENTRIES record.
+                   ;; The IR2-COMPONENT-ENTRIES records are set by
+                   ;; ENTRY-ANALYZE walking over COMPONENT-LAMBDAS.
+                   ;; Bug 138b arose because there was a HANDLEless
+                   ;; :ENTRY record which didn't correspond to an
+                   ;; IR2-COMPONENT-ENTRIES record. That problem is
+                   ;; hard to debug when it's caught at dump time, so
+                   ;; this assertion tries to catch it here.
+                   (aver (member fun
+                                 (component-lambdas (lambda-component fun))))
+
+                   ;; another bug-138-related issue: COMPONENT-NEW-FUNS
+                   ;; is an IR1 temporary, and now that we're doing IR2
+                   ;; it should've been completely flushed (but wasn't).
+                   (aver (null (component-new-funs (lambda-component fun))))
+
+                   (physenv-closure (get-lambda-physenv fun)))
                   (functional
-                   (aver (eq (functional-kind leaf) :top-level-xep))
+                   (aver (eq (functional-kind fun) :toplevel-xep))
                    nil))))
+
     (cond (closure
-          (let ((this-env (node-physenv node)))
-            (vop make-closure node block entry (length closure) res)
+          (let ((this-env (node-physenv ref)))
+            (vop make-closure ref ir2-block entry (length closure) res)
             (loop for what in closure and n from 0 do
               (unless (and (lambda-var-p what)
                            (null (leaf-refs what)))
-                (vop closure-init node block
+                (vop closure-init ref ir2-block
                      res
                      (find-in-physenv what this-env)
                      n)))))
          (t
-          (emit-move node block entry res))))
+          (emit-move ref ir2-block entry res))))
   (values))
 
 ;;; Convert a SET node. If the node's CONT is annotated, then we also
       (global-var
        (ecase (global-var-kind leaf)
         ((:special :global)
-         (aver (symbolp (leaf-name leaf)))
-         (vop set node block (emit-constant (leaf-name leaf)) val)))))
+         (aver (symbolp (leaf-source-name leaf)))
+         (vop set node block (emit-constant (leaf-source-name leaf)) val)))))
     (when locs
       (emit-move node block val (first locs))
       (move-continuation-result node block locs cont)))
          dest))
   (values))
 
-;;; If necessary, emit coercion code needed to deliver the Results to
+;;; If necessary, emit coercion code needed to deliver the RESULTS to
 ;;; the specified continuation. NODE and BLOCK provide context for
 ;;; emitting code. Although usually obtained from STANDARD-RESULT-TNs
 ;;; or CONTINUATION-RESULT-TNs, RESULTS my be a list of any type or
            (locs loc))))
 
       (when old-fp
-       (dolist (thing (ir2-physenv-environment called-env))
+       (dolist (thing (ir2-physenv-closure called-env))
          (temps (find-in-physenv (car thing) this-1env))
          (locs (cdr thing)))
        
          ((node-tail-p node)
           (ir2-convert-tail-local-call node block fun))
          (t
-          (let ((start (block-label (node-block (lambda-bind fun))))
+          (let ((start (block-label (lambda-block fun)))
                 (returns (tail-set-info (lambda-tail-set fun)))
                 (cont (node-cont node)))
             (ecase (if returns
 \f
 ;;;; full call
 
-;;; Given a function continuation Fun, return as values a TN holding
+;;; Given a function continuation FUN, return as values a TN holding
 ;;; the thing that we call and true if the thing is named (false if it
 ;;; is a function). There are two interesting non-named cases:
-;;; -- Known to be a function, no check needed: return the continuation loc.
-;;; -- Not known what it is.
+;;;   -- Known to be a function, no check needed: return the
+;;;      continuation loc.
+;;;   -- Not known what it is.
 (defun function-continuation-tn (node block cont)
   (declare (type continuation cont))
   (let ((2cont (continuation-info cont)))
     (if (eq (ir2-continuation-kind 2cont) :delayed)
-       (let ((name (continuation-function-name cont t)))
+       (let ((name (continuation-fun-name cont t)))
          (aver name)
          (values (make-load-time-constant-tn :fdefinition name) t))
        (let* ((locs (ir2-continuation-locs 2cont))
 ;;;     a DEFSETF or some such thing elsewhere in the program?
 (defun check-full-call (node)
   (let* ((cont (basic-combination-fun node))
-        (fname (continuation-function-name cont t)))
+        (fname (continuation-fun-name cont t)))
     (declare (type (or symbol cons) fname))
 
     #!+sb-show (unless (gethash fname *full-called-fnames*)
   (declare (type bind node) (type ir2-block block) (type clambda fun))
   (let ((start-label (entry-info-offset (leaf-info fun)))
        (env (physenv-info (node-physenv node))))
-    (let ((ef (functional-entry-function fun)))
+    (let ((ef (functional-entry-fun fun)))
       (cond ((and (optional-dispatch-p ef) (optional-dispatch-more-entry ef))
             ;; Special case the xep-allocate-frame + copy-more-arg case.
             (vop xep-allocate-frame node block start-label t)
            (t
             ;; No more args, so normal entry.
             (vop xep-allocate-frame node block start-label nil)))
-      (if (ir2-physenv-environment env)
+      (if (ir2-physenv-closure env)
          (let ((closure (make-normal-tn *backend-t-primitive-type*)))
            (vop setup-closure-environment node block start-label closure)
            (when (getf (functional-plist ef) :fin-function)
              (vop funcallable-instance-lexenv node block closure closure))
            (let ((n -1))
-             (dolist (loc (ir2-physenv-environment env))
+             (dolist (loc (ir2-physenv-closure env))
                (vop closure-ref node block closure (incf n) (cdr loc)))))
          (vop setup-environment node block start-label)))
 
-    (unless (eq (functional-kind fun) :top-level)
+    (unless (eq (functional-kind fun) :toplevel)
       (let ((vars (lambda-vars fun))
            (n 0))
        (when (leaf-refs (first vars))
   (let* ((fun (bind-lambda node))
         (env (physenv-info (lambda-physenv fun))))
     (aver (member (functional-kind fun)
-                 '(nil :external :optional :top-level :cleanup)))
+                 '(nil :external :optional :toplevel :cleanup)))
 
-    (when (external-entry-point-p fun)
+    (when (xep-p fun)
       (init-xep-environment node block fun)
       #!+sb-dyncount
       (when *collect-dynamic-statistics*
         (returns (tail-set-info (lambda-tail-set fun))))
     (cond
      ((and (eq (return-info-kind returns) :fixed)
-          (not (external-entry-point-p fun)))
+          (not (xep-p fun)))
       (let ((locs (continuation-tns node block cont
                                    (return-info-types returns))))
        (vop* known-return node block
 ;;; stack. It returns the OLD-FP and RETURN-PC for the current
 ;;; function as multiple values.
 (defoptimizer (sb!kernel:%caller-frame-and-pc ir2-convert) (() node block)
-  (let ((env (physenv-info (node-physenv node))))
+  (let ((ir2-physenv (physenv-info (node-physenv node))))
     (move-continuation-result node block
-                             (list (ir2-physenv-old-fp env)
-                                   (ir2-physenv-return-pc env))
+                             (list (ir2-physenv-old-fp ir2-physenv)
+                                   (ir2-physenv-return-pc ir2-physenv))
                              (node-cont node))))
 \f
 ;;;; multiple values
 ;;; This is trivial, given our assumption of a shallow-binding
 ;;; implementation.
 (defoptimizer (%special-bind ir2-convert) ((var value) node block)
-  (let ((name (leaf-name (continuation-value var))))
+  (let ((name (leaf-source-name (continuation-value var))))
     (vop bind node block (continuation-tn node block value)
         (emit-constant name))))
 (defoptimizer (%special-unbind ir2-convert) ((var) node block)
            (ir2-continuation-locs (continuation-info (second args)))
            nil))
          (nil)))
-
   (move-continuation-result node block () (node-cont node))
   (values))
 
            (when *collect-dynamic-statistics*
              (let ((first-node (continuation-next (block-start block))))
                (unless (or (and (bind-p first-node)
-                                (external-entry-point-p
-                                 (bind-lambda first-node)))
-                           (eq (continuation-function-name
+                                (xep-p (bind-lambda first-node)))
+                           (eq (continuation-fun-name
                                 (node-cont first-node))
                                '%nlx-entry))
                  (vop count-me
                          (eq (basic-combination-kind last) :full))
                 (let* ((fun (basic-combination-fun last))
                        (use (continuation-use fun))
-                       (name (and (ref-p use) (leaf-name (ref-leaf use)))))
+                       (name (and (ref-p use)
+                                  (leaf-has-source-name-p (ref-leaf use))
+                                  (leaf-source-name (ref-leaf use)))))
                   (unless (or (node-tail-p last)
                               (info :function :info name)
                               (policy last (zerop safety)))
         (cond
          ((eq (basic-combination-kind node) :local)
           (ir2-convert-mv-bind node 2block))
-         ((eq (continuation-function-name (basic-combination-fun node))
+         ((eq (continuation-fun-name (basic-combination-fun node))
               '%throw)
           (ir2-convert-throw node 2block))
          (t