[project @ 2003-11-17 14:38:22 by simonmar]
[ghc-hetmet.git] / ghc / compiler / profiling / CostCentre.lhs
index 15cd2af..ed40a5e 100644 (file)
@@ -9,13 +9,15 @@ module CostCentre (
                -- All abstract except to friend: ParseIface.y
 
        CostCentreStack,
+       CollectedCCs,
        noCCS, subsumedCCS, currentCCS, overheadCCS, dontCareCCS,
-       noCostCentre, noCCAttached,
+       noCostCentre,
        noCCSAttached, isCurrentCCS,  isSubsumedCCS, currentOrSubsumedCCS,
+       isDerivedFromCurrentCCS,
 
        mkUserCC, mkAutoCC, mkAllCafsCC, 
-       mkSingletonCCS, cafifyCC, dupifyCC,
-       isCafCC, isDupdCC, isEmptyCC, isCafCCS,
+       mkSingletonCCS, dupifyCC, pushCCOnCCS,
+       isCafCCS,
        isSccCountCostCentre,
        sccAbleCostCentre,
        ccFromThisModule,
@@ -32,10 +34,12 @@ import Name         ( UserFS, EncodedFS, encodeFS, decode,
                          getOccName, occNameFS
                        )
 import Module          ( Module, ModuleName, moduleName,
-                         pprModuleName, moduleNameUserString
+                         moduleNameUserString
                        )
 import Outputable      
 import CStrings                ( pprStringInCStyle )
+import FastTypes
+import FastString
 import Util            ( thenCmp )
 \end{code}
 
@@ -84,14 +88,17 @@ data CostCentreStack
                        -- accumulate any costs.  But we still need
                        -- the placeholder.  This CCS is it.
 
-  | SingletonCCS CostCentre
-                       -- This is primarily for CAF cost centres, which
-                       -- are attached to top-level thunks right at the
-                       -- end of STG processing, before code generation.
-                       -- Hence, a CAF cost centre never appears as the
-                       -- argument of an _scc_.
-                       -- Also, we generate these singleton CCSs statically
-                       -- as part of code generation.
+  | PushCC CostCentre CostCentreStack
+               -- These are used during code generation as the CCSs
+               -- attached to closures.  A PushCC never appears as
+               -- the argument to an _scc_.
+               --
+               -- The tail (2nd argument) is either NoCCS, indicating
+               -- a staticly allocated CCS, or CurrentCCS indicating
+               -- a dynamically created CCS.  We only support
+               -- statically allocated *singleton* CCSs at the
+               -- moment, for the purposes of initialising the CCS
+               -- field of a CAF.
 
   deriving (Eq, Ord)   -- needed for Ord on CLabel
 \end{code}
@@ -133,6 +140,14 @@ data IsDupdCC
                        -- "dupd".
 
 data IsCafCC = CafCC | NotCafCC
+
+-- synonym for triple which describes the cost centre info in the generated
+-- code for a module.
+type CollectedCCs
+  = ( [CostCentre]       -- local cost-centres that need to be decl'd
+    , [CostCentre]       -- "extern" cost-centres
+    , [CostCentreStack]  -- pre-defined "singleton" cost centre stacks
+    )
 \end{code}
 
 WILL: Would there be any merit to recording ``I am now using a
@@ -168,9 +183,13 @@ isCurrentCCS _                             = False
 isSubsumedCCS SubsumedCCS              = True
 isSubsumedCCS _                                = False
 
-isCafCCS (SingletonCCS cc)             = isCafCC cc
+isCafCCS (PushCC cc NoCCS)             = isCafCC cc
 isCafCCS _                             = False
 
+isDerivedFromCurrentCCS CurrentCCS     = True
+isDerivedFromCurrentCCS (PushCC _ ccs) = isDerivedFromCurrentCCS ccs
+isDerivedFromCurrentCCS _              = False
+
 currentOrSubsumedCCS SubsumedCCS       = True
 currentOrSubsumedCCS CurrentCCS                = True
 currentOrSubsumedCCS _                 = False
@@ -180,14 +199,12 @@ Building cost centres
 
 \begin{code}
 mkUserCC :: UserFS -> Module -> CostCentre
-
 mkUserCC cc_name mod
   = NormalCC { cc_name = encodeFS cc_name, cc_mod =  moduleName mod,
               cc_is_dupd = OriginalCC, cc_is_caf = NotCafCC {-might be changed-}
     }
 
 mkAutoCC :: Id -> Module -> IsCafCC -> CostCentre
-
 mkAutoCC id mod is_caf
   = NormalCC { cc_name = occNameFS (getOccName id), cc_mod =  moduleName mod,
               cc_is_dupd = OriginalCC, cc_is_caf = is_caf
@@ -195,18 +212,13 @@ mkAutoCC id mod is_caf
 
 mkAllCafsCC m = AllCafsCC  { cc_mod = moduleName m }
 
-mkSingletonCCS :: CostCentre -> CostCentreStack
-mkSingletonCCS cc = SingletonCCS cc
 
-cafifyCC, dupifyCC  :: CostCentre -> CostCentre
 
-cafifyCC cc@(NormalCC {cc_is_caf = is_caf})
-  = ASSERT(not_a_caf_already is_caf)
-    cc {cc_is_caf = CafCC}
-  where
-    not_a_caf_already CafCC = False
-    not_a_caf_already _       = True
-cafifyCC cc = pprPanic "cafifyCC" (ppr cc)
+mkSingletonCCS :: CostCentre -> CostCentreStack
+mkSingletonCCS cc = pushCCOnCCS cc NoCCS
+
+pushCCOnCCS :: CostCentre -> CostCentreStack -> CostCentreStack
+pushCCOnCCS = PushCC
 
 dupifyCC cc = cc {cc_is_dupd = DupdCC}
 
@@ -267,10 +279,10 @@ cmpCostCentre other_1 other_2
        tag1 = tag_CC other_1
        tag2 = tag_CC other_2
     in
-    if tag1 _LT_ tag2 then LT else GT
+    if tag1 <# tag2 then LT else GT
   where
-    tag_CC (NormalCC   {}) = (ILIT(1) :: FAST_INT)
-    tag_CC (AllCafsCC  {}) = ILIT(2)
+    tag_CC (NormalCC   {}) = (_ILIT 1 :: FastInt)
+    tag_CC (AllCafsCC  {}) = _ILIT 2
 
 cmp_caf NotCafCC CafCC     = LT
 cmp_caf NotCafCC NotCafCC  = EQ
@@ -281,23 +293,28 @@ cmp_caf CafCC    NotCafCC  = GT
 -----------------------------------------------------------------------------
 Printing Cost Centre Stacks.
 
-There are two ways to print a CCS:
+The outputable instance for CostCentreStack prints the CCS as a C
+expression.
 
-       - for debugging output (i.e. -ddump-whatever),
-       - as a C label
+NOTE: Not all cost centres are suitable for using in a static
+initializer.  In particular, the PushCC forms where the tail is CCCS
+may only be used in inline C code because they expand to a
+non-constant C expression.
 
 \begin{code}
 instance Outputable CostCentreStack where
-  ppr ccs = case ccs of
-               NoCCS           -> ptext SLIT("NO_CCS")
-               CurrentCCS      -> ptext SLIT("CCCS")
-               OverheadCCS     -> ptext SLIT("CCS_OVERHEAD")
-               DontCareCCS     -> ptext SLIT("CCS_DONT_CARE")
-               SubsumedCCS     -> ptext SLIT("CCS_SUBSUMED")
-               SingletonCCS cc -> ppr cc <> ptext SLIT("_ccs")
-
+  ppr NoCCS            = ptext SLIT("NO_CCS")
+  ppr CurrentCCS       = ptext SLIT("CCCS")
+  ppr OverheadCCS      = ptext SLIT("CCS_OVERHEAD")
+  ppr DontCareCCS      = ptext SLIT("CCS_DONT_CARE")
+  ppr SubsumedCCS      = ptext SLIT("CCS_SUBSUMED")
+  ppr (PushCC cc NoCCS) = ppr cc <> ptext SLIT("_ccs")
+  ppr (PushCC cc ccs)   = ptext SLIT("PushCostCentre") <> 
+                          parens (ppr ccs <> comma <> ppr cc)
+
+-- print the static declaration for a singleton CCS.
 pprCostCentreStackDecl :: CostCentreStack -> SDoc
-pprCostCentreStackDecl ccs@(SingletonCCS cc)
+pprCostCentreStackDecl ccs@(PushCC cc NoCCS)
   = hcat [ ptext SLIT("CCS_DECLARE"), char '(',
           ppr ccs,             comma,  -- better be codeStyle
           ppCostCentreLbl cc,  comma,
@@ -332,12 +349,12 @@ instance Outputable CostCentre where
 
 -- Printing in an interface file or in Core generally
 pprCostCentreCore (AllCafsCC {cc_mod = m})
-  = text "__sccC" <+> braces (pprModuleName m)
+  = text "__sccC" <+> braces (ppr m)
 pprCostCentreCore (NormalCC {cc_name = n, cc_mod = m,
                             cc_is_caf = caf, cc_is_dupd = dup})
   = text "__scc" <+> braces (hsep [
-       ptext n,
-       pprModuleName m,        
+       ftext n,
+       ppr m,  
        pp_dup dup,
        pp_caf caf
     ])
@@ -351,9 +368,9 @@ pp_caf other   = empty
 
 -- Printing as a C label
 ppCostCentreLbl (NoCostCentre)           = text "NONE_cc"
-ppCostCentreLbl (AllCafsCC  {cc_mod = m}) = pprModuleName m <> text "_CAFs_cc"
+ppCostCentreLbl (AllCafsCC  {cc_mod = m}) = ppr m <> text "_CAFs_cc"
 ppCostCentreLbl (NormalCC {cc_name = n, cc_mod = m, cc_is_caf = is_caf}) 
-  = pprModuleName m <> ptext n <> 
+  = ppr m <> ftext n <> 
        text (case is_caf of { CafCC -> "_CAF"; _ -> "" }) <> text "_cc"
 
 -- This is the name to go in the user-displayed string, 
@@ -361,7 +378,7 @@ ppCostCentreLbl (NormalCC {cc_name = n, cc_mod = m, cc_is_caf = is_caf})
 costCentreUserName (NoCostCentre)  = "NO_CC"
 costCentreUserName (AllCafsCC {})  = "CAF"
 costCentreUserName cc@(NormalCC {cc_name = name, cc_is_caf = is_caf})
-  =  case is_caf of { CafCC -> "CAF:";   _ -> "" } ++ decode (_UNPK_ name)
+  =  case is_caf of { CafCC -> "CAF:";   _ -> "" } ++ decode (unpackFS name)
 \end{code}
 
 Cost Centre Declarations
@@ -378,7 +395,7 @@ pprCostCentreDecl is_local cc
            cc_ident,                                                   comma,
            pprStringInCStyle (costCentreUserName cc),                  comma,
            pprStringInCStyle (moduleNameUserString mod_name),          comma,
-           ptext is_subsumed,                                          comma,
+           is_subsumed,                                                comma,
            empty,      -- Now always externally visible
            text ");"]
     else
@@ -388,7 +405,7 @@ pprCostCentreDecl is_local cc
     mod_name   = cc_mod cc
     is_subsumed = ccSubsumed cc
 
-ccSubsumed :: CostCentre -> FAST_STRING                -- subsumed value
-ccSubsumed cc | isCafCC  cc = SLIT("CC_IS_CAF")
-             | otherwise   = SLIT("CC_IS_BORING")
+ccSubsumed :: CostCentre -> SDoc               -- subsumed value
+ccSubsumed cc | isCafCC  cc = ptext SLIT("CC_IS_CAF")
+             | otherwise   = ptext SLIT("CC_IS_BORING")
 \end{code}