#include "HsVersions.h"
-import CmdLineOpts ( opt_D_dump_simpl, opt_D_verbose_core2core, opt_UsageSPOn )
+import CmdLineOpts ( DynFlags, DynFlag(..), opt_UsageSPOn, dopt )
import CoreSyn
import CoreUnfold ( noUnfolding )
-import CoreLint ( beginPass, endPass )
-import Rules ( ProtoCoreRule(..) )
+import CoreLint ( showPass, endPass )
import UsageSPInf ( doUsageSPInf )
import VarEnv
import VarSet
-import Var ( Id, IdOrTyVar )
-import Id ( idType, idInfo, idName,
+import Var ( Id, Var )
+import Id ( idType, idInfo, idName, isExportedId,
mkVanillaId, mkId, exportWithOrigOccName,
- getIdStrictness, setIdStrictness,
- getIdDemandInfo, setIdDemandInfo,
+ idStrictness, setIdStrictness,
+ idDemandInfo, setIdDemandInfo,
)
import IdInfo ( specInfo, setSpecInfo,
- inlinePragInfo, setInlinePragInfo, InlinePragInfo(..),
setUnfoldingInfo, setDemandInfo,
- workerInfo, setWorkerInfo
+ workerInfo, setWorkerInfo, WorkerInfo(..)
)
import Demand ( wwLazy )
-import Name ( getOccName, tidyTopName, mkLocalName, isLocallyDefined )
+import Name ( getOccName, tidyTopName, mkLocalName )
import OccName ( initTidyOccEnv, tidyOccName )
-import Type ( tidyTopType, tidyType, tidyTypes, tidyTyVar, tidyTyVars )
+import Type ( tidyTopType, tidyType, tidyTyVar )
import Module ( Module )
-import UniqSupply ( UniqSupply )
+import UniqSupply ( mkSplitUniqSupply )
import Unique ( Uniquable(..) )
+import ErrUtils ( showPass )
import SrcLoc ( noSrcLoc )
import Util ( mapAccumL )
-import Outputable
\end{code}
Several tasks are done by @tidyCorePgm@
-1. Make certain top-level bindings into Globals. The point is that
+1. If @opt_UsageSPOn@ then compute usage information (which is
+ needed by Core2Stg). ** NOTE _scc_ HERE **
+ Do this first, because it may introduce new binders.
+
+2. Make certain top-level bindings into Globals. The point is that
Global things get externally-visible labels at code generation
time
-2. Give all binders a nice print-name. Their uniques aren't changed;
+3. Give all binders a nice print-name. Their uniques aren't changed;
rather we give them lexically unique occ-names, so that we can
safely print the OccNae only in the interface file. [Bad idea to
change the uniques, because the code generator makes global labels
from the uniques for local thunks etc.]
-
-3. If @opt_UsageSPOn@ then compute usage information (which is
- needed by Core2Stg). ** NOTE _scc_ HERE **
-
\begin{code}
-tidyCorePgm :: UniqSupply -> Module -> [CoreBind] -> [ProtoCoreRule]
- -> IO ([CoreBind], [ProtoCoreRule])
-tidyCorePgm us module_name binds_in rules
+tidyCorePgm :: DynFlags -> Module
+ -> [CoreBind] -> [IdCoreRule]
+ -> IO ([CoreBind], [IdCoreRule])
+tidyCorePgm dflags module_name binds_in orphans_in
= do
- beginPass "Tidy Core"
+ us <- mkSplitUniqSupply 'u'
+
+ showPass dflags "Tidy Core"
- let (tidy_env1, binds_tidy) = mapAccumL (tidyBind (Just module_name)) init_tidy_env binds_in
- rules_out = tidyProtoRules tidy_env1 rules
+ binds_in1 <- if opt_UsageSPOn
+ then _scc_ "CoreUsageSPInf"
+ doUsageSPInf dflags us binds_in
+ else return binds_in
- binds_out <- if opt_UsageSPOn
- then _scc_ "CoreUsageSPInf" doUsageSPInf us binds_tidy
- else return binds_tidy
+ let (tidy_env1, binds_out) = mapAccumL (tidyBind (Just module_name))
+ init_tidy_env binds_in1
+ orphans_out = tidyIdRules tidy_env1 orphans_in
- endPass "Tidy Core" (opt_D_dump_simpl || opt_D_verbose_core2core) binds_out
- return (binds_out, rules_out)
+ endPass dflags "Tidy Core" (dopt Opt_D_dump_simpl dflags ||
+ dopt Opt_D_verbose_core2core dflags)
+ binds_out
+
+ return (binds_out, orphans_out)
where
-- We also make sure to avoid any exported binders. Consider
-- f{-u1-} = 1 -- Local decl
-> (TidyEnv, CoreBind)
tidyBind maybe_mod env (NonRec bndr rhs)
= let
- (env', bndr') = tidy_bndr maybe_mod env env bndr
- rhs' = tidyExpr env rhs
+ (env', bndr') = tidy_bndr maybe_mod env' env bndr
+ rhs' = tidyExpr env' rhs
+ -- We use env' when tidying the RHS even though it's not
+ -- strictly necessary; it makes the code pretty hard to read
+ -- if we don't!
in
(env', NonRec bndr' rhs')
(env', Rec (zip bndrs' rhss'))
tidyExpr env (Type ty) = Type (tidyType env ty)
-tidyExpr env (Con con args) = Con con (map (tidyExpr env) args)
+tidyExpr env (Lit lit) = Lit lit
tidyExpr env (App f a) = App (tidyExpr env f) (tidyExpr env a)
tidyExpr env (Note n e) = Note (tidyNote env n) (tidyExpr env e)
%************************************************************************
\begin{code}
-tidyBndr :: TidyEnv -> IdOrTyVar -> (TidyEnv, IdOrTyVar)
+tidyBndr :: TidyEnv -> Var -> (TidyEnv, Var)
tidyBndr env var | isTyVar var = tidyTyVar env var
| otherwise = tidyId env var
-tidyBndrs :: TidyEnv -> [IdOrTyVar] -> (TidyEnv, [IdOrTyVar])
+tidyBndrs :: TidyEnv -> [Var] -> (TidyEnv, [Var])
tidyBndrs env vars = mapAccumL tidyBndr env vars
tidyId :: TidyEnv -> Id -> (TidyEnv, Id)
(tidy_env', occ') = tidyOccName tidy_env (getOccName id)
ty' = tidyType env (idType id)
id' = mkVanillaId name' ty'
- `setIdStrictness` getIdStrictness id
- `setIdDemandInfo` getIdDemandInfo id
+ `setIdStrictness` idStrictness id
+ `setIdDemandInfo` idDemandInfo id
-- NB: This throws away the IdInfo of the Id, which we
-- no longer need. That means we don't need to
-- run over it with env, nor renumber it.
tidyTopId mod env@(tidy_env, var_env) env_idinfo id
= -- Top level variables
let
- (tidy_env', name') | exportWithOrigOccName id = (tidy_env, idName id)
- | otherwise = tidyTopName mod tidy_env (idName id)
+ (tidy_env', name') = tidyTopName mod tidy_env (isExportedId id) (idName id)
ty' = tidyTopType (idType id)
idinfo' = tidyIdInfo env_idinfo (idInfo id)
id' = mkId name' ty' idinfo'
\begin{code}
-- tidyIdInfo does these things:
--- a) tidy the specialisation info (if any)
--- b) zap a complicated ICanSafelyBeINLINEd pragma,
--- c) zap the unfolding
+-- a) tidy the specialisation info and worker info (if any)
+-- b) zap the unfolding and demand info
-- The latter two are to avoid space leaks
tidyIdInfo env info
where
rules = specInfo info
- info1 | isEmptyCoreRules rules = info
+ info2 | isEmptyCoreRules rules = info
| otherwise = info `setSpecInfo` tidyRules env rules
- info2 = case inlinePragInfo info of
- ICanSafelyBeINLINEd _ _ -> info1 `setInlinePragInfo` NoInlinePragInfo
- other -> info1
-
info3 = info2 `setUnfoldingInfo` noUnfolding
- info4 = info3 `setDemandInfo` wwLazy -- I don't understand why...
+ info4 = info3 `setDemandInfo` wwLazy
info5 = case workerInfo info of
- Nothing -> info4
- Just w -> info4 `setWorkerInfo` Just (tidyVarOcc env w)
+ NoWorker -> info4
+ HasWorker w a -> info4 `setWorkerInfo` HasWorker (tidyVarOcc env w) a
-tidyProtoRules :: TidyEnv -> [ProtoCoreRule] -> [ProtoCoreRule]
-tidyProtoRules env rules
- = [ ProtoCoreRule is_local (tidyVarOcc env fn) (tidyRule env rule)
- | ProtoCoreRule is_local fn rule <- rules
- ]
+tidyIdRules :: TidyEnv -> [IdCoreRule] -> [IdCoreRule]
+tidyIdRules env rules
+ = [ (tidyVarOcc env fn, tidyRule env rule) | (fn,rule) <- rules ]
tidyRules :: TidyEnv -> CoreRules -> CoreRules
tidyRules env (Rules rules fvs)
tidy_set_elem var new_set = extendVarSet new_set (tidyVarOcc env var)
tidyRule :: TidyEnv -> CoreRule -> CoreRule
+tidyRule env rule@(BuiltinRule _) = rule
tidyRule env (Rule name vars tpl_args rhs)
= (Rule name vars' (map (tidyExpr env') tpl_args) (tidyExpr env' rhs))
where