[project @ 2003-09-23 14:32:57 by simonmar]
[ghc-hetmet.git] / ghc / compiler / codeGen / CgBindery.lhs
index 4548136..b195b5c 100644 (file)
@@ -8,7 +8,7 @@ module CgBindery (
        CgBindings, CgIdInfo,
        StableLoc, VolatileLoc,
 
-       stableAmodeIdInfo, heapIdInfo, newTempAmodeAndIdInfo,
+       stableAmodeIdInfo, heapIdInfo, 
        letNoEscapeIdInfo, idInfoToAmode,
 
        addBindC, addBindsC,
@@ -18,12 +18,12 @@ module CgBindery (
 
        bindNewToStack,  rebindToStack,
        bindNewToNode, bindNewToReg, bindArgsToRegs,
-       bindNewToTemp, bindNewPrimToAmode,
+       bindNewToTemp, 
        getArgAmode, getArgAmodes,
        getCAddrModeAndInfo, getCAddrMode,
        getCAddrModeIfVolatile, getVolatileRegs,
 
-       buildLivenessMask, buildContLivenessMask
+       buildContLivenessMask
     ) where
 
 #include "HsVersions.h"
@@ -32,23 +32,20 @@ import AbsCSyn
 import CgMonad
 
 import CgUsages                ( getHpRelOffset, getSpRelOffset, getRealSp )
-import CgStackery      ( freeStackSlots )
+import CgStackery      ( freeStackSlots, getStackFrame )
 import CLabel          ( mkClosureLabel,
                          mkBitmapLabel, pprCLabel )
 import ClosureInfo     ( mkLFImported, mkLFArgument, LambdaFormInfo )
-import BitSet          ( mkBS, emptyBS )
+import Bitmap
 import PrimRep         ( isFollowableRep, getPrimRepSize )
-import DataCon         ( DataCon, dataConName )
-import Id              ( Id, idPrimRep, idType, isDataConWrapId )
+import Id              ( Id, idPrimRep, idType )
 import Type            ( typePrimRep )
 import VarEnv
 import VarSet          ( varSetElems )
 import Literal         ( Literal )
-import Maybes          ( catMaybes, maybeToBool )
-import Name            ( isLocallyDefined, NamedThing(..) )
-#ifdef DEBUG
-import PprAbsC         ( pprAmode )
-#endif
+import Maybes          ( catMaybes, maybeToBool, seqMaybe )
+import Name            ( isInternalName, NamedThing(..) )
+import PprAbsC         ( pprAmode, pprMagicId )
 import PrimRep          ( PrimRep(..) )
 import StgSyn          ( StgArg, StgLiveVars, GenStgArg(..), isStgTypeArg )
 import Unique           ( Unique, Uniquable(..) )
@@ -86,7 +83,7 @@ data VolatileLoc
   | TempVarLoc Unique
 
   | RegLoc     MagicId                 -- in one of the magic registers
-                                       -- (probably {Int,Float,Char,etc}Reg
+                                       -- (probably {Int,Float,Char,etc}Reg)
 
   | VirHpLoc   VirtualHeapOffset       -- Hp+offset (address of closure)
 
@@ -110,6 +107,25 @@ maybeStkLoc (VirStkLoc offset) = Just offset
 maybeStkLoc _                 = Nothing
 \end{code}
 
+\begin{code}
+instance Outputable CgIdInfo where
+  ppr (MkCgIdInfo id vol stb lf)
+    = ppr id <+> ptext SLIT("-->") <+> vcat [ppr vol, ppr stb]
+
+instance Outputable VolatileLoc where
+  ppr NoVolatileLoc = empty
+  ppr (TempVarLoc u) = ptext SLIT("tmp") <+> ppr u
+  ppr (RegLoc r)     = ptext SLIT("reg") <+> pprMagicId r
+  ppr (VirHpLoc v)   = ptext SLIT("vh") <+> ppr v
+  ppr (VirNodeLoc v) = ptext SLIT("vn") <+> ppr v
+
+instance Outputable StableLoc where
+  ppr NoStableLoc       = empty
+  ppr (VirStkLoc v)     = ptext SLIT("vs") <+> ppr v
+  ppr (LitLoc l)        = ptext SLIT("lit") <+> ppr l
+  ppr (StableAmodeLoc a) = ptext SLIT("amode") <+> pprAmode a
+\end{code}
+
 %************************************************************************
 %*                                                                     *
 \subsection[Bindery-idInfo]{Manipulating IdInfo}
@@ -124,15 +140,6 @@ tempIdInfo i uniq         lf_info = MkCgIdInfo i (TempVarLoc uniq) NoStableLoc l
 letNoEscapeIdInfo i sp lf_info
   = MkCgIdInfo i NoVolatileLoc (StableAmodeLoc (CJoinPoint sp)) lf_info
 
-newTempAmodeAndIdInfo :: Id -> LambdaFormInfo -> (CAddrMode, CgIdInfo)
-
-newTempAmodeAndIdInfo name lf_info
-  = (temp_amode, temp_idinfo)
-  where
-    uniq               = getUnique name
-    temp_amode = CTemp uniq (idPrimRep name)
-    temp_idinfo = tempIdInfo name uniq lf_info
-
 idInfoToAmode :: PrimRep -> CgIdInfo -> FCode CAddrMode
 idInfoToAmode kind (MkCgIdInfo _ vol stab _) = idInfoPiecesToAmode kind vol stab
 
@@ -177,41 +184,44 @@ The name should not already be bound. (nice ASSERT, eh?)
 
 \begin{code}
 addBindC :: Id -> CgIdInfo -> Code
-addBindC name stuff_to_bind info_down (MkCgState absC binds usage)
-  = MkCgState absC (extendVarEnv binds name stuff_to_bind) usage
+addBindC name stuff_to_bind = do
+       binds <- getBinds
+       setBinds $ extendVarEnv binds name stuff_to_bind
 
 addBindsC :: [(Id, CgIdInfo)] -> Code
-addBindsC new_bindings info_down (MkCgState absC binds usage)
-  = MkCgState absC new_binds usage
-  where
-    new_binds = foldl (\ binds (name,info) -> extendVarEnv binds name info)
-                     binds
-                     new_bindings
+addBindsC new_bindings = do
+       binds <- getBinds
+       let new_binds = foldl (\ binds (name,info) -> extendVarEnv binds name info)
+               binds
+               new_bindings
+       setBinds new_binds
 
 modifyBindC :: Id -> (CgIdInfo -> CgIdInfo) -> Code
-modifyBindC name mangle_fn info_down (MkCgState absC binds usage)
-  = MkCgState absC (modifyVarEnv mangle_fn binds name) usage
+modifyBindC name mangle_fn = do
+       binds <- getBinds
+       setBinds $ modifyVarEnv mangle_fn binds name
 
 lookupBindC :: Id -> FCode CgIdInfo
-lookupBindC name info_down@(MkCgInfoDown _ static_binds srt ticky _)
-                state@(MkCgState absC local_binds usage)
-  = (val, state)
-  where
-    val = case (lookupVarEnv local_binds name) of
-           Nothing     -> try_static
-           Just this   -> this
-
-    try_static = 
-      case (lookupVarEnv static_binds name) of
-       Just this -> this
-       Nothing
-         -> cgPanic (text "lookupBindC: no info for" <+> ppr name) info_down state
-
-cgPanic :: SDoc -> CgInfoDownwards -> CgState -> a
-cgPanic doc info_down@(MkCgInfoDown _ static_binds srt ticky _)
-           state@(MkCgState absC local_binds usage)
-  = pprPanic "cgPanic"
-            (vcat [doc,
+lookupBindC id = do maybe_info <- lookupBindC_maybe id
+                   case maybe_info of
+                     Just info -> return info
+                     Nothing   -> cgLookupPanic id
+
+lookupBindC_maybe :: Id -> FCode (Maybe CgIdInfo)
+lookupBindC_maybe id
+  = do static_binds <- getStaticBinds
+       local_binds  <- getBinds
+       return (lookupVarEnv local_binds id
+                       `seqMaybe`
+               lookupVarEnv static_binds id)
+                       
+cgLookupPanic :: Id -> FCode a
+cgLookupPanic id
+  = do static_binds <- getStaticBinds
+       local_binds <- getBinds
+       srt <- getSRTLabel
+       pprPanic "cgPanic"
+               (vcat [ppr id,
                ptext SLIT("static binds for:"),
                vcat [ ppr i | (MkCgIdInfo i _ _ _) <- rngVarEnv static_binds ],
                ptext SLIT("local binds for:"),
@@ -249,40 +259,29 @@ nukeVolatileBinds binds
 I {\em think} all looking-up is done through @getCAddrMode(s)@.
 
 \begin{code}
-getCAddrModeAndInfo :: Id -> FCode (CAddrMode, LambdaFormInfo)
+getCAddrModeAndInfo :: Id -> FCode (Id, CAddrMode, LambdaFormInfo)
 
 getCAddrModeAndInfo id
-  | not (isLocallyDefined name) || isDataConWrapId id
-       -- Why the isDataConWrapId?  Because CoreToStg changes a call to 
-       -- a nullary constructor worker fn to a call to its wrapper,
-       -- which may not  be defined until later
-
-    {-                 -- OLD: the unpack stuff isn't injected now Jan 2000
-       Why the "isWiredInName"?
-       Imagine you are compiling PrelBase.hs (a module that
-       supplies some of the wired-in values).  What can
-       happen is that the compiler will inject calls to
-       (e.g.) GHCbase.unpackPS, where-ever it likes -- it
-       assumes those values are ubiquitously available.
-       The main point is: it may inject calls to them earlier
-       in GHCbase.hs than the actual definition...
-    -}
-  = returnFC (global_amode, mkLFImported id)
-
-  | otherwise = -- *might* be a nested defn: in any case, it's something whose
-               -- definition we will know about...
-    lookupBindC id `thenFC` \ (MkCgIdInfo _ volatile_loc stable_loc lf_info) ->
-    idInfoPiecesToAmode kind volatile_loc stable_loc `thenFC` \ amode ->
-    returnFC (amode, lf_info)
+  = do
+       maybe_cg_id_info <- lookupBindC_maybe id
+       case maybe_cg_id_info of
+
+               -- Nothing => not in the environment, so should be imported
+         Nothing | isInternalName name -> cgLookupPanic id
+                 | otherwise        -> returnFC (id, global_amode, mkLFImported id)
+
+         Just (MkCgIdInfo id' volatile_loc stable_loc lf_info)
+                 -> do amode <- idInfoPiecesToAmode kind volatile_loc stable_loc
+                       return (id', amode, lf_info)
   where
     name = getName id
     global_amode = CLbl (mkClosureLabel name) kind
     kind = idPrimRep id
 
 getCAddrMode :: Id -> FCode CAddrMode
-getCAddrMode name
-  = getCAddrModeAndInfo name `thenFC` \ (amode, _) ->
-    returnFC amode
+getCAddrMode name = do
+       (_, amode, _) <- getCAddrModeAndInfo name
+       return amode
 \end{code}
 
 \begin{code}
@@ -290,13 +289,13 @@ getCAddrModeIfVolatile :: Id -> FCode (Maybe CAddrMode)
 getCAddrModeIfVolatile name
 --  | toplevelishId name = returnFC Nothing
 --  | otherwise
-  = lookupBindC name `thenFC` \ ~(MkCgIdInfo _ volatile_loc stable_loc lf_info) ->
-    case stable_loc of
-       NoStableLoc ->  -- Aha!  So it is volatile!
-           idInfoPiecesToAmode (idPrimRep name) volatile_loc NoStableLoc `thenFC` \ amode ->
-           returnFC (Just amode)
-
-       a_stable_loc -> returnFC Nothing
+       = do
+       (MkCgIdInfo _ volatile_loc stable_loc lf_info) <- lookupBindC name
+       case stable_loc of
+               NoStableLoc -> do -- Aha!  So it is volatile!
+                       amode <- idInfoPiecesToAmode (idPrimRep name) volatile_loc NoStableLoc
+                       return $ Just amode
+               a_stable_loc -> return Nothing
 \end{code}
 
 @getVolatileRegs@ gets a set of live variables, and returns a list of
@@ -309,50 +308,49 @@ forget the volatile one.
 \begin{code}
 getVolatileRegs :: StgLiveVars -> FCode [MagicId]
 
-getVolatileRegs vars
-  = mapFCs snaffle_it (varSetElems vars) `thenFC` \ stuff ->
-    returnFC (catMaybes stuff)
-  where
-    snaffle_it var
-      = lookupBindC var        `thenFC` \ (MkCgIdInfo _ volatile_loc stable_loc lf_info) ->
-       let
-           -- commoned-up code...
-           consider_reg reg
-             = if not (isVolatileReg reg) then
-                       -- Potentially dies across C calls
-                       -- For now, that's everything; we leave
-                       -- it to the save-macros to decide which
-                       -- regs *really* need to be saved.
-                   returnFC Nothing
-               else
-                   case stable_loc of
-                     NoStableLoc -> returnFC (Just reg) -- got one!
-                     is_a_stable_loc ->
-                       -- has both volatile & stable locations;
-                       -- force it to rely on the stable location
-                       modifyBindC var nuke_vol_bind `thenC`
-                       returnFC Nothing
-       in
-       case volatile_loc of
-         RegLoc reg   -> consider_reg reg
-         VirHpLoc _   -> consider_reg Hp
-         VirNodeLoc _ -> consider_reg node
-         non_reg_loc  -> returnFC Nothing
-
-    nuke_vol_bind (MkCgIdInfo i _ stable_loc lf_info)
-      = MkCgIdInfo i NoVolatileLoc stable_loc lf_info
+getVolatileRegs vars = do
+       stuff <- mapFCs snaffle_it (varSetElems vars)
+       returnFC $ catMaybes stuff
+       where
+       snaffle_it var = do
+               (MkCgIdInfo _ volatile_loc stable_loc lf_info) <- lookupBindC var 
+               let
+               -- commoned-up code...
+                       consider_reg reg =
+                               if not (isVolatileReg reg) then
+                               -- Potentially dies across C calls
+                               -- For now, that's everything; we leave
+                               -- it to the save-macros to decide which
+                               -- regs *really* need to be saved.
+                                       returnFC Nothing
+                               else
+                                       case stable_loc of
+                                               NoStableLoc -> returnFC (Just reg) -- got one!
+                                               is_a_stable_loc -> do
+                                                       -- has both volatile & stable locations;
+                                                       -- force it to rely on the stable location
+                                                       modifyBindC var nuke_vol_bind 
+                                                       return Nothing
+                       in
+                       case volatile_loc of
+                               RegLoc reg   -> consider_reg reg
+                               VirNodeLoc _ -> consider_reg node
+                               non_reg_loc  -> returnFC Nothing
+
+       nuke_vol_bind (MkCgIdInfo i _ stable_loc lf_info)
+               = MkCgIdInfo i NoVolatileLoc stable_loc lf_info
 \end{code}
 
 \begin{code}
 getArgAmodes :: [StgArg] -> FCode [CAddrMode]
 getArgAmodes [] = returnFC []
 getArgAmodes (atom:atoms)
-  | isStgTypeArg atom 
-  = getArgAmodes atoms
-  | otherwise
-  = getArgAmode  atom  `thenFC` \ amode ->
-    getArgAmodes atoms `thenFC` \ amodes ->
-    returnFC ( amode : amodes )
+       | isStgTypeArg atom 
+       = getArgAmodes atoms
+       | otherwise = do
+               amode <- getArgAmode  atom 
+               amodes <- getArgAmodes atoms
+               return ( amode : amodes )
 
 getArgAmode :: StgArg -> FCode CAddrMode
 
@@ -371,7 +369,7 @@ bindNewToStack :: (Id, VirtualSpOffset) -> Code
 bindNewToStack (name, offset)
   = addBindC name info
   where
-    info = MkCgIdInfo name NoVolatileLoc (VirStkLoc offset) mkLFArgument
+    info = MkCgIdInfo name NoVolatileLoc (VirStkLoc offset) (mkLFArgument name)
 
 bindNewToNode :: Id -> VirtualHeapOffset -> LambdaFormInfo -> Code
 bindNewToNode name offset lf_info
@@ -383,14 +381,15 @@ bindNewToNode name offset lf_info
 -- bind the id to it, and return the addressing mode for the
 -- temporary.
 bindNewToTemp :: Id -> FCode CAddrMode
-bindNewToTemp name
-  = let (temp_amode, id_info) = newTempAmodeAndIdInfo name mkLFArgument
-               -- This is used only for things we don't know
-               -- anything about; values returned by a case statement,
-               -- for example.
-    in
-    addBindC name id_info      `thenC`
-    returnFC temp_amode
+bindNewToTemp id
+  = do addBindC id id_info
+       return temp_amode
+  where
+    uniq       = getUnique id
+    temp_amode = CTemp uniq (idPrimRep id)
+    id_info    = tempIdInfo id uniq lf_info
+    lf_info    = mkLFArgument id       -- Always used of things we
+                                       -- know nothing about
 
 bindNewToReg :: Id -> MagicId -> LambdaFormInfo -> Code
 bindNewToReg name magic_id lf_info
@@ -398,34 +397,11 @@ bindNewToReg name magic_id lf_info
   where
     info = MkCgIdInfo name (RegLoc magic_id) NoStableLoc lf_info
 
-bindNewToLit name lit
-  = addBindC name info
-  where
-    info = MkCgIdInfo name NoVolatileLoc (LitLoc lit) (error "bindNewToLit")
-
 bindArgsToRegs :: [Id] -> [MagicId] -> Code
 bindArgsToRegs args regs
   = listCs (zipWithEqual "bindArgsToRegs" bind args regs)
   where
-    arg `bind` reg = bindNewToReg arg reg mkLFArgument
-\end{code}
-
-@bindNewPrimToAmode@ works only for certain addressing modes.  Making
-this work for stack offsets is non-trivial (virt vs. real stack offset
-difficulties).
-
-\begin{code}
-bindNewPrimToAmode :: Id -> CAddrMode -> Code
-bindNewPrimToAmode name (CReg reg) 
-  = bindNewToReg name reg (panic "bindNewPrimToAmode")
-
-bindNewPrimToAmode name (CTemp uniq kind)
-  = addBindC name (tempIdInfo name uniq (panic "bindNewPrimToAmode"))
-
-#ifdef DEBUG
-bindNewPrimToAmode name amode
-  = pprPanic "bindNew...:" (pprAmode amode)
-#endif
+    arg `bind` reg = bindNewToReg arg reg (mkLFArgument arg)
 \end{code}
 
 \begin{code}
@@ -443,8 +419,6 @@ rebindToStack name offset
 %*                                                                     *
 %************************************************************************
 
-ToDo: remove the dependency on 32-bit words.
-
 There are four kinds of things on the stack:
 
        - pointer variables (bound in the environment)
@@ -452,89 +426,52 @@ There are four kinds of things on the stack:
        - free slots (recorded in the stack free list)
        - non-pointer data slots (recorded in the stack free list)
 
-We build up a bitmap of non-pointer slots by looking down the
-environment for all the non-pointer variables, and merging this with
-the slots recorded in the stack free list.
-
-There's a bit of a hack here to do with update frames: since nothing
-is recorded in either the environment or the stack free list for an
-update frame, the code below defaults to assuming the slots taken up
-by an update frame contain pointers.  Furthermore, update frames are
-always in slots 0-2 at the bottom of the stack.  The bitmap will
-therefore end at slot 3, which is what we want (the update frame info
-pointer has its own bitmap to describe the update frame).
+We build up a bitmap of non-pointer slots by searching the environment
+for all the pointer variables, and subtracting these from a bitmap
+with initially all bits set (up to the size of the stack frame).
 
 \begin{code}
 buildLivenessMask 
-       :: Unique               -- unique for for large bitmap label
+       :: VirtualSpOffset      -- size of the stack frame
        -> VirtualSpOffset      -- offset from which the bitmap should start
-       -> FCode Liveness       -- mask for free/unlifted slots
-
-buildLivenessMask uniq sp info_down
-       state@(MkCgState abs_c binds ((vsp, free, _, _), heap_usage))
-  = ASSERT(all (>=0) rel_slots) 
-    livenessToAbsC uniq liveness_mask info_down state 
-  where
-       -- find all unboxed stack-resident ids
-       unboxed_slots =                    
-         [ (ofs, size) | 
-                    (MkCgIdInfo id _ (VirStkLoc ofs) _) <- rngVarEnv binds,
-               let rep = idPrimRep id; size = getPrimRepSize rep,
-               not (isFollowableRep rep),
-               size > 0
-         ]
-
-       -- flatten this list into a list of unboxed stack slots
-       flatten_slots = sortLt (<) 
-               (foldr (\(ofs,size) r -> [ofs-size+1 .. ofs] ++ r) []
-                     unboxed_slots)
-
-       -- merge in the free slots
-       all_slots = mergeSlots flatten_slots (map fst free) ++ 
-                   if vsp < sp then [vsp+1 .. sp] else []
-
-        -- recalibrate the list to be sp-relative
-       rel_slots = reverse (map (sp-) all_slots)
-
-       -- build the bitmap
-       liveness_mask = listToLivenessMask rel_slots
-
-mergeSlots :: [Int] -> [Int] -> [Int]
-mergeSlots cs [] = cs
-mergeSlots [] ns = ns
-mergeSlots (c:cs) (n:ns)
- = if c < n then
-       c : mergeSlots cs (n:ns)
-   else if c > n then
-       n : mergeSlots (c:cs) ns
-   else
-       panic ("mergeSlots: equal slots: " ++ show (c:cs) ++ show (n:ns))
-
-listToLivenessMask :: [Int] -> LivenessMask
-listToLivenessMask []    = []
-listToLivenessMask slots = 
-   mkBS this : listToLivenessMask (map (\x -> x-32) rest)
-   where (this,rest) = span (<32) slots
-
-livenessToAbsC :: Unique -> LivenessMask -> FCode Liveness
-livenessToAbsC uniq []    = returnFC (LvSmall emptyBS)
-livenessToAbsC uniq [one] = returnFC (LvSmall one)
-livenessToAbsC uniq many  = 
-       absC (CBitmap lbl many) `thenC`
-       returnFC (LvLarge lbl)
-  where lbl = mkBitmapLabel uniq
-\end{code}
-
-In a continuation, we want a liveness mask that starts from just after
-the return address, which is on the stack at realSp.
-
-\begin{code}
-buildContLivenessMask
-       :: Unique
-       -> FCode Liveness
-buildContLivenessMask uniq
-  = getRealSp  `thenFC` \ realSp ->
-    buildLivenessMask uniq (realSp-1)
+       -> FCode Bitmap         -- mask for free/unlifted slots
+
+buildLivenessMask size sp = do {
+    -- find all live stack-resident pointers
+    binds <- getBinds;
+    ((vsp, _, free, _, _), heap_usage) <- getUsage;
+
+    let {
+       rel_slots = sortLt (<) 
+           [ sp - ofs  -- get slots relative to top of frame
+           | (MkCgIdInfo id _ (VirStkLoc ofs) _) <- rngVarEnv binds,
+             isFollowableRep (idPrimRep id)
+           ];
+    };
+
+    WARN( not (all (>=0) rel_slots), ppr size $$ ppr sp $$ ppr rel_slots $$ ppr binds )
+    return (intsToReverseBitmap size rel_slots)
+  }
+
+-- In a continuation, we want a liveness mask that starts from just after
+-- the return address, which is on the stack at realSp.
+
+buildContLivenessMask :: Id -> FCode Liveness
+       -- The Id is used just for its unique to make a label
+buildContLivenessMask id = do
+       realSp <- getRealSp
+
+       frame_sp <- getStackFrame
+       -- realSp points to the frame-header for the current stack frame,
+       -- and the end of this frame is frame_sp.  The size is therefore
+       -- realSp - frame_sp - 1 (subtract one for the frame-header).
+       let frame_size = realSp - frame_sp - 1
+
+       mask <- buildLivenessMask frame_size (realSp-1)
+
+        let liveness = Liveness (mkBitmapLabel (getName id)) frame_size mask
+       absC (maybeLargeBitmap liveness)
+       return liveness
 \end{code}
 
 %************************************************************************
@@ -561,16 +498,14 @@ Probably *naughty* to look inside monad...
 \begin{code}
 nukeDeadBindings :: StgLiveVars  -- All the *live* variables
                 -> Code
-
-nukeDeadBindings live_vars info_down (MkCgState abs_c binds usage)
-  = freeStackSlots extra_free info_down (MkCgState abs_c (mkVarEnv bs') usage)
-  where
-    (dead_stk_slots, bs')
-      = dead_slots live_vars
-                  [] []
-                  [ (i, b) | b@(MkCgIdInfo i _ _ _) <- rngVarEnv binds ]
-
-    extra_free = sortLt (<) dead_stk_slots
+nukeDeadBindings live_vars = do
+       binds <- getBinds
+       let (dead_stk_slots, bs') =
+               dead_slots live_vars 
+                       [] []
+                       [ (i, b) | b@(MkCgIdInfo i _ _ _) <- rngVarEnv binds ]
+       setBinds $ mkVarEnv bs'
+       freeStackSlots dead_stk_slots
 \end{code}
 
 Several boring auxiliary functions to do the dirty work.