0.8.3.70:
[sbcl.git] / src / compiler / node.lisp
index 293641e..0025ca5 100644 (file)
 
 (in-package "SB!C")
 
-;;; The front-end data structure (IR1) is composed of nodes and
-;;; continuations. The general idea is that continuations contain
-;;; top-down information and nodes contain bottom-up, derived
-;;; information. A continuation represents a place in the code, while
-;;; a node represents code that does something.
-;;;
-;;; This representation is more of a flow-graph than an augmented
-;;; syntax tree. The evaluation order is explicitly represented in the
-;;; linkage by continuations, rather than being implicit in the nodes
-;;; which receive the the results of evaluation. This allows us to
-;;; decouple the flow of results from the flow of control. A
-;;; continuation represents both, but the continuation can represent
-;;; the case of a discarded result by having no DEST.
+;;; The front-end data structure (IR1) is composed of nodes,
+;;; representing actual evaluations. Linear sequences of nodes in
+;;; control-flow order are combined into blocks (but see
+;;; JOIN-SUCCESSOR-IF-POSSIBLE for precise conditions); control
+;;; transfers inside a block are represented with CTRANs and between
+;;; blocks -- with BLOCK-SUCC/BLOCK-PRED lists; data transfers are
+;;; represented with LVARs.
 
