new SSA IL

Matthew Fluet mfluet@intertrust.com
Tue, 7 Aug 2001 22:01:55 -0700 (PDT)


> * Should the common Var.t vector be lifted out of Exp.t and Transfer.t?
>   It would save syntax tree space, but you lose a little bit of compile-time
>   checking (like Select only taking one arg).  I lean very slightly towards
>   not lifting.

I'm not sure what you mean by this.  I think there are enough variantes in
Exp.t and Transfer.t that don't require a Var.t vector.

> * What should be done about case branches and value carrying constructors?
>   Should we stick with the current scheme, in which all selects are done
>   implicitly by the case, or go back to the old scheme, in which the case just
>   narrows the value and there is a separate ConSelect expression?  I lean
>   towards leaving as is, and revisiting the issue after the conversion is
>   complete.

I agree that leaving it as is would be the right first step.

> * Should we create separate classes of labels, Handler.t and Cont.t?
>   If we did this, SetHandler would now take a Handler and nontail Call would
>   take a Cont.  This would give the necessary hooks to the backend for
>   generating the wrapper blocks, but I'm not sure if it helps anywhere else.  I
>   lean against doing this.

The backend is already infering where the wrapper blocks are needed.  On
the other hand, if you look at the machine IL in the live-stack-slots
branch, you'll see that I am starting to make these distinctions more
explicit.  They are even more explicit in the pseudo-x86 IL of the new
codegen.

The only other place that I think it helps is in know where and how to
break blocks up.  In the unusedArgs pass, I introduce wrapper functions
that essentially separate the Handler or Cont label from the Jump block.
If we really made the separation explicity, then I would argue that there
are really three types of blocks: Jump blocks, Handler blocks, and Cont
blocks.  Handler and Cont blocks should just immediately jump to a Jump
block (dropping and/or shuffling args as necessary).  Of course, you've
got a similar issue with Case labels -- mabye there are DeCon blocks as
well.  Anyways, this seems awfully complicated, so I'm not advocating it.

>       structure Function:
> 	 sig
> 	    datatype t =
> 	       T of {
> 		     name: Func.t,
> 		     args: (Var.t * Type.t) vector,
> 		     start: Label.t, (* Must be nullary. *)
> 		     blocks: Block.t vector,
> 		     returns: Type.t vector
> 		     }
> 	 end

I like the start label.  Related to my complaints about the common block
elimination, the fact that there are decs and a transfer that aren't under
a Jump.t can be kind of annoying sometimes.  It also nicely allows us to
rewrite non-tail calls to self as Goto's, which is something that requires
a little hackery in backend.fun (and even more under the new codegen,
where the kind of transfer is more important).