module Lvm.Core.RemoveDead (coreRemoveDead) where
import qualified Data.Set as Set
import Data.Set (Set)
import Lvm.Common.Id
import Lvm.Common.IdSet
import Lvm.Core.Expr
import Lvm.Core.FreeVar
import Lvm.Core.Utils
import Data.List
type Identity = (DeclKind,Id)
type Used = Set Identity
declIdentity :: CoreDecl -> Identity
declIdentity decl@(DeclExtern {})
= (DeclKindValue, declName decl)
declIdentity decl
= (declKindFromDecl decl, declName decl)
coreRemoveDead :: CoreModule -> CoreModule
coreRemoveDead m
= m { moduleDecls = filter (isUsed used) (moduleDecls m) }
where
used = foldl' usageDecl alwaysUsed (moduleDecls m)
alwaysUsed = Set.fromList
[ (DeclKindValue, idFromString "main$")
, (DeclKindValue, idFromString "main")
]
isUsed :: Used -> CoreDecl -> Bool
isUsed used decl
= accessPublic (declAccess decl) || Set.member (declIdentity decl) used
usageDecl :: Used -> CoreDecl -> Used
usageDecl used decl
= let usedCustoms = usageCustoms used (declCustoms decl)
in case decl of
DeclValue{} -> let usedExpr = usageValue usedCustoms (valueValue decl)
usedEnc = case valueEnc decl of
Just x -> Set.insert (DeclKindValue,x) usedExpr
Nothing -> usedExpr
in usedEnc
_ -> usedCustoms
usageCustoms :: Used -> [Custom] -> Used
usageCustoms = foldl' usageCustom
usageCustom :: Set (DeclKind, Id) -> Custom -> Set (DeclKind, Id)
usageCustom used custom
= case custom of
CustomLink x kind -> Set.insert (kind,x) used
CustomDecl _ customs -> usageCustoms used customs
_ -> used
usageValue :: Used -> Expr -> Used
usageValue = usageExpr emptySet
usageExprs :: IdSet -> Used -> [Expr] -> Used
usageExprs = foldl' . usageExpr
usageExpr :: IdSet -> Used -> Expr -> Used
usageExpr locals used expr
= case expr of
Let binds e -> let used' = usageBinds locals used binds
locals' = unionSet locals (binder binds)
in usageExpr locals' used' e
Lam x e -> usageExpr (insertSet x locals) used e
Match x alts -> usageAlts locals (usageVar locals used x) alts
Ap e1 e2 -> usageExpr locals (usageExpr locals used e1) e2
Var x -> usageVar locals used x
Con con -> usageCon locals used con
Lit _ -> used
usageVar :: IdSet -> Set (DeclKind, Id) -> Id -> Set (DeclKind, Id)
usageVar locals used x
| elemSet x locals = used
| otherwise = Set.insert (DeclKindValue,x) used
usageCon :: IdSet -> Set (DeclKind, Id) -> Con Expr -> Set (DeclKind, Id)
usageCon locals used con
= case con of
ConId x -> Set.insert (DeclKindCon,x) used
ConTag tag _ -> usageExpr locals used tag
usageBinds :: IdSet -> Used -> Binds -> Used
usageBinds locals used binds
= case binds of
NonRec (Bind _ rhs) -> usageExpr locals used rhs
Strict (Bind _ rhs) -> usageExpr locals used rhs
Rec bs -> let (ids,rhss) = unzipBinds bs
locals' = unionSet locals (setFromList ids)
in usageExprs locals' used rhss
usageAlts :: IdSet -> Set (DeclKind, Id) -> [Alt] -> Set (DeclKind, Id)
usageAlts = foldl' . usageAlt
usageAlt :: IdSet -> Set (DeclKind, Id) -> Alt -> Used
usageAlt locals used (Alt pat expr)
= case pat of
PatCon con ids -> let locals' = unionSet locals (setFromList ids)
used' = usageConPat used con
in usageExpr locals' used' expr
_ -> usageExpr locals used expr
usageConPat :: Set (DeclKind, Id) -> Con t -> Set (DeclKind, Id)
usageConPat used con
= case con of
ConId x -> Set.insert (DeclKindCon,x) used
ConTag _ _ -> used