-(def!struct (continuation
+;;; "Lead-in" Control TRANsfer [to some node]
+(def!struct (ctran
             (:make-load-form-fun ignore-it)
-            (:constructor make-continuation (&optional dest)))
+            (:constructor make-ctran))
   ;; an indication of the way that this continuation is currently used
   ;;
   ;; :UNUSED
   ;;   until it is assigned a block, and may be also be temporarily
   ;;   unused during later manipulations of IR1. In a consistent
   ;;   state there should never be any mention of :UNUSED
-  ;;   continuations. Next can have a non-null value if the next node
+  ;;   continuations. NEXT can have a non-null value if the next node
   ;;   has already been determined.
   ;;
-  ;; :DELETED
-  ;;   A continuation that has been deleted from IR1. Any pointers into
-  ;;   IR1 are cleared. There are two conditions under which a deleted
-  ;;   continuation may appear in code:
-  ;;    -- The CONT of the LAST node in a block may be a deleted
-  ;;       continuation when the original receiver of the continuation's
-  ;;       value was deleted. Note that DEST in a deleted continuation is
-  ;;       null, so it is easy to know not to attempt delivering any
-  ;;       values to the continuation.
-  ;;    -- Unreachable code that hasn't been deleted yet may receive
-  ;;       deleted continuations. All such code will be in blocks that
-  ;;       have DELETE-P set. All unreachable code is deleted by control
-  ;;       optimization, so the backend doesn't have to worry about this.
-  ;;
   ;; :BLOCK-START
-  ;;   The continuation that is the START of BLOCK. This is the only kind
-  ;;   of continuation that can have more than one use. The BLOCK's
-  ;;   START-USES is a list of all the uses.
-  ;;
-  ;; :DELETED-BLOCK-START
-  ;;   Like :BLOCK-START, but BLOCK has been deleted. A block
-  ;;   starting continuation is made into a deleted block start when
-  ;;   the block is deleted, but the continuation still may have
-  ;;   value semantics. Since there isn't any code left, next is
-  ;;   null.
+  ;;   The continuation that is the START of BLOCK.
   ;;
   ;; :INSIDE-BLOCK
-  ;;   A continuation that is the CONT of some node in BLOCK.
-  (kind :unused :type (member :unused :deleted :inside-block :block-start
-                             :deleted-block-start))
-  ;; The node which receives this value, if any. In a deleted
-  ;; continuation, this is null even though the node that receives
-  ;; this continuation may not yet be deleted.
-  (dest nil :type (or node null))
-  ;; If this is a NODE, then it is the node which is to be evaluated
-  ;; next. This is always null in :DELETED and :UNUSED continuations,
-  ;; and will be null in a :INSIDE-BLOCK continuation when this is the
-  ;; CONT of the LAST.
+  ;;   A continuation that is the NEXT of some node in BLOCK.
+  (kind :unused :type (member :unused :inside-block :block-start))
+  ;; A NODE which is to be evaluated next. Null only temporary.
   (next nil :type (or node null))
-  ;; an assertion on the type of this continuation's value
-  (asserted-type *wild-type* :type ctype)
-  ;; cached type of this continuation's value. If NIL, then this must
-  ;; be recomputed: see CONTINUATION-DERIVED-TYPE.
-  (%derived-type nil :type (or ctype null))
-  ;; the node where this continuation is used, if unique. This is always
-  ;; null in :DELETED and :UNUSED continuations, and is never null in
-  ;; :INSIDE-BLOCK continuations. In a :BLOCK-START continuation, the
-  ;; Block's START-USES indicate whether NIL means no uses or more
-  ;; than one use.
+  ;; the node where this CTRAN is used, if unique. This is always null
+  ;; in :UNUSED and :BLOCK-START CTRANs, and is never null in
+  ;; :INSIDE-BLOCK continuations.
   (use nil :type (or node null))
   ;; the basic block this continuation is in. This is null only in
-  ;; :DELETED and :UNUSED continuations. Note that blocks that are
-  ;; unreachable but still in the DFO may receive deleted
-  ;; continuations, so it isn't o.k. to assume that any continuation
-  ;; that you pick up out of its DEST node has a BLOCK.
-  (block nil :type (or cblock null))
-  ;; set to true when something about this continuation's value has
-  ;; changed. See REOPTIMIZE-CONTINUATION. This provides a way for IR1
+  ;; :UNUSED continuations.
+  (block nil :type (or cblock null)))
+
+(def!method print-object ((x ctran) stream)
+  (print-unreadable-object (x stream :type t :identity t)
+    (format stream " #~D" (cont-num x))))
+
+;;; Linear VARiable. Multiple-value (possibly of unknown number)
+;;; temporal storage.
+(def!struct (lvar
+            (:make-load-form-fun ignore-it)
+            (:constructor make-lvar (&optional dest)))
+  ;; The node which receives this value. NIL only temporarily.
+  (dest nil :type (or node null))
+  ;; cached type of this lvar's value. If NIL, then this must be
+  ;; recomputed: see LVAR-DERIVED-TYPE.
+  (%derived-type nil :type (or ctype null))
+  ;; the node (if unique) or a list of nodes where this lvar is used.
+  (uses nil :type (or node list))
+  ;; set to true when something about this lvar's value has
+  ;; changed. See REOPTIMIZE-LVAR. This provides a way for IR1
   ;; optimize to determine which operands to a node have changed. If
   ;; the optimizer for this node type doesn't care, it can elect not
   ;; to clear this flag.
   (reoptimize t :type boolean)
-  ;; an indication of what we have proven about how this contination's
-  ;; type assertion is satisfied:
-  ;;
-  ;; NIL
-  ;;    No type check is necessary (proven type is a subtype of the assertion.)
-  ;;
-  ;; T
-  ;;    A type check is needed.
-  ;;
-  ;; :DELETED
-  ;;    Don't do a type check, but believe (intersect) the assertion.
-  ;;    A T check can be changed to :DELETED if we somehow prove the
-  ;;    check is unnecessary, or if we eliminate it through a policy
-  ;;    decision.
-  ;;
-  ;; :NO-CHECK
-  ;;    Type check generation sets the slot to this if a check is
-  ;;    called for, but it believes it has proven that the check won't
-  ;;    be done for policy reasons or because a safe implementation
-  ;;    will be used. In the latter case, LTN must ensure that a safe
-  ;;    implementation *is* used.
-  ;;
-  ;; This is computed lazily by CONTINUATION-DERIVED-TYPE, so use
-  ;; CONTINUATION-TYPE-CHECK instead of the %'ed slot accessor.
-  (%type-check t :type (member t nil :deleted :no-check))
-  ;; Asserted type, weakend according to policies
-  (type-to-check *wild-type* :type ctype)
   ;; Cached type which is checked by DEST. If NIL, then this must be
-  ;; recomputed: see CONTINUATION-EXTERNALLY-CHECKABLE-TYPE.
+  ;; recomputed: see LVAR-EXTERNALLY-CHECKABLE-TYPE.
   (%externally-checkable-type nil :type (or null ctype))
-  ;; something or other that the back end annotates this continuation with
-  (info nil)
-  ;; uses of this continuation in the lexical environment. They are
-  ;; recorded so that when one continuation is substituted for another
-  ;; the environment may be updated properly.
-  (lexenv-uses nil :type list))
+  ;; something or other that the back end annotates this lvar with
+  (info nil))
 
