+\begin{code}
+mkVirtStkOffsets
+ :: VirtualSpOffset -- Offset of the last allocated thing
+ -> [(CgRep,a)] -- things to make offsets for
+ -> (VirtualSpOffset, -- OUTPUTS: Topmost allocated word
+ [(a, VirtualSpOffset)]) -- things with offsets (voids filtered out)
+
+mkVirtStkOffsets init_Sp_offset things
+ = loop init_Sp_offset [] (reverse things)
+ where
+ loop offset offs [] = (offset,offs)
+ loop offset offs ((VoidArg,t):things) = loop offset offs things
+ -- ignore Void arguments
+ loop offset offs ((rep,t):things)
+ = loop thing_slot ((t,thing_slot):offs) things
+ where
+ thing_slot = offset + cgRepSizeW rep
+ -- offset of thing is offset+size, because we're
+ -- growing the stack *downwards* as the offsets increase.
+
+-- | 'mkStkAmodes' is a higher-level version of
+-- 'mkVirtStkOffsets'. It starts from the tail-call locations.
+-- It returns a single list of addressing modes for the stack
+-- locations, and therefore is in the monad. It /doesn't/ adjust the
+-- high water mark.
+
+mkStkAmodes
+ :: VirtualSpOffset -- Tail call positions
+ -> [(CgRep,CmmExpr)] -- things to make offsets for
+ -> FCode (VirtualSpOffset, -- OUTPUTS: Topmost allocated word
+ CmmStmts) -- Assignments to appropriate stk slots
+
+mkStkAmodes tail_Sp things
+ = do { rSp <- getRealSp
+ ; let (last_Sp_offset, offsets) = mkVirtStkOffsets tail_Sp things
+ abs_cs = [ CmmStore (cmmRegOffW spReg (spRel rSp offset)) amode
+ | (amode, offset) <- offsets
+ ]
+ ; returnFC (last_Sp_offset, toOL abs_cs) }