[project @ 2000-11-15 14:37:08 by simonpj]
[ghc-hetmet.git] / ghc / compiler / codeGen / CgCase.lhs
index f4da725..1d58b62 100644 (file)
@@ -1,7 +1,7 @@
 %
 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
-% $Id: CgCase.lhs,v 1.18 1998/12/02 13:17:46 simonm Exp $
+% $Id: CgCase.lhs,v 1.50 2000/11/15 14:37:08 simonpj Exp $
 %
 %********************************************************
 %*                                                     *
@@ -10,8 +10,8 @@
 %********************************************************
 
 \begin{code}
-module CgCase (        cgCase, saveVolatileVarsAndRegs, restoreCurrentCostCentre,
-               splitAlgTyConAppThroughNewTypes ) where
+module CgCase (        cgCase, saveVolatileVarsAndRegs, restoreCurrentCostCentre
+       ) where
 
 #include "HsVersions.h"
 
@@ -24,47 +24,40 @@ import AbsCSyn
 import AbsCUtils       ( mkAbstractCs, mkAbsCStmts, mkAlgAltsCSwitch,
                          getAmodeRep, nonemptyAbsC
                        )
-import CoreSyn         ( isDeadBinder )
 import CgUpdate                ( reserveSeqFrame )
 import CgBindery       ( getVolatileRegs, getArgAmodes,
                          bindNewToReg, bindNewToTemp,
                          bindNewPrimToAmode,
                          rebindToStack, getCAddrMode,
                          getCAddrModeAndInfo, getCAddrModeIfVolatile,
-                         buildContLivenessMask, nukeDeadBindings
+                         buildContLivenessMask, nukeDeadBindings,
                        )
 import CgCon           ( bindConArgs, bindUnboxedTupleComponents )
-import CgHeapery       ( altHeapCheck, yield )
+import CgHeapery       ( altHeapCheck )
 import CgRetConv       ( dataReturnConvPrim, ctrlReturnConvAlg,
                          CtrlReturnConvention(..)
                        )
 import CgStackery      ( allocPrimStack, allocStackTop,
-                         deAllocStackTop, freeStackSlots
+                         deAllocStackTop, freeStackSlots, dataStackSlots
                        )
 import CgTailCall      ( tailCallFun )
-import CgUsages                ( getSpRelOffset, getRealSp )
-import CLabel          ( CLabel, mkVecTblLabel, mkReturnPtLabel, 
-                         mkDefaultLabel, mkAltLabel, mkReturnInfoLabel,
-                         mkErrorStdEntryLabel, mkClosureTblLabel
+import CgUsages                ( getSpRelOffset )
+import CLabel          ( mkVecTblLabel, mkClosureTblLabel,
+                         mkDefaultLabel, mkAltLabel, mkReturnInfoLabel
                        )
 import ClosureInfo     ( mkLFArgument )
-import CmdLineOpts     ( opt_SccProfilingOn, opt_GranMacros )
-import CostCentre      ( CostCentre )
-import Id              ( Id, idPrimRep )
-import DataCon         ( DataCon, dataConTag, fIRST_TAG, ConTag,
-                         isUnboxedTupleCon, dataConType )
+import CmdLineOpts     ( opt_SccProfilingOn )
+import Id              ( Id, idPrimRep, isDeadBinder )
+import DataCon         ( DataCon, dataConTag, fIRST_TAG, ConTag )
 import VarSet          ( varSetElems )
-import Const           ( Con(..), Literal )
+import Literal         ( Literal )
 import PrimOp          ( primOpOutOfLine, PrimOp(..) )
 import PrimRep         ( getPrimRepSize, retPrimRepSize, PrimRep(..)
                        )
-import TyCon           ( TyCon, isEnumerationTyCon, isUnboxedTupleTyCon,
-                         isNewTyCon, isAlgTyCon,
-                         tyConDataCons, tyConFamilySize )
-import Type            ( GenType(..), typePrimRep, splitAlgTyConApp, Type,
-                         splitFunTys, applyTys )
-import Unique           ( Unique, Uniquable(..) )
+import TyCon           ( isEnumerationTyCon, isUnboxedTupleTyCon, tyConPrimRep )
+import Unique           ( Unique, Uniquable(..), newTagUnique )
 import Maybes          ( maybeToBool )
+import Util
 import Outputable
 \end{code}
 
@@ -115,14 +108,6 @@ Against:
 
        This never hurts us if there is only one alternative.
 
-
-*** NOT YET DONE ***  The difficulty is that \tr{!B!}, \tr{!C!} need
-to take account of what is live, and that includes all live volatile
-variables, even if they also have stable analogues.  Furthermore, the
-stack pointers must be lined up properly so that GC sees tidy stacks.
-If these things are done, then the heap checks can be done at \tr{!B!} and
-\tr{!C!} without a full save-volatile-vars sequence.
-
 \begin{code}
 cgCase :: StgExpr
        -> StgLiveVars
@@ -133,28 +118,108 @@ cgCase   :: StgExpr
        -> Code
 \end{code}
 
-Several special cases for inline primitive operations.
+Special case #1:  PrimOps returning enumeration types.
+
+For enumeration types, we invent a temporary (builtin-unique 1) to
+hold the tag, and cross our fingers that this doesn't clash with
+anything else.  Builtin-unique 0 is used for a similar reason when
+compiling enumerated-type primops in CgExpr.lhs.  We can't use the
+unique from the case binder, because this is used to hold the actual
+closure (when the case binder is live, that is).
+
+There is an extra special case for
+
+       case tagToEnum# x of
+               ...
+
+which generates no code for the primop, unless x is used in the
+alternatives (in which case we lookup the tag in the relevant closure
+table to get the closure).
+
+Being a bit short of uniques for temporary variables here, we use
+newTagUnique to generate a new unique from the case binder.  The case
+binder's unique will presumably have the 'c' tag (generated by
+CoreToStg), so we just change its tag to 'C' (for 'case') to ensure it
+doesn't clash with anything else.
 
 \begin{code}