-(def!method print-object ((x continuation) stream)
-  (print-unreadable-object (x stream :type t :identity t)))
+(def!method print-object ((x lvar) stream)
+  (print-unreadable-object (x stream :type t :identity t)
+    (format stream " #~D" (cont-num x))))
 
 (defstruct (node (:constructor nil)
                 (:copier nil))
   ;; unique ID for debugging
   #!+sb-show (id (new-object-id) :read-only t)
-  ;; the bottom-up derived type for this node. This does not take into
-  ;; consideration output type assertions on this node (actually on its CONT).
-  (derived-type *wild-type* :type ctype)
   ;; True if this node needs to be optimized. This is set to true
-  ;; whenever something changes about the value of a continuation
-  ;; whose DEST is this node.
+  ;; whenever something changes about the value of an lvar whose DEST
+  ;; is this node.
   (reoptimize t :type boolean)
-  ;; the continuation which receives the value of this node. This also
-  ;; indicates what we do controlwise after evaluating this node. This
-  ;; may be null during IR1 conversion.
-  (cont nil :type (or continuation null))
-  ;; the continuation that this node is the next of. This is null
-  ;; during IR1 conversion when we haven't linked the node in yet or
-  ;; in nodes that have been deleted from the IR1 by UNLINK-NODE.
-  (prev nil :type (or continuation null))
+  ;; the ctran indicating what we do controlwise after evaluating this
+  ;; node. This is null if the node is the last in its block.
+  (next nil :type (or ctran null))
+  ;; the ctran that this node is the NEXT of. This is null during IR1
+  ;; conversion when we haven't linked the node in yet or in nodes
+  ;; that have been deleted from the IR1 by UNLINK-NODE.
+  (prev nil :type (or ctran null))
   ;; the lexical environment this node was converted in
   (lexenv *lexenv* :type lexenv)
   ;; a representation of the source code responsible for generating
   ;; can null out this slot.
   (tail-p nil :type boolean))
 
+(defstruct (valued-node (:conc-name node-)
+                        (:include node)
+                        (:constructor nil)
+                        (:copier nil))
+  ;; the bottom-up derived type for this node.
+  (derived-type *wild-type* :type ctype)
+  ;; Lvar, receiving the values, produced by this node. May be NIL if
+  ;; the value is unused.
+  (lvar nil :type (or lvar null)))
+
 ;;; Flags that are used to indicate various things about a block, such
 ;;; as what optimizations need to be done on it:
 ;;; -- REOPTIMIZE is set when something interesting happens the uses of a
-;;;    continuation whose DEST is in this block. This indicates that the
+;;;    lvar whose DEST is in this block. This indicates that the
 ;;;    value-driven (forward) IR1 optimizations should be done on this block.
 ;;; -- FLUSH-P is set when code in this block becomes potentially flushable,
-;;;    usually due to a continuation's DEST becoming null.
+;;;    usually due to an lvar's DEST becoming null.
 ;;; -- TYPE-CHECK is true when the type check phase should be run on this
 ;;;    block. IR1 optimize can introduce new blocks after type check has
 ;;;    already run. We need to check these blocks, but there is no point in
 ;;;    phases should not attempt to examine or modify blocks with DELETE-P
 ;;;    set, since they may:
 ;;;     - be in the process of being deleted, or
-;;;     - have no successors, or
-;;;     - receive :DELETED continuations.
+;;;     - have no successors.
 ;;; -- TYPE-ASSERTED, TEST-MODIFIED
 ;;;    These flags are used to indicate that something in this block
 ;;;    might be of interest to constraint propagation. TYPE-ASSERTED
