+Unboxed tuples are handled slightly differently - the object is
+returned in registers and on the stack instead of the heap.
+
+\begin{code}
+bindUnboxedTupleComponents
+ :: [Id] -- Aargs
+ -> FCode ([MagicId], -- Regs assigned
+ Int, -- Number of pointer stack slots
+ Int, -- Number of non-pointer stack slots
+ VirtualSpOffset) -- Offset of return address slot
+ -- (= realSP on entry)
+
+bindUnboxedTupleComponents args
+ = -- Assign as many components as possible to registers
+ let (arg_regs, _leftovers) = assignRegs [] (map idPrimRep args)
+ (reg_args, stk_args) = splitAtList arg_regs args
+
+ -- separate the rest of the args into pointers and non-pointers
+ (ptr_args, nptr_args) =
+ partition (isFollowableRep . idPrimRep) stk_args
+ in
+
+ -- Allocate the rest on the stack
+ -- The real SP points to the return address, above which any
+ -- leftover unboxed-tuple components will be allocated
+ getVirtSp `thenFC` \ vsp ->
+ getRealSp `thenFC` \ rsp ->
+ let
+ (ptr_sp, ptr_offsets) = mkVirtStkOffsets rsp idPrimRep ptr_args
+ (nptr_sp, nptr_offsets) = mkVirtStkOffsets ptr_sp idPrimRep nptr_args
+ ptrs = ptr_sp - rsp
+ nptrs = nptr_sp - ptr_sp
+ in
+
+ -- The stack pointer points to the last stack-allocated component
+ setRealAndVirtualSp nptr_sp `thenC`
+
+ -- We have just allocated slots starting at real SP + 1, and set the new
+ -- virtual SP to the topmost allocated slot.
+ -- If the virtual SP started *below* the real SP, we've just jumped over
+ -- some slots that won't be in the free-list, so put them there
+ -- This commonly happens because we've freed the return-address slot
+ -- (trimming back the virtual SP), but the real SP still points to that slot
+ freeStackSlots [vsp+1,vsp+2 .. rsp] `thenC`
+
+ bindArgsToRegs reg_args arg_regs `thenC`
+ mapCs bindNewToStack ptr_offsets `thenC`
+ mapCs bindNewToStack nptr_offsets `thenC`
+
+ returnFC (arg_regs, ptrs, nptrs, rsp)
+\end{code}