Note [Unarisation]
The idea of this pass is to translate away *all* unboxed-tuple and unboxed-sum
binders. So for example:
f (x :: (# Int, Bool #)) = f x + f (# 1, True #)
==>
f (x1 :: Int) (x2 :: Bool) = f x1 x2 + f 1 True
It is important that we do this at the STG level and NOT at the Core level
because it would be very hard to make this pass Core-type-preserving. In this
example the type of 'f' changes, for example.
STG fed to the code generators *must* be unarised because the code generators do
not support unboxed tuple and unboxed sum binders natively.
In more detail: (see next note for unboxed sums)
Suppose that a variable x : (# t1, t2 #).
* At the binding site for x, make up fresh vars x1:t1, x2:t2
* Extend the UnariseEnv x :-> MultiVal [x1,x2]
* Replace the binding with a curried binding for x1,x2
Lambda: \x.e ==> \x1 x2. e
Case alt: MkT a b x c d -> e ==> MkT a b x1 x2 c d -> e
* Replace argument occurrences with a sequence of args via a lookup in
UnariseEnv
f a b x c d ==> f a b x1 x2 c d
* Replace tail-call occurrences with an unboxed tuple via a lookup in
UnariseEnv
x ==> (# x1, x2 #)
So, for example
f x = x ==> f x1 x2 = (# x1, x2 #)
* We /always/ eliminate a case expression when
- It scrutinises an unboxed tuple or unboxed sum
- The scrutinee is a variable (or when it is an explicit tuple, but the
simplifier eliminates those)
The case alternative (there can be only one) can be one of these two
things:
- An unboxed tuple pattern. e.g.
case v of x { (# x1, x2, x3 #) -> ... }
Scrutinee has to be in form `(# t1, t2, t3 #)` so we just extend the
environment with
x :-> MultiVal [t1,t2,t3]
x1 :-> UnaryVal t1, x2 :-> UnaryVal t2, x3 :-> UnaryVal t3
- A DEFAULT alternative. Just the same, without the bindings for x1,x2,x3
By the end of this pass, we only have unboxed tuples in return positions.
Unboxed sums are completely eliminated, see next note. References 0
This Note does not link to any other.
Referenced by 2
- Constructor applications in STG GHC.Stg.Syntax
- GHC.Types.RepType call site