-;;;    is set when a continuation type assertion is strengthened.
+;;;    is set when an lvar type assertion is strengthened.
 ;;;    TEST-MODIFIED is set whenever the test for the ending IF has
 ;;;    changed (may be true when there is no IF.)
 (!def-boolean-attribute block
                   (:constructor make-block (start))
                   (:constructor make-block-key)
                   (:conc-name block-)
-                  (:predicate block-p)
-                  (:copier copy-block))
+                  (:predicate block-p))
   ;; a list of all the blocks that are predecessors/successors of this
   ;; block. In well-formed IR1, most blocks will have one successor.
   ;; The only exceptions are:
   ;;  3. blocks with DELETE-P set (zero)
   (pred nil :type list)
   (succ nil :type list)
-  ;; the continuation which heads this block (either a :BLOCK-START or
-  ;; :DELETED-BLOCK-START), or NIL when we haven't made the start
-  ;; continuation yet (and in the dummy component head and tail
-  ;; blocks)
-  (start nil :type (or continuation null))
-  ;; a list of all the nodes that have START as their CONT
-  (start-uses nil :type list)
+  ;; the ctran which heads this block (a :BLOCK-START), or NIL when we
+  ;; haven't made the start ctran yet (and in the dummy component head
+  ;; and tail blocks)
+  (start nil :type (or ctran null))
   ;; the last node in this block. This is NIL when we are in the
   ;; process of building a block (and in the dummy component head and
   ;; tail blocks.)
   (flags (block-attributes reoptimize flush-p type-check type-asserted
                           test-modified)
         :type attributes)
-  ;; CMU CL had a KILL slot here, documented as "set used by
-  ;; constraint propagation", which was used in constraint propagation
-  ;; as a list of LAMBDA-VARs killed, and in copy propagation as an
-  ;; SSET, representing I dunno what. I (WHN) found this confusing,
-  ;; and furthermore it caused type errors when I was trying to make
-  ;; the compiler produce fully general LAMBDA functions directly
-  ;; (instead of doing as CMU CL always did, producing extra little
-  ;; functions which return the LAMDBA you need) and therefore taking
-  ;; a new path through the compiler. So I split this into two:
-  ;;   KILL-LIST = list of LAMBDA-VARs killed, used in constraint propagation
-  ;;   KILL-SSET = an SSET value, used in copy propagation
-  (kill-list nil :type list)
-  (kill-sset nil :type (or sset null))
+  ;; in constraint propagation: list of LAMBDA-VARs killed in this block
+  ;; in copy propagation: list of killed TNs
+  (kill nil)
   ;; other sets used in constraint propagation and/or copy propagation
   (gen nil)
   (in nil)
   (flag nil)
   ;; some kind of info used by the back end
   (info nil)
