(This is the module that knows all about stack layouts, etc.)
\begin{code}
-{-# OPTIONS -w #-}
--- The above warning supression flag is a temporary kludge.
--- While working on this module you are encouraged to remove it and fix
--- any warnings in the module. See
--- http://hackage.haskell.org/trac/ghc/wiki/CodingStyle#Warnings
--- for details
-
module CgStackery (
spRel, getVirtSp, getRealSp, setRealSp,
setRealAndVirtualSp, getSpRelOffset,
setStackFrame, getStackFrame,
mkVirtStkOffsets, mkStkAmodes,
freeStackSlots,
- pushUpdateFrame, emitPushUpdateFrame,
+ pushUpdateFrame, pushBHUpdateFrame, emitPushUpdateFrame,
) where
#include "HsVersions.h"
import CLabel
import Constants
import Util
-import FastString
import OrdList
import Outputable
+
+import Control.Monad
\end{code}
%************************************************************************
= loop init_Sp_offset [] (reverse things)
where
loop offset offs [] = (offset,offs)
- loop offset offs ((VoidArg,t):things) = loop offset offs things
+ loop offset offs ((VoidArg,_):things) = loop offset offs things
-- ignore Void arguments
loop offset offs ((rep,t):things)
= loop thing_slot ((t,thing_slot):offs) things
Allocate a chunk ON TOP OF the stack.
\begin{code}
-allocStackTop :: WordOff -> FCode VirtualSpOffset
+allocStackTop :: WordOff -> FCode ()
allocStackTop size
= do { stk_usg <- getStkUsage
; let push_virt_sp = virtSp stk_usg + size
; setStkUsage (stk_usg { virtSp = push_virt_sp,
- hwSp = hwSp stk_usg `max` push_virt_sp })
- ; return push_virt_sp }
+ hwSp = hwSp stk_usg `max` push_virt_sp }) }
\end{code}
Pop some words from the current top of stack. This is used for
de-allocating the return address in a case alternative.
\begin{code}
-deAllocStackTop :: WordOff -> FCode VirtualSpOffset
+deAllocStackTop :: WordOff -> FCode ()
deAllocStackTop size
= do { stk_usg <- getStkUsage
; let pop_virt_sp = virtSp stk_usg - size
- ; setStkUsage (stk_usg { virtSp = pop_virt_sp })
- ; return pop_virt_sp }
+ ; setStkUsage (stk_usg { virtSp = pop_virt_sp }) }
\end{code}
\begin{code}
\begin{code}
getFinalStackHW :: (VirtualSpOffset -> Code) -> Code
getFinalStackHW fcode
- = do { fixC (\hw_sp -> do
+ = do { fixC_ (\hw_sp -> do
{ fcode hw_sp
; stk_usg <- getStkUsage
; return (hwSp stk_usg) })
\begin{code}
pushUpdateFrame :: CmmExpr -> Code -> Code
-
pushUpdateFrame updatee code
- = do {
-#ifdef DEBUG
- EndOfBlockInfo _ sequel <- getEndOfBlockInfo ;
- ASSERT(case sequel of { OnStack -> True; _ -> False})
-#endif
+ = pushSpecUpdateFrame mkUpdInfoLabel updatee code
- allocStackTop (fixedHdrSize +
+pushBHUpdateFrame :: CmmExpr -> Code -> Code
+pushBHUpdateFrame updatee code
+ = pushSpecUpdateFrame mkBHUpdInfoLabel updatee code
+
+pushSpecUpdateFrame :: CLabel -> CmmExpr -> Code -> Code
+pushSpecUpdateFrame lbl updatee code
+ = do {
+ when debugIsOn $ do
+ { EndOfBlockInfo _ sequel <- getEndOfBlockInfo ;
+ ; MASSERT(case sequel of { OnStack -> True; _ -> False}) }
+ ; allocStackTop (fixedHdrSize +
sIZEOF_StgUpdateFrame_NoHdr `quot` wORD_SIZE)
; vsp <- getVirtSp
; setStackFrame vsp
-- The location of the lowest-address
-- word of the update frame itself
- ; setEndOfBlockInfo (EndOfBlockInfo vsp UpdateCode) $
- do { emitPushUpdateFrame frame_addr updatee
+ -- NB. we used to set the Sequel to 'UpdateCode' so
+ -- that we could jump directly to the update code if
+ -- we know that the next frame on the stack is an
+ -- update frame. However, the RTS can sometimes
+ -- change an update frame into something else (see
+ -- e.g. Note [upd-black-hole] in rts/sm/Scav.c), so we
+ -- no longer make this assumption.
+ ; setEndOfBlockInfo (EndOfBlockInfo vsp OnStack) $
+ do { emitSpecPushUpdateFrame lbl frame_addr updatee
; code }
}
emitPushUpdateFrame :: CmmExpr -> CmmExpr -> Code
-emitPushUpdateFrame frame_addr updatee = do
+emitPushUpdateFrame = emitSpecPushUpdateFrame mkUpdInfoLabel
+
+emitSpecPushUpdateFrame :: CLabel -> CmmExpr -> CmmExpr -> Code
+emitSpecPushUpdateFrame lbl frame_addr updatee = do
stmtsC [ -- Set the info word
- CmmStore frame_addr (mkLblExpr mkUpdInfoLabel)
+ CmmStore frame_addr (mkLblExpr lbl)
, -- And the updatee
CmmStore (cmmOffsetB frame_addr off_updatee) updatee ]
initUpdFrameProf frame_addr
off_updatee :: ByteOff
off_updatee = fixedHdrSize*wORD_SIZE + oFFSET_StgUpdateFrame_updatee
-\end{code}
+\end{code}
%************************************************************************