-cgCase (StgCon (PrimOp op) args res_ty) live_in_whole_case live_in_alts bndr srt alts
+cgCase (StgPrimApp op args _)
+       live_in_whole_case live_in_alts bndr srt (StgAlgAlts (Just tycon) alts deflt)
+  | isEnumerationTyCon tycon
+  = getArgAmodes args `thenFC` \ arg_amodes ->
+
+    let tag_amode = case op of 
+                       TagToEnumOp -> only arg_amodes
+                       _ -> CTemp (newTagUnique (getUnique bndr) 'C') IntRep
+
+       closure = CVal (CIndex (CLbl (mkClosureTblLabel tycon) PtrRep) tag_amode PtrRep) PtrRep
+    in
+
+    case op of {
+       TagToEnumOp -> nopC;  -- no code!
+
+       _ ->    -- Perform the operation
+              getVolatileRegs live_in_alts     `thenFC` \ vol_regs ->
+
+              absC (COpStmt [tag_amode] op
+                arg_amodes -- note: no liveness arg
+                vol_regs)
+    }                                          `thenC`
+
+       -- bind the default binder if necessary
+       -- The deadness info is set by StgVarInfo
+    (if (isDeadBinder bndr)
+       then nopC
+       else bindNewToTemp bndr                 `thenFC` \ bndr_amode ->
+            absC (CAssign bndr_amode closure))
+                                               `thenC`
+
+       -- compile the alts
+    cgAlgAlts NoGC (getUnique bndr) Nothing{-cc_slot-} False{-no semi-tagging-}
+               False{-not poly case-} alts deflt
+                False{-don't emit yield-}      `thenFC` \ (tagged_alts, deflt_c) ->
+
+       -- Do the switch
+    absC (mkAlgAltsCSwitch tag_amode tagged_alts deflt_c)
+\end{code}
+
+Special case #2: inline PrimOps.
+
+\begin{code}
+cgCase (StgPrimApp op args _) 
+       live_in_whole_case live_in_alts bndr srt alts
   | not (primOpOutOfLine op)
   =
        -- Get amodes for the arguments and results
     getArgAmodes args                  `thenFC` \ arg_amodes ->
-    let
-       result_amodes = getPrimAppResultAmodes (getUnique bndr) alts
-    in
-       -- Perform the operation
     getVolatileRegs live_in_alts        `thenFC` \ vol_regs ->
 
-    absC (COpStmt result_amodes op
-                arg_amodes -- note: no liveness arg
-                vol_regs)              `thenC`
-
-       -- Scrutinise the result
-    cgInlineAlts bndr alts
+    case alts of 
+      StgPrimAlts tycon alts deflt     -- PRIMITIVE ALTS
+       -> absC (COpStmt [CTemp (getUnique bndr) (tyConPrimRep tycon)]
+                        op
+                        arg_amodes     -- note: no liveness arg
+                        vol_regs)              `thenC`
+          cgPrimInlineAlts bndr tycon alts deflt
+
+      StgAlgAlts (Just tycon) [(_, args, _, rhs)] StgNoDefault 
+       |  isUnboxedTupleTyCon tycon    -- UNBOXED TUPLE ALTS
+       ->      -- no heap check, no yield, just get in there and do it.
+          absC (COpStmt [ CTemp (getUnique arg) (idPrimRep arg) | arg <- args ]
+                        op
+                        arg_amodes      -- note: no liveness arg
+                        vol_regs)              `thenC`
+          mapFCs bindNewToTemp args `thenFC` \ _ ->
+          cgExpr rhs
+
+      other -> pprPanic "cgCase: case of primop has strange alts" (pprStgAlts alts)
 \end{code}
 
+TODO: Case-of-case of primop can probably be done inline too (but
+maybe better to translate it out beforehand).  See
+ghc/lib/misc/PackedString.lhs for examples where this crops up (with
+4.02).
+
 Another special case: scrutinising a primitive-typed variable. No
 evaluation required.  We don't save volatile variables, nor do we do a
 heap-check in the alternatives.         Instead, the heap usage of the
@@ -164,7 +229,7 @@ eliminate a heap check altogether.
 
 \begin{code}
 cgCase (StgApp v []) live_in_whole_case live_in_alts bndr srt
-                       (StgPrimAlts ty alts deflt)
+                       (StgPrimAlts tycon alts deflt)
 
   = 
     getCAddrMode v             `thenFC` \amode ->
@@ -175,10 +240,8 @@ cgCase (StgApp v []) live_in_whole_case live_in_alts bndr srt
        two bindings pointing at the same stack locn doesn't work (it
        confuses nukeDeadBindings).  Hence, use a new temp.
     -}
