data T = MkT Int Bool Char
f :: (a, b) -> Int -> T
f = \x y -> E
mkWwBodies _ f ['x::(a,b)','y::Int'] '(a,b)' ['1P(L,L)', '1P(L)'] '1'
returns
The wrapper body context for the call to the worker function, lacking
only the Id for the worker function:
W[_] :: Id -> CoreExpr
W[work_fn] = \x y -> -- args of the wrapper (cloned_arg_vars)
case x of (a, b) -> -- unbox wrapper args (wrap_fn_str)
case y of I# n -> --
case <work_fn> a b n of -- call to the worker fun (call_work)
(# i, b, c #) -> MkT i b c -- rebox result (wrap_fn_cpr)
The worker body context that wraps around its hole reboxing defns for x
and y, as well as returning CPR transit variables of the unboxed MkT
result in an unboxed tuple:
w[_] :: CoreExpr -> CoreExpr
w[fn_rhs] = \a b n -> -- args of the worker (work_lam_args)
let { y = I# n; x = (a, b) } in -- reboxing wrapper args (work_fn_str)
case <fn_rhs> x y of -- call to the original RHS (call_rhs)
MkT i b c -> (# i, b, c #) -- return CPR transit vars (work_fn_cpr)
NB: The wrap_rhs hole is to be filled with the original wrapper RHS
x y -> E. This is so that we can also use w to transform stable
unfoldings, the lambda args of which may be different than x and y.
Id details for the worker function like demands on arguments and its join
arity.
All without looking at E (except for beta reduction, see Note [Join points
and beta-redexes]), which allows us to apply the same split to function body
and its unfolding(s) alike.
The information needed to build a pattern for a DataCon to be unboxed.
The pattern can be generated from dcpc_dc and dcpc_tc_args via
dataConRepInstPat. The coercion dcpc_co is for newtype
wrappers.
If we get DataConPatContext dc tys co for some type ty
and dataConRepInstPat ... dc tys = (exs, flds), then
isRecDataCon _ fuel dc, where tc = dataConTyCon dc returns
DefinitelyRecursive if the analysis found that tc is reachable
through one of dc's arg_tys.
NonRecursiveOrUnsure if the analysis found that tc is not reachable
through one of dc's fields (so surely non-recursive).
NonRecursiveOrUnsure when fuel /= Infinity
and fuel expansions of nested data TyCons were not enough to prove
non-recursiveness, nor arrive at an occurrence of tc thus proving
recursiveness. (So not sure if non-recursive.)
NonRecursiveOrUnsure when we hit an abstract TyCon (one without
visible DataCons), such as those imported from .hs-boot files.
Similarly for stuck type and data families.
If fuel = Infinity and there are no boot files involved, then the result
is never Nothing and the analysis is a depth-first search. If fuel = Int
f, then the analysis behaves like a depth-limited DFS and returns Nothing
if the search was inconclusive.
See Note [Detecting recursive data constructors] for which recursive DataCons
we want to flag.
Exactly dataConInstArgTys, but lacks the (ASSERT'ed) precondition that
the DataCon may not have existentials. The lack of cloning the
existentials this function "dubious"; only use it where type variables
aren't substituted for! Why may the data con bind existentials?
See Note [Which types are unboxed?]