{-# LANGUAGE TypeFamilies #-}
module GHC.Stg.FVs (
depSortWithAnnotStgPgm,
annBindingFreeVars
) where
import GHC.Prelude hiding (mod)
import GHC.Stg.Syntax
import GHC.Stg.Utils (bindersOf)
import GHC.Types.Id
import GHC.Types.Name (Name, nameIsLocalOrFrom)
import GHC.Types.Tickish ( GenTickish(Breakpoint) )
import GHC.Types.Unique.Set (nonDetEltsUniqSet)
import GHC.Types.Var.Set
import GHC.Unit.Module (Module)
import GHC.Utils.Misc
import Data.Graph (SCC (..))
import GHC.Data.Graph.Directed( Node(..), stronglyConnCompFromEdgedVerticesUniq )
depSortWithAnnotStgPgm :: Module -> [StgTopBinding] -> [CgStgTopBinding]
depSortWithAnnotStgPgm :: Module -> [StgTopBinding] -> [CgStgTopBinding]
depSortWithAnnotStgPgm Module
this_mod [StgTopBinding]
binds
= {-# SCC "STG.depSortWithAnnotStgPgm" #-}
[CgStgTopBinding]
lit_binds forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map forall {pass :: StgPass}.
SCC (BinderP pass, GenStgRhs pass) -> GenStgTopBinding pass
from_scc [SCC (Id, CgStgRhs)]
sccs
where
lit_binds :: [CgStgTopBinding]
pairs :: [(Id, StgRhs)]
([CgStgTopBinding]
lit_binds, [(Id, StgRhs)]
pairs) = [StgTopBinding] -> ([CgStgTopBinding], [(Id, StgRhs)])
flattenTopStgBindings [StgTopBinding]
binds
nodes :: [Node Name (Id, CgStgRhs)]
nodes :: [Node Name (Id, CgStgRhs)]
nodes = forall a b. (a -> b) -> [a] -> [b]
map (Env -> (Id, StgRhs) -> Node Name (Id, CgStgRhs)
annotateTopPair Env
env0) [(Id, StgRhs)]
pairs
env0 :: Env
env0 = Env { locals :: IdSet
locals = IdSet
emptyVarSet, mod :: Module
mod = Module
this_mod }
sccs :: [SCC (Id,CgStgRhs)]
sccs :: [SCC (Id, CgStgRhs)]
sccs = forall key payload.
Uniquable key =>
[Node key payload] -> [SCC payload]
stronglyConnCompFromEdgedVerticesUniq [Node Name (Id, CgStgRhs)]
nodes
from_scc :: SCC (BinderP pass, GenStgRhs pass) -> GenStgTopBinding pass
from_scc (CyclicSCC [(BinderP pass, GenStgRhs pass)]
pairs) = forall (pass :: StgPass).
GenStgBinding pass -> GenStgTopBinding pass
StgTopLifted (forall (pass :: StgPass).
[(BinderP pass, GenStgRhs pass)] -> GenStgBinding pass
StgRec [(BinderP pass, GenStgRhs pass)]
pairs)
from_scc (AcyclicSCC (BinderP pass
bndr,GenStgRhs pass
rhs)) = forall (pass :: StgPass).
GenStgBinding pass -> GenStgTopBinding pass
StgTopLifted (forall (pass :: StgPass).
BinderP pass -> GenStgRhs pass -> GenStgBinding pass
StgNonRec BinderP pass
bndr GenStgRhs pass
rhs)
flattenTopStgBindings :: [StgTopBinding] -> ([CgStgTopBinding], [(Id,StgRhs)])
flattenTopStgBindings :: [StgTopBinding] -> ([CgStgTopBinding], [(Id, StgRhs)])
flattenTopStgBindings [StgTopBinding]
binds
= forall {pass :: StgPass} {pass :: StgPass}.
[GenStgTopBinding pass]
-> [(BinderP pass, GenStgRhs pass)]
-> [GenStgTopBinding pass]
-> ([GenStgTopBinding pass], [(BinderP pass, GenStgRhs pass)])
go [] [] [StgTopBinding]
binds
where
go :: [GenStgTopBinding pass]
-> [(BinderP pass, GenStgRhs pass)]
-> [GenStgTopBinding pass]
-> ([GenStgTopBinding pass], [(BinderP pass, GenStgRhs pass)])
go [GenStgTopBinding pass]
lits [(BinderP pass, GenStgRhs pass)]
pairs [] = ([GenStgTopBinding pass]
lits, [(BinderP pass, GenStgRhs pass)]
pairs)
go [GenStgTopBinding pass]
lits [(BinderP pass, GenStgRhs pass)]
pairs (GenStgTopBinding pass
bind:[GenStgTopBinding pass]
binds)
= case GenStgTopBinding pass
bind of
StgTopStringLit Id
bndr ByteString
rhs -> [GenStgTopBinding pass]
-> [(BinderP pass, GenStgRhs pass)]
-> [GenStgTopBinding pass]
-> ([GenStgTopBinding pass], [(BinderP pass, GenStgRhs pass)])
go (forall (pass :: StgPass). Id -> ByteString -> GenStgTopBinding pass
StgTopStringLit Id
bndr ByteString
rhsforall a. a -> [a] -> [a]
:[GenStgTopBinding pass]
lits) [(BinderP pass, GenStgRhs pass)]
pairs [GenStgTopBinding pass]
binds
StgTopLifted GenStgBinding pass
stg_bind -> [GenStgTopBinding pass]
-> [(BinderP pass, GenStgRhs pass)]
-> [GenStgTopBinding pass]
-> ([GenStgTopBinding pass], [(BinderP pass, GenStgRhs pass)])
go [GenStgTopBinding pass]
lits (forall {pass :: StgPass}.
GenStgBinding pass -> [(BinderP pass, GenStgRhs pass)]
flatten_one GenStgBinding pass
stg_bind forall a. [a] -> [a] -> [a]
++ [(BinderP pass, GenStgRhs pass)]
pairs) [GenStgTopBinding pass]
binds
flatten_one :: GenStgBinding pass -> [(BinderP pass, GenStgRhs pass)]
flatten_one (StgNonRec BinderP pass
b GenStgRhs pass
r) = [(BinderP pass
b,GenStgRhs pass
r)]
flatten_one (StgRec [(BinderP pass, GenStgRhs pass)]
pairs) = [(BinderP pass, GenStgRhs pass)]
pairs
annotateTopPair :: Env -> (Id, StgRhs) -> Node Name (Id, CgStgRhs)
annotateTopPair :: Env -> (Id, StgRhs) -> Node Name (Id, CgStgRhs)
annotateTopPair Env
env0 (Id
bndr, StgRhs
rhs)
= DigraphNode { node_key :: Name
node_key = Id -> Name
idName Id
bndr
, node_payload :: (Id, CgStgRhs)
node_payload = (Id
bndr, CgStgRhs
rhs')
, node_dependencies :: [Name]
node_dependencies = forall a b. (a -> b) -> [a] -> [b]
map Id -> Name
idName (forall elt. UniqSet elt -> [elt]
nonDetEltsUniqSet IdSet
top_fvs) }
where
(CgStgRhs
rhs', IdSet
top_fvs, LocalFVs
_) = Env -> StgRhs -> (CgStgRhs, IdSet, LocalFVs)
rhsFVs Env
env0 StgRhs
rhs
data Env
= Env
{
Env -> IdSet
locals :: IdSet
, Env -> Module
mod :: Module
}
addLocals :: [Id] -> Env -> Env
addLocals :: [Id] -> Env -> Env
addLocals [Id]
bndrs Env
env
= Env
env { locals :: IdSet
locals = IdSet -> [Id] -> IdSet
extendVarSetList (Env -> IdSet
locals Env
env) [Id]
bndrs }
type TopFVs = IdSet
type LocalFVs = DIdSet
annBindingFreeVars :: Module -> StgBinding -> CgStgBinding
annBindingFreeVars :: Module -> StgBinding -> CgStgBinding
annBindingFreeVars Module
this_mod = forall a b c. (a, b, c) -> a
fstOf3 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Env -> LocalFVs -> StgBinding -> (CgStgBinding, IdSet, LocalFVs)
bindingFVs (IdSet -> Module -> Env
Env IdSet
emptyVarSet Module
this_mod) LocalFVs
emptyDVarSet
bindingFVs :: Env -> LocalFVs -> StgBinding -> (CgStgBinding, TopFVs, LocalFVs)
bindingFVs :: Env -> LocalFVs -> StgBinding -> (CgStgBinding, IdSet, LocalFVs)
bindingFVs Env
env LocalFVs
body_fv StgBinding
b =
case StgBinding
b of
StgNonRec BinderP 'Vanilla
bndr StgRhs
r -> (forall (pass :: StgPass).
BinderP pass -> GenStgRhs pass -> GenStgBinding pass
StgNonRec BinderP 'Vanilla
bndr CgStgRhs
r', IdSet
fvs, LocalFVs
lcl_fvs)
where
(CgStgRhs
r', IdSet
fvs, LocalFVs
rhs_lcl_fvs) = Env -> StgRhs -> (CgStgRhs, IdSet, LocalFVs)
rhsFVs Env
env StgRhs
r
lcl_fvs :: LocalFVs
lcl_fvs = LocalFVs -> Id -> LocalFVs
delDVarSet LocalFVs
body_fv BinderP 'Vanilla
bndr LocalFVs -> LocalFVs -> LocalFVs
`unionDVarSet` LocalFVs
rhs_lcl_fvs
StgRec [(BinderP 'Vanilla, StgRhs)]
pairs -> (forall (pass :: StgPass).
[(BinderP pass, GenStgRhs pass)] -> GenStgBinding pass
StgRec [(Id, CgStgRhs)]
pairs', IdSet
fvs, LocalFVs
lcl_fvss)
where
bndrs :: [Id]
bndrs = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(BinderP 'Vanilla, StgRhs)]
pairs
env' :: Env
env' = [Id] -> Env -> Env
addLocals [Id]
bndrs Env
env
([CgStgRhs]
rhss, [IdSet]
rhs_fvss, [LocalFVs]
rhs_lcl_fvss) = forall a b c d. (a -> (b, c, d)) -> [a] -> ([b], [c], [d])
mapAndUnzip3 (Env -> StgRhs -> (CgStgRhs, IdSet, LocalFVs)
rhsFVs Env
env' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd) [(BinderP 'Vanilla, StgRhs)]
pairs
fvs :: IdSet
fvs = [IdSet] -> IdSet
unionVarSets [IdSet]
rhs_fvss
pairs' :: [(Id, CgStgRhs)]
pairs' = forall a b. [a] -> [b] -> [(a, b)]
zip [Id]
bndrs [CgStgRhs]
rhss
lcl_fvss :: LocalFVs
lcl_fvss = LocalFVs -> [Id] -> LocalFVs
delDVarSetList ([LocalFVs] -> LocalFVs
unionDVarSets (LocalFVs
body_fvforall a. a -> [a] -> [a]
:[LocalFVs]
rhs_lcl_fvss)) [Id]
bndrs
varFVs :: Env -> Id -> (TopFVs, LocalFVs) -> (TopFVs, LocalFVs)
varFVs :: Env -> Id -> (IdSet, LocalFVs) -> (IdSet, LocalFVs)
varFVs Env
env Id
v (IdSet
top_fvs, LocalFVs
lcl_fvs)
| Id
v Id -> IdSet -> Bool
`elemVarSet` Env -> IdSet
locals Env
env
= (IdSet
top_fvs, LocalFVs
lcl_fvs LocalFVs -> Id -> LocalFVs
`extendDVarSet` Id
v)
| Module -> Name -> Bool
nameIsLocalOrFrom (Env -> Module
mod Env
env) (Id -> Name
idName Id
v)
= (IdSet
top_fvs IdSet -> Id -> IdSet
`extendVarSet` Id
v, LocalFVs
lcl_fvs)
| Bool
otherwise
= (IdSet
top_fvs, LocalFVs
lcl_fvs)
exprFVs :: Env -> StgExpr -> (CgStgExpr, TopFVs, LocalFVs)
exprFVs :: Env -> StgExpr -> (CgStgExpr, IdSet, LocalFVs)
exprFVs Env
env = StgExpr -> (CgStgExpr, IdSet, LocalFVs)
go
where
go :: StgExpr -> (CgStgExpr, IdSet, LocalFVs)
go (StgApp Id
f [StgArg]
as)
| (IdSet
top_fvs, LocalFVs
lcl_fvs) <- Env -> Id -> (IdSet, LocalFVs) -> (IdSet, LocalFVs)
varFVs Env
env Id
f (Env -> [StgArg] -> (IdSet, LocalFVs)
argsFVs Env
env [StgArg]
as)
= (forall (pass :: StgPass). Id -> [StgArg] -> GenStgExpr pass
StgApp Id
f [StgArg]
as, IdSet
top_fvs, LocalFVs
lcl_fvs)
go (StgLit Literal
lit) = (forall (pass :: StgPass). Literal -> GenStgExpr pass
StgLit Literal
lit, IdSet
emptyVarSet, LocalFVs
emptyDVarSet)
go (StgConApp DataCon
dc ConstructorNumber
n [StgArg]
as [Type]
tys)
| (IdSet
top_fvs, LocalFVs
lcl_fvs) <- Env -> [StgArg] -> (IdSet, LocalFVs)
argsFVs Env
env [StgArg]
as
= (forall (pass :: StgPass).
DataCon
-> ConstructorNumber -> [StgArg] -> [Type] -> GenStgExpr pass
StgConApp DataCon
dc ConstructorNumber
n [StgArg]
as [Type]
tys, IdSet
top_fvs, LocalFVs
lcl_fvs)
go (StgOpApp StgOp
op [StgArg]
as Type
ty)
| (IdSet
top_fvs, LocalFVs
lcl_fvs) <- Env -> [StgArg] -> (IdSet, LocalFVs)
argsFVs Env
env [StgArg]
as
= (forall (pass :: StgPass).
StgOp -> [StgArg] -> Type -> GenStgExpr pass
StgOpApp StgOp
op [StgArg]
as Type
ty, IdSet
top_fvs, LocalFVs
lcl_fvs)
go (StgCase StgExpr
scrut BinderP 'Vanilla
bndr AltType
ty [GenStgAlt 'Vanilla]
alts)
| (CgStgExpr
scrut',IdSet
scrut_top_fvs,LocalFVs
scrut_lcl_fvs) <- Env -> StgExpr -> (CgStgExpr, IdSet, LocalFVs)
exprFVs Env
env StgExpr
scrut
, ([CgStgAlt]
alts',[IdSet]
alts_top_fvss,[LocalFVs]
alts_lcl_fvss)
<- forall a b c d. (a -> (b, c, d)) -> [a] -> ([b], [c], [d])
mapAndUnzip3 (Env -> GenStgAlt 'Vanilla -> (CgStgAlt, IdSet, LocalFVs)
altFVs ([Id] -> Env -> Env
addLocals [BinderP 'Vanilla
bndr] Env
env)) [GenStgAlt 'Vanilla]
alts
, let top_fvs :: IdSet
top_fvs = IdSet
scrut_top_fvs IdSet -> IdSet -> IdSet
`unionVarSet` [IdSet] -> IdSet
unionVarSets [IdSet]
alts_top_fvss
alts_lcl_fvs :: LocalFVs
alts_lcl_fvs = [LocalFVs] -> LocalFVs
unionDVarSets [LocalFVs]
alts_lcl_fvss
lcl_fvs :: LocalFVs
lcl_fvs = LocalFVs -> Id -> LocalFVs
delDVarSet (LocalFVs -> LocalFVs -> LocalFVs
unionDVarSet LocalFVs
scrut_lcl_fvs LocalFVs
alts_lcl_fvs) BinderP 'Vanilla
bndr
= (forall (pass :: StgPass).
GenStgExpr pass
-> BinderP pass -> AltType -> [GenStgAlt pass] -> GenStgExpr pass
StgCase CgStgExpr
scrut' BinderP 'Vanilla
bndr AltType
ty [CgStgAlt]
alts', IdSet
top_fvs,LocalFVs
lcl_fvs)
go (StgLet XLet 'Vanilla
ext StgBinding
bind StgExpr
body) = (CgStgBinding -> CgStgExpr -> CgStgExpr)
-> StgBinding -> StgExpr -> (CgStgExpr, IdSet, LocalFVs)
go_bind (forall (pass :: StgPass).
XLet pass
-> GenStgBinding pass -> GenStgExpr pass -> GenStgExpr pass
StgLet XLet 'Vanilla
ext) StgBinding
bind StgExpr
body
go (StgLetNoEscape XLetNoEscape 'Vanilla
ext StgBinding
bind StgExpr
body) = (CgStgBinding -> CgStgExpr -> CgStgExpr)
-> StgBinding -> StgExpr -> (CgStgExpr, IdSet, LocalFVs)
go_bind (forall (pass :: StgPass).
XLetNoEscape pass
-> GenStgBinding pass -> GenStgExpr pass -> GenStgExpr pass
StgLetNoEscape XLetNoEscape 'Vanilla
ext) StgBinding
bind StgExpr
body
go (StgTick StgTickish
tick StgExpr
e)
| (CgStgExpr
e', IdSet
top_fvs, LocalFVs
lcl_fvs) <- Env -> StgExpr -> (CgStgExpr, IdSet, LocalFVs)
exprFVs Env
env StgExpr
e
, let lcl_fvs' :: LocalFVs
lcl_fvs' = LocalFVs -> LocalFVs -> LocalFVs
unionDVarSet (forall {pass :: TickishPass}.
(XTickishId pass ~ Id) =>
GenTickish pass -> LocalFVs
tickish StgTickish
tick) LocalFVs
lcl_fvs
= (forall (pass :: StgPass).
StgTickish -> GenStgExpr pass -> GenStgExpr pass
StgTick StgTickish
tick CgStgExpr
e', IdSet
top_fvs, LocalFVs
lcl_fvs')
where
tickish :: GenTickish pass -> LocalFVs
tickish (Breakpoint XBreakpoint pass
_ Int
_ [XTickishId pass]
ids) = [Id] -> LocalFVs
mkDVarSet [XTickishId pass]
ids
tickish GenTickish pass
_ = LocalFVs
emptyDVarSet
go_bind :: (CgStgBinding -> CgStgExpr -> CgStgExpr)
-> StgBinding -> StgExpr -> (CgStgExpr, IdSet, LocalFVs)
go_bind CgStgBinding -> CgStgExpr -> CgStgExpr
dc StgBinding
bind StgExpr
body = (CgStgBinding -> CgStgExpr -> CgStgExpr
dc CgStgBinding
bind' CgStgExpr
body', IdSet
top_fvs, LocalFVs
lcl_fvs)
where
env' :: Env
env' = [Id] -> Env -> Env
addLocals (forall (a :: StgPass). (BinderP a ~ Id) => GenStgBinding a -> [Id]
bindersOf StgBinding
bind) Env
env
(CgStgExpr
body', IdSet
body_top_fvs, LocalFVs
body_lcl_fvs) = Env -> StgExpr -> (CgStgExpr, IdSet, LocalFVs)
exprFVs Env
env' StgExpr
body
(CgStgBinding
bind', IdSet
bind_top_fvs, LocalFVs
lcl_fvs) = Env -> LocalFVs -> StgBinding -> (CgStgBinding, IdSet, LocalFVs)
bindingFVs Env
env' LocalFVs
body_lcl_fvs StgBinding
bind
top_fvs :: IdSet
top_fvs = IdSet
bind_top_fvs IdSet -> IdSet -> IdSet
`unionVarSet` IdSet
body_top_fvs
rhsFVs :: Env -> StgRhs -> (CgStgRhs, TopFVs, LocalFVs)
rhsFVs :: Env -> StgRhs -> (CgStgRhs, IdSet, LocalFVs)
rhsFVs Env
env (StgRhsClosure XRhsClosure 'Vanilla
_ CostCentreStack
ccs UpdateFlag
uf [BinderP 'Vanilla]
bs StgExpr
body)
| (CgStgExpr
body', IdSet
top_fvs, LocalFVs
lcl_fvs) <- Env -> StgExpr -> (CgStgExpr, IdSet, LocalFVs)
exprFVs ([Id] -> Env -> Env
addLocals [BinderP 'Vanilla]
bs Env
env) StgExpr
body
, let lcl_fvs' :: LocalFVs
lcl_fvs' = LocalFVs -> [Id] -> LocalFVs
delDVarSetList LocalFVs
lcl_fvs [BinderP 'Vanilla]
bs
= (forall (pass :: StgPass).
XRhsClosure pass
-> CostCentreStack
-> UpdateFlag
-> [BinderP pass]
-> GenStgExpr pass
-> GenStgRhs pass
StgRhsClosure LocalFVs
lcl_fvs' CostCentreStack
ccs UpdateFlag
uf [BinderP 'Vanilla]
bs CgStgExpr
body', IdSet
top_fvs, LocalFVs
lcl_fvs')
rhsFVs Env
env (StgRhsCon CostCentreStack
ccs DataCon
dc ConstructorNumber
mu [StgTickish]
ts [StgArg]
bs)
| (IdSet
top_fvs, LocalFVs
lcl_fvs) <- Env -> [StgArg] -> (IdSet, LocalFVs)
argsFVs Env
env [StgArg]
bs
= (forall (pass :: StgPass).
CostCentreStack
-> DataCon
-> ConstructorNumber
-> [StgTickish]
-> [StgArg]
-> GenStgRhs pass
StgRhsCon CostCentreStack
ccs DataCon
dc ConstructorNumber
mu [StgTickish]
ts [StgArg]
bs, IdSet
top_fvs, LocalFVs
lcl_fvs)
argsFVs :: Env -> [StgArg] -> (TopFVs, LocalFVs)
argsFVs :: Env -> [StgArg] -> (IdSet, LocalFVs)
argsFVs Env
env = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (IdSet, LocalFVs) -> StgArg -> (IdSet, LocalFVs)
f (IdSet
emptyVarSet, LocalFVs
emptyDVarSet)
where
f :: (IdSet, LocalFVs) -> StgArg -> (IdSet, LocalFVs)
f (IdSet
fvs,LocalFVs
ids) StgLitArg{} = (IdSet
fvs, LocalFVs
ids)
f (IdSet
fvs,LocalFVs
ids) (StgVarArg Id
v) = Env -> Id -> (IdSet, LocalFVs) -> (IdSet, LocalFVs)
varFVs Env
env Id
v (IdSet
fvs, LocalFVs
ids)
altFVs :: Env -> StgAlt -> (CgStgAlt, TopFVs, LocalFVs)
altFVs :: Env -> GenStgAlt 'Vanilla -> (CgStgAlt, IdSet, LocalFVs)
altFVs Env
env GenStgAlt{alt_con :: forall (pass :: StgPass). GenStgAlt pass -> AltCon
alt_con=AltCon
con, alt_bndrs :: forall (pass :: StgPass). GenStgAlt pass -> [BinderP pass]
alt_bndrs=[BinderP 'Vanilla]
bndrs, alt_rhs :: forall (pass :: StgPass). GenStgAlt pass -> GenStgExpr pass
alt_rhs=StgExpr
e}
| (CgStgExpr
e', IdSet
top_fvs, LocalFVs
lcl_fvs) <- Env -> StgExpr -> (CgStgExpr, IdSet, LocalFVs)
exprFVs ([Id] -> Env -> Env
addLocals [BinderP 'Vanilla]
bndrs Env
env) StgExpr
e
, let lcl_fvs' :: LocalFVs
lcl_fvs' = LocalFVs -> [Id] -> LocalFVs
delDVarSetList LocalFVs
lcl_fvs [BinderP 'Vanilla]
bndrs
, let newAlt :: CgStgAlt
newAlt = GenStgAlt{alt_con :: AltCon
alt_con=AltCon
con, alt_bndrs :: [BinderP 'CodeGen]
alt_bndrs=[BinderP 'Vanilla]
bndrs, alt_rhs :: CgStgExpr
alt_rhs=CgStgExpr
e'}
= (CgStgAlt
newAlt, IdSet
top_fvs, LocalFVs
lcl_fvs')