| ThunkInfo ClosureLayout C_SRT
| ThunkSelectorInfo SelectorOffset C_SRT
| ContInfo
- [Maybe LocalReg] -- stack layout
+ [Maybe LocalReg] -- Stack layout: Just x, an item x
+ -- Nothing: a 1-word gap
+ -- Start of list is the *young* end
C_SRT
data CmmReturnInfo = CmmMayReturn
deriving (Eq, Ord)
data AreaId
- = Old -- entry parameters, jumps, and returns share one call area at old end of stack
+ = Old -- See Note [Old Area]
| Young BlockId
deriving (Eq, Ord)
+{- Note [Old Area]
+~~~~~~~~~~~~~~~~~~
+There is a single call area 'Old', allocated at the extreme old
+end of the stack frame (ie just younger than the return address)
+which holds:
+ * incoming (overflow) parameters,
+ * outgoing (overflow) parameter to tail calls,
+ * outgoing (overflow) result values
+ * the update frame (if any)
+
+Its size is the max of all these requirements. On entry, the stack
+pointer will point to the youngest incoming parameter, which is not
+necessarily at the young end of the Old area.
+
+End of note -}
+
type SubArea = (Area, Int, Int) -- area, offset, width
type SubAreaSet = FiniteMap Area [SubArea]
type AreaMap = FiniteMap Area Int
-- one -> second block etc
-- Undefined outside range, and when there's a Nothing
| LastCall { -- A call (native or safe foreign)
- cml_target :: CmmExpr, -- never a CmmPrim to a CallishMachOp!
- cml_cont :: Maybe BlockId,
+ cml_target :: CmmExpr, -- never a CmmPrim to a CallishMachOp!
+
+ cml_cont :: Maybe BlockId,
-- BlockId of continuation (Nothing for return or tail call)
- cml_args :: ByteOff, -- byte offset for youngest outgoing arg
- -- (includes update frame, which must be younger)
- cml_ret_args:: ByteOff, -- byte offset for youngest incoming arg
- cml_ret_off :: Maybe UpdFrameOffset}
- -- stack offset for return (update frames);
+
+ cml_args :: ByteOff,
+ -- Byte offset, from the *old* end of the Area associated with
+ -- the BlockId (if cml_cont = Nothing, then Old area), of
+ -- youngest outgoing arg. Set the stack pointer to this before
+ -- transferring control.
+ -- (NB: an update frame might also have been stored in the Old
+ -- area, but it'll be in an older part than the args.)
+
+ cml_ret_args :: ByteOff,
+ -- For calls *only*, the byte offset for youngest returned value
+ -- This is really needed at the *return* point rather than here
+ -- at the call, but in practice it's convenient to record it here.
+
+ cml_ret_off :: Maybe UpdFrameOffset
+ -- Stack offset for return (update frames);
-- The return offset should be Nothing only if we have to create
-- a new call, e.g. for a procpoint, in which case it's an invariant
-- that the call does not stand for a return or a tail call,
-- and the successor does not need an info table.
+ }
data MidCallTarget -- The target of a MidUnsafeCall
= ForeignTarget -- A foreign procedure