-    (if (isDeadBinder bndr)
-       then nopC
-       else bindNewToTemp bndr  `thenFC`  \deflt_amode ->
-            absC (CAssign deflt_amode amode)) `thenC`
+    bindNewToTemp bndr                 `thenFC`  \deflt_amode ->
+    absC (CAssign deflt_amode amode)   `thenC`
 
     cgPrimAlts NoGC amode alts deflt []
 \end{code}
@@ -189,7 +252,8 @@ we can reuse/trim the stack slot holding the variable (if it is in one).
 
 \begin{code}
 cgCase (StgApp fun args)
-       live_in_whole_case live_in_alts bndr srt alts@(StgAlgAlts ty _ _)
+       live_in_whole_case live_in_alts bndr srt alts   -- @(StgAlgAlts _ _ _)
+                                                       -- SLPJ: Surely PrimAlts is ok too?
   =
     getCAddrModeAndInfo fun            `thenFC` \ (fun_amode, lf_info) ->
     getArgAmodes args                  `thenFC` \ arg_amodes ->
@@ -202,24 +266,12 @@ cgCase (StgApp fun args)
     allocStackTop retPrimRepSize       `thenFC` \_ ->
 
     forkEval alts_eob_info nopC (
-               deAllocStackTop retPrimRepSize `thenFC` \_ ->
-               cgEvalAlts maybe_cc_slot bndr srt alts) 
+            deAllocStackTop retPrimRepSize `thenFC` \_ ->
+            cgEvalAlts maybe_cc_slot bndr srt alts) 
                                         `thenFC` \ scrut_eob_info ->
 
-    let real_scrut_eob_info =
-               if not_con_ty
-                       then reserveSeqFrame scrut_eob_info
-                       else scrut_eob_info
-    in
-
-    setEndOfBlockInfo real_scrut_eob_info (
-      tailCallFun fun fun_amode lf_info arg_amodes save_assts
-      )
-
-  where
-     not_con_ty = case (getScrutineeTyCon ty) of
-                       Just _ -> False
-                       other  -> True
+    setEndOfBlockInfo (maybeReserveSeqFrame alts scrut_eob_info)       $
+    tailCallFun fun fun_amode lf_info arg_amodes save_assts
 \end{code}
 
 Note about return addresses: we *always* push a return address, even
@@ -248,26 +300,15 @@ cgCase expr live_in_whole_case live_in_alts bndr srt alts
 
     -- generate code for the alts
     forkEval alts_eob_info
