+%********************************************************
+%* *
+%* Setting up update frames *
+%* *
+%********************************************************
+
+@pushUpdateFrame@ $updatee$ pushes a general update frame which
+points to $updatee$ as the thing to be updated. It is only used
+when a thunk has just been entered, so the (real) stack pointers
+are guaranteed to be nicely aligned with the top of stack.
+@pushUpdateFrame@ adjusts the virtual and tail stack pointers
+to reflect the frame pushed.
+
+\begin{code}
+pushUpdateFrame :: CmmExpr -> Code -> Code
+
+pushUpdateFrame updatee code
+ = do {
+#ifdef DEBUG
+ EndOfBlockInfo _ sequel <- getEndOfBlockInfo ;
+ ASSERT(case sequel of { OnStack -> True; _ -> False})
+#endif
+
+ allocStackTop (fixedHdrSize +
+ sIZEOF_StgUpdateFrame_NoHdr `quot` wORD_SIZE)
+ ; vsp <- getVirtSp
+ ; setStackFrame vsp
+ ; frame_addr <- getSpRelOffset vsp
+ -- The location of the lowest-address
+ -- word of the update frame itself
+
+ ; setEndOfBlockInfo (EndOfBlockInfo vsp UpdateCode) $
+ do { emitPushUpdateFrame frame_addr updatee
+ ; code }
+ }
+
+emitPushUpdateFrame :: CmmExpr -> CmmExpr -> Code
+emitPushUpdateFrame frame_addr updatee = do
+ stmtsC [ -- Set the info word
+ CmmStore frame_addr (mkLblExpr mkUpdInfoLabel)
+ , -- And the updatee
+ CmmStore (cmmOffsetB frame_addr off_updatee) updatee ]
+ initUpdFrameProf frame_addr
+
+off_updatee :: ByteOff
+off_updatee = fixedHdrSize*wORD_SIZE + oFFSET_StgUpdateFrame_updatee