-  ;; If true, then constraints that hold in this block and its
-  ;; successors by merit of being tested by its IF predecessor.
+  ;; constraints that hold in this block and its successors by merit
+  ;; of being tested by its IF predecessors.
   (test-constraint nil :type (or sset null)))
 (def!method print-object ((cblock cblock) stream)
   (print-unreadable-object (cblock stream :type t :identity t)
 ;;;   size of flow analysis problems, this allows back-end data
 ;;;   structures to be reclaimed after the compilation of each
 ;;;   component.
-(defstruct (component (:copier nil))
+(defstruct (component (:copier nil)
+                      (:constructor
+                       make-component (head tail &aux (last-block tail))))
   ;; unique ID for debugging
   #!+sb-show (id (new-object-id) :read-only t)
   ;; the kind of component
   ;; the blocks that are the dummy head and tail of the DFO
   ;;
   ;; Entry/exit points have these blocks as their
-  ;; predecessors/successors. Null temporarily. The start and return
-  ;; from each non-deleted function is linked to the component head
-  ;; and tail. Until physical environment analysis links NLX entry
-  ;; stubs to the component head, every successor of the head is a
-  ;; function start (i.e. begins with a BIND node.)
-  (head nil :type (or null cblock))
-  (tail nil :type (or null cblock))
+  ;; predecessors/successors. The start and return from each
+  ;; non-deleted function is linked to the component head and
+  ;; tail. Until physical environment analysis links NLX entry stubs
+  ;; to the component head, every successor of the head is a function
+  ;; start (i.e. begins with a BIND node.)
+  (head (missing-arg) :type cblock)
+  (tail (missing-arg) :type cblock)
+  ;; New blocks are inserted before this.
+  (last-block (missing-arg) :type cblock)
   ;; This becomes a list of the CLAMBDA structures for all functions
   ;; in this component. OPTIONAL-DISPATCHes are represented only by
   ;; their XEP and other associated lambdas. This doesn't contain any
 ;;; The "mess-up" action is explicitly represented by a funny function
 ;;; call or ENTRY node.
 ;;;
-;;; We guarantee that CLEANUPs only need to be done at block boundaries
-;;; by requiring that the exit continuations initially head their
+;;; We guarantee that CLEANUPs only need to be done at block
+;;; boundaries by requiring that the exit ctrans initially head their
 ;;; blocks, and then by not merging blocks when there is a cleanup
 ;;; change.
 (defstruct (cleanup (:copier nil))
 (defstruct (physenv (:copier nil))
   ;; the function that allocates this physical environment
   (lambda (missing-arg) :type clambda :read-only t)
-  #| ; seems not to be used as of sbcl-0.pre7.51
-  ;; a list of all the lambdas that allocate variables in this
-  ;; physical environment
-  (lambdas nil :type list)
-  |#
   ;; This ultimately converges to a list of all the LAMBDA-VARs and
   ;; NLX-INFOs needed from enclosing environments by code in this
   ;; physical environment. In the meantime, it may be
 
 ;;; An NLX-INFO structure is used to collect various information about
 ;;; non-local exits. This is effectively an annotation on the
-;;; CONTINUATION, although it is accessed by searching in the
+;;; continuation, although it is accessed by searching in the
 ;;; PHYSENV-NLX-INFO.
-(def!struct (nlx-info (:make-load-form-fun ignore-it))
+(def!struct (nlx-info (:constructor make-nlx-info
+                                    (cleanup exit &aux (lvar (node-lvar exit))))
+                      (:make-load-form-fun ignore-it))
   ;; the cleanup associated with this exit. In a catch or
   ;; unwind-protect, this is the :CATCH or :UNWIND-PROTECT cleanup,
   ;; and not the cleanup for the escape block. The CLEANUP-KIND of
   ;; For this purpose, the ENTRY must also be used to disambiguate,
   ;; since exits to different places may deliver their result to the
   ;; same continuation.
-  (continuation (missing-arg) :type continuation)
+  (exit (missing-arg) :type exit)
+  (lvar (missing-arg) :type (or lvar null))
   ;; the entry stub inserted by physical environment analysis. This is
   ;; a block containing a call to the %NLX-ENTRY funny function that
   ;; has the original exit destination as its successor. Null only
   ;; some kind of info used by the back end
   info)
 (defprinter (nlx-info :identity t)
-  continuation
+  exit
   target
   info)
 \f
   (sets () :type list))
 
 ;;; The GLOBAL-VAR structure represents a value hung off of the symbol
-;;; NAME. We use a :CONSTANT VAR when we know that the thing is a
-;;; constant, but don't know what the value is at compile time.
+;;; NAME.
 (def!struct (global-var (:include basic-var))
   ;; kind of variable described
   (kind (missing-arg)
   ;; Unlike the SOURCE-NAME slot, this slot's value should never
   ;; affect ordinary code behavior, only debugging/diagnostic behavior.
   ;;
+  ;; Ha.  Ah, the starry-eyed idealism of the writer of the above
+  ;; paragraph.  FUNCTION-LAMBDA-EXPRESSION's behaviour, as of
+  ;; sbcl-0.7.11.x, differs if the name of the a function is a string
+  ;; or not, as if it is a valid function name then it can look for an
+  ;; inline expansion.
+  ;;
   ;; The value of this slot can be anything, except that it shouldn't
   ;; be a legal function name, since otherwise debugging gets
   ;; confusing. (If a legal function name is a good name for the
   ;;   a lambda that is used in only one local call, and has in
   ;;   effect been substituted directly inline. The return node is
   ;;   deleted, and the result is computed with the actual result
-  ;;   continuation for the call.
+  ;;   lvar for the call.
   ;;
   ;;    :MV-LET
   ;;   Similar to :LET (as per FUNCTIONAL-LETLIKE-P), but the call
   ;; KIND was :TOPLEVEL. Now it must be set explicitly, both for
   ;; :TOPLEVEL functions and for any other kind of functions that we
   ;; want to dump or return from #'CL:COMPILE or whatever.
-  (has-external-references-p nil) 
+  (has-external-references-p nil)
   ;; In a normal function, this is the external entry point (XEP)
   ;; lambda for this function, if any. Each function that is used
   ;; other than in a local call has an XEP, and all of the
       ;; anonymous. In SBCL (as opposed to CMU CL) we make all
       ;; FUNCTIONALs have debug names. The CMU CL code didn't bother
       ;; in many FUNCTIONALs, especially those which were likely to be
-      ;; optimized away before the user saw them. However, getting 
+      ;; optimized away before the user saw them. However, getting
       ;; that right requires a global understanding of the code,
       ;; which seems bad, so we just require names for everything.
       (leaf-source-name functional)))
   ;; bind (because there are no variables left), but have not yet
   ;; actually deleted the LAMBDA yet.
   (bind nil :type (or bind null))
-  ;; the RETURN node for this LAMBDA, or NIL if it has been deleted.
-  ;; This marks the end of the lambda, receiving the result of the
-  ;; body. In a LET, the return node is deleted, and the body delivers
-  ;; the value to the actual continuation. The return may also be
+  ;; the RETURN node for this LAMBDA, or NIL if it has been
+  ;; deleted. This marks the end of the lambda, receiving the result
+  ;; of the body. In a LET, the return node is deleted, and the body
+  ;; delivers the value to the actual lvar. The return may also be
   ;; deleted if it is unreachable.
   (return nil :type (or creturn null))
   ;; If this CLAMBDA is a LET, then this slot holds the LAMBDA whose
   ;; the total number of required and optional arguments. Args at
   ;; positions >= to this are &REST, &KEY or illegal args.
   (max-args 0 :type unsigned-byte)
-  ;; list of the LAMBDAs which are the entry points for non-rest,
-  ;; non-key calls. The entry for MIN-ARGS is first, MIN-ARGS+1
-  ;; second, ... MAX-ARGS last. The last entry-point always calls the
-  ;; main entry; in simple cases it may be the main entry.
+  ;; list of the (maybe delayed) LAMBDAs which are the entry points
+  ;; for non-rest, non-key calls. The entry for MIN-ARGS is first,
+  ;; MIN-ARGS+1 second, ... MAX-ARGS last. The last entry-point always
+  ;; calls the main entry; in simple cases it may be the main entry.
   (entry-points nil :type list)
   ;; an entry point which takes MAX-ARGS fixed arguments followed by
   ;; an argument context pointer and an argument count. This entry
 ;;; end must check for and ignore unreferenced variables. Note that a
 ;;; deleted LAMBDA-VAR may have sets; in this case the back end is
 ;;; still responsible for propagating the SET-VALUE to the set's CONT.
-(def!struct (lambda-var (:include basic-var))
+(!def-boolean-attribute lambda-var
   ;; true if this variable has been declared IGNORE
-  (ignorep nil :type boolean)
-  ;; the CLAMBDA that this var belongs to. This may be null when we are
-  ;; building a lambda during IR1 conversion.
-  (home nil :type (or null clambda))
+  ignore
   ;; This is set by physical environment analysis if it chooses an
   ;; indirect (value cell) representation for this variable because it
   ;; is both set and closed over.
-  (indirect nil :type boolean)
+  indirect)
+
+(def!struct (lambda-var (:include basic-var))
+  (flags (lambda-var-attributes)
+         :type attributes)
+  ;; the CLAMBDA that this var belongs to. This may be null when we are
+  ;; building a lambda during IR1 conversion.
+  (home nil :type (or null clambda))
   ;; The following two slots are only meaningful during IR1 conversion
   ;; of hairy lambda vars:
   ;;
   #!+sb-show id
   (type :test (not (eq type *universal-type*)))
   (where-from :test (not (eq where-from :assumed)))
-  (ignorep :test ignorep)
+  (flags :test (not (zerop flags))
+         :prin1 (decode-lambda-var-attributes flags))
   (arg-info :test arg-info)
   (specvar :test specvar))
+
+(defmacro lambda-var-ignorep (var)
+  `(lambda-var-attributep (lambda-var-flags ,var) ignore))
+(defmacro lambda-var-indirect (var)
+  `(lambda-var-attributep (lambda-var-flags ,var) indirect))
 \f
 ;;;; basic node types
 
 ;;; A REF represents a reference to a LEAF. REF-REOPTIMIZE is
 ;;; initially (and forever) NIL, since REFs don't receive any values
 ;;; and don't have any IR1 optimizer.
-(defstruct (ref (:include node (reoptimize nil))
-               (:constructor make-ref (derived-type leaf))
+(defstruct (ref (:include valued-node (reoptimize nil))
+               (:constructor make-ref
+                              (leaf
+                               &aux (leaf-type (leaf-type leaf))
+                                    (derived-type
+                                     (make-single-value-type leaf-type))))
                (:copier nil))
   ;; The leaf referenced.
   (leaf nil :type leaf))
   leaf)
 
 ;;; Naturally, the IF node always appears at the end of a block.
-;;; NODE-CONT is a dummy continuation, and is there only to keep
-;;; people happy.
 (defstruct (cif (:include node)
                (:conc-name if-)
                (:predicate if-p)
                (:constructor make-if)
                (:copier copy-if))
-  ;; CONTINUATION for the predicate
-  (test (missing-arg) :type continuation)
+  ;; LVAR for the predicate
+  (test (missing-arg) :type lvar)
   ;; the blocks that we execute next in true and false case,
   ;; respectively (may be the same)
   (consequent (missing-arg) :type cblock)
   (alternative (missing-arg) :type cblock))
 (defprinter (cif :conc-name if- :identity t)
-  (test :prin1 (continuation-use test))
+  (test :prin1 (lvar-uses test))
   consequent
   alternative)
 
-(defstruct (cset (:include node
-                          (derived-type *universal-type*))
+(defstruct (cset (:include valued-node
+                          (derived-type (make-single-value-type
+                                          *universal-type*)))
                 (:conc-name set-)
                 (:predicate set-p)
                 (:constructor make-set)
                 (:copier copy-set))
   ;; descriptor for the variable set
   (var (missing-arg) :type basic-var)
-  ;; continuation for the value form
-  (value (missing-arg) :type continuation))
+  ;; LVAR for the value form
+  (value (missing-arg) :type lvar))
 (defprinter (cset :conc-name set- :identity t)
   var
-  (value :prin1 (continuation-use value)))
+  (value :prin1 (lvar-uses value)))
 
 ;;; The BASIC-COMBINATION structure is used to represent both normal
-;;; and multiple value combinations. In a local function call, this
+;;; and multiple value combinations. In a let-like function call, this
 ;;; node appears at the end of its block and the body of the called
-;;; function appears as the successor. The NODE-CONT remains the
-;;; continuation which receives the value of the call.
-(defstruct (basic-combination (:include node)
+;;; function appears as the successor; the NODE-LVAR is null.
+(defstruct (basic-combination (:include valued-node)
                              (:constructor nil)
                              (:copier nil))
-  ;; continuation for the function
-  (fun (missing-arg) :type continuation)
-  ;; list of CONTINUATIONs for the args. In a local call, an argument
-  ;; continuation may be replaced with NIL to indicate that the
-  ;; corresponding variable is unreferenced, and thus no argument
-  ;; value need be passed.
+  ;; LVAR for the function
+  (fun (missing-arg) :type lvar)
+  ;; list of LVARs for the args. In a local call, an argument lvar may
+  ;; be replaced with NIL to indicate that the corresponding variable
+  ;; is unreferenced, and thus no argument value need be passed.
   (args nil :type list)
   ;; the kind of function call being made. :LOCAL means that this is a
   ;; local call to a function in the same component, and that argument
                        (:copier nil)))
 (defprinter (combination :identity t)
   #!+sb-show id
-  (fun :prin1 (continuation-use fun))
+  (fun :prin1 (lvar-uses fun))
   (args :prin1 (mapcar (lambda (x)
                         (if x
-                            (continuation-use x)
+                            (lvar-uses x)
                             "<deleted>"))
                       args)))
 
+(defun call-full-like-p (call)
+  (declare (type combination call))
+  (let ((kind (basic-combination-kind call)))
+    (or (eq kind :full)
+        (and (fun-info-p kind)
+             (null (fun-info-templates kind))
+             (not (fun-info-ir2-convert kind))))))
+
 ;;; An MV-COMBINATION is to MULTIPLE-VALUE-CALL as a COMBINATION is to
 ;;; FUNCALL. This is used to implement all the multiple-value
 ;;; receiving forms.
                           (:constructor make-mv-combination (fun))
                           (:copier nil)))
 (defprinter (mv-combination)
-  (fun :prin1 (continuation-use fun))
-  (args :prin1 (mapcar #'continuation-use args)))
+  (fun :prin1 (lvar-uses fun))
+  (args :prin1 (mapcar #'lvar-uses args)))
 
 ;;; The BIND node marks the beginning of a lambda body and represents
 ;;; the creation and initialization of the variables.
   ;; the lambda we are returning from. Null temporarily during
   ;; ir1tran.
   (lambda nil :type (or clambda null))
-  ;; the continuation which yields the value of the lambda
-  (result (missing-arg) :type continuation)
+  ;; the lvar which yields the value of the lambda
+  (result (missing-arg) :type lvar)
   ;; the union of the node-derived-type of all uses of the result
   ;; other than by a local call, intersected with the result's
   ;; asserted-type. If there are no non-call uses, this is
 (defprinter (creturn :conc-name return- :identity t)
   lambda
   result-type)
+
+;;; The CAST node represents type assertions. The check for
+;;; TYPE-TO-CHECK is performed and then the VALUE is declared to be of
+;;; type ASSERTED-TYPE.
+(defstruct (cast (:include valued-node)
+                 (:constructor %make-cast))
+  (asserted-type (missing-arg) :type ctype)
+  (type-to-check (missing-arg) :type ctype)
+  ;; an indication of what we have proven about how this type
+  ;; assertion is satisfied:
+  ;;
+  ;; NIL
+  ;;    No type check is necessary (VALUE type is a subtype of the TYPE-TO-CHECK.)
+  ;;
+  ;; T
+  ;;    A type check is needed.
+  (%type-check t :type (member t nil))
+  ;; the lvar which is checked
+  (value (missing-arg) :type lvar))
+(defprinter (cast :identity t)
+  %type-check
+  value
+  asserted-type
+  type-to-check)
 \f
 ;;;; non-local exit support
 ;;;;
 ;;; if necessary. This is interposed between the uses of the exit
 ;;; continuation and the exit continuation's DEST. Instead of using
 ;;; the returned value being delivered directly to the exit
-;;; continuation, it is delivered to our VALUE continuation. The
-;;; original exit continuation is the exit node's CONT.
-(defstruct (exit (:include node)
+;;; continuation, it is delivered to our VALUE lvar. The original exit
+;;; lvar is the exit node's LVAR.
+(defstruct (exit (:include valued-node)
                 (:copier nil))
   ;; the ENTRY node that this is an exit for. If null, this is a
   ;; degenerate exit. A degenerate exit is used to "fill" an empty
   ;; block (which isn't allowed in IR1.) In a degenerate exit, Value
   ;; is always also null.
   (entry nil :type (or entry null))
-  ;; the continuation yielding the value we are to exit with. If NIL,
-  ;; then no value is desired (as in GO).
-  (value nil :type (or continuation null)))
+  ;; the lvar yielding the value we are to exit with. If NIL, then no
+  ;; value is desired (as in GO).
+  (value nil :type (or lvar null)))
 (defprinter (exit :identity t)
   #!+sb-show id
   (entry :test entry)
 ;;;; Freeze some structure types to speed type testing.
 
 #!-sb-fluid
-(declaim (freeze-type node leaf lexenv continuation cblock component cleanup
+(declaim (freeze-type node leaf lexenv ctran lvar cblock component cleanup
                      physenv tail-set nlx-info))