-       (
-        nukeDeadBindings live_in_alts `thenC` 
+       (nukeDeadBindings live_in_alts `thenC` 
         allocStackTop retPrimRepSize   -- space for retn address 
         `thenFC` \_ -> nopC
         )
        (deAllocStackTop retPrimRepSize `thenFC` \_ ->
         cgEvalAlts maybe_cc_slot bndr srt alts) `thenFC` \ scrut_eob_info ->
 
-    let real_scrut_eob_info =
-               if not_con_ty
-                       then reserveSeqFrame scrut_eob_info
-                       else scrut_eob_info
-    in
-
-    setEndOfBlockInfo real_scrut_eob_info (cgExpr expr)
-
-  where
-     not_con_ty = case (getScrutineeTyCon (alts_ty alts)) of
-                       Just _ -> False
-                       other  -> True
+    setEndOfBlockInfo (maybeReserveSeqFrame alts scrut_eob_info) $
+    cgExpr expr
 \end{code}
 
 There's a lot of machinery going on behind the scenes to manage the
@@ -305,89 +346,11 @@ don't follow the layout of closures when we're profiling.  The CCS
 could be anywhere within the record).
 
 \begin{code}
-alts_ty (StgAlgAlts ty _ _) = ty
-alts_ty (StgPrimAlts ty _ _) = ty
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[CgCase-primops]{Primitive applications}
-%*                                                                     *
-%************************************************************************
-
-Get result amodes for a primitive operation, in the case wher GC can't happen.
-The  amodes are returned in canonical order, ready for the prim-op!
-
-       Alg case: temporaries named as in the alternatives,
-                 plus (CTemp u) for the tag (if needed)
-       Prim case: (CTemp u)
-
-This is all disgusting, because these amodes must be consistent with those
-invented by CgAlgAlts.
-
-\begin{code}
-getPrimAppResultAmodes
-       :: Unique
-       -> StgCaseAlts
-       -> [CAddrMode]
-\end{code}
-
-\begin{code}
--- If there's an StgBindDefault which does use the bound
--- variable, then we can only handle it if the type involved is
--- an enumeration type.   That's important in the case
--- of comparisions:
---
---     case x ># y of
---       r -> f r
---
--- The only reason for the restriction to *enumeration* types is our
--- inability to invent suitable temporaries to hold the results;
--- Elaborating the CTemp addr mode to have a second uniq field
--- (which would simply count from 1) would solve the problem.
--- Anyway, cgInlineAlts is now capable of handling all cases;
--- it's only this function which is being wimpish.
-
-getPrimAppResultAmodes uniq (StgAlgAlts ty alts 
-                               (StgBindDefault rhs))
-  | isEnumerationTyCon spec_tycon = [tag_amode]
-  | otherwise                    = pprPanic "getPrimAppResultAmodes: non-enumeration algebraic alternatives with default" (ppr uniq <+> ppr rhs)
-  where
-    -- A temporary variable to hold the tag; this is unaffected by GC because
-    -- the heap-checks in the branches occur after the switch
-    tag_amode     = CTemp uniq IntRep
-    (spec_tycon, _, _) = splitAlgTyConApp ty
-\end{code}
-
-If we don't have a default case, we could be scrutinising an unboxed
-tuple, or an enumeration type...
-
-\begin{code}
-getPrimAppResultAmodes uniq (StgAlgAlts ty alts other_default)
-       -- Default is either StgNoDefault or StgBindDefault with unused binder
-
-  | isEnumerationTyCon tycon = [CTemp uniq IntRep]
-
-  | isUnboxedTupleTyCon tycon = 
-       case alts of 
-           [(con, args, use_mask, rhs)] -> 
-               [ CTemp (getUnique arg) (idPrimRep arg) | arg <- args ]
-           _ -> panic "getPrimAppResultAmodes: case of unboxed tuple has multiple branches"
-
-  | otherwise = panic ("getPrimAppResultAmodes: case of primop has strange type: " ++ showSDoc (ppr ty))
-
-  where (tycon, _, _) = splitAlgTyConApp ty
+-- We need to reserve a seq frame for a polymorphic case
+maybeReserveSeqFrame (StgAlgAlts Nothing _ _) scrut_eob_info = reserveSeqFrame scrut_eob_info
+maybeReserveSeqFrame other                   scrut_eob_info = scrut_eob_info
 \end{code}
 
-The situation is simpler for primitive results, because there is only
-one!
-
-\begin{code}
-getPrimAppResultAmodes uniq (StgPrimAlts ty _ _)
-  = [CTemp uniq (typePrimRep ty)]
-\end{code}
-
-
 %************************************************************************
 %*                                                                     *
 \subsection[CgCase-alts]{Alternatives}
@@ -411,22 +374,15 @@ cgEvalAlts cc_slot bndr srt alts
   =    
     let uniq = getUnique bndr in
 
