New implementation of BLACKHOLEs
[ghc-hetmet.git] / compiler / codeGen / CgStackery.lhs
index bcb59ce..532127a 100644 (file)
@@ -17,7 +17,7 @@ module CgStackery (
        setStackFrame, getStackFrame,
        mkVirtStkOffsets, mkStkAmodes,
        freeStackSlots, 
-       pushUpdateFrame, emitPushUpdateFrame,
+       pushUpdateFrame, pushBHUpdateFrame, emitPushUpdateFrame,
     ) where
 
 #include "HsVersions.h"
@@ -198,25 +198,23 @@ allocPrimStack rep
 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}
@@ -231,7 +229,7 @@ A knot-tying beast.
 \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) })
@@ -267,6 +265,14 @@ to reflect the frame pushed.
 \begin{code}
 pushUpdateFrame :: CmmExpr -> Code -> Code
 pushUpdateFrame updatee code
+  = pushSpecUpdateFrame mkUpdInfoLabel updatee code
+
+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 ;
@@ -279,15 +285,25 @@ pushUpdateFrame updatee code
                -- 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