[project @ 1998-01-08 18:03:08 by simonm]
[ghc-hetmet.git] / ghc / compiler / codeGen / CgClosure.lhs
index af31842..8fbf5c6 100644 (file)
@@ -1,5 +1,5 @@
 %
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
 %
 \section[CgClosure]{Code generation for closures}
 
@@ -8,35 +8,29 @@ with {\em closures} on the RHSs of let(rec)s.  See also
 @CgCon@, which deals with constructors.
 
 \begin{code}
+module CgClosure ( cgTopRhsClosure, cgRhsClosure ) where
+
 #include "HsVersions.h"
 
-module CgClosure ( cgTopRhsClosure, cgRhsClosure ) where
+import {-# SOURCE #-} CgExpr ( cgExpr )
 
-import StgSyn
 import CgMonad
 import AbsCSyn
+import StgSyn
 
-import PrelInfo                ( PrimOp(..), Name
-                         IF_ATTACK_PRAGMAS(COMMA tagOf_PrimOp)
-                         IF_ATTACK_PRAGMAS(COMMA pprPrimOp)
-                       )
-import Type            ( isPrimType, isPrimTyCon,
-                         getTauType, showTypeCategory, getTyConDataCons
-                       )
-import CgBindery       ( getCAddrMode, getAtomAmodes,
-                         getCAddrModeAndInfo,
-                         bindNewToNode, bindNewToAStack, bindNewToBStack,
-                         bindNewToReg, bindArgsToRegs
+import AbsCUtils       ( mkAbstractCs, getAmodeRep )
+import CgBindery       ( getCAddrMode, getArgAmodes,
+                         getCAddrModeAndInfo, bindNewToNode,
+                         bindNewToAStack, bindNewToBStack,
+                         bindNewToReg, bindArgsToRegs,
+                         stableAmodeIdInfo, heapIdInfo, CgIdInfo
                        )
-import CgCompInfo      ( spARelToInt, spBRelToInt )
-import CgExpr          ( cgExpr, cgSccExpr )
+import Constants       ( spARelToInt, spBRelToInt )
 import CgUpdate                ( pushUpdateFrame )
 import CgHeapery       ( allocDynClosure, heapCheck
-#ifdef GRAN
-                         , heapCheckOnly, fetchAndReschedule  -- HWL
-#endif  {- GRAN -}
+                         , heapCheckOnly, fetchAndReschedule, yield  -- HWL
                        )
-import CgRetConv       ( ctrlReturnConvAlg, dataReturnConvAlg, mkLiveRegsBitMask,
+import CgRetConv       ( ctrlReturnConvAlg, dataReturnConvAlg, 
                          CtrlReturnConvention(..), DataReturnConvention(..)
                        )
 import CgStackery      ( getFinalStackHW, mkVirtStkOffsets,
@@ -46,20 +40,32 @@ import CgUsages             ( getVirtSps, setRealAndVirtualSps,
                          getSpARelOffset, getSpBRelOffset,
                          getHpRelOffset
                        )
-import CLabel
+import CLabel          ( mkClosureLabel, mkConUpdCodePtrVecLabel, mkFastEntryLabel,
+                         mkStdUpdCodePtrVecLabel, mkStdUpdVecTblLabel,
+                         mkErrorStdEntryLabel, mkRednCountsLabel
+                       )
 import ClosureInfo     -- lots and lots of stuff
-import CostCentre
-import Id              ( idType, getIdPrimRep, isSysLocalId, myWrapperMaybe,
-                         showId, getIdInfo, getIdStrictness,
-                         getDataConTag
+import CmdLineOpts     ( opt_ForConcurrent, opt_GranMacros )
+import CostCentre      ( useCurrentCostCentre, currentOrSubsumedCosts,
+                         noCostCentreAttached, costsAreSubsumed,
+                         isCafCC, isDictCC, overheadCostCentre, showCostCentre,
+                         CostCentre
+                       )
+import HeapOffs                ( VirtualHeapOffset )
+import Id              ( idType, idPrimRep, 
+                         showId, getIdStrictness, dataConTag,
+                         emptyIdSet,
+                         Id
                        )
-import IdInfo
 import ListSetOps      ( minusList )
-import Maybes          ( Maybe(..), maybeToBool )
-import PrimRep         ( isFollowableRep )
-import UniqSet
-import Unpretty
-import Util
+import Maybes          ( maybeToBool )
+import PrimRep         ( isFollowableRep, PrimRep(..) )
+import TyCon           ( isPrimTyCon, tyConDataCons )
+import Type             ( showTypeCategory )
+import Util            ( isIn )
+import Outputable
+
+getWrapperArgTypeCategories = panic "CgClosure.getWrapperArgTypeCategories (ToDo)"
 \end{code}
 
 %********************************************************
@@ -95,7 +101,7 @@ cgTopRhsClosure name cc binder_info args body lf_info
        -- Don't build Vap info tables etc for
        -- a function whose result is an unboxed type,
        -- because we can never have thunks with such a type.
-    (if closureReturnsUnboxedType closure_info then
+    (if closureReturnsUnpointedType closure_info then
        nopC
     else
        let
@@ -171,7 +177,7 @@ cgRhsClosure binder cc binder_info fvs args body lf_info
   -- ToDo: check non-primitiveness (ASSERT)
   = (
        -- LAY OUT THE OBJECT
-    getAtomAmodes std_thunk_payload            `thenFC` \ amodes ->
+    getArgAmodes std_thunk_payload             `thenFC` \ amodes ->
     let
        (closure_info, amodes_w_offsets)
          = layOutDynClosure binder getAmodeRep amodes lf_info
@@ -226,7 +232,7 @@ cgRhsClosure binder cc binder_info fvs args body lf_info
 
        amodes_w_offsets = [(amode,offset) | ((_, (amode,_)), offset) <- bind_details]
 
-       get_kind (id, amode_and_info) = getIdPrimRep id
+       get_kind (id, amode_and_info) = idPrimRep id
     in
        -- BUILD ITS INFO TABLE AND CODE
     forkClosureBody (
@@ -247,7 +253,7 @@ cgRhsClosure binder cc binder_info fvs args body lf_info
        -- Don't build Vap info tables etc for
        -- a function whose result is an unboxed type,
        -- because we can never have thunks with such a type.
-    (if closureReturnsUnboxedType closure_info then
+    (if closureReturnsUnpointedType closure_info then
        nopC
     else
        cgVapInfoTables False {- Not top level -} nopC binder_info binder args lf_info
@@ -302,7 +308,8 @@ cgVapInfoTable perhaps_bind_the_fun upd_flag fun args fun_in_payload fun_lf_info
        -- If f is not top-level, then f is one of the free variables too,
        -- hence "payload_ids" isn't the same as "arg_ids".
        --
-       vap_entry_rhs = StgApp (StgVarArg fun) (map StgVarArg args) emptyUniqSet
+       stg_args      = map StgVarArg args
+       vap_entry_rhs = StgApp (StgVarArg fun) stg_args emptyIdSet
                                                                        -- Empty live vars
 
        arg_ids_w_info = [(name,mkLFArgument) | name <- args]
@@ -312,15 +319,14 @@ cgVapInfoTable perhaps_bind_the_fun upd_flag fun args fun_in_payload fun_lf_info
        payload_ids | fun_in_payload = fun : args               -- Sigh; needed for mkClosureLFInfo
                    | otherwise      = args
 
-       vap_lf_info   = mkClosureLFInfo False {-not top level-} payload_ids
-                                       upd_flag [] vap_entry_rhs
+       vap_lf_info   = mkVapLFInfo payload_ids upd_flag fun stg_args fun_in_payload
                -- It's not top level, even if we're currently compiling a top-level
                -- function, because any VAP *use* of this function will be for a
                -- local thunk, thus
                --              let x = f p q   -- x isn't top level!
                --              in ...
 
-       get_kind (id, info) = getIdPrimRep id
+       get_kind (id, info) = idPrimRep id
 
        payload_bind_details :: [((Id, LambdaFormInfo), VirtualHeapOffset)]
        (closure_info, payload_bind_details) = layOutDynClosure
@@ -385,23 +391,26 @@ closureCodeBody binder_info closure_info cc [] body
              Just (tc,_,_) -> (True,  tc)
     in
     if has_tycon && isPrimTyCon tycon then
-       pprPanic "closureCodeBody:thunk:prim type!" (ppr PprDebug tycon)
+       pprPanic "closureCodeBody:thunk:prim type!" (ppr tycon)
     else
 #endif
     getAbsC body_code  `thenFC` \ body_absC ->
     moduleName         `thenFC` \ mod_name ->
-    getIntSwitchChkrC  `thenFC` \ isw_chkr ->
 
     absC (CClosureInfoAndCode closure_info body_absC Nothing
                              stdUpd (cl_descr mod_name)
-                             (dataConLiveness isw_chkr closure_info))
+                             (dataConLiveness closure_info))
   where
     cl_descr mod_name = closureDescription mod_name (closureId closure_info) [] body
 
     body_addr   = CLbl (entryLabelFromCI closure_info) CodePtrRep
     body_code   = profCtrC SLIT("ENT_THK") []                  `thenC`
-                 enterCostCentreCode closure_info cc IsThunk   `thenC`
-                 thunkWrapper closure_info (cgSccExpr body)
+                 thunkWrapper closure_info (
+                       -- We only enter cc after setting up update so that cc
+                       -- of enclosing scope will be recorded in update frame
+                       -- CAF/DICT functions will be subsumed by this enclosing cc
+                   enterCostCentreCode closure_info cc IsThunk `thenC`
+                   cgExpr body)
 
     stdUpd      = CLbl mkErrorStdEntryLabel CodePtrRep
 \end{code}
@@ -418,22 +427,17 @@ Node points to closure is available. -- HWL
 \begin{code}
 closureCodeBody binder_info closure_info cc all_args body
   = getEntryConvention id lf_info
-                      (map getIdPrimRep all_args)              `thenFC` \ entry_conv ->
-
-    isSwitchSetC EmitArityChecks                       `thenFC` \ do_arity_chks ->
-
-    isSwitchSetC ForConcurrent                         `thenFC` \ is_concurrent ->
-
-    isStringSwitchSetC AsmTarget                       `thenFC` \ native_code ->
-
+                      (map idPrimRep all_args)         `thenFC` \ entry_conv ->
     let
-       stg_arity = length all_args
+       -- Figure out what is needed and what isn't
+       slow_code_needed   = slowFunEntryCodeRequired id binder_info entry_conv
+       info_table_needed  = funInfoTableRequired id binder_info lf_info
 
        -- Arg mapping for standard (slow) entry point; all args on stack
        (spA_all_args, spB_all_args, all_bxd_w_offsets, all_ubxd_w_offsets)
           = mkVirtStkOffsets
                0 0             -- Initial virtual SpA, SpB
-               getIdPrimRep
+               idPrimRep
                all_args
 
        -- Arg mapping for the fast entry point; as many args as poss in
@@ -446,18 +450,21 @@ closureCodeBody binder_info closure_info cc all_args body
                ViaNode | is_concurrent    -> []
                other                      -> panic "closureCodeBody:arg_regs"
 
-       stk_args = drop (length arg_regs) all_args
+       num_arg_regs = length arg_regs
+       
+       (reg_args, stk_args) = splitAt num_arg_regs all_args
+
        (spA_stk_args, spB_stk_args, stk_bxd_w_offsets, stk_ubxd_w_offsets)
          = mkVirtStkOffsets
                0 0             -- Initial virtual SpA, SpB
-               getIdPrimRep
+               idPrimRep
                stk_args
 
        -- HWL; Note: empty list of live regs in slow entry code
        -- Old version (reschedule combined with heap check);
        -- see argSatisfactionCheck for new version
        --slow_entry_code = forceHeapCheck [node] True slow_entry_code'
-       --                where node = VanillaReg PtrRep 1
+       --                where node = UnusedReg PtrRep 1
        --slow_entry_code = forceHeapCheck [] True slow_entry_code'
 
        slow_entry_code
@@ -481,12 +488,6 @@ closureCodeBody binder_info closure_info cc all_args body
            -- Now adjust real stack pointers
            adjustRealSps spA_stk_args spB_stk_args             `thenC`
 
-           -- set the arity checker, if asked
-           absC (
-               if do_arity_chks
-               then CMacroStmt SET_ARITY [mkIntCLit stg_arity]
-               else AbsCNop
-           )                                                   `thenC`
            absC (CFallThrough (CLbl fast_label CodePtrRep))
 
        assign_to_reg reg_id amode = CAssign (CReg reg_id) amode
@@ -499,23 +500,22 @@ closureCodeBody binder_info closure_info cc all_args body
        fast_entry_code
          = profCtrC SLIT("ENT_FUN_DIRECT") [
                    CLbl (mkRednCountsLabel id) PtrRep,
-                   CString (_PK_ (showId PprDebug id)),
+                   CString (_PK_ (showId id)),
                    mkIntCLit stg_arity,        -- total # of args
                    mkIntCLit spA_stk_args,     -- # passed on A stk
                    mkIntCLit spB_stk_args,     -- B stk (rest in regs)
                    CString (_PK_ (map (showTypeCategory . idType) all_args)),
-                   CString (_PK_ (show_wrapper_name wrapper_maybe)),
-                   CString (_PK_ (show_wrapper_arg_kinds wrapper_maybe))
+                   CString SLIT(""), CString SLIT("")
+
+-- Nuked for now; see comment at end of file
+--                 CString (_PK_ (show_wrapper_name wrapper_maybe)),
+--                 CString (_PK_ (show_wrapper_arg_kinds wrapper_maybe))
+
                ]                       `thenC`
-           absC (
-               if do_arity_chks
-               then CMacroStmt CHK_ARITY [mkIntCLit stg_arity]
-               else AbsCNop
-           )                           `thenC`
 
                -- Bind args to regs/stack as appropriate, and
                -- record expected position of sps
-           bindArgsToRegs all_args arg_regs                `thenC`
+           bindArgsToRegs reg_args arg_regs                `thenC`
            mapCs bindNewToAStack stk_bxd_w_offsets         `thenC`
            mapCs bindNewToBStack stk_ubxd_w_offsets        `thenC`
            setRealAndVirtualSps spA_stk_args spB_stk_args  `thenC`
@@ -531,7 +531,6 @@ closureCodeBody binder_info closure_info cc all_args body
                                `thenFC` \ slow_abs_c ->
     forkAbsC fast_entry_code   `thenFC` \ fast_abs_c ->
     moduleName                 `thenFC` \ mod_name ->
-    getIntSwitchChkrC          `thenFC` \ isw_chkr ->
 
        -- Now either construct the info table, or put the fast code in alone
        -- (We never have slow code without an info table)
@@ -539,41 +538,39 @@ closureCodeBody binder_info closure_info cc all_args body
       if info_table_needed then
        CClosureInfoAndCode closure_info slow_abs_c (Just fast_abs_c)
                        stdUpd (cl_descr mod_name)
-                       (dataConLiveness isw_chkr closure_info)
+                       (dataConLiveness closure_info)
       else
        CCodeBlock fast_label fast_abs_c
     )
   where
+    is_concurrent = opt_ForConcurrent
+    stg_arity = length all_args
     lf_info = closureLFInfo closure_info
 
     cl_descr mod_name = closureDescription mod_name id all_args body
 
-       -- Figure out what is needed and what isn't
-    slow_code_needed   = slowFunEntryCodeRequired id binder_info
-    info_table_needed  = funInfoTableRequired id binder_info lf_info
-
        -- Manufacture labels
     id        = closureId closure_info
+    fast_label = mkFastEntryLabel id stg_arity
+    stdUpd     = CLbl mkErrorStdEntryLabel CodePtrRep
 
-    fast_label = fastLabelFromCI closure_info
-
-    stdUpd = CLbl mkErrorStdEntryLabel CodePtrRep
-
+{- OLD... see note at end of file
     wrapper_maybe = get_ultimate_wrapper Nothing id
       where
        get_ultimate_wrapper deflt x -- walk all the way up a "wrapper chain"
-         = case (myWrapperMaybe x) of
+         = case myWrapperMaybe x of
              Nothing -> deflt
              Just xx -> get_ultimate_wrapper (Just xx) xx
 
     show_wrapper_name Nothing   = ""
-    show_wrapper_name (Just xx) = showId PprDebug xx
+    show_wrapper_name (Just xx) = showId xx
 
     show_wrapper_arg_kinds Nothing   = ""
     show_wrapper_arg_kinds (Just xx)
       = case (getWrapperArgTypeCategories (idType xx) (getIdStrictness xx)) of
          Nothing  -> ""
          Just str -> str
+-}
 \end{code}
 
 For lexically scoped profiling we have to load the cost centre from
@@ -585,6 +582,9 @@ Node is guaranteed to point to it, if profiling and not inherited.
 
 \begin{code}
 data IsThunk = IsThunk | IsFunction -- Bool-like, local
+--#ifdef DEBUG
+       deriving Eq
+--#endif
 
 enterCostCentreCode :: ClosureInfo -> CostCentre -> IsThunk -> Code
 
@@ -592,37 +592,32 @@ enterCostCentreCode closure_info cc is_thunk
   = costCentresFlag    `thenFC` \ profiling_on ->
     if not profiling_on then
        nopC
-    else -- down to business
+    else
        ASSERT(not (noCostCentreAttached cc))
 
        if costsAreSubsumed cc then
-           nopC
-
-       else if is_current_CC cc then -- fish the CC out of the closure,
-                                     -- where we put it when we alloc'd;
-                                     -- NB: chk defn of "is_current_CC"
-                                     -- if you go to change this! (WDP 94/12)
-           costCentresC
-               (case is_thunk of
-                  IsThunk    -> SLIT("ENTER_CC_TCL")
-                  IsFunction -> SLIT("ENTER_CC_FCL"))
-               [CReg node]
-
-       else if isCafCC cc then
-           costCentresC
-               SLIT("ENTER_CC_CAF")
-               [mkCCostCentre cc]
+           --ASSERT(isToplevClosure closure_info)
+           --ASSERT(is_thunk == IsFunction)
+           (if isToplevClosure closure_info && is_thunk == IsFunction then \x->x else pprTrace "enterCostCenterCode:" (hsep [ppr (is_thunk == IsFunction){-, ppr closure_info-}, text (showCostCentre False cc)])) $
+           costCentresC SLIT("ENTER_CC_FSUB") []
+
+       else if currentOrSubsumedCosts cc then 
+           -- i.e. current; subsumed dealt with above
+           -- get CCC out of the closure, where we put it when we alloc'd
+           case is_thunk of 
+               IsThunk    -> costCentresC SLIT("ENTER_CC_TCL") [CReg node]
+               IsFunction -> costCentresC SLIT("ENTER_CC_FCL") [CReg node]
+
+       else if isCafCC cc && isToplevClosure closure_info then
+           ASSERT(is_thunk == IsThunk)
+           costCentresC SLIT("ENTER_CC_CAF") [mkCCostCentre cc]
 
        else -- we've got a "real" cost centre right here in our hands...
-           costCentresC
-               (case is_thunk of
-                  IsThunk    -> SLIT("ENTER_CC_T")
-                  IsFunction -> SLIT("ENTER_CC_F"))
-               [mkCCostCentre cc]
-  where
-    is_current_CC cc
-      = currentOrSubsumedCosts cc
-       -- but we've already ruled out "subsumed", so it must be "current"!
+           case is_thunk of 
+               IsThunk    -> costCentresC SLIT("ENTER_CC_T") [mkCCostCentre cc]
+               IsFunction -> if isCafCC cc || isDictCC cc
+                             then costCentresC SLIT("ENTER_CC_FCAF") [mkCCostCentre cc]
+                             else costCentresC SLIT("ENTER_CC_FLOAD") [mkCCostCentre cc]
 \end{code}
 
 %************************************************************************
@@ -652,31 +647,43 @@ argSatisfactionCheck closure_info args
 
     nodeMustPointToIt (closureLFInfo closure_info)     `thenFC` \ node_points ->
 
-#ifdef GRAN
-    -- HWL:
+    let
+       emit_gran_macros = opt_GranMacros
+    in
+
+    -- HWL  ngo' ngoq:
     -- absC (CMacroStmt GRAN_FETCH [])                         `thenC`
-    -- forceHeapCheck [] node_points (absC AbsCNop)    `thenC`
-    (if node_points
-       then fetchAndReschedule  [] node_points
-       else absC AbsCNop)                              `thenC`
-#endif  {- GRAN -}
+    -- forceHeapCheck [] node_points (absC AbsCNop)                    `thenC`
+    (if emit_gran_macros 
+      then if node_points 
+             then fetchAndReschedule  [] node_points 
+             else yield [] node_points
+      else absC AbsCNop)                       `thenC`
 
     getCAddrMode (last args)                           `thenFC` \ last_amode ->
 
     if (isFollowableRep (getAmodeRep last_amode)) then
        getSpARelOffset 0       `thenFC` \ (SpARel spA off) ->
+       let
+           a_rel_int = spARelToInt spA off
+           a_rel_arg = mkIntCLit a_rel_int
+       in
+       ASSERT(a_rel_int /= 0)
        if node_points then
-           absC (CMacroStmt ARGS_CHK_A [mkIntCLit (spARelToInt spA off)])
+           absC (CMacroStmt ARGS_CHK_A [a_rel_arg])
        else
-           absC (CMacroStmt ARGS_CHK_A_LOAD_NODE
-                               [mkIntCLit (spARelToInt spA off), set_Node_to_this])
+           absC (CMacroStmt ARGS_CHK_A_LOAD_NODE [a_rel_arg, set_Node_to_this])
     else
-       getSpBRelOffset 0       `thenFC` \ b_rel_offset ->
+       getSpBRelOffset 0       `thenFC` \ (SpBRel spB off) ->
+       let
+           b_rel_int = spBRelToInt spB off
+           b_rel_arg = mkIntCLit b_rel_int
+       in
+       ASSERT(b_rel_int /= 0)
        if node_points then
-           absC (CMacroStmt ARGS_CHK_B [mkIntCLit (spBRelToInt b_rel_offset)])
+           absC (CMacroStmt ARGS_CHK_B [b_rel_arg])
        else
-           absC (CMacroStmt ARGS_CHK_B_LOAD_NODE
-                               [mkIntCLit (spBRelToInt b_rel_offset), set_Node_to_this])
+           absC (CMacroStmt ARGS_CHK_B_LOAD_NODE [b_rel_arg, set_Node_to_this])
   where
     -- We must tell the arg-satis macro whether Node is pointing to
     -- the closure or not.  If it isn't so pointing, then we give to
@@ -697,28 +704,33 @@ thunkWrapper closure_info thunk_code
   =    -- Stack and heap overflow checks
     nodeMustPointToIt (closureLFInfo closure_info)     `thenFC` \ node_points ->
 
-#ifdef GRAN
-    -- HWL insert macros for GrAnSim if node is live here
-    (if node_points
-       then fetchAndReschedule [] node_points
-       else absC AbsCNop)                                      `thenC`
-#endif  {- GRAN -}
+    let
+       emit_gran_macros = opt_GranMacros
+    in
+       -- HWL: insert macros for GrAnSim; 2 versions depending on liveness of node
+       -- (we prefer fetchAndReschedule-style context switches to yield ones)
+    (if emit_gran_macros 
+      then if node_points 
+             then fetchAndReschedule  [] node_points 
+             else yield [] node_points
+      else absC AbsCNop)                       `thenC`
 
     stackCheck closure_info [] node_points (   -- stackCheck *encloses* the rest
 
-    -- Must be after stackCheck: if stchk fails new stack
-    -- space has to be allocated from the heap
+       -- heapCheck must be after stackCheck: if stchk fails
+       -- new stack space is allocated from the heap which
+       -- would violate any previous heapCheck
 
-    heapCheck [] node_points (
-                                       -- heapCheck *encloses* the rest
-       -- The "[]" says there are no live argument registers
+    heapCheck [] node_points (                 -- heapCheck *encloses* the rest
+       -- The "[]" says there are no live argument registers
 
        -- Overwrite with black hole if necessary
-    blackHoleIt closure_info                           `thenC`
+    blackHoleIt closure_info                   `thenC`
 
-       -- Push update frame if necessary
-    setupUpdate closure_info (         -- setupUpdate *encloses* the rest
-       thunk_code
+    setupUpdate closure_info (                 -- setupUpdate *encloses* the rest
+
+       -- Finally, do the business
+    thunk_code
     )))
 
 funWrapper :: ClosureInfo      -- Closure whose code body this is
@@ -728,11 +740,19 @@ funWrapper :: ClosureInfo         -- Closure whose code body this is
 funWrapper closure_info arg_regs fun_body
   =    -- Stack overflow check
     nodeMustPointToIt (closureLFInfo closure_info)     `thenFC` \ node_points ->
-    stackCheck closure_info arg_regs node_points (     -- stackCheck *encloses* the rest
+    let
+       emit_gran_macros = opt_GranMacros
+    in
+    -- HWL   chu' ngoq:
+    (if emit_gran_macros
+      then yield  arg_regs node_points
+      else absC AbsCNop)                                 `thenC`
+
+    stackCheck closure_info arg_regs node_points (
+       -- stackCheck *encloses* the rest
 
-       -- Heap overflow check
     heapCheck arg_regs node_points (
-                                       -- heapCheck *encloses* the rest
+       -- heapCheck *encloses* the rest
 
        -- Finally, do the business
     fun_body
@@ -780,9 +800,9 @@ stackCheck closure_info regs node_reqd code
     )
   where
     all_regs = if node_reqd then node:regs else regs
-    liveness_mask = mkLiveRegsBitMask all_regs
+    liveness_mask = mkLiveRegsMask all_regs
 
-    returns_prim_type = closureReturnsUnboxedType closure_info
+    returns_prim_type = closureReturnsUnpointedType closure_info
 \end{code}
 
 %************************************************************************
@@ -817,8 +837,7 @@ setupUpdate :: ClosureInfo -> Code -> Code  -- Only called for thunks
 setupUpdate closure_info code
  = if (closureUpdReqd closure_info) then
        link_caf_if_needed      `thenFC` \ update_closure ->
-       getIntSwitchChkrC       `thenFC` \ isw_chkr ->
-       pushUpdateFrame update_closure (vector isw_chkr) code
+       pushUpdateFrame update_closure vector code
    else
        profCtrC SLIT("UPDF_OMITTED") [] `thenC`
        code
@@ -847,9 +866,7 @@ setupUpdate closure_info code
                                                        `thenC`
          returnFC amode
 
-   closure_label = mkClosureLabel (closureId closure_info)
-
-   vector isw_chkr
+   vector
      = case (closureType closure_info) of
        Nothing -> CReg StdUpdRetVecReg
        Just (spec_tycon, _, spec_datacons) ->
@@ -857,9 +874,9 @@ setupUpdate closure_info code
              UnvectoredReturn 1 ->
                        let
                    spec_data_con = head spec_datacons
-                   only_tag = getDataConTag spec_data_con
+                   only_tag = dataConTag spec_data_con
 
-                   direct = case (dataReturnConvAlg isw_chkr spec_data_con) of
+                   direct = case (dataReturnConvAlg spec_data_con) of
                        ReturnInRegs _ -> mkConUpdCodePtrVecLabel spec_tycon only_tag
                        ReturnInHeap   -> mkStdUpdCodePtrVecLabel spec_tycon only_tag
 
@@ -893,13 +910,13 @@ closureDescription :: FAST_STRING -- Module
        -- Not called for StgRhsCon which have global info tables built in
        -- CgConTbls.lhs with a description generated from the data constructor
 
-closureDescription mod_name name args body =
-    uppShow 0 (prettyToUn (
-       ppBesides [ppChar '<',
-                  ppPStr mod_name,
-                  ppChar '.',
-                  ppr PprDebug name,
-                  ppChar '>']))
+closureDescription mod_name name args body
+  = showSDoc (
+       hcat [char '<',
+                  ptext mod_name,
+                  char '.',
+                  ppr name,
+                  char '>'])
 \end{code}
 
 \begin{code}
@@ -916,9 +933,53 @@ chooseDynCostCentres cc args fvs body
                | just1 == fun
                -> mkCCostCentre overheadCostCentre
              _ -> use_cc
+
            -- if it's an utterly trivial RHS, then it must be
            -- one introduced by boxHigherOrderArgs for profiling,
            -- so we charge it to "OVERHEAD".
     in
     (use_cc, blame_cc)
 \end{code}
+
+
+
+========================================================================
+OLD CODE THAT EMITTED INFORMATON FOR QUANTITATIVE ANALYSIS
+
+It's pretty wierd, so I've nuked it for now.  SLPJ Nov 96
+
+\begin{pseudocode}
+getWrapperArgTypeCategories
+       :: Type                         -- wrapper's type
+       -> StrictnessInfo bdee          -- strictness info about its args
+       -> Maybe String
+
+getWrapperArgTypeCategories _ NoStrictnessInfo     = Nothing
+getWrapperArgTypeCategories _ BottomGuaranteed
+  = trace "getWrapperArgTypeCategories:BottomGuaranteed!" Nothing  -- wrong
+getWrapperArgTypeCategories _ (StrictnessInfo [] _) = Nothing
+
+getWrapperArgTypeCategories ty (StrictnessInfo arg_info _)
+  = Just (mkWrapperArgTypeCategories ty arg_info)
+
+mkWrapperArgTypeCategories
+       :: Type         -- wrapper's type
+       -> [Demand]     -- info about its arguments
+       -> String       -- a string saying lots about the args
+
+mkWrapperArgTypeCategories wrapper_ty wrap_info
+  = case (splitFunTy_maybe wrapper_ty) of { Just (arg_tys,_) ->
+    map do_one (wrap_info `zip` (map showTypeCategory arg_tys)) }
+  where
+    -- ToDo: this needs FIXING UP (it was a hack anyway...)
+    do_one (WwPrim, _) = 'P'
+    do_one (WwEnum, _) = 'E'
+    do_one (WwStrict, arg_ty_char) = arg_ty_char
+    do_one (WwUnpack _ _ _, arg_ty_char)
+      = if arg_ty_char `elem` "CIJFDTS"
+       then toLower arg_ty_char
+       else if arg_ty_char == '+' then 't'
+       else trace ("mkWrapp..:funny char:"++[arg_ty_char]) '-'
+    do_one (other_wrap_info, _) = '-'
+\end{pseudocode}
+