-@mkVirtStkOffsets@ is given a list of arguments. The first argument
-gets the {\em largest} virtual stack offset (remember, virtual offsets
-increase towards the top of stack).
-
-\begin{code}
-mkVirtStkOffsets :: VirtualSpAOffset -- Offset of the last allocated thing
- -> VirtualSpBOffset -- ditto
- -> (a -> PrimRep) -- to be able to grab kinds
- -> [a] -- things to make offsets for
- -> (VirtualSpAOffset, -- OUTPUTS: Topmost allocated word
- VirtualSpBOffset, -- ditto
- [(a, VirtualSpAOffset)], -- boxed things with offsets
- [(a, VirtualSpBOffset)]) -- unboxed things with offsets
-
-mkVirtStkOffsets init_SpA_offset init_SpB_offset kind_fun things
- = let (boxeds, unboxeds)
- = separateByPtrFollowness kind_fun things
- (last_SpA_offset, boxd_w_offsets)
- = mapAccumR computeOffset init_SpA_offset boxeds
- (last_SpB_offset, ubxd_w_offsets)
- = mapAccumR computeOffset init_SpB_offset unboxeds
- in
- (last_SpA_offset, last_SpB_offset, boxd_w_offsets, ubxd_w_offsets)
- where
- computeOffset offset thing
- = (offset + (max 1 . getPrimRepSize . kind_fun) thing, (thing, offset+(1::Int)))
- -- The "max 1" bit is ULTRA important
- -- Why? mkVirtStkOffsets is the unique function that lays out function
- -- arguments on the stack. The "max 1" ensures that every argument takes
- -- at least one stack slot, even if it's of kind VoidKind that actually
- -- takes no space at all.
- -- This is important to make sure that argument satisfaction checks work
- -- properly. Consider
- -- f a b s# = (a,b)
- -- where s# is a VoidKind. f's argument satisfaction check will check
- -- that s# is on the B stack above SuB; but if s# takes zero space, the
- -- check will be ARGS_B_CHK(0), which always succeeds. As a result, even
- -- if a,b aren't available either, the PAP update won't trigger and
- -- we are throughly hosed. (SLPJ 96/05)
-\end{code}