%
% (c) The University of Glasgow 2006
% (c) The GRASP/AQUA Project, Glasgow University, 19931998
%
\section[IdInfo]{@IdInfos@: Nonessential information about @Ids@}
(And a pretty good illustration of quite a few things wrong with
Haskell. [WDP 94/11])
\begin{code}
module IdInfo (
IdDetails(..), pprIdDetails,
IdInfo,
vanillaIdInfo, noCafIdInfo,
seqIdInfo, megaSeqIdInfo,
zapLamInfo, zapDemandInfo, zapFragileInfo,
ArityInfo,
unknownArity,
arityInfo, setArityInfo, ppArityInfo,
strictnessInfo, setStrictnessInfo,
demandInfo, setDemandInfo, pprStrictness,
unfoldingInfo, setUnfoldingInfo, setUnfoldingInfoLazily,
InlinePragInfo,
inlinePragInfo, setInlinePragInfo,
OccInfo(..),
isDeadOcc, isLoopBreaker,
occInfo, setOccInfo,
InsideLam, OneBranch,
insideLam, notInsideLam, oneBranch, notOneBranch,
SpecInfo(..),
isEmptySpecInfo, specInfoFreeVars,
specInfoRules, seqSpecInfo, setSpecInfoHead,
specInfo, setSpecInfo,
CafInfo(..),
ppCafInfo, mayHaveCafRefs,
cafInfo, setCafInfo,
LBVarInfo(..),
noLBVarInfo, hasNoLBVarInfo,
lbvarInfo, setLBVarInfo,
TickBoxOp(..), TickBoxId,
) where
import CoreSyn
import Class
import PrimOp
import Name
import VarSet
import BasicTypes
import DataCon
import TyCon
import ForeignCall
import Demand
import Outputable
import Module
import FastString
import Data.Maybe
infixl 1 `setSpecInfo`,
`setArityInfo`,
`setInlinePragInfo`,
`setUnfoldingInfo`,
`setLBVarInfo`,
`setOccInfo`,
`setCafInfo`,
`setStrictnessInfo`,
`setDemandInfo`
\end{code}
%************************************************************************
%* *
IdDetails
%* *
%************************************************************************
\begin{code}
data IdDetails
= VanillaId
| RecSelId
{ sel_tycon :: TyCon
, sel_naughty :: Bool
}
| DataConWorkId DataCon
| DataConWrapId DataCon
| ClassOpId Class
| PrimOpId PrimOp
| FCallId ForeignCall
| TickBoxOpId TickBoxOp
| DFunId Bool
instance Outputable IdDetails where
ppr = pprIdDetails
pprIdDetails :: IdDetails -> SDoc
pprIdDetails VanillaId = empty
pprIdDetails other = brackets (pp other)
where
pp VanillaId = panic "pprIdDetails"
pp (DataConWorkId _) = ptext (sLit "DataCon")
pp (DataConWrapId _) = ptext (sLit "DataConWrapper")
pp (ClassOpId {}) = ptext (sLit "ClassOp")
pp (PrimOpId _) = ptext (sLit "PrimOp")
pp (FCallId _) = ptext (sLit "ForeignCall")
pp (TickBoxOpId _) = ptext (sLit "TickBoxOp")
pp (DFunId b) = ptext (sLit "DFunId") <>
ppWhen b (ptext (sLit "(newtype)"))
pp (RecSelId { sel_naughty = is_naughty })
= brackets $ ptext (sLit "RecSel")
<> ppWhen is_naughty (ptext (sLit "(naughty)"))
\end{code}
%************************************************************************
%* *
\subsection{The main IdInfo type}
%* *
%************************************************************************
\begin{code}
data IdInfo
= IdInfo {
arityInfo :: !ArityInfo,
specInfo :: SpecInfo,
unfoldingInfo :: Unfolding,
cafInfo :: CafInfo,
lbvarInfo :: LBVarInfo,
inlinePragInfo :: InlinePragma,
occInfo :: OccInfo,
strictnessInfo :: Maybe StrictSig,
demandInfo :: Maybe Demand
}
seqIdInfo :: IdInfo -> ()
seqIdInfo (IdInfo {}) = ()
megaSeqIdInfo :: IdInfo -> ()
megaSeqIdInfo info
= seqSpecInfo (specInfo info) `seq`
seqDemandInfo (demandInfo info) `seq`
seqStrictnessInfo (strictnessInfo info) `seq`
seqCaf (cafInfo info) `seq`
seqLBVar (lbvarInfo info) `seq`
seqOccInfo (occInfo info)
seqStrictnessInfo :: Maybe StrictSig -> ()
seqStrictnessInfo Nothing = ()
seqStrictnessInfo (Just ty) = seqStrictSig ty
seqDemandInfo :: Maybe Demand -> ()
seqDemandInfo Nothing = ()
seqDemandInfo (Just dmd) = seqDemand dmd
\end{code}
Setters
\begin{code}
setSpecInfo :: IdInfo -> SpecInfo -> IdInfo
setSpecInfo info sp = sp `seq` info { specInfo = sp }
setInlinePragInfo :: IdInfo -> InlinePragma -> IdInfo
setInlinePragInfo info pr = pr `seq` info { inlinePragInfo = pr }
setOccInfo :: IdInfo -> OccInfo -> IdInfo
setOccInfo info oc = oc `seq` info { occInfo = oc }
setUnfoldingInfoLazily :: IdInfo -> Unfolding -> IdInfo
setUnfoldingInfoLazily info uf
=
info { unfoldingInfo = uf }
setUnfoldingInfo :: IdInfo -> Unfolding -> IdInfo
setUnfoldingInfo info uf
=
info { unfoldingInfo = uf }
setArityInfo :: IdInfo -> ArityInfo -> IdInfo
setArityInfo info ar = info { arityInfo = ar }
setCafInfo :: IdInfo -> CafInfo -> IdInfo
setCafInfo info caf = info { cafInfo = caf }
setLBVarInfo :: IdInfo -> LBVarInfo -> IdInfo
setLBVarInfo info lb = info { lbvarInfo = lb }
setDemandInfo :: IdInfo -> Maybe Demand -> IdInfo
setDemandInfo info dd = dd `seq` info { demandInfo = dd }
setStrictnessInfo :: IdInfo -> Maybe StrictSig -> IdInfo
setStrictnessInfo info dd = dd `seq` info { strictnessInfo = dd }
\end{code}
\begin{code}
vanillaIdInfo :: IdInfo
vanillaIdInfo
= IdInfo {
cafInfo = vanillaCafInfo,
arityInfo = unknownArity,
specInfo = emptySpecInfo,
unfoldingInfo = noUnfolding,
lbvarInfo = NoLBVarInfo,
inlinePragInfo = defaultInlinePragma,
occInfo = NoOccInfo,
demandInfo = Nothing,
strictnessInfo = Nothing
}
noCafIdInfo :: IdInfo
noCafIdInfo = vanillaIdInfo `setCafInfo` NoCafRefs
\end{code}
%************************************************************************
%* *
\subsection[arityIdInfo]{Arity info about an @Id@}
%* *
%************************************************************************
For locallydefined Ids, the code generator maintains its own notion
of their arities; so it should not be asking... (but other things
besides the codegenerator need arity info!)
\begin{code}
type ArityInfo = Arity
unknownArity :: Arity
unknownArity = 0 :: Arity
ppArityInfo :: Int -> SDoc
ppArityInfo 0 = empty
ppArityInfo n = hsep [ptext (sLit "Arity"), int n]
\end{code}
%************************************************************************
%* *
\subsection{Inlinepragma information}
%* *
%************************************************************************
\begin{code}
type InlinePragInfo = InlinePragma
\end{code}
%************************************************************************
%* *
Strictness
%* *
%************************************************************************
\begin{code}
pprStrictness :: Maybe StrictSig -> SDoc
pprStrictness Nothing = empty
pprStrictness (Just sig) = ppr sig
\end{code}
%************************************************************************
%* *
SpecInfo
%* *
%************************************************************************
Note [Specialisations and RULES in IdInfo]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Generally speaking, a GlobalIdshas an *empty* SpecInfo. All their
RULES are contained in the globallybuilt rulebase. In principle,
one could attach the to M.f the RULES for M.f that are defined in M.
But we don't do that for instance declarations and so we just treat
them all uniformly.
The EXCEPTION is PrimOpIds, which do have rules in their IdInfo. That is
jsut for convenience really.
However, LocalIds may have nonempty SpecInfo. We treat them
differently because:
a) they might be nested, in which case a global table won't work
b) the RULE might mention free variables, which we use to keep things alive
In TidyPgm, when the LocalId becomes a GlobalId, its RULES are stripped off
and put in the global list.
\begin{code}
data SpecInfo
= SpecInfo
[CoreRule]
VarSet
emptySpecInfo :: SpecInfo
emptySpecInfo = SpecInfo [] emptyVarSet
isEmptySpecInfo :: SpecInfo -> Bool
isEmptySpecInfo (SpecInfo rs _) = null rs
specInfoFreeVars :: SpecInfo -> VarSet
specInfoFreeVars (SpecInfo _ fvs) = fvs
specInfoRules :: SpecInfo -> [CoreRule]
specInfoRules (SpecInfo rules _) = rules
setSpecInfoHead :: Name -> SpecInfo -> SpecInfo
setSpecInfoHead fn (SpecInfo rules fvs)
= SpecInfo (map (setRuleIdName fn) rules) fvs
seqSpecInfo :: SpecInfo -> ()
seqSpecInfo (SpecInfo rules fvs) = seqRules rules `seq` seqVarSet fvs
\end{code}
%************************************************************************
%* *
\subsection[CGIdInfo]{Code generatorrelated information}
%* *
%************************************************************************
\begin{code}
data CafInfo
= MayHaveCafRefs
| NoCafRefs
deriving (Eq, Ord)
vanillaCafInfo :: CafInfo
vanillaCafInfo = MayHaveCafRefs
mayHaveCafRefs :: CafInfo -> Bool
mayHaveCafRefs MayHaveCafRefs = True
mayHaveCafRefs _ = False
seqCaf :: CafInfo -> ()
seqCaf c = c `seq` ()
instance Outputable CafInfo where
ppr = ppCafInfo
ppCafInfo :: CafInfo -> SDoc
ppCafInfo NoCafRefs = ptext (sLit "NoCafRefs")
ppCafInfo MayHaveCafRefs = empty
\end{code}
%************************************************************************
%* *
\subsection[lbvarIdInfo]{Lambdabound var info about an @Id@}
%* *
%************************************************************************
\begin{code}
data LBVarInfo = NoLBVarInfo
| IsOneShotLambda
noLBVarInfo :: LBVarInfo
noLBVarInfo = NoLBVarInfo
hasNoLBVarInfo :: LBVarInfo -> Bool
hasNoLBVarInfo NoLBVarInfo = True
hasNoLBVarInfo IsOneShotLambda = False
seqLBVar :: LBVarInfo -> ()
seqLBVar l = l `seq` ()
pprLBVarInfo :: LBVarInfo -> SDoc
pprLBVarInfo NoLBVarInfo = empty
pprLBVarInfo IsOneShotLambda = ptext (sLit "OneShot")
instance Outputable LBVarInfo where
ppr = pprLBVarInfo
instance Show LBVarInfo where
showsPrec p c = showsPrecSDoc p (ppr c)
\end{code}
%************************************************************************
%* *
\subsection{Bulk operations on IdInfo}
%* *
%************************************************************************
\begin{code}
zapLamInfo :: IdInfo -> Maybe IdInfo
zapLamInfo info@(IdInfo {occInfo = occ, demandInfo = demand})
| is_safe_occ occ && is_safe_dmd demand
= Nothing
| otherwise
= Just (info {occInfo = safe_occ, demandInfo = Nothing})
where
is_safe_occ (OneOcc in_lam _ _) = in_lam
is_safe_occ _other = True
safe_occ = case occ of
OneOcc _ once int_cxt -> OneOcc insideLam once int_cxt
_other -> occ
is_safe_dmd Nothing = True
is_safe_dmd (Just dmd) = not (isStrictDmd dmd)
\end{code}
\begin{code}
zapDemandInfo :: IdInfo -> Maybe IdInfo
zapDemandInfo info@(IdInfo {demandInfo = dmd})
| isJust dmd = Just (info {demandInfo = Nothing})
| otherwise = Nothing
\end{code}
\begin{code}
zapFragileInfo :: IdInfo -> Maybe IdInfo
zapFragileInfo info
= Just (info `setSpecInfo` emptySpecInfo
`setUnfoldingInfo` noUnfolding
`setOccInfo` zapFragileOcc occ)
where
occ = occInfo info
\end{code}
%************************************************************************
%* *
\subsection{TickBoxOp}
%* *
%************************************************************************
\begin{code}
type TickBoxId = Int
data TickBoxOp
= TickBox Module !TickBoxId
instance Outputable TickBoxOp where
ppr (TickBox mod n) = ptext (sLit "tick") <+> ppr (mod,n)
\end{code}