summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/deSugar/Coverage.hs21
-rw-r--r--compiler/deSugar/DsExpr.hs5
-rw-r--r--compiler/deSugar/DsMonad.hs14
-rw-r--r--compiler/ghc.cabal.in1
-rw-r--r--compiler/profiling/CostCentre.hs131
-rw-r--r--compiler/profiling/CostCentreState.hs36
-rw-r--r--compiler/stgSyn/CoreToStg.hs2
-rw-r--r--compiler/typecheck/TcBinds.hs16
-rw-r--r--compiler/typecheck/TcRnMonad.hs29
-rw-r--r--compiler/typecheck/TcRnTypes.hs8
10 files changed, 188 insertions, 75 deletions
diff --git a/compiler/deSugar/Coverage.hs b/compiler/deSugar/Coverage.hs
index b2e9ea2cf6..1c118a84b6 100644
--- a/compiler/deSugar/Coverage.hs
+++ b/compiler/deSugar/Coverage.hs
@@ -27,6 +27,7 @@ import NameSet hiding (FreeVars)
import Name
import Bag
import CostCentre
+import CostCentreState
import CoreSyn
import Id
import VarSet
@@ -34,7 +35,6 @@ import Data.List
import FastString
import HscTypes
import TyCon
-import UniqSupply
import BasicTypes
import MonadUtils
import Maybes
@@ -75,7 +75,6 @@ addTicksToBinds hsc_env mod mod_loc exports tyCons binds
Just orig_file <- ml_hs_file mod_loc,
not ("boot" `isSuffixOf` orig_file) = do
- us <- mkSplitUniqSupply 'C' -- for cost centres
let orig_file2 = guessSourceFile binds orig_file
tickPass tickish (binds,st) =
@@ -98,7 +97,7 @@ addTicksToBinds hsc_env mod mod_loc exports tyCons binds
initState = TT { tickBoxCount = 0
, mixEntries = []
- , uniqSupply = us
+ , ccIndices = newCostCentreState
}
(binds1,st) = foldr tickPass (binds, initState) passes
@@ -1002,7 +1001,7 @@ liftL f (L loc a) = do
data TickTransState = TT { tickBoxCount:: Int
, mixEntries :: [MixEntry_]
- , uniqSupply :: UniqSupply
+ , ccIndices :: CostCentreState
}
data TickTransEnv = TTE { fileName :: FastString
@@ -1077,10 +1076,11 @@ instance Monad TM where
instance HasDynFlags TM where
getDynFlags = TM $ \ env st -> (tte_dflags env, noFVs, st)
-instance MonadUnique TM where
- getUniqueSupplyM = TM $ \_ st -> (uniqSupply st, noFVs, st)
- getUniqueM = TM $ \_ st -> let (u, us') = takeUniqFromSupply (uniqSupply st)
- in (u, noFVs, st { uniqSupply = us' })
+-- | Get the next HPC cost centre index for a given centre name
+getCCIndexM :: FastString -> TM CostCentreIndex
+getCCIndexM n = TM $ \_ st -> let (idx, is') = getCCIndex n $
+ ccIndices st
+ in (idx, noFVs, st { ccIndices = is' })
getState :: TM TickTransState
getState = TM $ \ _ st -> (st, noFVs, st)
@@ -1208,8 +1208,9 @@ mkTickish boxLabel countEntries topOnly pos fvs decl_path = do
return $ HpcTick (this_mod env) c
ProfNotes -> do
- ccUnique <- getUniqueM
- let cc = mkUserCC (mkFastString cc_name) (this_mod env) pos ccUnique
+ let nm = mkFastString cc_name
+ flavour <- HpcCC <$> getCCIndexM nm
+ let cc = mkUserCC nm (this_mod env) pos flavour
count = countEntries && gopt Opt_ProfCountEntries dflags
return $ ProfNote cc count True{-scopes-}
diff --git a/compiler/deSugar/DsExpr.hs b/compiler/deSugar/DsExpr.hs
index 2f3739e4c2..0b439a14b2 100644
--- a/compiler/deSugar/DsExpr.hs
+++ b/compiler/deSugar/DsExpr.hs
@@ -392,8 +392,9 @@ ds_expr _ (HsSCC _ cc expr@(L loc _)) = do
then do
mod_name <- getModule
count <- goptM Opt_ProfCountEntries
- uniq <- newUnique
- Tick (ProfNote (mkUserCC (sl_fs cc) mod_name loc uniq) count True)
+ let nm = sl_fs cc
+ flavour <- ExprCC <$> getCCIndexM nm
+ Tick (ProfNote (mkUserCC nm mod_name loc flavour) count True)
<$> dsLExpr expr
else dsLExpr expr
diff --git a/compiler/deSugar/DsMonad.hs b/compiler/deSugar/DsMonad.hs
index ae39e3de5a..d075d0a118 100644
--- a/compiler/deSugar/DsMonad.hs
+++ b/compiler/deSugar/DsMonad.hs
@@ -91,6 +91,7 @@ import Var (EvVar)
import qualified GHC.LanguageExtensions as LangExt
import UniqFM ( lookupWithDefaultUFM )
import Literal ( mkMachString )
+import CostCentreState
import Data.IORef
import Control.Monad
@@ -182,6 +183,7 @@ mkDsEnvsFromTcGbl :: MonadIO m
-> m (DsGblEnv, DsLclEnv)
mkDsEnvsFromTcGbl hsc_env msg_var tcg_env
= do { pm_iter_var <- liftIO $ newIORef 0
+ ; cc_st_var <- liftIO $ newIORef newCostCentreState
; let dflags = hsc_dflags hsc_env
this_mod = tcg_mod tcg_env
type_env = tcg_type_env tcg_env
@@ -190,7 +192,7 @@ mkDsEnvsFromTcGbl hsc_env msg_var tcg_env
complete_matches = hptCompleteSigs hsc_env
++ tcg_complete_matches tcg_env
; return $ mkDsEnvs dflags this_mod rdr_env type_env fam_inst_env
- msg_var pm_iter_var complete_matches
+ msg_var pm_iter_var cc_st_var complete_matches
}
runDs :: HscEnv -> (DsGblEnv, DsLclEnv) -> DsM a -> IO (Messages, Maybe a)
@@ -210,6 +212,7 @@ runDs hsc_env (ds_gbl, ds_lcl) thing_inside
initDsWithModGuts :: HscEnv -> ModGuts -> DsM a -> IO (Messages, Maybe a)
initDsWithModGuts hsc_env guts thing_inside
= do { pm_iter_var <- newIORef 0
+ ; cc_st_var <- newIORef newCostCentreState
; msg_var <- newIORef emptyMessages
; let dflags = hsc_dflags hsc_env
type_env = typeEnvFromEntities ids (mg_tcs guts) (mg_fam_insts guts)
@@ -225,7 +228,7 @@ initDsWithModGuts hsc_env guts thing_inside
envs = mkDsEnvs dflags this_mod rdr_env type_env
fam_inst_env msg_var pm_iter_var
- complete_matches
+ cc_st_var complete_matches
; runDs hsc_env envs thing_inside
}
@@ -253,9 +256,9 @@ initTcDsForSolver thing_inside
thing_inside }
mkDsEnvs :: DynFlags -> Module -> GlobalRdrEnv -> TypeEnv -> FamInstEnv
- -> IORef Messages -> IORef Int -> [CompleteMatch]
- -> (DsGblEnv, DsLclEnv)
-mkDsEnvs dflags mod rdr_env type_env fam_inst_env msg_var pmvar
+ -> IORef Messages -> IORef Int -> IORef CostCentreState
+ -> [CompleteMatch] -> (DsGblEnv, DsLclEnv)
+mkDsEnvs dflags mod rdr_env type_env fam_inst_env msg_var pmvar cc_st_var
complete_matches
= let if_genv = IfGblEnv { if_doc = text "mkDsEnvs",
if_rec_types = Just (mod, return type_env) }
@@ -271,6 +274,7 @@ mkDsEnvs dflags mod rdr_env type_env fam_inst_env msg_var pmvar
, ds_dph_env = emptyGlobalRdrEnv
, ds_parr_bi = panic "DsMonad: uninitialised ds_parr_bi"
, ds_complete_matches = completeMatchMap
+ , ds_cc_st = cc_st_var
}
lcl_env = DsLclEnv { dsl_meta = emptyNameEnv
, dsl_loc = real_span
diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in
index 384a50ff7e..5ffc3cebfd 100644
--- a/compiler/ghc.cabal.in
+++ b/compiler/ghc.cabal.in
@@ -390,6 +390,7 @@ Library
TysPrim
TysWiredIn
CostCentre
+ CostCentreState
ProfInit
RnBinds
RnEnv
diff --git a/compiler/profiling/CostCentre.hs b/compiler/profiling/CostCentre.hs
index 0043fd4bbc..91a4ef0ec7 100644
--- a/compiler/profiling/CostCentre.hs
+++ b/compiler/profiling/CostCentre.hs
@@ -1,6 +1,6 @@
{-# LANGUAGE DeriveDataTypeable #-}
module CostCentre (
- CostCentre(..), CcName, IsCafCC(..),
+ CostCentre(..), CcName, CCFlavour(..),
-- All abstract except to friend: ParseIface.y
CostCentreStack,
@@ -31,6 +31,7 @@ import Outputable
import SrcLoc
import FastString
import Util
+import CostCentreState
import Data.Data
@@ -41,21 +42,18 @@ import Data.Data
data CostCentre
= NormalCC {
- cc_key :: {-# UNPACK #-} !Int,
+ cc_flavour :: CCFlavour,
-- ^ Two cost centres may have the same name and
-- module but different SrcSpans, so we need a way to
-- distinguish them easily and give them different
- -- object-code labels. So every CostCentre has a
- -- Unique that is distinct from every other
- -- CostCentre in the same module.
- --
- -- XXX: should really be using Unique here, but we
- -- need to derive Data below and there's no Data
- -- instance for Unique.
+ -- object-code labels. So every CostCentre has an
+ -- associated flavour that indicates how it was
+ -- generated, and flavours that allow multiple instances
+ -- of the same name and module have a deterministic 0-based
+ -- index.
cc_name :: CcName, -- ^ Name of the cost centre itself
cc_mod :: Module, -- ^ Name of module defining this CC.
- cc_loc :: SrcSpan,
- cc_is_caf :: IsCafCC -- see below
+ cc_loc :: SrcSpan
}
| AllCafsCC {
@@ -66,9 +64,22 @@ data CostCentre
type CcName = FastString
-data IsCafCC = NotCafCC | CafCC
- deriving (Eq, Ord, Data)
-
+-- | The flavour of a cost centre.
+--
+-- Index fields represent 0-based indices giving source-code ordering of
+-- centres with the same module, name, and flavour.
+data CCFlavour = CafCC -- ^ Auto-generated top-level thunk
+ | ExprCC !CostCentreIndex -- ^ Explicitly annotated expression
+ | DeclCC !CostCentreIndex -- ^ Explicitly annotated declaration
+ | HpcCC !CostCentreIndex -- ^ Generated by HPC for coverage
+ deriving (Eq, Ord, Data)
+
+-- | Extract the index from a flavour
+flavourIndex :: CCFlavour -> Int
+flavourIndex CafCC = 0
+flavourIndex (ExprCC x) = unCostCentreIndex x
+flavourIndex (DeclCC x) = unCostCentreIndex x
+flavourIndex (HpcCC x) = unCostCentreIndex x
instance Eq CostCentre where
c1 == c2 = case c1 `cmpCostCentre` c2 of { EQ -> True; _ -> False }
@@ -81,10 +92,10 @@ cmpCostCentre :: CostCentre -> CostCentre -> Ordering
cmpCostCentre (AllCafsCC {cc_mod = m1}) (AllCafsCC {cc_mod = m2})
= m1 `compare` m2
-cmpCostCentre NormalCC {cc_key = n1, cc_mod = m1}
- NormalCC {cc_key = n2, cc_mod = m2}
- -- first key is module name, then the integer key
- = (m1 `compare` m2) `thenCmp` (n1 `compare` n2)
+cmpCostCentre NormalCC {cc_flavour = f1, cc_mod = m1, cc_name = n1}
+ NormalCC {cc_flavour = f2, cc_mod = m2, cc_name = n2}
+ -- first key is module name, then centre name, then flavour
+ = (m1 `compare` m2) `thenCmp` (n1 `compare` n2) `thenCmp` (f1 `compare` f2)
cmpCostCentre other_1 other_2
= let
@@ -102,9 +113,9 @@ cmpCostCentre other_1 other_2
-- Predicates on CostCentre
isCafCC :: CostCentre -> Bool
-isCafCC (AllCafsCC {}) = True
-isCafCC (NormalCC {cc_is_caf = CafCC}) = True
-isCafCC _ = False
+isCafCC (AllCafsCC {}) = True
+isCafCC (NormalCC {cc_flavour = CafCC}) = True
+isCafCC _ = False
-- | Is this a cost-centre which records scc counts
isSccCountCC :: CostCentre -> Bool
@@ -123,18 +134,17 @@ ccFromThisModule cc m = cc_mod cc == m
-----------------------------------------------------------------------------
-- Building cost centres
-mkUserCC :: FastString -> Module -> SrcSpan -> Unique -> CostCentre
-mkUserCC cc_name mod loc key
- = NormalCC { cc_key = getKey key, cc_name = cc_name, cc_mod = mod, cc_loc = loc,
- cc_is_caf = NotCafCC {-might be changed-}
+mkUserCC :: FastString -> Module -> SrcSpan -> CCFlavour -> CostCentre
+mkUserCC cc_name mod loc flavour
+ = NormalCC { cc_name = cc_name, cc_mod = mod, cc_loc = loc,
+ cc_flavour = flavour
}
-mkAutoCC :: Id -> Module -> IsCafCC -> CostCentre
-mkAutoCC id mod is_caf
- = NormalCC { cc_key = getKey (getUnique id),
- cc_name = str, cc_mod = mod,
+mkAutoCC :: Id -> Module -> CostCentre
+mkAutoCC id mod
+ = NormalCC { cc_name = str, cc_mod = mod,
cc_loc = nameSrcSpan (getName id),
- cc_is_caf = is_caf
+ cc_flavour = CafCC
}
where
name = getName id
@@ -249,26 +259,44 @@ instance Outputable CostCentre where
pprCostCentreCore :: CostCentre -> SDoc
pprCostCentreCore (AllCafsCC {cc_mod = m})
= text "__sccC" <+> braces (ppr m)
-pprCostCentreCore (NormalCC {cc_key = key, cc_name = n, cc_mod = m, cc_loc = loc,
- cc_is_caf = caf})
+pprCostCentreCore (NormalCC {cc_flavour = flavour, cc_name = n,
+ cc_mod = m, cc_loc = loc})
= text "__scc" <+> braces (hsep [
ppr m <> char '.' <> ftext n,
- whenPprDebug (ppr key),
- pp_caf caf,
+ pprFlavourCore flavour,
whenPprDebug (ppr loc)
])
-pp_caf :: IsCafCC -> SDoc
-pp_caf CafCC = text "__C"
-pp_caf _ = empty
+-- ^ Print a flavour in Core
+pprFlavourCore :: CCFlavour -> SDoc
+pprFlavourCore CafCC = text "__C"
+pprFlavourCore f = pprIdxCore $ flavourIndex f
+
+-- ^ Print a flavour's index in Core
+pprIdxCore :: Int -> SDoc
+pprIdxCore 0 = empty
+pprIdxCore idx = whenPprDebug $ ppr idx
-- Printing as a C label
ppCostCentreLbl :: CostCentre -> SDoc
ppCostCentreLbl (AllCafsCC {cc_mod = m}) = ppr m <> text "_CAFs_cc"
-ppCostCentreLbl (NormalCC {cc_key = k, cc_name = n, cc_mod = m,
- cc_is_caf = is_caf})
+ppCostCentreLbl (NormalCC {cc_flavour = f, cc_name = n, cc_mod = m})
= ppr m <> char '_' <> ztext (zEncodeFS n) <> char '_' <>
- case is_caf of { CafCC -> text "CAF"; _ -> ppr (mkUniqueGrimily k)} <> text "_cc"
+ ppFlavourLblComponent f <> text "_cc"
+
+-- ^ Print the flavour component of a C label
+ppFlavourLblComponent :: CCFlavour -> SDoc
+ppFlavourLblComponent CafCC = text "CAF"
+ppFlavourLblComponent (ExprCC i) = text "EXPR" <> ppIdxLblComponent i
+ppFlavourLblComponent (DeclCC i) = text "DECL" <> ppIdxLblComponent i
+ppFlavourLblComponent (HpcCC i) = text "HPC" <> ppIdxLblComponent i
+
+-- ^ Print the flavour index component of a C label
+ppIdxLblComponent :: CostCentreIndex -> SDoc
+ppIdxLblComponent n =
+ case unCostCentreIndex n of
+ 0 -> empty
+ n -> ppr n
-- This is the name to go in the user-displayed string,
-- recorded in the cost centre declaration
@@ -277,7 +305,7 @@ costCentreUserName = unpackFS . costCentreUserNameFS
costCentreUserNameFS :: CostCentre -> FastString
costCentreUserNameFS (AllCafsCC {}) = mkFastString "CAF"
-costCentreUserNameFS (NormalCC {cc_name = name, cc_is_caf = is_caf})
+costCentreUserNameFS (NormalCC {cc_name = name, cc_flavour = is_caf})
= case is_caf of
CafCC -> mkFastString "CAF:" `appendFS` name
_ -> name
@@ -285,24 +313,32 @@ costCentreUserNameFS (NormalCC {cc_name = name, cc_is_caf = is_caf})
costCentreSrcSpan :: CostCentre -> SrcSpan
costCentreSrcSpan = cc_loc
-instance Binary IsCafCC where
+instance Binary CCFlavour where
put_ bh CafCC = do
putByte bh 0
- put_ bh NotCafCC = do
+ put_ bh (ExprCC i) = do
putByte bh 1
+ put_ bh i
+ put_ bh (DeclCC i) = do
+ putByte bh 2
+ put_ bh i
+ put_ bh (HpcCC i) = do
+ putByte bh 3
+ put_ bh i
get bh = do
h <- getByte bh
case h of
0 -> do return CafCC
- _ -> do return NotCafCC
+ 1 -> ExprCC <$> get bh
+ 2 -> DeclCC <$> get bh
+ _ -> HpcCC <$> get bh
instance Binary CostCentre where
- put_ bh (NormalCC aa ab ac _ad ae) = do
+ put_ bh (NormalCC aa ab ac _ad) = do
putByte bh 0
put_ bh aa
put_ bh ab
put_ bh ac
- put_ bh ae
put_ bh (AllCafsCC ae _af) = do
putByte bh 1
put_ bh ae
@@ -312,8 +348,7 @@ instance Binary CostCentre where
0 -> do aa <- get bh
ab <- get bh
ac <- get bh
- ae <- get bh
- return (NormalCC aa ab ac noSrcSpan ae)
+ return (NormalCC aa ab ac noSrcSpan)
_ -> do ae <- get bh
return (AllCafsCC ae noSrcSpan)
diff --git a/compiler/profiling/CostCentreState.hs b/compiler/profiling/CostCentreState.hs
new file mode 100644
index 0000000000..0050c1d033
--- /dev/null
+++ b/compiler/profiling/CostCentreState.hs
@@ -0,0 +1,36 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module CostCentreState ( CostCentreState, newCostCentreState
+ , CostCentreIndex, unCostCentreIndex, getCCIndex
+ ) where
+
+import GhcPrelude
+import FastString
+import FastStringEnv
+
+import Data.Data
+import Binary
+
+-- | Per-module state for tracking cost centre indices.
+--
+-- See documentation of 'CostCentre.cc_flavour' for more details.
+newtype CostCentreState = CostCentreState (FastStringEnv Int)
+
+-- | Initialize cost centre state.
+newCostCentreState :: CostCentreState
+newCostCentreState = CostCentreState emptyFsEnv
+
+-- | An index into a given cost centre module,name,flavour set
+newtype CostCentreIndex = CostCentreIndex { unCostCentreIndex :: Int }
+ deriving (Eq, Ord, Data, Binary)
+
+-- | Get a new index for a given cost centre name.
+getCCIndex :: FastString
+ -> CostCentreState
+ -> (CostCentreIndex, CostCentreState)
+getCCIndex nm (CostCentreState m) =
+ (CostCentreIndex idx, CostCentreState m')
+ where
+ m_idx = lookupFsEnv m nm
+ idx = maybe 0 id m_idx
+ m' = extendFsEnv m nm (idx + 1)
diff --git a/compiler/stgSyn/CoreToStg.hs b/compiler/stgSyn/CoreToStg.hs
index 671f3eb5b5..f85382bc55 100644
--- a/compiler/stgSyn/CoreToStg.hs
+++ b/compiler/stgSyn/CoreToStg.hs
@@ -803,7 +803,7 @@ mkTopStgRhs dflags this_mod ccs rhs_fvs bndr binder_info rhs
| otherwise = Updatable
-- CAF cost centres generated for -fcaf-all
- caf_cc = mkAutoCC bndr modl CafCC
+ caf_cc = mkAutoCC bndr modl
caf_ccs = mkSingletonCCS caf_cc
-- careful: the binder might be :Main.main,
-- which doesn't belong to module mod_name.
diff --git a/compiler/typecheck/TcBinds.hs b/compiler/typecheck/TcBinds.hs
index 0c5179c473..60ed962bae 100644
--- a/compiler/typecheck/TcBinds.hs
+++ b/compiler/typecheck/TcBinds.hs
@@ -22,7 +22,7 @@ import {-# SOURCE #-} TcExpr ( tcMonoExpr )
import {-# SOURCE #-} TcPatSyn ( tcInferPatSynDecl, tcCheckPatSynDecl
, tcPatSynBuilderBind )
import CoreSyn (Tickish (..))
-import CostCentre (mkUserCC)
+import CostCentre (mkUserCC, CCFlavour(DeclCC))
import DynFlags
import FastString
import HsSyn
@@ -62,7 +62,6 @@ import BasicTypes
import Outputable
import PrelNames( ipClassName )
import TcValidity (checkValidType)
-import Unique (getUnique)
import UniqFM
import UniqSet
import qualified GHC.LanguageExtensions as LangExt
@@ -714,11 +713,12 @@ tcPolyCheck prag_fn
; poly_id <- addInlinePrags poly_id prag_sigs
; mod <- getModule
+ ; tick <- funBindTicks nm_loc mono_id mod prag_sigs
; let bind' = FunBind { fun_id = L nm_loc mono_id
, fun_matches = matches'
, fun_co_fn = co_fn
, bind_fvs = placeHolderNamesTc
- , fun_tick = funBindTicks nm_loc mono_id mod prag_sigs }
+ , fun_tick = tick }
export = ABE { abe_wrap = idHsWrapper
, abe_poly = poly_id
@@ -739,7 +739,7 @@ tcPolyCheck _prag_fn sig bind
= pprPanic "tcPolyCheck" (ppr sig $$ ppr bind)
funBindTicks :: SrcSpan -> TcId -> Module -> [LSig GhcRn]
- -> [Tickish TcId]
+ -> TcM [Tickish TcId]
funBindTicks loc fun_id mod sigs
| (mb_cc_str : _) <- [ cc_name | L _ (SCCFunSig _ _ cc_name) <- sigs ]
-- this can only be a singleton list, as duplicate pragmas are rejected
@@ -750,10 +750,12 @@ funBindTicks loc fun_id mod sigs
| otherwise
= getOccFS (Var.varName fun_id)
cc_name = moduleNameFS (moduleName mod) `appendFS` consFS '.' cc_str
- cc = mkUserCC cc_name mod loc (getUnique fun_id)
- = [ProfNote cc True True]
+ = do
+ flavour <- DeclCC <$> getCCIndexM cc_name
+ let cc = mkUserCC cc_name mod loc flavour
+ return [ProfNote cc True True]
| otherwise
- = []
+ = return []
{- Note [Instantiate sig with fresh variables]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/compiler/typecheck/TcRnMonad.hs b/compiler/typecheck/TcRnMonad.hs
index 184093f066..20185aebe1 100644
--- a/compiler/typecheck/TcRnMonad.hs
+++ b/compiler/typecheck/TcRnMonad.hs
@@ -128,6 +128,9 @@ module TcRnMonad(
withException,
+ -- * Stuff for cost centres.
+ ContainsCostCentreState(..), getCCIndexM,
+
-- * Types etc.
module TcRnTypes,
module IOEnv
@@ -170,6 +173,7 @@ import Util
import Annotations
import BasicTypes( TopLevelFlag )
import Maybes
+import CostCentreState
import qualified GHC.LanguageExtensions as LangExt
@@ -217,6 +221,7 @@ initTc hsc_env hsc_src keep_rn_syntax mod loc do_this
dependent_files_var <- newIORef [] ;
static_wc_var <- newIORef emptyWC ;
+ cc_st_var <- newIORef newCostCentreState ;
th_topdecls_var <- newIORef [] ;
th_foreign_files_var <- newIORef [] ;
th_topnames_var <- newIORef emptyNameSet ;
@@ -302,7 +307,8 @@ initTc hsc_env hsc_src keep_rn_syntax mod loc do_this
tcg_tc_plugins = [],
tcg_top_loc = loc,
tcg_static_wc = static_wc_var,
- tcg_complete_matches = []
+ tcg_complete_matches = [],
+ tcg_cc_st = cc_st_var
} ;
} ;
@@ -1872,3 +1878,24 @@ up as the value of the unsafeInterleaveIO thunk (see #8006 for a detailed
discussion). We don't currently know a general solution to this problem, but
we can use uninterruptibleMask_ to avoid the situation.
-}
+
+-- | Environments which track 'CostCentreState'
+class ContainsCostCentreState e where
+ extractCostCentreState :: e -> TcRef CostCentreState
+
+instance ContainsCostCentreState TcGblEnv where
+ extractCostCentreState = tcg_cc_st
+
+instance ContainsCostCentreState DsGblEnv where
+ extractCostCentreState = ds_cc_st
+
+-- | Get the next cost centre index associated with a given name.
+getCCIndexM :: (ContainsCostCentreState gbl)
+ => FastString -> TcRnIf gbl lcl CostCentreIndex
+getCCIndexM nm = do
+ env <- getGblEnv
+ let cc_st_ref = extractCostCentreState env
+ cc_st <- readTcRef cc_st_ref
+ let (idx, cc_st') = getCCIndex nm cc_st
+ writeTcRef cc_st_ref cc_st'
+ return idx
diff --git a/compiler/typecheck/TcRnTypes.hs b/compiler/typecheck/TcRnTypes.hs
index 4b11fa6114..27482b1841 100644
--- a/compiler/typecheck/TcRnTypes.hs
+++ b/compiler/typecheck/TcRnTypes.hs
@@ -189,6 +189,7 @@ import qualified GHC.LanguageExtensions as LangExt
import Fingerprint
import Util
import PrelNames ( isUnboundName )
+import CostCentreState
import Control.Monad (ap, liftM, msum)
import qualified Control.Monad.Fail as MonadFail
@@ -394,6 +395,8 @@ data DsGblEnv
, ds_parr_bi :: PArrBuiltin -- desugarer names for '-XParallelArrays'
, ds_complete_matches :: CompleteMatchMap
-- Additional complete pattern matches
+ , ds_cc_st :: IORef CostCentreState
+ -- Tracking indices for cost centre annotations
}
instance ContainsModule DsGblEnv where
@@ -700,7 +703,10 @@ data TcGblEnv
tcg_static_wc :: TcRef WantedConstraints,
-- ^ Wanted constraints of static forms.
-- See Note [Constraints in static forms].
- tcg_complete_matches :: [CompleteMatch]
+ tcg_complete_matches :: [CompleteMatch],
+
+ -- ^ Tracking indices for cost centre annotations
+ tcg_cc_st :: TcRef CostCentreState
}
-- NB: topModIdentity, not topModSemantic!