x86 backend design

Matthew Fluet fluet@research.nj.nec.com
Mon, 26 Jun 2000 14:06:58 -0400 (EDT)


> You would of course create a new sum type for every place Operand.t
> occurs on as a constructor argument in the Operand.t datatype (I count 
> six such occurrences).
> 
> Does this seem reasonable?

I think it's a reasonable idea, but I think it would be nontrivial to add
it to the existing machine/machine-output framework.  For example, one of
the simplest variants should be CastInt of t, which should only be applied
to some pointer variant (Register, StackOffset, etc.)  But, looking at
backend.fun, the only application of machine.castInt is wrapped up in the
genCase function, which sometimes needs the test as a full operand and
sometimes passes off to castInt.  The basic issue is that backend.fun
gives every variable an operand in it's property list and passes around
the varOperand function to get the corresponding operand.  Since this
varOperand is used all over the place, some serious reworking would be
required.  And the actual applications of the ArrayOffset variant is even
more difficult to track down.

And, even if we were to push such a hierarchy through, I'm not sure that
it would give us the information that we want.  The real "typing" issue
that we would like to check is that the base for an offset should always
be a pointer type, but just restricting it to a Register.t or
StackOffset.t doesn't enforce it.  

>       structure ArrayOffsetBase:
>          sig
>             datatype t =
>                Global of Global.t
>              | Register of Register.t 
>              | StackOffset of int
>          end
> 
> Then, you would change structure Operand so that instead of
>
>         val arrayOffset: {base: t, offset: t, ty: Type.t} -> t
>
> you would have
> 
>         val arrayOffset: {base: ArrayOffsetBase.t, offset: t, ty: Type.t}
>                          -> t

And, while this takes care of part of the "deepness" issue, it still is
important to distinguish between Register.t and StackOffset in the x86
backend -- because RP(20) is a directly addressible piece of memory, while
SP(20) requires one more level of indirection.  So, some case analysis
would still need to be done to determine the complexities of the
StackOffset vs. Register.