-    -- Generate the instruction to restore cost centre, if any
-    restoreCurrentCostCentre cc_slot   `thenFC` \ cc_restore ->
-
-    -- get the stack liveness for the info table (after the CC slot has
-    -- been freed - this is important).
     buildContLivenessMask uniq         `thenFC` \ liveness_mask ->
 
     case alts of
 
       -- algebraic alts ...
-      (StgAlgAlts ty alts deflt) ->
+      StgAlgAlts maybe_tycon alts deflt ->
 
           -- bind the default binder (it covers all the alternatives)
-       (if (isDeadBinder bndr)
-               then nopC
-               else bindNewToReg bndr node mkLFArgument) `thenC`
+       bindNewToReg bndr node mkLFArgument      `thenC`
 
        -- Generate sequel info for use downstream
        -- At the moment, we only do it if the type is vector-returnable.
@@ -437,16 +393,15 @@ cgEvalAlts cc_slot bndr srt alts
        --
        -- which is worse than having the alt code in the switch statement
 
-       let     tycon_info      = getScrutineeTyCon ty
-               is_alg          = maybeToBool tycon_info
-               Just spec_tycon = tycon_info
+       let     is_alg          = maybeToBool maybe_tycon
+               Just spec_tycon = maybe_tycon
        in
 
        -- deal with the unboxed tuple case
        if is_alg && isUnboxedTupleTyCon spec_tycon then
            case alts of 
                [alt] -> let lbl = mkReturnInfoLabel uniq in
-                        cgUnboxedTupleAlt lbl cc_restore True alt
+                        cgUnboxedTupleAlt uniq cc_slot True alt
                                `thenFC` \ abs_c ->
                         getSRTLabel `thenFC` \srt_label -> 
                         absC (CRetDirect uniq abs_c (srt_label, srt) 
@@ -470,7 +425,7 @@ cgEvalAlts cc_slot bndr srt alts
                        Nothing -- no semi-tagging info
 
        in
-       cgAlgAlts GCMayHappen uniq cc_restore use_labelled_alts (not is_alg) 
+       cgAlgAlts GCMayHappen uniq cc_slot use_labelled_alts (not is_alg) 
                alts deflt True `thenFC` \ (tagged_alt_absCs, deflt_absC) ->
 
        mkReturnVector uniq tagged_alt_absCs deflt_absC srt liveness_mask 
@@ -479,10 +434,13 @@ cgEvalAlts cc_slot bndr srt alts
        returnFC (CaseAlts return_vec semi_tagged_stuff)
 
       -- primitive alts...
-      (StgPrimAlts ty alts deflt) ->
+      StgPrimAlts tycon alts deflt ->
+
+       -- Restore the cost centre
+       restoreCurrentCostCentre cc_slot                `thenFC` \ cc_restore ->
 
        -- Generate the switch
-       getAbsC (cgPrimEvalAlts bndr ty alts deflt)     `thenFC` \ abs_c ->
+       getAbsC (cgPrimEvalAlts bndr tycon alts deflt)  `thenFC` \ abs_c ->
 
        -- Generate the labelled block, starting with restore-cost-centre
        getSRTLabel                                     `thenFC` \srt_label ->
@@ -490,78 +448,16 @@ cgEvalAlts cc_slot bndr srt alts
                        (srt_label,srt) liveness_mask)  `thenC`
 
        -- Return an amode for the block
-       returnFC (CaseAlts (CLbl (mkReturnPtLabel uniq) RetRep) Nothing)
+       returnFC (CaseAlts (CLbl (mkReturnInfoLabel uniq) RetRep) Nothing)
 \end{code}
 
 
-\begin{code}
-cgInlineAlts :: Id
-            -> StgCaseAlts
-            -> Code
-\end{code}
-
 HWL comment on {\em GrAnSim\/}  (adding GRAN_YIELDs for context switch): If
 we  do  an inlining of the  case  no separate  functions  for returning are
 created, so we don't have to generate a GRAN_YIELD in that case.  This info
 must be  propagated  to cgAlgAltRhs (where the  GRAN_YIELD  macro might  be
 emitted). Hence, the new Bool arg to cgAlgAltRhs.
 
