Commit ceffd7fe authored by Ben Gamari's avatar Ben Gamari 🐢

Revert "An overhaul of the SRT representation"

This reverts commit eb8e692c.
parent dee22948
......@@ -14,11 +14,12 @@ module CLabel (
pprDebugCLabel,
mkClosureLabel,
mkSRTLabel,
mkTopSRTLabel,
mkInfoTableLabel,
mkEntryLabel,
mkRednCountsLabel,
mkConInfoTableLabel,
mkLargeSRTLabel,
mkApEntryLabel,
mkApInfoTableLabel,
mkClosureTableLabel,
......@@ -53,7 +54,6 @@ module CLabel (
mkSMAP_DIRTY_infoLabel,
mkBadAlignmentLabel,
mkArrWords_infoLabel,
mkSRTInfoLabel,
mkTopTickyCtrLabel,
mkCAFBlackHoleInfoTableLabel,
......@@ -250,7 +250,10 @@ data CLabel
| HpcTicksLabel Module
-- | Static reference table
| SRTLabel
| SRTLabel !Unique
-- | Label of an StgLargeSRT
| LargeSRTLabel
{-# UNPACK #-} !Unique
-- | A bitmap (function or case return)
......@@ -300,6 +303,8 @@ instance Ord CLabel where
compare a1 a2
compare (SRTLabel u1) (SRTLabel u2) =
nonDetCmpUnique u1 u2
compare (LargeSRTLabel u1) (LargeSRTLabel u2) =
nonDetCmpUnique u1 u2
compare (LargeBitmapLabel u1) (LargeBitmapLabel u2) =
nonDetCmpUnique u1 u2
compare IdLabel{} _ = LT
......@@ -332,6 +337,8 @@ instance Ord CLabel where
compare _ HpcTicksLabel{} = GT
compare SRTLabel{} _ = LT
compare _ SRTLabel{} = GT
compare LargeSRTLabel{} _ = LT
compare _ LargeSRTLabel{} = GT
-- | Record where a foreign label is stored.
data ForeignLabelSource
......@@ -380,6 +387,9 @@ pprDebugCLabel lbl
data IdLabelInfo
= Closure -- ^ Label for closure
| SRT -- ^ Static reference table (TODO: could be removed
-- with the old code generator, but might be needed
-- when we implement the New SRT Plan)
| InfoTable -- ^ Info tables for closures; always read-only
| Entry -- ^ Entry point
| Slow -- ^ Slow entry point
......@@ -449,8 +459,8 @@ data DynamicLinkerLabelInfo
-- Constructing IdLabels
-- These are always local:
mkSRTLabel :: Unique -> CLabel
mkSRTLabel u = SRTLabel u
mkTopSRTLabel :: Unique -> CLabel
mkTopSRTLabel u = SRTLabel u
mkRednCountsLabel :: Name -> CLabel
mkRednCountsLabel name =
......@@ -508,29 +518,6 @@ mkSMAP_FROZEN_DIRTY_infoLabel = CmmLabel rtsUnitId (fsLit "stg_SMALL_MUT_ARR_P
mkSMAP_DIRTY_infoLabel = CmmLabel rtsUnitId (fsLit "stg_SMALL_MUT_ARR_PTRS_DIRTY") CmmInfo
mkBadAlignmentLabel = CmmLabel rtsUnitId (fsLit "stg_badAlignment") CmmEntry
mkSRTInfoLabel :: Int -> CLabel
mkSRTInfoLabel n = CmmLabel rtsUnitId lbl CmmInfo
where
lbl =
case n of
1 -> fsLit "stg_SRT_1"
2 -> fsLit "stg_SRT_2"
3 -> fsLit "stg_SRT_3"
4 -> fsLit "stg_SRT_4"
5 -> fsLit "stg_SRT_5"
6 -> fsLit "stg_SRT_6"
7 -> fsLit "stg_SRT_7"
8 -> fsLit "stg_SRT_8"
9 -> fsLit "stg_SRT_9"
10 -> fsLit "stg_SRT_10"
11 -> fsLit "stg_SRT_11"
12 -> fsLit "stg_SRT_12"
13 -> fsLit "stg_SRT_13"
14 -> fsLit "stg_SRT_14"
15 -> fsLit "stg_SRT_15"
16 -> fsLit "stg_SRT_16"
_ -> panic "mkSRTInfoLabel"
-----
mkCmmInfoLabel, mkCmmEntryLabel, mkCmmRetInfoLabel, mkCmmRetLabel,
mkCmmCodeLabel, mkCmmDataLabel, mkCmmClosureLabel
......@@ -615,6 +602,9 @@ isSomeRODataLabel (IdLabel _ _ ConInfoTable) = True
isSomeRODataLabel (IdLabel _ _ InfoTable) = True
isSomeRODataLabel (IdLabel _ _ LocalInfoTable) = True
isSomeRODataLabel (IdLabel _ _ BlockInfoTable) = True
-- static reference tables defined in haskell (.hs)
isSomeRODataLabel (IdLabel _ _ SRT) = True
isSomeRODataLabel (SRTLabel _) = True
-- info table defined in cmm (.cmm)
isSomeRODataLabel (CmmLabel _ _ CmmInfo) = True
isSomeRODataLabel _lbl = False
......@@ -626,7 +616,9 @@ foreignLabelStdcallInfo _lbl = Nothing
-- Constructing Large*Labels
mkLargeSRTLabel :: Unique -> CLabel
mkBitmapLabel :: Unique -> CLabel
mkLargeSRTLabel uniq = LargeSRTLabel uniq
mkBitmapLabel uniq = LargeBitmapLabel uniq
-- Constructing Cost Center Labels
......@@ -684,6 +676,8 @@ mkAsmTempDieLabel l = mkAsmTempDerivedLabel l (fsLit "_die")
-- Convert between different kinds of label
toClosureLbl :: CLabel -> CLabel
toClosureLbl (IdLabel n _ BlockInfoTable)
= pprPanic "toClosureLbl: BlockInfoTable" (ppr n)
toClosureLbl (IdLabel n c _) = IdLabel n c Closure
toClosureLbl (CmmLabel m str _) = CmmLabel m str CmmClosure
toClosureLbl l = pprPanic "toClosureLbl" (ppr l)
......@@ -752,6 +746,7 @@ needsCDecl :: CLabel -> Bool
-- don't bother declaring Bitmap labels, we always make sure
-- they are defined before use.
needsCDecl (SRTLabel _) = True
needsCDecl (LargeSRTLabel _) = False
needsCDecl (LargeBitmapLabel _) = False
needsCDecl (IdLabel _ _ _) = True
needsCDecl (LocalBlockLabel _) = True
......@@ -898,10 +893,12 @@ externallyVisibleCLabel (DynamicLinkerLabel _ _) = False
externallyVisibleCLabel (HpcTicksLabel _) = True
externallyVisibleCLabel (LargeBitmapLabel _) = False
externallyVisibleCLabel (SRTLabel _) = False
externallyVisibleCLabel (LargeSRTLabel _) = False
externallyVisibleCLabel (PicBaseLabel {}) = panic "externallyVisibleCLabel PicBaseLabel"
externallyVisibleCLabel (DeadStripPreventer {}) = panic "externallyVisibleCLabel DeadStripPreventer"
externallyVisibleIdLabel :: IdLabelInfo -> Bool
externallyVisibleIdLabel SRT = False
externallyVisibleIdLabel LocalInfoTable = False
externallyVisibleIdLabel LocalEntry = False
externallyVisibleIdLabel BlockInfoTable = False
......@@ -957,6 +954,7 @@ labelType (DynamicLinkerLabel _ _) = DataLabel -- Is this right?
labelType PicBaseLabel = DataLabel
labelType (DeadStripPreventer _) = DataLabel
labelType (HpcTicksLabel _) = DataLabel
labelType (LargeSRTLabel _) = DataLabel
labelType (LargeBitmapLabel _) = DataLabel
idInfoLabelType :: IdLabelInfo -> CLabelType
......@@ -1045,6 +1043,7 @@ internal names. <type> is one of the following:
info Info table
srt Static reference table
srtd Static reference table descriptor
entry Entry code (function, closure)
slow Slow entry code (if any)
ret Direct return address
......@@ -1183,6 +1182,7 @@ pprCLbl (StringLitLabel u)
pprCLbl (SRTLabel u)
= pprUniqueAlways u <> pp_cSEP <> text "srt"
pprCLbl (LargeSRTLabel u) = pprUniqueAlways u <> pp_cSEP <> text "srtd"
pprCLbl (LargeBitmapLabel u) = text "b" <> pprUniqueAlways u <> pp_cSEP <> text "btm"
-- Some bitsmaps for tuple constructors have a numeric tag (e.g. '7')
-- until that gets resolved we'll just force them to start
......@@ -1275,6 +1275,7 @@ ppIdFlavor :: IdLabelInfo -> SDoc
ppIdFlavor x = pp_cSEP <>
(case x of
Closure -> text "closure"
SRT -> text "srt"
InfoTable -> text "info"
LocalInfoTable -> text "info"
Entry -> text "entry"
......
......@@ -18,6 +18,7 @@ module Cmm (
-- * Info Tables
CmmTopInfo(..), CmmStackInfo(..), CmmInfoTable(..), topInfoTable,
ClosureTypeInfo(..),
C_SRT(..), needsSRT,
ProfilingInfo(..), ConstrDescription,
-- * Statements, expressions and types
......@@ -137,13 +138,24 @@ data CmmInfoTable
cit_lbl :: CLabel, -- Info table label
cit_rep :: SMRep,
cit_prof :: ProfilingInfo,
cit_srt :: Maybe CLabel -- empty, or a closure address
cit_srt :: C_SRT
}
data ProfilingInfo
= NoProfilingInfo
| ProfilingInfo [Word8] [Word8] -- closure_type, closure_desc
-- C_SRT is what StgSyn.SRT gets translated to...
-- we add a label for the table, and expect only the 'offset/length' form
data C_SRT = NoC_SRT
| C_SRT !CLabel !WordOff !StgHalfWord {-bitmap or escape-}
deriving (Eq)
needsSRT :: C_SRT -> Bool
needsSRT NoC_SRT = False
needsSRT (C_SRT _ _ _) = True
-----------------------------------------------------------------------------
-- Static Data
-----------------------------------------------------------------------------
......
{-# LANGUAGE GADTs, BangPatterns, RecordWildCards,
GeneralizedNewtypeDeriving, NondecreasingIndentation #-}
{-# LANGUAGE BangPatterns, GADTs #-}
module CmmBuildInfoTables
( CAFSet, CAFEnv, cafAnal
, doSRTs, ModuleSRTInfo, emptySRT
) where
( CAFSet, CAFEnv, cafAnal
, doSRTs, TopSRT, emptySRT, isEmptySRT, srtToData )
where
import GhcPrelude hiding (succ)
import BlockId
import Hoopl.Block
import Hoopl.Graph
import Hoopl.Label
import Hoopl.Collections
import Hoopl.Dataflow
import Module
import Digraph
import Bitmap
import CLabel
import PprCmmDecl ()
import Cmm
import CmmUtils
import CmmInfo
import Data.List
import DynFlags
import Maybes
import Outputable
import SMRep
import UniqSupply
import CostCentre
import StgCmmHeap
import Util
import PprCmm()
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Tuple
import Control.Monad
import Control.Monad.Trans.State
import Control.Monad.Trans.Class
foldSet :: (a -> b -> b) -> b -> Set a -> b
foldSet = Set.foldr
{- Note [SRTs]
-----------------------------------------------------------------------
-- SRTs
SRTs are the mechanism by which the garbage collector can determine
the live CAFs in the program.
Representation
^^^^^^^^^^^^^^
+------+
| info |
| | +-----+---+---+---+
| -------->|SRT_2| | | | | 0 |
|------| +-----+-|-+-|-+---+
| | | |
| code | | |
| | v v
An SRT is simply an object in the program's data segment. It has the
same representation as a static constructor. There are 16
pre-compiled SRT info tables: stg_SRT_1_info, .. stg_SRT_16_info,
representing SRT objects with 1-16 pointers, respectively.
The entries of an SRT object point to static closures, which are either
- FUN_STATIC, THUNK_STATIC or CONSTR
- Another SRT (actually just a CONSTR)
The final field of the SRT is the static link field, used by the
garbage collector to chain together static closures that it visits and
to determine whether a static closure has been visited or not. (see
Note [STATIC_LINK fields])
By traversing the transitive closure of an SRT, the GC will reach all
of the CAFs that are reachable from the code associated with this SRT.
If we need to create an SRT with more than 16 entries, we build a
chain of SRT objects with all but the last having 16 entries.
+-----+---+- -+---+---+
|SRT16| | | | | | 0 |
+-----+-|-+- -+-|-+---+
| |
v v
+----+---+---+---+
|SRT2| | | | | 0 |
+----+-|-+-|-+---+
| |
| |
v v
Referring to an SRT from the info table
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The following things have SRTs:
- Static functions (FUN)
- Static thunks (THUNK), ie. CAFs
- Continuations (RET_SMALL, etc.)
In each case, the info table points to the SRT.
- info->srt is zero if there's no SRT, otherwise:
- info->srt == 1 and info->f.srt_offset points to the SRT
(but see TODO below, we can improve this)
e.g. for a FUN with an SRT:
StgFunInfoTable +------+
info->f.srt_offset | ------------> offset to SRT object
StgStdInfoTable +------+
info->layout.ptrs | ... |
info->layout.nptrs | ... |
info->srt | 1 |
info->type | ... |
|------|
EXAMPLE
^^^^^^^
{- EXAMPLE
f = \x. ... g ...
where
......@@ -139,218 +62,28 @@ CmmDecls. e.g. for f_entry, we might end up with
where f1_ret is a return point, and f2_proc is a proc-point. We have
a CAFSet for each of these CmmDecls, let's suppose they are
[ f_entry{g_info}, f1_ret{g_info}, f2_proc{} ]
[ g_entry{h_info, c1_closure} ]
[ f_entry{g_closure}, f1_ret{g_closure}, f2_proc{} ]
[ g_entry{h_closure, c1_closure} ]
[ h_entry{c2_closure} ]
Next, we make an SRT for each of these functions:
f_srt : [g_info]
g_srt : [h_info, c1_closure]
h_srt : [c2_closure]
Now, for g_info and h_info, we want to refer to the SRTs for g and h
respectively, which we'll label g_srt and h_srt:
f_srt : [g_srt]
g_srt : [h_srt, c1_closure]
h_srt : [c2_closure]
Now, when an SRT has a single entry, we don't actually generate an SRT
closure for it, instead we just replace references to it with its
single element. So, since h_srt == c2_closure, we have
f_srt : [g_srt]
g_srt : [c2_closure, c1_closure]
h_srt : [c2_closure]
and the only SRT closure we generate is
g_srt = SRT_2 [c2_closure, c1_closure]
Optimisations
^^^^^^^^^^^^^
To reduce the code size overhead and the cost of traversing SRTs in
the GC, we want to simplify SRTs where possible. We therefore apply
the following optimisations. Each has a [keyword]; search for the
keyword in the code below to see where the optimisation is
implemented.
1. [Shortcut] we never create an SRT with a single entry, instead
we replace all references to the singleton SRT with a reference
to its element. This includes references from info tables.
i.e. instead of
+------+
| info |
| | +-----+---+---+
| -------->|SRT_1| | | 0 |
|------| +-----+-|-+---+
| | |
| code | |
| | v
closure
we can point directly to the closure:
+------+
| info |
| |
| -------->closure
|------|
| |
| code |
| |
The exception to this is when we're doing dynamic linking. In that
case, if the closure is not locally defined then we can't point to
it directly from the info table, because this is the text section
which cannot contain runtime relocations. In this case we skip this
optimisation and generate the singleton SRT, becase SRTs are in the
data section and *can* have relocatable references.
2. [FUN] If an SRT refers to a top-level function (a FUN_STATIC), then
we can shortcut the reference to point directly to the function's
SRT instead.
i.e. instead of
+---+---+---
|SRT| | |
+---+-|-+---
|
v
+---+---+
| | | 0 |
+-|-+---+
|
| +------+
| | info |
| | | +-----+---+---+
| | -------->|SRT_1| | | 0 |
`----->|------| +-----+-|-+---+
| | |
| code | |
| | v
closure
we can generate
+---+---+---
|SRT| | |
+---+-|-+---
`----------------------,
|
+---+---+ |
| | | 0 | |
+-|-+---+ |
| |
| +------+ |
| | info | v
| | | +-----+---+---+
| | -------->|SRT_1| | | 0 |
`----->|------| +-----+-|-+---+
| | |
| code | |
| | v
closure
This is quicker for the garbage collector to traverse, and avoids
setting the static link field on the function's closure.
Of course we can only do this if we know what the function's SRT
is. Due to [Shortcut] the function's SRT can be an arbitrary
closure, so this optimisation only applies within a module.
Note: we can *not* do this optimisation for top-level thunks
(CAFs), because we want the SRT to point directly to the
CAF. Otherwise the SRT would keep the CAF's static references alive
even after the CAF had been evaluated!
3. [Common] Identical SRTs can be commoned up.
4. [Filter] If an SRT A refers to an SRT B and a closure C, and B also
refers to C (perhaps transitively), then we can omit the reference
to C from A.
As an alternative to [FUN]: we could merge the FUN's SRT with the FUN
object itself.
TODO: make info->srt be an offset to the SRT, or zero if none (save
one word per info table that has an SRT)
Note that there are many other optimisations that we could do, but
aren't implemented. In general, we could omit any reference from an
SRT if everything reachable from it is also reachable from the other
fields in the SRT. Our [Filter] optimisation is a special case of
this.
Another opportunity we don't exploit is this:
A = {X,Y,Z}
B = {Y,Z}
C = {X,B}
Here we could use C = {A} and therefore [Shortcut] C = A.
-}
-- ---------------------------------------------------------------------
-- Label types
-- Labels that come from cafAnal can be:
-- - _closure labels for static functions or CAFs
-- - _info labels for dynamic functions, thunks, or continuations
-- - _entry labels for functions or thunks
--
-- Meanwhile the labels on top-level blocks are _entry labels.
--
-- To put everything in the same namespace we convert all labels to
-- closure labels using toClosureLbl. Note that some of these
-- labels will not actually exist; that's ok because we're going to
-- map them to SRTEntry later, which ranges over labels that do exist.
--
newtype CAFLabel = CAFLabel CLabel
deriving (Eq,Ord,Outputable)
Now, note that we cannot use g_closure and h_closure in an SRT,
because there are no static closures corresponding to these functions.
So we have to flatten out the structure, replacing g_closure and
h_closure with their contents:
type CAFSet = Set CAFLabel
type CAFEnv = LabelMap CAFSet
mkCAFLabel :: CLabel -> CAFLabel
mkCAFLabel lbl = CAFLabel (toClosureLbl lbl)
[ f_entry{c2_closure, c1_closure}, f1_ret{c2_closure,c1_closure}, f2_proc{} ]
[ g_entry{c2_closure, c1_closure} ]
[ h_entry{c2_closure} ]
-- This is a label that we can put in an SRT. It *must* be a closure label,
-- pointing to either a FUN_STATIC, THUNK_STATIC, or CONSTR.
newtype SRTEntry = SRTEntry CLabel
deriving (Eq, Ord, Outputable)
This is what flattenCAFSets is doing.
-- ---------------------------------------------------------------------
-- CAF analysis
-}
-- |
-- For each code block:
-- - collect the references reachable from this code block to FUN,
-- THUNK or RET labels for which hasCAF == True
--
-- This gives us a `CAFEnv`: a mapping from code block to sets of labels
--
cafAnal
:: LabelSet -- The blocks representing continuations, ie. those
-- that will get RET info tables. These labels will
-- get their own SRTs, so we don't aggregate CAFs from
-- references to these labels, we just use the label.
-> CLabel -- The top label of the proc
-> CmmGraph
-> CAFEnv
cafAnal contLbls topLbl cmmGraph =
analyzeCmmBwd cafLattice
(cafTransfers contLbls (g_entry cmmGraph) topLbl) cmmGraph mapEmpty
-----------------------------------------------------------------------
-- Finding the CAFs used by a procedure
type CAFSet = Set CLabel
type CAFEnv = LabelMap CAFSet
cafLattice :: DataflowLattice CAFSet
cafLattice = DataflowLattice Set.empty add
......@@ -359,329 +92,279 @@ cafLattice = DataflowLattice Set.empty add
let !new' = old `Set.union` new
in changedIf (Set.size new' > Set.size old) new'
cafTransfers :: LabelSet -> Label -> CLabel -> TransferFun CAFSet
cafTransfers contLbls entry topLbl
(BlockCC eNode middle xNode) fBase =
let joined = cafsInNode xNode $! live'
cafTransfers :: TransferFun CAFSet
cafTransfers (BlockCC eNode middle xNode) fBase =
let joined = cafsInNode xNode $! joinOutFacts cafLattice xNode fBase
!result = foldNodesBwdOO cafsInNode middle joined
facts = mapMaybe successorFact (successors xNode)
live' = joinFacts cafLattice facts
successorFact s
-- If this is a loop back to the entry, we can refer to the
-- entry label.
| s == entry = Just (add topLbl Set.empty)
-- If this is a continuation, we want to refer to the
-- SRT for the continuation's info table
| s `setMember` contLbls
= Just (Set.singleton (mkCAFLabel (infoTblLbl s)))
-- Otherwise, takes the CAF references from the destination
| otherwise
= lookupFact s fBase
cafsInNode :: CmmNode e x -> CAFSet -> CAFSet
cafsInNode node set = foldExpDeep addCaf node set
addCaf expr !set =
case expr of
CmmLit (CmmLabel c) -> add c set
CmmLit (CmmLabelOff c _) -> add c set
CmmLit (CmmLabelDiffOff c1 c2 _ _) -> add c1 $! add c2 set
_ -> set
add l s | hasCAF l = Set.insert (mkCAFLabel l) s
| otherwise = s
in mapSingleton (entryLabel eNode) result
-- -----------------------------------------------------------------------------
-- ModuleSRTInfo
data ModuleSRTInfo = ModuleSRTInfo
{ thisModule :: Module
-- ^ Current module being compiled. Required for calling labelDynamic.
, dedupSRTs :: Map (Set SRTEntry) SRTEntry
-- ^ previous SRTs we've emitted, so we can de-duplicate.
-- Used to implement the [Common] optimisation.
, flatSRTs :: Map SRTEntry (Set SRTEntry)
-- ^ The reverse mapping, so that we can remove redundant
-- entries. e.g. if we have an SRT [a,b,c], and we know that b
-- points to [c,d], we can omit c and emit [a,b].
-- Used to implement the [Filter] optimisation.
cafsInNode :: CmmNode e x -> CAFSet -> CAFSet
cafsInNode node set = foldExpDeep addCaf node set
where
addCaf expr !set =
case expr of
CmmLit (CmmLabel c) -> add c set
CmmLit (CmmLabelOff c _) -> add c set
CmmLit (CmmLabelDiffOff c1 c2 _ _) -> add c1 $! add c2 set
_ -> set
add l s | hasCAF l = Set.insert (toClosureLbl l) s
| otherwise = s
-- | An analysis to find live CAFs.
cafAnal :: CmmGraph -> CAFEnv
cafAnal cmmGraph = analyzeCmmBwd cafLattice cafTransfers cmmGraph mapEmpty
-----------------------------------------------------------------------
-- Building the SRTs
-- Description of the SRT for a given module.
-- Note that this SRT may grow as we greedily add new CAFs to it.
data TopSRT = TopSRT
{ lbl :: CLabel
, next_elt :: {-# UNPACK #-} !Int -- the next entry in the table
, rev_elts :: [CLabel]
, elt_map :: !(Map CLabel Int) -- CLabel -> its last entry in the table
}
instance Outputable ModuleSRTInfo where
ppr ModuleSRTInfo{..} =
text "ModuleSRTInfo:" <+> ppr dedupSRTs <+> ppr flatSRTs
emptySRT :: Module -> ModuleSRTInfo
emptySRT mod =
ModuleSRTInfo
{ thisModule = mod
, dedupSRTs = Map.empty
, flatSRTs = Map.empty }
-- -----------------------------------------------------------------------------
-- Constructing SRTs
{- Implementation notes
- In each CmmDecl there is a mapping info_tbls from Label -> CmmInfoTable
- The entry in info_tbls corresponding to g_entry is the closure info
table, the rest are continuations.
- Each entry in info_tbls possibly needs an SRT. We need to make a
label for each of these.
- We get the CAFSet for each entry from the CAFEnv
-}
-- | Return a (Label,CLabel) pair for each labelled block of a CmmDecl,
-- where the label is
-- - the info label for a continuation or dynamic closure
-- - the closure label for a top-level function (not a CAF)
getLabelledBlocks :: CmmDecl -> [(Label, CAFLabel)]
getLabelledBlocks (CmmData _ _) = []
getLabelledBlocks (CmmProc top_info _ _ _) =
[ (blockId, mkCAFLabel (cit_lbl info))
| (blockId, info) <- mapToList (info_tbls top_info)
, let rep = cit_rep info
, not (isStaticRep rep) || not (isThunkRep rep)
]
-- | Get (Label,CLabel) pairs for each block that represents a CAF.
-- These are treated differently from other labelled blocks:
-- - we never resolve a reference to a CAF to the contents of its SRT, since
-- the point of SRTs is to keep CAFs alive.
-- - CAFs therefore don't take part in the dependency analysis in depAnalSRTs.
-- instead we generate their SRTs after everything else, so that we can
-- resolve references in the CAF's SRT.
getCAFs :: CmmDecl -> [(Label, CAFLabel)]
getCAFs (CmmData _ _) = []
getCAFs (CmmProc top_info topLbl _ g)
| Just info <- mapLookup (g_entry g) (info_tbls top_info)
, let rep = cit_rep info
, isStaticRep rep && isThunkRep rep = [(g_entry g, mkCAFLabel topLbl)]
| otherwise = []