%
% (c) The University of Glasgow 2006
% (c) The GRASP/AQUA Project, Glasgow University, 1993-1998
%
\section[IdInfo]{@IdInfos@: Non-essential 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, coVarDetails,
IdInfo,
vanillaIdInfo, noCafIdInfo,
seqIdInfo, megaSeqIdInfo,
OneShotInfo(..),
oneShotInfo, noOneShotInfo, hasNoOneShotInfo,
setOneShotInfo,
zapLamInfo, zapFragileInfo,
zapDemandInfo,
ArityInfo,
unknownArity,
arityInfo, setArityInfo, ppArityInfo,
strictnessInfo, setStrictnessInfo,
demandInfo, setDemandInfo, pprStrictness,
unfoldingInfo, setUnfoldingInfo, setUnfoldingInfoLazily,
InlinePragInfo,
inlinePragInfo, setInlinePragInfo,
OccInfo(..),
isDeadOcc, isStrongLoopBreaker, isWeakLoopBreaker,
occInfo, setOccInfo,
InsideLam, OneBranch,
insideLam, notInsideLam, oneBranch, notOneBranch,
SpecInfo(..),
emptySpecInfo,
isEmptySpecInfo, specInfoFreeVars,
specInfoRules, seqSpecInfo, setSpecInfoHead,
specInfo, setSpecInfo,
CafInfo(..),
ppCafInfo, mayHaveCafRefs,
cafInfo, setCafInfo,
TickBoxOp(..), TickBoxId,
) where
import CoreSyn
import Class
import PrimOp (PrimOp)
import Name
import VarSet
import BasicTypes
import DataCon
import TyCon
import ForeignCall
import Outputable
import Module
import FastString
import Demand
infixl 1 `setSpecInfo`,
`setArityInfo`,
`setInlinePragInfo`,
`setUnfoldingInfo`,
`setOneShotInfo`,
`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 Int Bool
coVarDetails :: IdDetails
coVarDetails = VanillaId
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 ns nt) = ptext (sLit "DFunId")
<> ppWhen (ns /= 0) (brackets (int ns))
<> ppWhen nt (ptext (sLit "(nt)"))
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,
oneShotInfo :: OneShotInfo,
inlinePragInfo :: InlinePragma,
occInfo :: OccInfo,
strictnessInfo :: StrictSig,
demandInfo :: 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`
seqOneShot (oneShotInfo info) `seq`
seqOccInfo (occInfo info)
seqOneShot :: OneShotInfo -> ()
seqOneShot l = l `seq` ()
seqStrictnessInfo :: StrictSig -> ()
seqStrictnessInfo ty = seqStrictSig ty
seqDemandInfo :: Demand -> ()
seqDemandInfo 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 }
setOneShotInfo :: IdInfo -> OneShotInfo -> IdInfo
setOneShotInfo info lb = info { oneShotInfo = lb }
setDemandInfo :: IdInfo -> Demand -> IdInfo
setDemandInfo info dd = dd `seq` info { demandInfo = dd }
setStrictnessInfo :: IdInfo -> 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,
oneShotInfo = NoOneShotInfo,
inlinePragInfo = defaultInlinePragma,
occInfo = NoOccInfo,
demandInfo = topDmd,
strictnessInfo = nopSig
}
noCafIdInfo :: IdInfo
noCafIdInfo = vanillaIdInfo `setCafInfo` NoCafRefs
\end{code}
%************************************************************************
%* *
\subsection[arity-IdInfo]{Arity info about an @Id@}
%* *
%************************************************************************
For locally-defined Ids, the code generator maintains its own notion
of their arities; so it should not be asking... (but other things
besides the code-generator 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{Inline-pragma information}
%* *
%************************************************************************
\begin{code}
type InlinePragInfo = InlinePragma
\end{code}
%************************************************************************
%* *
Strictness
%* *
%************************************************************************
\begin{code}
pprStrictness :: StrictSig -> SDoc
pprStrictness 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 globally-built rule-base. 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 non-empty 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[CG-IdInfo]{Code generator-related 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{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 = topDmd})
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 dmd = not (isStrictDmd dmd)
\end{code}
\begin{code}
zapDemandInfo :: IdInfo -> Maybe IdInfo
zapDemandInfo info = Just (info {demandInfo = topDmd})
\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}