-First case: primitive op returns an unboxed tuple.
-
-\begin{code}
-cgInlineAlts bndr (StgAlgAlts ty [alt@(con,args,use_mask,rhs)] StgNoDefault)
-  | isUnboxedTupleCon con
-  = -- no heap check, no yield, just get in there and do it.
-    mapFCs bindNewToTemp args `thenFC` \ _ ->
-    cgExpr rhs
-
-  | otherwise
-  = panic "cgInlineAlts: single alternative, not an unboxed tuple"
-\end{code}
-
-Hack: to deal with 
-
-       case <# x y of z {
-          DEFAULT -> ...
-        }
-
-\begin{code}
-cgInlineAlts bndr (StgAlgAlts ty [] (StgBindDefault rhs))
-  = bindNewToTemp bndr                 `thenFC` \amode ->
-    let
-       (tycon, _, _) = splitAlgTyConApp ty
-       closure_lbl = CTableEntry (CLbl (mkClosureTblLabel tycon) PtrRep) amode PtrRep
-    in
-    absC (CAssign amode closure_lbl)   `thenC`
-    cgExpr rhs
-\end{code}
-
-Second case: algebraic case, several alternatives.
-Tag is held in a temporary.
-
-\begin{code}
-cgInlineAlts bndr (StgAlgAlts ty alts deflt)
-  = cgAlgAlts NoGC uniq AbsCNop{-restore_cc-} False{-no semi-tagging-}
-               False{-not poly case-} alts deflt
-                False{-don't emit yield-}      `thenFC` \ (tagged_alts, deflt_c) ->
-
-       -- Do the switch
-    absC (mkAlgAltsCSwitch tag_amode tagged_alts deflt_c)
- where
-    -- A temporary variable to hold the tag; this is unaffected by GC because
-    -- the heap-checks in the branches occur after the switch
-    tag_amode = CTemp uniq IntRep
-    uniq = getUnique bndr
-\end{code}
-
-Third (real) case: primitive result type.
-
-\begin{code}
-cgInlineAlts bndr (StgPrimAlts ty alts deflt)
-  = cgPrimInlineAlts bndr ty alts deflt
-\end{code}
-
-
 %************************************************************************
 %*                                                                     *
 \subsection[CgCase-alg-alts]{Algebraic alternatives}
@@ -579,7 +475,7 @@ are inlined alternatives.
 \begin{code}
 cgAlgAlts :: GCFlag
          -> Unique
-         -> AbstractC                          -- Restore-cost-centre instruction
+         -> Maybe VirtualSpOffset
          -> Bool                               -- True <=> branches must be labelled
          -> Bool                               -- True <=> polymorphic case
          -> [(DataCon, [Id], [Bool], StgExpr)] -- The alternatives
@@ -599,23 +495,25 @@ cgAlgAlts gc_flag uniq restore_cc must_label_branches is_fun alts deflt
 \begin{code}
 cgAlgDefault :: GCFlag
             -> Bool                    -- could be a function-typed result?
-            -> Unique -> AbstractC -> Bool -- turgid state...
+            -> Unique -> Maybe VirtualSpOffset -> Bool -- turgid state...
             -> StgCaseDefault          -- input
             -> Bool
             -> FCode AbstractC         -- output
 
-cgAlgDefault gc_flag is_fun uniq restore_cc must_label_branch StgNoDefault _
+cgAlgDefault gc_flag is_fun uniq cc_slot must_label_branch StgNoDefault _
   = returnFC AbsCNop
 
-cgAlgDefault gc_flag is_fun uniq restore_cc must_label_branch
+cgAlgDefault gc_flag is_fun uniq cc_slot must_label_branch
             (StgBindDefault rhs)
           emit_yield{-should a yield macro be emitted?-}
 
   =    -- We have arranged that Node points to the thing
+    restoreCurrentCostCentre cc_slot `thenFC` \restore_cc ->
     getAbsC (absC restore_cc `thenC`
-             (if opt_GranMacros && emit_yield
-                then yield [node] False
-                else absC AbsCNop)                            `thenC`     
+             -- HWL: maybe need yield here
+             --(if emit_yield
+             --   then yield [node] True
+             --   else absC AbsCNop)                            `thenC`     
             possibleHeapCheck gc_flag is_fun [node] [] Nothing (cgExpr rhs)
        -- Node is live, but doesn't need to point at the thing itself;
        -- it's ok for Node to point to an indirection or FETCH_ME
@@ -633,18 +531,21 @@ cgAlgDefault gc_flag is_fun uniq restore_cc must_label_branch
 -- HWL comment on GrAnSim: GRAN_YIELDs needed; emitted in cgAlgAltRhs
 
 cgAlgAlt :: GCFlag
-        -> Unique -> AbstractC -> Bool         -- turgid state
+        -> Unique -> Maybe VirtualSpOffset -> Bool     -- turgid state
         -> Bool                               -- Context switch at alts?
         -> (DataCon, [Id], [Bool], StgExpr)
         -> FCode (ConTag, AbstractC)
 
-cgAlgAlt gc_flag uniq restore_cc must_label_branch 
+cgAlgAlt gc_flag uniq cc_slot must_label_branch 
          emit_yield{-should a yield macro be emitted?-}
          (con, args, use_mask, rhs)
-  = getAbsC (absC restore_cc `thenC`
-            (if opt_GranMacros && emit_yield
-               then yield [node] True          -- XXX live regs wrong
-               else absC AbsCNop)                               `thenC`     
+  = 
+    restoreCurrentCostCentre cc_slot `thenFC` \restore_cc ->
+    getAbsC (absC restore_cc `thenC`
+             -- HWL: maybe need yield here
+            -- (if emit_yield
+            --    then yield [node] True               -- XXX live regs wrong
+            --    else absC AbsCNop)                               `thenC`    
             (case gc_flag of
                NoGC        -> mapFCs bindNewToTemp args `thenFC` \_ -> nopC
                GCMayHappen -> bindConArgs con args
@@ -662,21 +563,24 @@ cgAlgAlt gc_flag uniq restore_cc must_label_branch
     lbl = mkAltLabel uniq tag
 
 cgUnboxedTupleAlt
-       :: CLabel                       -- label of the alternative
-       -> AbstractC                    -- junk
+       :: Unique                       -- unique for label of the alternative
+       -> Maybe VirtualSpOffset        -- Restore cost centre
        -> Bool                         -- ctxt switch
        -> (DataCon, [Id], [Bool], StgExpr) -- alternative
        -> FCode AbstractC
 
-cgUnboxedTupleAlt lbl restore_cc emit_yield (con,args,use_mask,rhs)
+cgUnboxedTupleAlt lbl cc_slot emit_yield (con,args,use_mask,rhs)
   = getAbsC (
-       absC restore_cc `thenC`
-
        bindUnboxedTupleComponents args 
                      `thenFC` \ (live_regs,tags,stack_res) ->
-       (if opt_GranMacros && emit_yield
-           then yield live_regs True           -- XXX live regs wrong?
-           else absC AbsCNop)                         `thenC`     
+
+        restoreCurrentCostCentre cc_slot `thenFC` \restore_cc ->
+       absC restore_cc `thenC`
+
+        -- HWL: maybe need yield here
+       -- (if emit_yield
+       --    then yield live_regs True         -- XXX live regs wrong?
+       --    else absC AbsCNop)                         `thenC`     
        let 
              -- ToDo: could maybe use Nothing here if stack_res is False
              -- since the heap-check can just return to the top of the 
@@ -749,23 +653,23 @@ the maximum stack depth encountered down any branch.
 As usual, no binders in the alternatives are yet bound.
 
 \begin{code}
-cgPrimInlineAlts bndr ty alts deflt
+cgPrimInlineAlts bndr tycon alts deflt
   = cgPrimAltsWithDefault bndr NoGC (CTemp uniq kind) alts deflt []
   where
        uniq = getUnique bndr
-       kind = typePrimRep ty
+       kind = tyConPrimRep tycon
 
-cgPrimEvalAlts bndr ty alts deflt
+cgPrimEvalAlts bndr tycon alts deflt
   = cgPrimAltsWithDefault bndr GCMayHappen (CReg reg) alts deflt [reg]
   where
-       reg = dataReturnConvPrim kind
-       kind = typePrimRep ty
+       reg  = WARN( case kind of { PtrRep -> True; other -> False }, 
+                    text "cgPrimEE" <+> ppr bndr <+> ppr tycon  )
+              dataReturnConvPrim kind
+       kind = tyConPrimRep tycon
 
 cgPrimAltsWithDefault bndr gc_flag scrutinee alts deflt regs
   =    -- first bind the default if necessary
-    (if isDeadBinder bndr 
-       then nopC
-       else bindNewPrimToAmode bndr scrutinee)         `thenC`
+    bindNewPrimToAmode bndr scrutinee          `thenC`
     cgPrimAlts gc_flag scrutinee alts deflt regs
 
 cgPrimAlts gc_flag scrutinee alts deflt regs
@@ -868,21 +772,20 @@ saveCurrentCostCentre
   = if not opt_SccProfilingOn then
        returnFC (Nothing, AbsCNop)
     else
-       allocPrimStack (getPrimRepSize CostCentreRep)  `thenFC` \ slot ->
+       allocPrimStack (getPrimRepSize CostCentreRep) `thenFC` \ slot ->
+       dataStackSlots [slot]                         `thenC`
        getSpRelOffset slot                           `thenFC` \ sp_rel ->
        returnFC (Just slot,
                  CAssign (CVal sp_rel CostCentreRep) (CReg CurCostCentre))
 
 restoreCurrentCostCentre :: Maybe VirtualSpOffset -> FCode AbstractC
-
-restoreCurrentCostCentre Nothing
- = returnFC AbsCNop
+restoreCurrentCostCentre Nothing = returnFC AbsCNop
 restoreCurrentCostCentre (Just slot)
  = getSpRelOffset slot                          `thenFC` \ sp_rel ->
    freeStackSlots [slot]                        `thenC`
    returnFC (CCallProfCCMacro SLIT("RESTORE_CCCS") [CVal sp_rel CostCentreRep])
     -- we use the RESTORE_CCCS macro, rather than just
-    -- assigning into CurCostCentre, in case RESTORE_CCC
+    -- assigning into CurCostCentre, in case RESTORE_CCCS
     -- has some sanity-checking in it.
 \end{code}
 
@@ -907,8 +810,6 @@ mkReturnVector :: Unique
 mkReturnVector uniq tagged_alt_absCs deflt_absC srt liveness ret_conv
   = getSRTLabel `thenFC` \srt_label ->
     let
-     srt_info = (srt_label, srt)
-
      (return_vec_amode, vtbl_body) = case ret_conv of {
 
        -- might be a polymorphic case...
@@ -956,7 +857,7 @@ mkReturnVector uniq tagged_alt_absCs deflt_absC srt liveness ret_conv
     deflt_lbl = 
        case nonemptyAbsC deflt_absC of
                 -- the simplifier might have eliminated a case
-          Nothing -> CLbl mkErrorStdEntryLabel CodePtrRep 
+          Nothing -> mkIntCLit 0 -- CLbl mkErrorStdEntryLabel CodePtrRep 
           Just absC@(CCodeBlock lbl _) -> CLbl lbl CodePtrRep
 
     mk_vector_entry :: ConTag -> (CAddrMode, AbstractC)
@@ -983,7 +884,7 @@ possibleHeapCheck
        -> Bool                         --  True <=> algebraic case
        -> [MagicId]                    --  live registers
        -> [(VirtualSpOffset,Int)]      --  stack slots to tag
-       -> Maybe CLabel                 --  return address
+       -> Maybe Unique                 --  return address unique
        -> Code                         --  continuation
        -> Code
 
@@ -992,42 +893,3 @@ possibleHeapCheck GCMayHappen is_alg regs tags lbl code
 possibleHeapCheck NoGC _ _ tags lbl code 
   = code
 \end{code}
-
-splitTyConAppThroughNewTypes is like splitAlgTyConApp_maybe except
-that it looks through newtypes in addition to synonyms.  It's
-useful in the back end where we're not interested in newtypes
-anymore.
-
-Sometimes, we've thrown away the constructors during pruning in the
-renamer.  In these cases, we emit a warning and fall back to using a
-SEQ_FRAME to evaluate the case scrutinee.
-
-\begin{code}
-getScrutineeTyCon :: Type -> Maybe TyCon
-getScrutineeTyCon ty =
-   case (splitAlgTyConAppThroughNewTypes ty) of
-       Nothing -> Nothing
-       Just (tc,_) -> 
-               if not (isAlgTyCon tc) then Just tc else
-               case (tyConFamilySize tc) of
-                       0 -> pprTrace "Warning" (hcat [
-                               text "constructors for ",
-                               ppr tc,
-                               text " not available.\n\tUse -fno-prune-tydecls to fix."
-                               ]) Nothing
-                       _ -> Just tc
-
-splitAlgTyConAppThroughNewTypes  :: Type -> Maybe (TyCon, [Type])
-splitAlgTyConAppThroughNewTypes (TyConApp tc tys) 
-       | isNewTyCon tc = 
-               case (tyConDataCons tc) of
-                       [con] -> let ([ty], _) = splitFunTys 
-                                             (applyTys (dataConType con) tys)
-                                in  splitAlgTyConAppThroughNewTypes ty
-                       _ -> Nothing
-       | otherwise = Just (tc, tys)
-
-splitAlgTyConAppThroughNewTypes (NoteTy _ ty)    = 
-       splitAlgTyConAppThroughNewTypes ty
-splitAlgTyConAppThroughNewTypes other       = Nothing
-\end{code}