getAmodeRep (CAddr _) = PtrRep
getAmodeRep (CReg magic_id) = magicIdPrimRep magic_id
getAmodeRep (CTemp uniq kind) = kind
-getAmodeRep (CLbl label kind) = kind
+getAmodeRep (CLbl _ kind) = kind
getAmodeRep (CCharLike _) = PtrRep
getAmodeRep (CIntLike _) = PtrRep
getAmodeRep (CLit lit) = literalPrimRep lit
CClosureInfoAndCode cl_info slow_heres fast_heres descr]
)
-flatAbsC (CCodeBlock label abs_C)
+flatAbsC (CCodeBlock lbl abs_C)
= flatAbsC abs_C `thenFlt` \ (absC_heres, absC_tops) ->
- returnFlt (AbsCNop, absC_tops `mkAbsCStmts` CCodeBlock label absC_heres)
+ returnFlt (AbsCNop, absC_tops `mkAbsCStmts` CCodeBlock lbl absC_heres)
flatAbsC (CRetDirect uniq slow_code srt liveness)
= flatAbsC slow_code `thenFlt` \ (heres, tops) ->
let nvrs = grab_non_void_amodes results
in ASSERT (length nvrs <= 1) nvrs
-pprAbsC (CCodeBlock label abs_C) _
+pprAbsC (CCodeBlock lbl abs_C) _
= if not (maybeToBool(nonemptyAbsC abs_C)) then
- pprTrace "pprAbsC: curious empty code block for" (pprCLabel label) empty
+ pprTrace "pprAbsC: curious empty code block for" (pprCLabel lbl) empty
else
case (pprTempAndExternDecls abs_C) of { (pp_temps, pp_exts) ->
vcat [
- hcat [text (if (externallyVisibleCLabel label)
+ hcat [text (if (externallyVisibleCLabel lbl)
then "FN_(" -- abbreviations to save on output
else "IFN_("),
- pprCLabel label, text ") {"],
+ pprCLabel lbl, text ") {"],
pp_exts, pp_temps,
LvSmall _ -> SLIT("RET_SMALL")
LvLarge _ -> SLIT("RET_BIG")
-pprAbsC stmt@(CRetVector label amodes srt liveness) _
+pprAbsC stmt@(CRetVector lbl amodes srt liveness) _
= case (pprTempAndExternDecls stmt) of { (_, pp_exts) ->
vcat [
pp_exts,
hcat [
ptext SLIT("VEC_INFO_") <> int size,
lparen,
- pprCLabel label, comma,
+ pprCLabel lbl, comma,
pp_liveness liveness, comma, -- bitmap liveness mask
pp_srt_info srt, -- SRT
ptext type_str, comma,
- ppLocalness label, comma
+ ppLocalness lbl, comma
],
nest 2 (sep (punctuate comma (map ppr_item amodes))),
text ");"
\end{code}
\begin{code}
-ppLocalness label
- = if (externallyVisibleCLabel label)
+ppLocalness lbl
+ = if (externallyVisibleCLabel lbl)
then empty
else ptext SLIT("static ")
ppr_amode (CTemp uniq kind) = char '_' <> pprUnique uniq <> char '_'
-ppr_amode (CLbl label kind) = pprCLabelAddr label
+ppr_amode (CLbl lbl kind) = pprCLabelAddr lbl
ppr_amode (CCharLike ch)
= hcat [ptext SLIT("CHARLIKE_CLOSURE"), char '(', pprAmode ch, rparen ]
False)
labelSeenTE :: CLabel -> TeM Bool
-labelSeenTE label env@(seen_uniqs, seen_labels)
- = if (label `elementOfCLabelSet` seen_labels)
+labelSeenTE lbl env@(seen_uniqs, seen_labels)
+ = if (lbl `elementOfCLabelSet` seen_labels)
then (env, True)
else ((seen_uniqs,
- addToCLabelSet seen_labels label),
+ addToCLabelSet seen_labels lbl),
False)
\end{code}
where
ppr_alt_stuff (_, absC) = ppr_decls_AbsC absC
-ppr_decls_AbsC (CCodeBlock label absC)
+ppr_decls_AbsC (CCodeBlock lbl absC)
= ppr_decls_AbsC absC
ppr_decls_AbsC (CInitHdr cl_info reg_rel cost_centre)
returnTE
(if temp_seen then Nothing else Just (pprTempDecl uniq kind), Nothing)
-ppr_decls_Amode (CLbl label VoidRep)
+ppr_decls_Amode (CLbl lbl VoidRep)
= returnTE (Nothing, Nothing)
-ppr_decls_Amode (CLbl label kind)
- = labelSeenTE label `thenTE` \ label_seen ->
+ppr_decls_Amode (CLbl lbl kind)
+ = labelSeenTE lbl `thenTE` \ label_seen ->
returnTE (Nothing,
- if label_seen then Nothing else Just (pprExternDecl False{-not in an SRT decl-} label))
+ if label_seen then Nothing else Just (pprExternDecl False{-not in an SRT decl-} lbl))
ppr_decls_Amode (CMacroExpr _ _ amodes)
= ppr_decls_Amodes amodes
ConTag, fIRST_TAG,
mkDataCon,
dataConType, dataConSig, dataConName, dataConTag,
- dataConOrigArgTys, dataConArgTys, dataConTyCon,
+ dataConArgTys, dataConTyCon,
dataConRawArgTys, dataConAllRawArgTys,
dataConFieldLabels, dataConStrictMarks, dataConSourceArity,
dataConNumFields, dataConNumInstArgs, dataConId, dataConRepStrictness,
isNullaryDataCon, isTupleCon, isUnboxedTupleCon,
- isExistentialDataCon,
+ isExistentialDataCon, splitProductType_maybe,
StrictnessMark(..), -- Representation visible to MkId only
markedStrict, notMarkedStrict, markedUnboxed, maybeMarkedUnboxed
splitAlgTyConApp_maybe
)
import PprType
-import TyCon ( TyCon, tyConDataCons, isDataTyCon,
+import TyCon ( TyCon, tyConDataCons, isDataTyCon, isProductTyCon,
isTupleTyCon, isUnboxedTupleTyCon )
import Class ( classTyCon )
-import Name ( Name, NamedThing(..), nameUnique, isLocallyDefinedName )
+import Name ( Name, NamedThing(..), nameUnique, isLocallyDefined )
import Var ( TyVar, Id )
import FieldLabel ( FieldLabel )
import BasicTypes ( Arity )
import Unique ( Unique, Uniquable(..) )
import CmdLineOpts ( opt_UnboxStrictFields )
import UniqSet
+import Maybes ( maybeToBool )
import Maybe
import Util ( assoc )
\end{code}
-- Don't mark newtype things as strict!
isDataTyCon (classTyCon clas) = MarkedStrict
| otherwise = NotMarkedStrict
-
--- We attempt to unbox/unpack a strict field when either:
--- (i) The tycon is imported, and the field is marked '! !', or
--- (ii) The tycon is defined in this module, the field is marked '!',
--- and the -funbox-strict-fields flag is on.
---
--- This ensures that if we compile some modules with -funbox-strict-fields and
--- some without, the compiler doesn't get confused about the constructor
--- representations.
-
-unbox_strict_arg_ty :: TyCon -> StrictnessMark -> Type -> (StrictnessMark, [Type])
-unbox_strict_arg_ty tycon NotMarkedStrict ty
- = (NotMarkedStrict, [ty])
-unbox_strict_arg_ty tycon MarkedStrict ty
- | not opt_UnboxStrictFields
- || not (isLocallyDefinedName (getName tycon)) = (MarkedStrict, [ty])
-unbox_strict_arg_ty tycon marked_unboxed ty
- -- MarkedUnboxed || (MarkedStrict && opt_UnboxStrictFields && not imported)
- = case splitAlgTyConApp_maybe ty of
- Just (tycon,_,[])
- -> panic (showSDoc (hcat [
- text "unbox_strict_arg_ty: constructors for ",
- ppr tycon,
- text " not available."
- ]))
- Just (tycon,ty_args,[con])
- -> case maybe_unpack_fields emptyUniqSet
- (zip (dataConOrigArgTys con ty_args)
- (dcUserStricts con))
- of
- Nothing -> (MarkedStrict, [ty])
- Just tys -> (MarkedUnboxed con tys, tys)
- _ -> (MarkedStrict, [ty])
-
--- bail out if we encounter the same tycon twice. This avoids problems like
---
--- data A = !B
--- data B = !A
---
--- where no useful unpacking can be done.
-
-maybe_unpack_field :: UniqSet TyCon -> Type -> StrictnessMark -> Maybe [Type]
-maybe_unpack_field set ty NotMarkedStrict
- = Just [ty]
-maybe_unpack_field set ty MarkedStrict | not opt_UnboxStrictFields
- = Just [ty]
-maybe_unpack_field set ty strict
- = case splitAlgTyConApp_maybe ty of
- Just (tycon,ty_args,[con])
- -- loop breaker
- | tycon `elementOfUniqSet` set -> Nothing
- -- don't unpack constructors with existential tyvars
- | not (null ex_tyvars) -> Nothing
- -- ok, let's do it
- | otherwise ->
- let set' = addOneToUniqSet set tycon in
- maybe_unpack_fields set'
- (zip (dataConOrigArgTys con ty_args)
- (dcUserStricts con))
- where (_, _, ex_tyvars, _, _, _) = dataConSig con
- _ -> Just [ty]
-
-maybe_unpack_fields :: UniqSet TyCon -> [(Type,StrictnessMark)] -> Maybe [Type]
-maybe_unpack_fields set tys
- | all isJust unpacked_fields = Just (concat (catMaybes unpacked_fields))
- | otherwise = Nothing
- where unpacked_fields = map (\(ty,str) -> maybe_unpack_field set ty str) tys
\end{code}
-
\begin{code}
dataConName :: DataCon -> Name
dataConName = dcName
dcOrigArgTys = arg_tys, dcTyCon = tycon})
= (tyvars, theta, ex_tyvars, ex_theta, arg_tys, tycon)
-dataConArgTys, dataConOrigArgTys :: DataCon
+dataConArgTys :: DataCon
-> [Type] -- Instantiated at these types
-- NB: these INCLUDE the existentially quantified arg types
-> [Type] -- Needs arguments of these types
dcExTyVars = ex_tyvars, dcExTheta = ex_theta}) inst_tys
= map (substTy (mkTyVarSubst (tyvars ++ ex_tyvars) inst_tys))
([mkDictTy cls tys | (cls,tys) <- ex_theta] ++ arg_tys)
-
-dataConOrigArgTys (MkData {dcOrigArgTys = arg_tys, dcTyVars = tyvars,
- dcExTyVars = ex_tyvars, dcExTheta = ex_theta}) inst_tys
- = map (substTy (mkTyVarSubst (tyvars ++ ex_tyvars) inst_tys))
- ([mkDictTy cls tys | (cls,tys) <- ex_theta] ++ arg_tys)
\end{code}
These two functions get the real argument types of the constructor,
isExistentialDataCon :: DataCon -> Bool
isExistentialDataCon (MkData {dcExTyVars = tvs}) = not (null tvs)
\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Splitting products}
+%* *
+%************************************************************************
+
+\begin{code}
+splitProductType_maybe
+ :: Type -- A product type, perhaps
+ -> Maybe (TyCon, -- The type constructor
+ [Type], -- Type args of the tycon
+ DataCon, -- The data constructor
+ [Type]) -- Its *representation* arg types
+
+ -- Returns (Just ...) for any
+ -- single-constructor
+ -- non-recursive type
+ -- not existentially quantified
+ -- type whether a data type or a new type
+ --
+ -- Rejecing existentials is conservative. Maybe some things
+ -- could be made to work with them, but I'm not going to sweat
+ -- it through till someone finds it's important.
+
+splitProductType_maybe ty
+ = case splitAlgTyConApp_maybe ty of
+ Just (tycon,ty_args,[data_con])
+ | isProductTyCon tycon && -- Checks for non-recursive
+ not (isExistentialDataCon data_con)
+ -> Just (tycon, ty_args, data_con, data_con_arg_tys)
+ where
+ data_con_arg_tys = map (substTy (mkTyVarSubst (dcTyVars data_con) ty_args))
+ (dcRepArgTys data_con)
+ other -> Nothing
+
+
+-- We attempt to unbox/unpack a strict field when either:
+-- (i) The tycon is imported, and the field is marked '! !', or
+-- (ii) The tycon is defined in this module, the field is marked '!',
+-- and the -funbox-strict-fields flag is on.
+--
+-- This ensures that if we compile some modules with -funbox-strict-fields and
+-- some without, the compiler doesn't get confused about the constructor
+-- representations.
+
+unbox_strict_arg_ty :: TyCon -> StrictnessMark -> Type -> (StrictnessMark, [Type])
+
+unbox_strict_arg_ty tycon strict_mark ty
+ | case strict_mark of
+ NotMarkedStrict -> False
+ MarkedUnboxed _ _ -> True
+ MarkedStrict -> opt_UnboxStrictFields &&
+ isLocallyDefined tycon &&
+ maybeToBool maybe_product &&
+ isDataTyCon arg_tycon
+ -- We can't look through newtypes in arguments (yet)
+ = (MarkedUnboxed con arg_tys, arg_tys)
+
+ | otherwise
+ = (strict_mark, [ty])
+
+ where
+ maybe_product = splitProductType_maybe ty
+ Just (arg_tycon, _, con, arg_tys) = maybe_product
+\end{code}
+
+
wwLazy, wwStrict, wwUnpackData, wwUnpackNew, wwPrim, wwEnum,
isStrict, isLazy, isPrim,
- pprDemands
+ pprDemands, seqDemand, seqDemands
) where
#include "HsVersions.h"
wwUnpackNew x = WwUnpack NewType False [x]
wwPrim = WwPrim
wwEnum = WwEnum
+
+seqDemand :: Demand -> ()
+seqDemand (WwLazy a) = a `seq` ()
+seqDemand (WwUnpack nd b ds) = nd `seq` b `seq` seqDemands ds
+seqDemand other = ()
+
+seqDemands [] = ()
+seqDemands (d:ds) = seqDemand d `seq` seqDemands ds
\end{code}
-- Modifying an Id
setIdName, setIdUnique, setIdType, setIdNoDiscard,
- setIdInfo, modifyIdInfo, maybeModifyIdInfo,
+ setIdInfo, lazySetIdInfo, modifyIdInfo, maybeModifyIdInfo,
-- Predicates
omitIfaceSigForId,
isId, mkIdVar,
idName, idType, idUnique, idInfo,
setIdName, setVarType, setIdUnique,
- setIdInfo, modifyIdInfo, maybeModifyIdInfo,
+ setIdInfo, lazySetIdInfo, modifyIdInfo, maybeModifyIdInfo,
externallyVisibleId
)
import VarSet
-import Type ( Type, tyVarsOfType, typePrimRep, addFreeTyVars )
+import Type ( Type, tyVarsOfType, typePrimRep, addFreeTyVars, seqType )
import IdInfo
import Demand ( Demand, isStrict, wwLazy )
import Name ( Name, OccName,
setIdType :: Id -> Type -> Id
-- Add free tyvar info to the type
-setIdType id ty = setVarType id (addFreeTyVars ty)
+setIdType id ty = seqType ty `seq` setVarType id (addFreeTyVars ty)
idPrimRep :: Id -> PrimRep
idPrimRep id = typePrimRep (idType id)
_interface_ IdInfo 1
_exports_
-IdInfo IdInfo ;
+IdInfo IdInfo seqIdInfo ;
_declarations_
1 data IdInfo ;
+1 seqIdInfo _:_ IdInfo -> PrelBase.() ;;
__interface IdInfo 1 0 where
-__export IdInfo IdInfo ;
+__export IdInfo IdInfo seqIdInfo ;
1 data IdInfo ;
+1 seqIdInfo :: IdInfo -> PrelBase.Z0T ;
+
module IdInfo (
IdInfo, -- Abstract
- vanillaIdInfo, mkIdInfo,
+ vanillaIdInfo, mkIdInfo, seqIdInfo, megaSeqIdInfo,
-- Flavour
IdFlavour(..), flavourInfo,
CprInfo(..), cprInfo, setCprInfo, ppCprInfo, noCprInfo,
-- Zapping
- zapLamIdInfo, zapFragileIdInfo,
+ zapLamIdInfo, zapFragileIdInfo, zapIdInfoForStg,
-- Lambda-bound variable info
LBVarInfo(..), lbvarInfo, setLBVarInfo, noLBVarInfo
#include "HsVersions.h"
-import {-# SOURCE #-} CoreUnfold ( Unfolding, noUnfolding, hasUnfolding )
-import {-# SOURCE #-} CoreSyn ( CoreExpr, CoreRules, emptyCoreRules, isEmptyCoreRules )
+import {-# SOURCE #-} CoreUnfold ( Unfolding, noUnfolding, hasUnfolding, seqUnfolding )
+import {-# SOURCE #-} CoreSyn ( CoreExpr, CoreRules, emptyCoreRules, isEmptyCoreRules, seqRules )
import {-# SOURCE #-} Const ( Con )
import Var ( Id )
import FieldLabel ( FieldLabel )
-import Demand ( Demand, isStrict, isLazy, wwLazy, pprDemands )
+import Demand ( Demand, isStrict, isLazy, wwLazy, pprDemands, seqDemand, seqDemands )
import Type ( UsageAnn )
import Outputable
import Maybe ( isJust )
cafInfo :: CafInfo,
cprInfo :: CprInfo, -- Function always constructs a product result
lbvarInfo :: LBVarInfo, -- Info about a lambda-bound variable
- inlinePragInfo :: !InlinePragInfo -- Inline pragmas
+ inlinePragInfo :: InlinePragInfo -- Inline pragmas
}
+
+seqIdInfo :: IdInfo -> ()
+seqIdInfo (IdInfo {}) = ()
+
+megaSeqIdInfo :: IdInfo -> ()
+megaSeqIdInfo info
+ = seqFlavour (flavourInfo info) `seq`
+ seqArity (arityInfo info) `seq`
+ seqDemand (demandInfo info) `seq`
+ seqRules (specInfo info) `seq`
+ seqStrictness (strictnessInfo info) `seq`
+ seqWorker (workerInfo info) `seq`
+
+-- seqUnfolding (unfoldingInfo info) `seq`
+-- Omitting this improves runtimes a little, presumably because
+-- some unfoldings are not calculated at all
+
+ seqCaf (cafInfo info) `seq`
+ seqCpr (cprInfo info) `seq`
+ seqLBVar (lbvarInfo info) `seq`
+ seqInlinePrag (inlinePragInfo info)
\end{code}
Setters
\begin{code}
+setWorkerInfo info wk = wk `seq` info { workerInfo = wk }
+setSpecInfo info sp = sp `seq` info { specInfo = sp }
+setInlinePragInfo info pr = pr `seq` info { inlinePragInfo = pr }
+setStrictnessInfo info st = st `seq` info { strictnessInfo = st }
+ -- Try to avoid spack leaks by seq'ing
+
+setUnfoldingInfo info uf = info { unfoldingInfo = uf }
+ -- We do *not* seq on the unfolding info, For some reason, doing so
+ -- actually increases residency significantly.
+
setUpdateInfo info ud = info { updateInfo = ud }
setDemandInfo info dd = info { demandInfo = dd }
-setStrictnessInfo info st = info { strictnessInfo = st }
-setWorkerInfo info wk = info { workerInfo = wk }
-setSpecInfo info sp = info { specInfo = sp }
setArityInfo info ar = info { arityInfo = ar }
-setInlinePragInfo info pr = info { inlinePragInfo = pr }
-setUnfoldingInfo info uf = info { unfoldingInfo = uf }
setCafInfo info cf = info { cafInfo = cf }
setCprInfo info cp = info { cprInfo = cp }
setLBVarInfo info lb = info { lbvarInfo = lb }
ppFlavourInfo (RecordSelId _) = ptext SLIT("[RecSel]")
ppFlavourInfo SpecPragmaId = ptext SLIT("[SpecPrag]")
ppFlavourInfo NoDiscardId = ptext SLIT("[NoDiscard]")
+
+seqFlavour :: IdFlavour -> ()
+seqFlavour f = f `seq` ()
\end{code}
The @SpecPragmaId@ exists only to make Ids that are
| ArityExactly Int -- Arity is exactly this
| ArityAtLeast Int -- Arity is this or greater
+seqArity :: ArityInfo -> ()
+seqArity a = arityLowerBound a `seq` ()
+
exactArity = ArityExactly
atLeastArity = ArityAtLeast
unknownArity = UnknownArity
| IMustBeINLINEd -- Absolutely must inline; used for PrimOps and
-- constructors only.
+seqInlinePrag :: InlinePragInfo -> ()
+seqInlinePrag (ICanSafelyBeINLINEd occ alts)
+ = occ `seq` alts `seq` ()
+seqInlinePrag other
+ = ()
+
instance Outputable InlinePragInfo where
ppr NoInlinePragInfo = empty
ppr IMustBeINLINEd = ptext SLIT("__UU")
-- BUT NB: f = \x y. error "urk"
-- will have info SI [SS] True
-- but still (f) and (f 2) are not bot; only (f 3 2) is bot
+
+seqStrictness :: StrictnessInfo -> ()
+seqStrictness (StrictnessInfo ds b) = b `seq` seqDemands ds
+seqStrictness other = ()
\end{code}
\begin{code}
mkWorkerInfo wk_id = Just wk_id
-}
+seqWorker :: WorkerInfo -> ()
+seqWorker (Just id) = id `seq` ()
+seqWorker Nothing = ()
+
ppWorkerInfo Nothing = empty
ppWorkerInfo (Just wk_id) = ptext SLIT("__P") <+> ppr wk_id
-- | OneCafRef Id
+seqCaf c = c `seq` ()
+
ppCafInfo NoCafRefs = ptext SLIT("__C")
ppCafInfo MayHaveCafRefs = empty
\end{code}
other -> inline_prag
\end{code}
+\begin{code}
+zapIdInfoForStg :: IdInfo -> IdInfo
+ -- Return only the info needed for STG stuff
+ -- Namely, nothing, I think
+zapIdInfoForStg info = vanillaIdInfo
+\end{code}
+
%************************************************************************
%* *
\end{code}
\begin{code}
+seqCpr :: CprInfo -> ()
+seqCpr (CPRInfo cs) = seqCprs cs
+seqCpr NoCPRInfo = ()
+
+seqCprs [] = ()
+seqCprs (c:cs) = seqCpr c `seq` seqCprs cs
+
noCprInfo = NoCPRInfo
-- HACK ALERT! placing this info here is a short-term hack,
-- but it minimises changes to the rest of the compiler.
-- Hack agreed by SLPJ/KSW 1999-04.
+
+seqLBVar l = l `seq` ()
\end{code}
\begin{code}
-%
+s%
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
\section{@Vars@: Variables}
-- Ids
Id, DictId,
idName, idType, idUnique, idInfo, modifyIdInfo, maybeModifyIdInfo,
- setIdName, setIdUnique, setIdInfo,
+ setIdName, setIdUnique, setIdInfo, lazySetIdInfo,
mkIdVar, isId, externallyVisibleId
) where
#include "HsVersions.h"
import {-# SOURCE #-} Type( Type, Kind )
-import {-# SOURCE #-} IdInfo( IdInfo )
+import {-# SOURCE #-} IdInfo( IdInfo, seqIdInfo )
import Unique ( Unique, Uniquable(..), mkUniqueGrimily, getKey )
import Name ( Name, OccName, NamedThing(..),
varUnique (Var {realUnique = uniq}) = mkUniqueGrimily uniq
setVarUnique :: Var -> Unique -> Var
-setVarUnique var uniq = var {realUnique = getKey uniq,
- varName = setNameUnique (varName var) uniq}
+setVarUnique var@(Var {varName = name}) uniq
+ = var {realUnique = getKey uniq,
+ varName = setNameUnique name uniq}
setVarName :: Var -> Name -> Var
setVarName var new_name
setIdName :: Id -> Name -> Id
setIdName = setVarName
+lazySetIdInfo :: Id -> IdInfo -> Id
+lazySetIdInfo var info = var {varInfo = info}
+
setIdInfo :: Id -> IdInfo -> Id
-setIdInfo var info = var {varInfo = info}
+setIdInfo var info = seqIdInfo info `seq` var {varInfo = info}
+ -- Try to avoid spack leaks by seq'ing
modifyIdInfo :: (IdInfo -> IdInfo) -> Id -> Id
-modifyIdInfo fn var@(Var {varInfo = info}) = var {varInfo = fn info}
+modifyIdInfo fn var@(Var {varInfo = info})
+ = seqIdInfo new_info `seq` var {varInfo = new_info}
+ where
+ new_info = fn info
-- maybeModifyIdInfo tries to avoid unnecesary thrashing
maybeModifyIdInfo :: (IdInfo -> Maybe IdInfo) -> Id -> Id
intersectVarSet, intersectsVarSet,
isEmptyVarSet, delVarSet, delVarSetByKey,
minusVarSet, foldVarSet, filterVarSet,
- lookupVarSet, mapVarSet,
+ lookupVarSet, mapVarSet, sizeVarSet, seqVarSet,
uniqAway
) where
-- Returns the set element, which may be
-- (==) to the argument, but not the same as
mapVarSet :: (Var -> Var) -> VarSet -> VarSet
+sizeVarSet :: VarSet -> Int
filterVarSet :: (Var -> Bool) -> VarSet -> VarSet
subVarSet :: VarSet -> VarSet -> Bool
foldVarSet = foldUniqSet
lookupVarSet = lookupUniqSet
mapVarSet = mapUniqSet
+sizeVarSet = sizeUniqSet
filterVarSet = filterUniqSet
a `subVarSet` b = isEmptyVarSet (a `minusVarSet` b)
delVarSetByKey = delFromUFM_Directly -- Can't be bothered to add this to UniqSet
\end{code}
\begin{code}
+seqVarSet :: VarSet -> ()
+seqVarSet s = sizeVarSet s `seq` ()
+\end{code}
+
+\begin{code}
uniqAway :: VarSet -> Var -> Var
-- Give the Var a new unique, different to any in the VarSet
uniqAway set var
%
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
-% $Id: CgClosure.lhs,v 1.33 1999/06/24 13:04:17 simonmar Exp $
+% $Id: CgClosure.lhs,v 1.34 1999/07/14 14:40:28 simonpj Exp $
%
\section[CgClosure]{Code generation for closures}
\begin{code}
thunkWrapper:: ClosureInfo -> CLabel -> Code -> Code
-thunkWrapper closure_info label thunk_code
+thunkWrapper closure_info lbl thunk_code
= -- Stack and heap overflow checks
nodeMustPointToIt (closureLFInfo closure_info) `thenFC` \ node_points ->
else absC AbsCNop) `thenC`
-- stack and/or heap checks
- thunkChecks label node_points (
+ thunkChecks lbl node_points (
-- Overwrite with black hole if necessary
blackHoleIt closure_info node_points `thenC`
#include "HsVersions.h"
-import IO ( hPutStr, stderr )
+import IO ( hPutStr, hPutStrLn, stderr )
import CmdLineOpts ( opt_D_show_passes, opt_DoCoreLinting, opt_PprStyle_Debug )
import CoreSyn
beginPass :: String -> IO ()
beginPass pass_name
| opt_D_show_passes
- = hPutStr stderr ("*** " ++ pass_name ++ "\n")
+ = hPutStrLn stderr ("*** " ++ pass_name)
| otherwise
= return ()
endPass :: String -> Bool -> [CoreBind] -> IO [CoreBind]
endPass pass_name dump_flag binds
= do
+ -- Report result size if required
+ -- This has the side effect of forcing the intermediate to be evaluated
+ if opt_D_show_passes then
+ hPutStrLn stderr (" Result size = " ++ show (coreBindsSize binds))
+ else
+ return ()
+
-- Report verbosely, if required
dumpIfSet dump_flag pass_name
(pprCoreBindings binds)
_interface_ CoreSyn 1
_exports_
-CoreSyn CoreExpr CoreRule CoreRules emptyCoreRules isEmptyCoreRules ;
+CoreSyn CoreExpr CoreRule CoreRules emptyCoreRules isEmptyCoreRules seqRules ;
_declarations_
-- Needed by IdInfo
1 data CoreRule ;
1 type CoreRules = [CoreRule] ;
1 emptyCoreRules _:_ CoreRules ;;
+1 seqRules _:_ CoreRules -> PrelBase.() ;;
1 isEmptyCoreRules _:_ CoreRules -> PrelBase.Bool ;;
__interface CoreSyn 1 0 where
-__export CoreSyn CoreExpr CoreRules CoreRule emptyCoreRules isEmptyCoreRules ;
+__export CoreSyn CoreExpr CoreRules CoreRule emptyCoreRules isEmptyCoreRules seqRules ;
-- Needed by IdInfo
1 type CoreExpr = Expr Var.IdOrTyVar;
1 data CoreRule ;
1 type CoreRules = [CoreRule] ;
1 emptyCoreRules :: CoreRules ;
+1 seqRules :: CoreRules -> PrelBase.Z0T ;
1 isEmptyCoreRules :: CoreRules -> PrelBase.Bool ;
isValArg, isTypeArg, valArgCount, valBndrCount,
+ -- Seq stuff
+ seqRules, seqExpr, seqExprs,
+
+ -- Size
+ coreBindsSize,
+
-- Annotated expressions
AnnExpr, AnnExpr'(..), AnnBind(..), AnnAlt, deAnnotate,
import CostCentre ( CostCentre, isDupdCC, noCostCentre )
import Var ( Var, Id, TyVar, IdOrTyVar, isTyVar, isId, idType )
import VarEnv
-import Id ( mkWildId, getInlinePragma )
-import Type ( Type, UsageAnn, mkTyVarTy, isUnLiftedType )
-import IdInfo ( InlinePragInfo(..) )
+import Id ( mkWildId, getInlinePragma, idInfo )
+import Type ( Type, UsageAnn, mkTyVarTy, isUnLiftedType, seqType )
+import IdInfo ( InlinePragInfo(..), megaSeqIdInfo )
import Const ( Con(..), DataCon, Literal(NoRepStr), PrimOp )
import TysWiredIn ( trueDataCon, falseDataCon )
import VarSet
%************************************************************************
%* *
+\subsection{Seq stuff}
+%* *
+%************************************************************************
+
+\begin{code}
+seqExpr :: CoreExpr -> ()
+seqExpr (Var v) = v `seq` ()
+seqExpr (Con c as) = seqExprs as
+seqExpr (App f a) = seqExpr f `seq` seqExpr a
+seqExpr (Lam b e) = seqBndr b `seq` seqExpr e
+seqExpr (Let b e) = seqBind b `seq` seqExpr e
+seqExpr (Case e b as) = seqExpr e `seq` seqBndr b `seq` seqAlts as
+seqExpr (Note n e) = seqNote n `seq` seqExpr e
+seqExpr (Type t) = seqType t
+
+seqExprs [] = ()
+seqExprs (e:es) = seqExpr e `seq` seqExprs es
+
+seqNote (Coerce t1 t2) = seqType t1 `seq` seqType t2
+seqNote other = ()
+
+seqBndr b = b `seq` ()
+
+seqBndrs [] = ()
+seqBndrs (b:bs) = seqBndr b `seq` seqBndrs bs
+
+seqBind (NonRec b e) = seqBndr b `seq` seqExpr e
+seqBind (Rec prs) = seqPairs prs
+
+seqPairs [] = ()
+seqPairs ((b,e):prs) = seqBndr b `seq` seqExpr e `seq` seqPairs prs
+
+seqAlts [] = ()
+seqAlts ((c,bs,e):alts) = seqBndrs bs `seq` seqExpr e `seq` seqAlts alts
+
+seqRules :: CoreRules -> ()
+seqRules (Rules rules fvs) = seq_rules rules `seq` seqVarSet fvs
+
+seq_rules [] = ()
+seq_rules (Rule fs bs es e : rules) = seqBndrs bs `seq` seqExprs (e:es) `seq` seq_rules rules
+\end{code}
+
+\begin{code}
+coreBindsSize :: [CoreBind] -> Int
+coreBindsSize bs = foldr ((+) . bindSize) 0 bs
+
+exprSize :: CoreExpr -> Int
+ -- A measure of the size of the expressions
+ -- It also forces the expression pretty drastically as a side effect
+exprSize (Var v) = varSize v
+exprSize (Con c as) = c `seq` exprsSize as
+exprSize (App f a) = exprSize f + exprSize a
+exprSize (Lam b e) = varSize b + exprSize e
+exprSize (Let b e) = bindSize b + exprSize e
+exprSize (Case e b as) = exprSize e + varSize b + foldr ((+) . altSize) 0 as
+exprSize (Note n e) = exprSize e
+exprSize (Type t) = seqType t `seq` 1
+
+exprsSize = foldr ((+) . exprSize) 0
+
+varSize :: IdOrTyVar -> Int
+varSize b | isTyVar b = 1
+ | otherwise = seqType (idType b) `seq`
+ megaSeqIdInfo (idInfo b) `seq`
+ 1
+
+varsSize = foldr ((+) . varSize) 0
+
+bindSize (NonRec b e) = varSize b + exprSize e
+bindSize (Rec prs) = foldr ((+) . pairSize) 0 prs
+
+pairSize (b,e) = varSize b + exprSize e
+
+altSize (c,bs,e) = c `seq` varsSize bs + exprSize e
+\end{code}
+
+
+%************************************************************************
+%* *
\subsection{Annotated core; annotation at every node in the tree}
%* *
%************************************************************************
_interface_ CoreUnfold 1
_exports_
-CoreUnfold Unfolding UnfoldingGuidance mkUnfolding noUnfolding hasUnfolding isEvaldUnfolding;
+CoreUnfold Unfolding UnfoldingGuidance mkUnfolding noUnfolding hasUnfolding isEvaldUnfolding seqUnfolding ;
_declarations_
1 data Unfolding;
1 data UnfoldingGuidance;
1 mkUnfolding _:_ CoreSyn.CoreExpr -> Unfolding ;;
1 noUnfolding _:_ Unfolding ;;
1 hasUnfolding _:_ Unfolding -> PrelBase.Bool ;;
+1 seqUnfolding _:_ Unfolding -> PrelBase.() ;;
1 isEvaldUnfolding _:_ Unfolding -> PrelBase.Bool ;;
__interface CoreUnfold 1 0 where
-__export CoreUnfold Unfolding UnfoldingGuidance mkUnfolding noUnfolding hasUnfolding isEvaldUnfolding;
+__export CoreUnfold Unfolding UnfoldingGuidance mkUnfolding noUnfolding hasUnfolding isEvaldUnfolding seqUnfolding ;
1 data Unfolding;
1 data UnfoldingGuidance;
1 mkUnfolding :: CoreSyn.CoreExpr -> Unfolding ;
1 noUnfolding :: Unfolding ;
1 hasUnfolding :: Unfolding -> PrelBase.Bool ;
+1 seqUnfolding :: Unfolding -> PrelBase.Z0T ;
1 isEvaldUnfolding :: Unfolding -> PrelBase.Bool ;
module CoreUnfold (
Unfolding, UnfoldingGuidance, -- types
- noUnfolding, mkUnfolding,
+ noUnfolding, mkUnfolding, seqUnfolding,
mkOtherCon, otherCons,
unfoldingTemplate, maybeUnfoldingTemplate,
isEvaldUnfolding, isCheapUnfolding,
certainlySmallEnoughToInline,
okToUnfoldInHiFile,
- calcUnfoldingGuidance,
+ calcUnfoldingGuidance,
callSiteInline, blackListed
) where
Bool -- exprIsValue template (cached); it is ok to discard a `seq` on
-- this variable
UnfoldingGuidance -- Tells about the *size* of the template.
+
+seqUnfolding :: Unfolding -> ()
+seqUnfolding (CoreUnfolding e b1 b2 g)
+ = seqExpr e `seq` b1 `seq` b2 `seq` seqGuidance g
+seqUnfolding other = ()
\end{code}
\begin{code}
Int -- Scrutinee discount: the discount to substract if the thing is in
-- a context (case (thing args) of ...),
-- (where there are the right number of arguments.)
+
+seqGuidance (UnfoldIfGoodArgs n ns a b) = n `seq` sum ns `seq` a `seq` b `seq` ()
+seqGuidance other = ()
\end{code}
\begin{code}
#include "HsVersions.h"
import CoreSyn ( Expr(..), Bind(..), Note(..), CoreExpr, CoreBndr,
- CoreRules(..), CoreRule(..), emptyCoreRules, isEmptyCoreRules
+ CoreRules(..), CoreRule(..),
+ emptyCoreRules, isEmptyCoreRules, seqRules
)
import CoreFVs ( exprFreeVars )
import Type ( Type(..), ThetaType, TyNote(..),
go (Var v) = case lookupSubst subst v of
Just (DoneEx e') -> e'
Just (ContEx env' e') -> subst_expr (setSubstEnv subst env') e'
+-- NO! NO! SLPJ 14 July 99
Nothing -> case lookupInScope subst v of
Just v' -> Var v'
Nothing -> Var v
-- of a variable may not be right; we should replace it with the
-- binder, from the in_scope set.
+-- Nothing -> Var v
+
go (Type ty) = Type (go_ty ty)
go (Con con args) = Con con (map go args)
go (App fun arg) = App (go fun) (go arg)
where
id_ty = idType old_id
id1 | noTypeSubst env || isEmptyVarSet (tyVarsOfType id_ty) = old_id
- | otherwise = setIdType old_id (substTy subst id_ty)
+ | otherwise = setIdType old_id (substTy subst id_ty)
id2 = maybeModifyIdInfo zapFragileIdInfo id1
new_id = setVarUnique id2 (uniqFromSupply us1)
%************************************************************************
\begin{code}
-substIdInfo :: Subst -> IdInfo -> IdInfo
-substIdInfo subst info
+substIdInfo :: Subst
+ -> IdInfo -- Get un-substituted ones from here
+ -> IdInfo -- Substitute it and add it to here
+ -> IdInfo -- To give this
+ -- Seq'ing on the returned IdInfo is enough to cause all the
+ -- substitutions to happen completely
+
+substIdInfo subst old_info new_info
= info2
where
- info1 | isEmptyCoreRules old_rules = info
- | otherwise = info `setSpecInfo` substRules subst old_rules
+ info1 | isEmptyCoreRules old_rules = new_info
+ | otherwise = new_info `setSpecInfo` new_rules
+ -- setSpecInfo does a seq
+ where
+ new_rules = substRules subst old_rules
info2 | not (workerExists old_wrkr) = info1
- | otherwise = info1 `setWorkerInfo` substWorker subst old_wrkr
+ | otherwise = info1 `setWorkerInfo` new_wrkr
+ -- setWorkerInfo does a seq
+ where
+ new_wrkr = substWorker subst old_wrkr
- old_rules = specInfo info
- old_wrkr = workerInfo info
+ old_rules = specInfo old_info
+ old_wrkr = workerInfo old_info
substWorker :: Subst -> WorkerInfo -> WorkerInfo
+ -- Seq'ing on the returned WorkerInfo is enough to cause all the
+ -- substitutions to happen completely
+
substWorker subst Nothing
= Nothing
substWorker subst (Just w)
Nothing -- Ditto
substRules :: Subst -> CoreRules -> CoreRules
+ -- Seq'ing on the returned CoreRules is enough to cause all the
+ -- substitutions to happen completely
+
+substRules subst rules
+ | isEmptySubst subst = rules
+
substRules subst (Rules rules rhs_fvs)
- = Rules (map do_subst rules)
- (subst_fvs (substEnv subst) rhs_fvs)
+ = seqRules new_rules `seq` new_rules
where
+ new_rules = Rules (map do_subst rules)
+ (subst_fvs (substEnv subst) rhs_fvs)
+
do_subst (Rule name tpl_vars lhs_args rhs)
= Rule name tpl_vars'
(map (substExpr subst') lhs_args)
import Id ( setIdCprInfo, getIdCprInfo, getIdUnfolding )
import IdInfo ( CprInfo(..) )
import VarEnv
-import Type ( Type(..), splitFunTys, splitForAllTys, splitTyConApp_maybe,
- splitAlgTyConApp_maybe )
+import Type ( Type(..), splitFunTys, splitForAllTys, splitNewType_maybe )
import TyCon ( isProductTyCon, isNewTyCon, isUnLiftedTyCon )
-import DataCon ( dataConTyCon, dataConArgTys )
+import DataCon ( dataConTyCon, splitProductType_maybe )
import Const ( Con(DataCon), isWHNFCon )
import Util ( zipEqual, zipWithEqual )
import Outputable
filterAbsTuple :: (AbsVal, Type) -> AbsVal
filterAbsTuple (av@(Tuple args), ty)
- = case split_ty of
- Nothing -> Top
- Just (data_con, tycon, tycon_arg_tys, inst_con_arg_tys) ->
- if isNewTyCon tycon then
- ASSERT ( null $ tail inst_con_arg_tys )
- filterAbsTuple (av, head inst_con_arg_tys)
- else
- Tuple $ map filterAbsTuple $ zipEqual "cprFilter" args inst_con_arg_tys
- where
- split_ty = case splitAlgTyConApp_maybe ty of
- Just (arg_tycon, tycon_arg_tys, [data_con]) ->
- -- The main event: a single-constructor data type
- Just (data_con, arg_tycon, tycon_arg_tys, dataConArgTys data_con tycon_arg_tys)
- Just (_, _, data_cons) ->
- pprPanic "cprFilter:" (text "not one constructor" $$ ppr ty)
- -- hmmm, Isn't this a panic too?
- Nothing -> Nothing
+ = case splitProductType_maybe ty of
+ Nothing -> WARN( True, text "filterAbsTuple" <+> ppr ty) -- Or should it be a panic?
+ Top
+ Just (tycon, _, data_con, inst_con_arg_tys)
+ | isNewTyCon tycon
+ -> ASSERT ( null $ tail inst_con_arg_tys )
+ filterAbsTuple (av, head inst_con_arg_tys)
+ | otherwise
+ -> Tuple $ map filterAbsTuple $ zipEqual "cprFilter" args inst_con_arg_tys
+
filterAbsTuple (av, _) = av
absToCprInfo :: AbsVal -> CprInfo
-- Taken from splitFunTys in Type.lhs. Modified to keep searching through newtypes
-- Should move to Type.lhs if it is doing something sensible.
splitFunTysIgnoringNewTypes :: Type -> ([Type], Type)
-splitFunTysIgnoringNewTypes ty = split [] ty ty
+splitFunTysIgnoringNewTypes ty = split ty
where
- split args orig_ty (FunTy arg res) = split (arg:args) res res
- split args orig_ty (NoteTy _ ty) = split args orig_ty ty
- split args orig_ty ty
- = case splitAlgTyConApp_maybe ty of
- Just (arg_tycon, tycon_arg_tys, [data_con]) ->
- let [inst_con_arg_ty] = dataConArgTys data_con tycon_arg_tys in
- if (isNewTyCon arg_tycon) then
- {- pprTrace "splitFunTysIgnoringNewTypes:"
- (ppr arg_tycon <+> text "from type" <+> ppr inst_con_arg_ty)
- -}
- (split args orig_ty inst_con_arg_ty)
- else
- (reverse args, orig_ty)
- Nothing -> (reverse args, orig_ty)
-
+ split ty = case splitNewType_maybe res of
+ Nothing -> (args, res)
+ Just rep_ty -> (args ++ args', res')
+ where
+ (args', res') = split rep_ty
+ where
+ (args, res) = splitFunTys ty
-- Is this the constructor for a product type (i.e. algebraic, single constructor)
isConProdType :: Con -> Bool
import Maybes ( maybeToBool )
import PrelInfo ( packStringForCId )
import PrimOp ( PrimOp(..) )
-import DataCon ( DataCon, dataConId, dataConArgTys )
+import DataCon ( DataCon, dataConId, splitProductType_maybe )
import CallConv
import Type ( isUnLiftedType, splitAlgTyConApp_maybe, mkFunTys,
splitTyConApp_maybe, Type
-> Type -- Type of the result (a boxed-prim IO type)
-> DsM CoreExpr
-dsCCall label args may_gc is_asm result_ty
+dsCCall lbl args may_gc is_asm result_ty
= newSysLocalDs realWorldStatePrimTy `thenDs` \ old_s ->
mapAndUnzipDs unboxArg args `thenDs` \ (unboxed_args, arg_wrappers) ->
-- it at the full type, including the state argument
inst_ty = mkFunTys (map coreExprType val_args) final_result_ty
- the_ccall_op = CCallOp (Left label) is_asm may_gc cCallConv
+ the_ccall_op = CCallOp (Left lbl) is_asm may_gc cCallConv
the_prim_app = mkPrimApp the_ccall_op final_args
the_body = foldr ($) (res_wrapper the_prim_app) arg_wrappers
\body -> Case (App (Var packStringForCId) arg)
prim_arg [(DEFAULT,[],body)])
- | null data_cons
- -- oops: we can't see the data constructors!!!
- = can'tSeeDataConsPanic "argument" arg_ty
-
-- Byte-arrays, both mutable and otherwise; hack warning
- | is_data_type &&
+ | is_product_type &&
length data_con_arg_tys == 2 &&
maybeToBool maybe_arg2_tycon &&
(arg2_tycon == byteArrayPrimTyCon ||
= newSysLocalDs arg_ty `thenDs` \ case_bndr ->
newSysLocalsDs data_con_arg_tys `thenDs` \ vars@[ixs_var, arr_cts_var] ->
returnDs (Var arr_cts_var,
- \ body -> Case arg case_bndr [(DataCon the_data_con,vars,body)]
+ \ body -> Case arg case_bndr [(DataCon data_con,vars,body)]
)
-- Data types with a single constructor, which has a single, primitive-typed arg
maybe_boxed_prim_arg_ty = maybeBoxedPrimType arg_ty
(Just (box_data_con, the_prim_arg_ty)) = maybe_boxed_prim_arg_ty
- maybe_data_type = splitAlgTyConApp_maybe arg_ty
- is_data_type = maybeToBool maybe_data_type
- (Just (tycon, tycon_arg_tys, data_cons)) = maybe_data_type
- (the_data_con : other_data_cons) = data_cons
-
- data_con_arg_tys = dataConArgTys the_data_con tycon_arg_tys
- (data_con_arg_ty1 : data_con_arg_ty2 : _) = data_con_arg_tys
+ maybe_product_type = splitProductType_maybe arg_ty
+ is_product_type = maybeToBool maybe_product_type
+ Just (tycon, _, data_con, data_con_arg_tys) = maybe_product_type
+ (data_con_arg_ty1 : data_con_arg_ty2 : _) = data_con_arg_tys
maybe_arg2_tycon = splitTyConApp_maybe data_con_arg_ty2
Just (arg2_tycon,_) = maybe_arg2_tycon
CoreExpr -> CoreExpr) -- Wrapper for the ccall
-- to box the result
boxResult result_ty
- | null data_cons
- -- oops! can't see the data constructors
- = can'tSeeDataConsPanic "result" result_ty
-
-- Data types with a single nullary constructor
- | (maybeToBool maybe_data_type) && -- Data type
- (null other_data_cons) && -- Just one constr
+ | (maybeToBool maybe_product_type) && -- Data type
(null data_con_arg_tys)
=
newSysLocalDs realWorldStatePrimTy `thenDs` \ prim_state_id ->
)
-- Data types with a single constructor, which has a single, primitive-typed arg
- | (maybeToBool maybe_data_type) && -- Data type
- (null other_data_cons) && -- Just one constr
+ | (maybeToBool maybe_product_type) && -- Data type
not (null data_con_arg_tys) && null other_args_tys && -- Just one arg
isUnLiftedType the_prim_result_ty -- of primitive type
=
newSysLocalDs ccall_res_type `thenDs` \ case_bndr ->
let
- the_result = mkConApp the_data_con (map Type tycon_arg_tys ++ [Var prim_result_id])
+ the_result = mkConApp data_con (map Type tycon_arg_tys ++ [Var prim_result_id])
the_pair = mkConApp unboxedPairDataCon
[Type realWorldStatePrimTy, Type result_ty,
Var prim_state_id, the_result]
| otherwise
= pprPanic "boxResult: " (ppr result_ty)
where
- maybe_data_type = splitAlgTyConApp_maybe result_ty
- Just (tycon, tycon_arg_tys, data_cons) = maybe_data_type
- (the_data_con : other_data_cons) = data_cons
- ccall_res_type = mkUnboxedTupleTy 2
- [realWorldStatePrimTy, the_prim_result_ty]
+ maybe_product_type = splitProductType_maybe result_ty
+ Just (tycon, tycon_arg_tys, data_con, data_con_arg_tys) = maybe_product_type
+ (the_prim_result_ty : other_args_tys) = data_con_arg_tys
- data_con_arg_tys = dataConArgTys the_data_con tycon_arg_tys
- (the_prim_result_ty : other_args_tys) = data_con_arg_tys
+ ccall_res_type = mkUnboxedTupleTy 2 [realWorldStatePrimTy, the_prim_result_ty]
-- wrap up an unboxed value.
wrapUnboxedValue :: Type -> DsM (Type, Id, CoreExpr)
wrapUnboxedValue ty
- | null data_cons
- -- oops! can't see the data constructors
- = can'tSeeDataConsPanic "result" ty
- -- Data types with a single constructor, which has a single, primitive-typed arg
- | (maybeToBool maybe_data_type) && -- Data type
- (null other_data_cons) && -- Just one constr
+ | (maybeToBool maybe_product_type) && -- Data type
not (null data_con_arg_tys) && null other_args_tys && -- Just one arg
isUnLiftedType the_prim_result_ty -- of primitive type
=
newSysLocalDs the_prim_result_ty `thenDs` \ prim_result_id ->
let
- the_result = mkConApp the_data_con (map Type tycon_arg_tys ++ [Var prim_result_id])
+ the_result = mkConApp data_con (map Type tycon_arg_tys ++ [Var prim_result_id])
in
returnDs (ccall_res_type, prim_result_id, the_result)
-- Data types with a single nullary constructor
- | (maybeToBool maybe_data_type) && -- Data type
- (null other_data_cons) && -- Just one constr
+ | (maybeToBool maybe_product_type) && -- Data type
(null data_con_arg_tys)
=
let unit = dataConId unitDataCon
scrut_ty = mkUnboxedTupleTy 1 [realWorldStatePrimTy]
in
returnDs (scrut_ty, unit, mkConApp unitDataCon [])
+
| otherwise
= pprPanic "boxResult: " (ppr ty)
where
- maybe_data_type = splitAlgTyConApp_maybe ty
- Just (tycon, tycon_arg_tys, data_cons) = maybe_data_type
- (the_data_con : other_data_cons) = data_cons
- ccall_res_type = mkUnboxedTupleTy 2
- [realWorldStatePrimTy, the_prim_result_ty]
-
- data_con_arg_tys = dataConArgTys the_data_con tycon_arg_tys
- (the_prim_result_ty : other_args_tys) = data_con_arg_tys
-
+ maybe_product_type = splitProductType_maybe ty
+ Just (tycon, tycon_arg_tys, data_con, data_con_arg_tys) = maybe_product_type
+ (the_prim_result_ty : other_args_tys) = data_con_arg_tys
+ ccall_res_type = mkUnboxedTupleTy 2 [realWorldStatePrimTy, the_prim_result_ty]
\end{code}
returnDs (bindNonRec y_id y_core $
Lam x_id (mkApps core_op [Var x_id, Var y_id]))
-dsExpr (CCall label args may_gc is_asm result_ty)
+dsExpr (CCall lbl args may_gc is_asm result_ty)
= mapDs dsExpr args `thenDs` \ core_args ->
- dsCCall label core_args may_gc is_asm result_ty
+ dsCCall lbl core_args may_gc is_asm result_ty
-- dsCCall does all the unboxification, etc.
dsExpr (HsSCC cc expr)
mk_alt con
= newSysLocalsDs (dataConArgTys con in_inst_tys) `thenDs` \ arg_ids ->
+ -- This call to dataConArgTys won't work for existentials
let
val_args = zipWithEqual "dsExpr:RecordUpd" mk_val_arg
(dataConFieldLabels con) arg_ids
(case ext_name of
Dynamic -> getUniqueDs `thenDs` \ u ->
returnDs (Right u)
- ExtName fs _ -> returnDs (Left fs)) `thenDs` \ label ->
+ ExtName fs _ -> returnDs (Left fs)) `thenDs` \ lbl ->
let
val_args = Var the_state_arg : unboxed_args
final_args = Type inst_ty : val_args
-- it at the full type, including the state argument
inst_ty = mkFunTys (map coreExprType val_args) final_result_ty
- the_ccall_op = CCallOp label False (not may_not_gc) cconv
+ the_ccall_op = CCallOp lbl False (not may_not_gc) cconv
the_prim_app = mkPrimApp the_ccall_op (final_args :: [CoreArg])
import Const ( Literal(..), Con(..) )
import TyCon ( isNewTyCon, tyConDataCons )
import DataCon ( DataCon, StrictnessMark, maybeMarkedUnboxed, dataConStrictMarks,
- dataConArgTys, dataConId
+ dataConId, splitProductType_maybe
)
import Type ( mkFunTy, isUnLiftedType, splitAlgTyConApp, unUsgTy,
Type
rebuildConArgs con (arg:args) (str:stricts) body
= rebuildConArgs con args stricts body `thenDs` \ (body', real_args) ->
case maybeMarkedUnboxed str of
- Just (pack_con, tys) ->
- let id_tys = dataConArgTys pack_con ty_args in
- newSysLocalsDs id_tys `thenDs` \ unpacked_args ->
- returnDs (
- mkDsLet (NonRec arg (Con (DataCon pack_con)
- (map Type ty_args ++
- map Var unpacked_args))) body',
- unpacked_args ++ real_args
- )
+ Just (pack_con1, _) ->
+ case splitProductType_maybe (idType arg) of
+ Just (_, tycon_args, pack_con, con_arg_tys) ->
+ ASSERT( pack_con == pack_con1 )
+ newSysLocalsDs con_arg_tys `thenDs` \ unpacked_args ->
+ returnDs (
+ mkDsLet (NonRec arg (Con (DataCon pack_con)
+ (map Type tycon_args ++
+ map Var unpacked_args))) body',
+ unpacked_args ++ real_args
+ )
+
_ -> returnDs (body', arg:real_args)
-
- where ty_args = case splitAlgTyConApp (idType arg) of { (_,args,_) -> args }
\end{code}
%************************************************************************
import MatchLit ( matchLiterals )
import PrelInfo ( pAT_ERROR_ID )
import Type ( isUnLiftedType, splitAlgTyConApp,
- Type
+ mkTyVarTys, Type
)
import TysPrim ( intPrimTy, charPrimTy, floatPrimTy, doublePrimTy,
addrPrimTy, wordPrimTy
-- re-express <con-something> as (ConPat ...) [directly]
-tidy1 v (RecPat data_con pat_ty tvs dicts rpats) match_result
+tidy1 v (RecPat data_con pat_ty ex_tvs dicts rpats) match_result
| null rpats
= -- Special case for C {}, which can be used for
-- a constructor that isn't declared to have
-- fields at all
- returnDs (ConPat data_con pat_ty tvs dicts (map WildPat con_arg_tys'), match_result)
+ returnDs (ConPat data_con pat_ty ex_tvs dicts (map WildPat con_arg_tys'), match_result)
| otherwise
- = returnDs (ConPat data_con pat_ty tvs dicts pats, match_result)
+ = returnDs (ConPat data_con pat_ty ex_tvs dicts pats, match_result)
where
pats = map mk_pat tagged_arg_tys
-- Boring stuff to find the arg-tys of the constructor
(_, inst_tys, _) = splitAlgTyConApp pat_ty
- con_arg_tys' = dataConArgTys data_con inst_tys
+ con_arg_tys' = dataConArgTys data_con (inst_tys ++ mkTyVarTys ex_tvs)
tagged_arg_tys = con_arg_tys' `zip` (dataConFieldLabels data_con)
-- mk_pat picks a WildPat of the appropriate type for absent fields,
\end{code}
These constructors only appear temporarily in the parser.
+The renamer translates them into the Right Thing.
\begin{code}
| EWildPat -- wildcard
ppr_expr (ArithSeqOut expr info)
= brackets (ppr info)
+ppr_expr EWildPat = char '_'
+ppr_expr (ELazyPat e) = char '~' <> pprParendExpr e
+ppr_expr (EAsPat v e) = ppr v <> char '@' <> pprParendExpr e
+
ppr_expr (CCall fun args _ is_asm result_ty)
= hang (if is_asm
then ptext SLIT("_casm_ ``") <> ptext fun <> ptext SLIT("''")
else ptext SLIT("_ccall_") <+> ptext fun)
4 (sep (map pprParendExpr args))
-ppr_expr (HsSCC label expr)
- = sep [ ptext SLIT("_scc_") <+> doubleQuotes (ptext label), pprParendExpr expr ]
+ppr_expr (HsSCC lbl expr)
+ = sep [ ptext SLIT("_scc_") <+> doubleQuotes (ptext lbl), pprParendExpr expr ]
ppr_expr (TyLam tyvars expr)
= hang (hsep [ptext SLIT("/\\"), interppSP tyvars, ptext SLIT("->")])
import Desugar ( deSugar )
import SimplCore ( core2core )
import CoreLint ( endPass )
+import CoreSyn ( coreBindsSize )
import CoreTidy ( tidyCorePgm )
import CoreToStg ( topCoreBindsToStg )
import StgSyn ( collectFinalStgBinders, pprStgBindings )
let
final_ids = collectFinalStgBinders (map fst stg_binds2)
in
+ coreBindsSize tidy_binds `seq`
+-- TEMP: the above call zaps some space usage allocated by the
+-- simplifier, which for reasons I don't understand, persists
+-- thoroughout code generation
+
ifaceDecls if_handle local_tycons local_classes
inst_info final_ids tidy_binds imp_rule_ids >>
endIface if_handle >>
ifaceId get_idinfo needed_ids is_rec id rhs
= Just (hsep [sig_pretty, prag_pretty, char ';'], new_needed_ids)
where
- idinfo = get_idinfo id
+ core_idinfo = idInfo id
+ stg_idinfo = get_idinfo id
ty_pretty = pprType (idType id)
sig_pretty = hsep [ppr (getOccName id), dcolon, ty_pretty]
ptext SLIT("##-}")]
------------ Arity --------------
- arity_pretty = ppArityInfo (arityInfo idinfo)
+ arity_pretty = ppArityInfo (arityInfo stg_idinfo)
------------ Caf Info --------------
- caf_pretty = ppCafInfo (cafInfo idinfo)
+ caf_pretty = ppCafInfo (cafInfo stg_idinfo)
------------ CPR Info --------------
- cpr_pretty = ppCprInfo (cprInfo idinfo)
+ cpr_pretty = ppCprInfo (cprInfo core_idinfo)
------------ Strictness --------------
- strict_info = strictnessInfo idinfo
+ strict_info = strictnessInfo core_idinfo
bottoming_fn = isBottomingStrictness strict_info
strict_pretty = ppStrictnessInfo strict_info
------------ Worker --------------
- work_info = workerInfo idinfo
+ work_info = workerInfo core_idinfo
has_worker = workerExists work_info
wrkr_pretty = ppWorkerInfo work_info
Just work_id = work_info
------------ Unfolding --------------
- inline_pragma = inlinePragInfo idinfo
+ inline_pragma = inlinePragInfo core_idinfo
dont_inline = case inline_pragma of
IMustNotBeINLINEd -> True
IAmALoopBreaker -> True
rhs_is_small = couldBeSmallEnoughToInline (calcUnfoldingGuidance opt_UF_HiFileThreshold rhs)
------------ Specialisations --------------
- spec_info = specInfo idinfo
+ spec_info = specInfo core_idinfo
------------ Extra free Ids --------------
new_needed_ids | opt_OmitInterfacePragmas = emptyVarSet
-> UniqSM [StixTree]
-}
- gentopcode (CCodeBlock label absC)
+ gentopcode (CCodeBlock lbl absC)
= gencode absC `thenUs` \ code ->
- returnUs (StSegment TextSegment : StFunBegin label : code [StFunEnd label])
+ returnUs (StSegment TextSegment : StFunBegin lbl : code [StFunEnd lbl])
- gentopcode stmt@(CStaticClosure label _ _ _)
+ gentopcode stmt@(CStaticClosure lbl _ _ _)
= genCodeStaticClosure stmt `thenUs` \ code ->
- returnUs (StSegment DataSegment : StLabel label : code [])
+ returnUs (StSegment DataSegment : StLabel lbl : code [])
- gentopcode stmt@(CRetVector label _ _ _)
+ gentopcode stmt@(CRetVector lbl _ _ _)
= genCodeVecTbl stmt `thenUs` \ code ->
- returnUs (StSegment TextSegment : code [StLabel label])
+ returnUs (StSegment TextSegment : code [StLabel lbl])
gentopcode stmt@(CRetDirect uniq absC srt liveness)
= gencode absC `thenUs` \ code ->
:: AbstractC
-> UniqSM StixTreeList
-}
- genCodeVecTbl (CRetVector label amodes srt liveness)
+ genCodeVecTbl (CRetVector lbl amodes srt liveness)
= genBitmapInfoTable liveness srt closure_type True `thenUs` \itbl ->
returnUs (\xs -> vectbl : itbl xs)
where
fltFix1 locs (StJump tree) = StJump (fltFix1 locs tree)
-fltFix1 locs (StCondJump label tree) =
- StCondJump label (fltFix1 locs tree)
+fltFix1 locs (StCondJump lbl tree) =
+ StCondJump lbl (fltFix1 locs tree)
fltFix1 locs (StPrim op trees) =
StPrim op (map (fltFix1 locs) trees)
TEST sz src dst -> usage (opToReg src ++ opToReg dst) []
CMP sz src dst -> usage (opToReg src ++ opToReg dst) []
SETCC cond op -> usage [] (opToReg op)
- JXX cond label -> usage [] []
+ JXX cond lbl -> usage [] []
JMP op -> usage (opToReg op) freeRegs
CALL imm -> usage [] callClobberedRegs
CLTD -> usage [eax] [edx]
returnRn (CCall fun args' may_gc is_casm fake_result_ty,
fvs_args `addOneFV` cc `addOneFV` cr `addOneFV` io)
-rnExpr (HsSCC label expr)
+rnExpr (HsSCC lbl expr)
= rnExpr expr `thenRn` \ (expr', fvs_expr) ->
- returnRn (HsSCC label expr', fvs_expr)
+ returnRn (HsSCC lbl expr', fvs_expr)
rnExpr (HsCase expr ms src_loc)
= pushSrcLocRn src_loc $
plusFVs [fvExpr1, fvExpr2, fvExpr3])
\end{code}
+These three are pattern syntax appearing in expressions.
+Since all the symbols are reservedops we can simply reject them.
+We return a (bogus) EWildPat in each case.
+
+\begin{code}
+rnExpr e@EWildPat = addErrRn (patSynErr e) `thenRn_`
+ returnRn (EWildPat, emptyFVs)
+
+rnExpr e@(EAsPat _ _) = addErrRn (patSynErr e) `thenRn_`
+ returnRn (EWildPat, emptyFVs)
+
+rnExpr e@(ELazyPat _) = addErrRn (patSynErr e) `thenRn_`
+ returnRn (EWildPat, emptyFVs)
+\end{code}
+
%************************************************************************
%* *
\subsubsection{@Rbinds@s and @Rpats@s: in record expressions}
$$ nest 4 (ptext SLIT("Use -fglasgow-exts to permit it"))
pp_op (op, fix) = hcat [ppr op, space, parens (ppr fix)]
+
+patSynErr e
+ = sep [ptext SLIT("Pattern syntax in expression context:"),
+ nest 4 (ppr e)]
\end{code}
let
subst = mkSubst emptyVarSet subst_env
v' = setVarUnique v uniq
- v'' = modifyIdInfo (substIdInfo subst) v'
+ v'' = modifyIdInfo (\info -> substIdInfo subst info info) v'
subst_env' = extendSubstEnv subst_env v (DoneEx (Var v''))
lvl_env' = extendVarEnv lvl_env v lvl
in
let
subst = mkSubst emptyVarSet subst_env'
vs' = zipWith setVarUnique vs uniqs
- vs'' = map (modifyIdInfo (substIdInfo subst)) vs'
+ vs'' = map (modifyIdInfo (\info -> substIdInfo subst info info)) vs'
subst_env' = extendSubstEnvList subst_env vs [DoneEx (Var v'') | v'' <- vs'']
lvl_env' = extendVarEnvList lvl_env (vs `zip` repeat lvl)
in
| FillInCaseDefault Id -- Case binder
| BottomFound
- | LeafVisit
| SimplifierDone -- Ticked at each iteration of the simplifier
isRuleFired (RuleFired _) = True
tickToTag (CaseIdentity _) = 12
tickToTag (FillInCaseDefault _) = 13
tickToTag BottomFound = 14
-tickToTag LeafVisit = 15
tickToTag SimplifierDone = 16
tickString :: Tick -> String
tickString (FillInCaseDefault _) = "FillInCaseDefault"
tickString BottomFound = "BottomFound"
tickString SimplifierDone = "SimplifierDone"
-tickString LeafVisit = "LeafVisit"
pprTickCts :: Tick -> SDoc
pprTickCts (PreInlineUnconditionally v) = ppr v
import Subst ( substBndrs, substBndr, substIds )
import Id ( Id, idType, getIdArity, isId, idName,
getInlinePragma, setInlinePragma,
- getIdDemandInfo, mkId
+ getIdDemandInfo, mkId, idInfo
)
import IdInfo ( arityLowerBound, InlinePragInfo(..), setInlinePragInfo, vanillaIdInfo )
import Maybes ( maybeToBool, catMaybes )
import Const ( Con(..) )
import Name ( isLocalName, setNameUnique )
import SimplMonad
-import Type ( Type, tyVarsOfType, tyVarsOfTypes, mkForAllTys,
+import Type ( Type, tyVarsOfType, tyVarsOfTypes, mkForAllTys, seqType,
splitTyConApp_maybe, mkTyVarTys, applyTys, splitFunTys, mkFunTys
)
import TysPrim ( statePrimTyCon )
let
(subst', bndrs') = substBndrs subst bndrs
in
- setSubst subst' $
- thing_inside bndrs'
+ seqBndrs bndrs' `seq`
+ setSubst subst' (thing_inside bndrs')
simplBinder :: InBinder -> (OutBinder -> SimplM a) -> SimplM a
simplBinder bndr thing_inside
let
(subst', bndr') = substBndr subst bndr
in
- setSubst subst' $
- thing_inside bndr'
+ seqBndr bndr' `seq`
+ setSubst subst' (thing_inside bndr')
-- Same semantics as simplBinders, but a little less
let
(subst', bndrs') = substIds subst ids
in
- setSubst subst' $
- thing_inside bndrs'
+ seqBndrs bndrs' `seq`
+ setSubst subst' (thing_inside bndrs')
+
+seqBndrs [] = ()
+seqBndrs (b:bs) = seqBndr b `seq` seqBndrs bs
+
+seqBndr b | isTyVar b = b `seq` ()
+ | otherwise = seqType (idType b) `seq`
+ idInfo b `seq`
+ ()
\end{code}
getIdArity, setIdArity, setIdInfo,
getIdStrictness,
setInlinePragma, getInlinePragma, idMustBeINLINEd,
- setOneShotLambda
+ setOneShotLambda, maybeModifyIdInfo
)
import IdInfo ( InlinePragInfo(..), OccInfo(..), StrictnessInfo(..),
- ArityInfo(..), atLeastArity, arityLowerBound, unknownArity,
+ ArityInfo(..), atLeastArity, arityLowerBound, unknownArity, zapFragileIdInfo,
specInfo, inlinePragInfo, zapLamIdInfo, setArityInfo, setInlinePragInfo, setUnfoldingInfo
)
import Demand ( Demand, isStrict, wwLazy )
)
import Rules ( lookupRule )
import CostCentre ( isSubsumedCCS, currentCCS, isEmptyCC )
-import Type ( Type, mkTyVarTy, mkTyVarTys, isUnLiftedType,
+import Type ( Type, mkTyVarTy, mkTyVarTys, isUnLiftedType, seqType,
mkFunTy, splitFunTys, splitTyConApp_maybe, splitFunTy_maybe,
funResultTy, isDictTy, isDataType, applyTy, applyTys, mkFunTys
)
top_binders = bindersOfBinds binds
simpl_binds [] = returnSmpl ([], panic "simplTopBinds corner")
- simpl_binds (NonRec bndr rhs : binds) = simplLazyBind TopLevel bndr bndr rhs (simpl_binds binds)
- simpl_binds (Rec pairs : binds) = simplRecBind TopLevel pairs (map fst pairs) (simpl_binds binds)
+ simpl_binds (NonRec bndr rhs : binds) = simplLazyBind TopLevel bndr (zap bndr) rhs (simpl_binds binds)
+ simpl_binds (Rec pairs : binds) = simplRecBind TopLevel pairs (map (zap . fst) pairs) (simpl_binds binds)
+
+ zap id = maybeModifyIdInfo zapFragileIdInfo id
+-- TEMP
simplRecBind :: TopLevelFlag -> [(InId, InExpr)] -> [OutId]
simplExprC expr (Stop (substTy subst (coreExprType expr)))
-- The type in the Stop continuation is usually not used
-- It's only needed when discarding continuations after finding
- -- a function that returns bottom
+ -- a function that returns bottom.
+ -- Hence the lazy substitution
simplExprC :: CoreExpr -> SimplCont -> SimplM CoreExpr
-- Simplify an expression, given a continuation
Nothing -> rebuild (Con (PrimOp op) args2) cont2
simplExprF (Con con@(DataCon _) args) cont
- = freeTick LeafVisit `thenSmpl_`
- simplConArgs args ( \ args' ->
+ = simplConArgs args ( \ args' ->
rebuild (Con con args') cont)
simplExprF expr@(Con con@(Literal _) args) cont
= ASSERT( null args )
- freeTick LeafVisit `thenSmpl_`
rebuild expr cont
simplExprF (App fun arg) cont
simplExprF (Note (Coerce to from) e) cont
| to == from = simplExprF e cont
- | otherwise = getSubst `thenSmpl` \ subst ->
- simplExprF e (CoerceIt (substTy subst to) cont)
+ | otherwise = simplType to `thenSmpl` \ to' ->
+ simplExprF e (CoerceIt to' cont)
-- hack: we only distinguish subsumed cost centre stacks for the purposes of
-- inlining. All other CCCSs are mapped to currentCCS.
let
ty' = substTy (mkSubst in_scope arg_se) ty_arg
in
+ seqType ty' `seq`
extendSubst bndr (DoneTy ty')
(go body body_cont)
simplType :: InType -> SimplM OutType
simplType ty
= getSubst `thenSmpl` \ subst ->
- returnSmpl (substTy subst ty)
+ let
+ new_ty = substTy subst ty
+ in
+ seqType new_ty `seq`
+ returnSmpl new_ty
\end{code}
let
-- We make new IdInfo for the new binder by starting from the old binder,
-- doing appropriate substitutions,
- old_bndr_info = idInfo old_bndr
- new_bndr_info = substIdInfo subst old_bndr_info
+ new_bndr_info = substIdInfo subst (idInfo old_bndr) (idInfo new_bndr)
`setArityInfo` ArityAtLeast (exprArity new_rhs)
- -- At the *binding* site we want to zap the now-out-of-date inline
- -- pragma, in case the expression is simplified a second time.
- -- This has already been done in new_bndr, so we get it from there
- binding_site_id = new_bndr `setIdInfo`
- (new_bndr_info `setInlinePragInfo` getInlinePragma new_bndr)
+ -- At the *binding* site we use the new binder info
+ binding_site_id = new_bndr `setIdInfo` new_bndr_info
- -- At the occurrence sites we want to know the unfolding,
- -- We want the occurrence info of the *original*, which is already
- -- in new_bndr_info
+ -- At the *occurrence* sites we want to know the unfolding
+ -- We also want the occurrence info of the *original*
occ_site_id = new_bndr `setIdInfo`
- (new_bndr_info `setUnfoldingInfo` mkUnfolding new_rhs)
+ (new_bndr_info `setUnfoldingInfo` mkUnfolding new_rhs
+ `setInlinePragInfo` getInlinePragma old_bndr)
in
- modifyInScope occ_site_id thing_inside `thenSmpl` \ stuff ->
- returnSmpl (addBind (NonRec binding_site_id new_rhs) stuff)
+ -- These seqs force the Ids, and hence the IdInfos, and hence any
+ -- inner substitutions
+ binding_site_id `seq`
+ occ_site_id `seq`
+
+ (modifyInScope occ_site_id thing_inside `thenSmpl` \ stuff ->
+ returnSmpl (addBind (NonRec binding_site_id new_rhs) stuff))
\end{code}
\begin{code}
simplVar var cont
- = freeTick LeafVisit `thenSmpl_`
- getSubst `thenSmpl` \ subst ->
+ = getSubst `thenSmpl` \ subst ->
case lookupSubst subst var of
Just (DoneEx (Var v)) -> zapSubstEnv (simplVar v cont)
Just (DoneEx e) -> zapSubstEnv (simplExprF e cont)
in
getBlackList `thenSmpl` \ black_list ->
getInScope `thenSmpl` \ in_scope ->
- completeCall black_list in_scope var' cont
+ completeCall black_list in_scope var var' cont
---------------------------------------------------------
-- Dealing with a call
-completeCall black_list_fn in_scope var cont
+completeCall black_list_fn in_scope orig_var var cont
+-- For reasons I'm not very clear about, it's important *not* to plug 'var',
+-- which is replete with an inlining in its IdInfo, into the resulting expression
+-- Doing so results in a significant space leak.
+-- Instead we pass orig_var, which has no inlinings etc.
+
-- Look for rules or specialisations that match
-- Do this *before* trying inlining because some functions
-- have specialisations *and* are strict; we don't want to
-- thing, but perhaps we want to inline it anyway
| maybeToBool maybe_inline
= tick (UnfoldingDone var) `thenSmpl_`
- zapSubstEnv (completeInlining var unf_template discard_inline_cont)
+ zapSubstEnv (completeInlining orig_var unf_template discard_inline_cont)
-- The template is already simplified, so don't re-substitute.
-- This is VITAL. Consider
-- let x = e in
| otherwise -- Neither rule nor inlining
-- Use prepareArgs to use function strictness
= prepareArgs (ppr var) (idType var) (get_str var) cont $ \ args' cont' ->
- rebuild (mkApps (Var var) args') cont'
+ rebuild (mkApps (Var orig_var) args') cont'
where
get_str var = case getIdStrictness var of
ty_arg' = substTy (mkSubst in_scope se) ty_arg
res_ty = applyTy fun_ty ty_arg'
in
+ seqType ty_arg' `seq`
go (Type ty_arg' : acc) ds res_ty cont
-- Value argument
varsAtoms args `thenLne` \ (args', args_fvs) ->
returnLne (StgCon con args' res_ty, args_fvs, getFVSet args_fvs)
-varsExpr (StgSCC label expr)
+varsExpr (StgSCC cc expr)
= varsExpr expr `thenLne` ( \ (expr2, fvs, escs) ->
- returnLne (StgSCC label expr2, fvs, escs) )
+ returnLne (StgSCC cc expr2, fvs, escs) )
\end{code}
Cases require a little more real work.
import CoreUtils ( coreExprType )
import SimplUtils ( findDefault )
import CostCentre ( noCCS )
-import Id ( Id, mkSysLocal, idType, getIdStrictness, idUnique, isExportedId,
+import Id ( Id, mkSysLocal, idType, getIdStrictness, idUnique, isExportedId, mkVanillaId,
externallyVisibleId, setIdUnique, idName, getIdDemandInfo, setIdType
)
import Var ( Var, varType, modifyIdInfo )
-import IdInfo ( setDemandInfo, StrictnessInfo(..) )
+import IdInfo ( setDemandInfo, StrictnessInfo(..), zapIdInfoForStg )
import UsageSPUtils ( primOpUsgTys )
import DataCon ( DataCon, dataConName, dataConId )
import Demand ( Demand, isStrict, wwStrict, wwLazy )
-import Name ( Name, nameModule, isLocallyDefinedName )
+import Name ( Name, nameModule, isLocallyDefinedName, setNameUnique )
import Module ( isDynamicModule )
import Const ( Con(..), Literal(..), isLitLitLit, conStrictness, isWHNFCon )
import VarEnv
import PrimOp ( PrimOp(..), primOpUsg, primOpSig )
import Type ( isUnLiftedType, isUnboxedTupleType, Type, splitFunTy_maybe,
- UsageAnn(..), tyUsg, applyTy, mkUsgTy, repType )
+ UsageAnn(..), tyUsg, applyTy, mkUsgTy, repType, seqType )
import TysPrim ( intPrimTy )
import UniqSupply -- all of it, really
import Util ( lengthExceeds )
_ -> False
exprToRhs dem _ expr
- = StgRhsClosure noCCS -- No cost centre (ToDo?)
- stgArgOcc -- safe
+ = upd `seq`
+ StgRhsClosure noCCS -- No cost centre (ToDo?)
+ stgArgOcc -- safe
noSRT -- figure out later
bOGUS_FVs
- (if isOnceDem dem then SingleEntry else Updatable)
- -- HA! Paydirt for "dem"
+ upd
[]
expr
+ where
+ upd = if isOnceDem dem then SingleEntry else Updatable
+ -- HA! Paydirt for "dem"
isDynCon :: DataCon -> Bool
isDynCon con = isDynName (dataConName con)
\begin{code}
coreExprToStgFloat env (Var var) dem
- = returnUs ([], StgApp (stgLookup env var) [])
+ = returnUs ([], mkStgApp (stgLookup env var) [])
coreExprToStgFloat env (Let bind body) dem
= coreBindToStg NotTopLevel env bind `thenUs` \ (new_bind, new_env) ->
case stg_body' of
StgLam ty lam_bndrs lam_body ->
-- If the body reduced to a lambda too, join them up
- returnUs ([], StgLam expr_ty (binders' ++ lam_bndrs) lam_body)
+ returnUs ([], mkStgLam expr_ty (binders' ++ lam_bndrs) lam_body)
other ->
-- Body didn't reduce to a lambda, so return one
- returnUs ([], StgLam expr_ty binders' stg_body')
+ returnUs ([], mkStgLam expr_ty binders' stg_body')
\end{code}
(Var fun_id, _) -> -- A function Id, so do an StgApp; it's ok if
-- there are no arguments.
returnUs (arg_floats,
- StgApp (stgLookup env fun_id) stg_args)
+ mkStgApp (stgLookup env fun_id) stg_args)
(non_var_fun, []) -> -- No value args, so recurse into the function
ASSERT( null arg_floats )
newStgVar (coreExprType fun) `thenUs` \ fun_id ->
coreExprToStgFloat env fun onceDem `thenUs` \ (fun_floats, stg_fun) ->
returnUs (NonRecF fun_id stg_fun onceDem fun_floats : arg_floats,
- StgApp fun_id stg_args)
+ mkStgApp fun_id stg_args)
where
-- Collect arguments and demands (*in reverse order*)
\begin{code}
coreExprToStgFloat env expr@(Con con args) dem
= let
+ expr_ty = coreExprType expr
(stricts,_) = conStrictness con
onces = case con of
DEFAULT -> panic "coreExprToStgFloat: DEFAULT"
_ -> returnUs con
) `thenUs` \ con' ->
- returnUs (arg_floats, StgCon con' stg_atoms (coreExprType expr))
+ returnUs (arg_floats, mkStgCon con' stg_atoms expr_ty)
\end{code}
= coreExprToStgFloat env scrut (bdrDem bndr) `thenUs` \ (binds, scrut') ->
newEvaldLocalId env bndr `thenUs` \ (env', bndr') ->
coreExprToStg env' default_rhs dem `thenUs` \ default_rhs' ->
- returnUs (binds, mkStgCase scrut' bndr' (StgPrimAlts (idType bndr) [] (StgBindDefault default_rhs')))
+ returnUs (binds, mkStgCase scrut' bndr' (StgPrimAlts (idType bndr') [] (StgBindDefault default_rhs')))
where
(other_alts, maybe_default) = findDefault alts
Just default_rhs = maybe_default
| prim_case
= default_to_stg env deflt `thenUs` \ deflt' ->
mapUs (prim_alt_to_stg env) alts `thenUs` \ alts' ->
- returnUs (StgPrimAlts scrut_ty alts' deflt')
+ returnUs (mkStgPrimAlts scrut_ty alts' deflt')
| otherwise
= default_to_stg env deflt `thenUs` \ deflt' ->
mapUs (alg_alt_to_stg env) alts `thenUs` \ alts' ->
- returnUs (StgAlgAlts scrut_ty alts' deflt')
+ returnUs (mkStgAlgAlts scrut_ty alts' deflt')
alg_alt_to_stg env (DataCon con, bs, rhs)
- = coreExprToStg env rhs dem `thenUs` \ stg_rhs ->
- returnUs (con, filter isId bs, [ True | b <- bs ]{-bogus use mask-}, stg_rhs)
+ = newLocalIds NotTopLevel env (filter isId bs) `thenUs` \ (env', stg_bs) ->
+ coreExprToStg env' rhs dem `thenUs` \ stg_rhs ->
+ returnUs (con, stg_bs, [ True | b <- stg_bs ]{-bogus use mask-}, stg_rhs)
-- NB the filter isId. Some of the binders may be
-- existential type variables, which STG doesn't care about
newStgVar :: Type -> UniqSM Id
newStgVar ty
= getUniqueUs `thenUs` \ uniq ->
+ seqType ty `seq`
returnUs (mkSysLocal SLIT("stg") uniq ty)
\end{code}
\begin{code}
+{- Now redundant, I believe
-- we overload the demandInfo field of an Id to indicate whether the Id is definitely
-- evaluated or not (i.e. whether it is a case binder). This can be used to eliminate
-- some redundant cases (c.f. dataToTag# above).
new_env = extendVarEnv env id id'
in
returnUs (new_env, id')
+-}
+newEvaldLocalId env id = newLocalId NotTopLevel env id
newLocalId TopLevel env id
- = returnUs (env, id)
-- Don't clone top-level binders. MkIface relies on their
-- uniques staying the same, so it can snaffle IdInfo off the
-- STG ids to put in interface files.
+ = let
+ name = idName id
+ ty = idType id
+ in
+ name `seq`
+ seqType ty `seq`
+ returnUs (env, mkVanillaId name ty)
+
newLocalId NotTopLevel env id
= -- Local binder, give it a new unique Id.
getUniqueUs `thenUs` \ uniq ->
let
- id' = setIdUnique id uniq
- new_env = extendVarEnv env id id'
+ name = idName id
+ ty = idType id
+ new_id = mkVanillaId (setNameUnique name uniq) ty
+ new_env = extendVarEnv env id new_id
in
- returnUs (new_env, id')
+ name `seq`
+ seqType ty `seq`
+ returnUs (new_env, new_id)
newLocalIds :: TopLevelFlag -> StgEnv -> [Id] -> UniqSM (StgEnv, [Id])
newLocalIds top_lev env []
\end{code}
+%************************************************************************
+%* *
+\subsection{Building STG syn}
+%* *
+%************************************************************************
+
+\begin{code}
+mkStgAlgAlts ty alts deflt = seqType ty `seq` StgAlgAlts ty alts deflt
+mkStgPrimAlts ty alts deflt = seqType ty `seq` StgPrimAlts ty alts deflt
+mkStgCon con args ty = seqType ty `seq` StgCon con args ty
+mkStgLam ty bndrs body = seqType ty `seq` StgLam ty bndrs body
+
+mkStgApp :: Id -> [StgArg] -> StgExpr
+mkStgApp fn args = fn `seq` StgApp fn args
+ -- Force the lookup
+\end{code}
+
\begin{code}
-- Stg doesn't have a lambda *expression*,
deStgLam (StgLam ty bndrs body) = mkStgLamExpr ty bndrs body
mkStgLamExpr ty bndrs body
= ASSERT( not (null bndrs) )
newStgVar ty `thenUs` \ fn ->
- returnUs (StgLet (StgNonRec fn lam_closure) (StgApp fn []))
+ returnUs (StgLet (StgNonRec fn lam_closure) (mkStgApp fn []))
where
lam_closure = StgRhsClosure noCCS
stgArgOcc
Just (tycon, tys_applied, cons) ->
let
arg_tys = dataConArgTys con tys_applied
+ -- This almost certainly does not work for existential constructors
in
checkL (con `elem` cons) (mkAlgAltMsg2 scrut_ty con) `thenL_`
checkL (length arg_tys == length args) (mkAlgAltMsg3 con args)
import PrimOp ( primOpStrictness )
import Id ( Id, idType, getIdStrictness, getIdUnfolding )
import Const ( Con(..) )
-import DataCon ( dataConTyCon, dataConArgTys )
+import DataCon ( dataConTyCon, splitProductType_maybe )
import IdInfo ( StrictnessInfo(..) )
import Demand ( Demand(..), wwPrim, wwStrict, wwEnum, wwUnpackData,
wwUnpackNew )
else -- It's strict (or we're pretending it is)!
- case (splitAlgTyConApp_maybe ty) of
+ case splitProductType_maybe ty of
- Nothing -> wwStrict
+ Nothing -> wwStrict -- Could have a test for wwEnum, but
+ -- we don't exploit it yet, so don't bother
- Just (tycon,tycon_arg_tys,[data_con]) | isProductTyCon tycon ->
- -- Non-recursive, single constructor case
- let
- cmpnt_tys = dataConArgTys data_con tycon_arg_tys
- prod_len = length cmpnt_tys
- in
-
- if isNewTyCon tycon then -- A newtype!
- ASSERT( null (tail cmpnt_tys) )
+ Just (tycon,_,data_con,cmpnt_tys) -- Non-recursive, single constructor case
+ | isNewTyCon tycon -- A newtype!
+ -> ASSERT( null (tail cmpnt_tys) )
let
demand = findRecDemand str_fn abs_fn (head cmpnt_tys)
in
wwUnpackNew demand
- else -- A data type!
- let
+
+ | null compt_strict_infos -- A nullary data type
+ -> wwStrict
+
+ | otherwise -- Some other data type
+ -> wwUnpackData compt_strict_infos
+
+ where
+ prod_len = length cmpnt_tys
compt_strict_infos
= [ findRecDemand
(\ cmpnt_val ->
)
cmpnt_ty
| (cmpnt_ty, i) <- cmpnt_tys `zip` [1..] ]
- in
- if null compt_strict_infos then
- if isEnumerationTyCon tycon then wwEnum else wwStrict
- else
- wwUnpackData compt_strict_infos
-
- Just (tycon,_,_) ->
- -- Multi-constr data types, *or* an abstract data
- -- types, *or* things we don't have a way of conveying
- -- the info over module boundaries (class ops,
- -- superdict sels, dfns).
- if isEnumerationTyCon tycon then
- wwEnum
- else
- wwStrict
+
where
is_numeric_type ty
= case (splitAlgTyConApp_maybe ty) of -- NB: duplicates stuff done above
)
import IdInfo ( CprInfo(..), noCprInfo, vanillaIdInfo )
import Const ( Con(..), DataCon )
-import DataCon ( dataConArgTys )
+import DataCon ( splitProductType_maybe )
import Demand ( Demand(..) )
import PrelInfo ( realWorldPrimId, aBSENT_ERROR_ID )
import TysPrim ( realWorldStatePrimTy )
import Type ( isUnLiftedType, mkTyVarTys, mkTyVarTy, mkFunTys,
splitForAllTys, splitFunTys, splitFunTysN,
splitAlgTyConApp_maybe, splitAlgTyConApp,
- mkTyConApp, newTypeRep, isNewType,
+ mkTyConApp, splitNewType_maybe,
Type
)
import TyCon ( isNewTyCon,
\begin{code}
mkWWcoerce body_ty
- | not (isNewType body_ty)
- = (id, id)
-
- | otherwise
- = (wrap_fn . mkNote (Coerce body_ty rep_ty),
- mkNote (Coerce rep_ty body_ty) . work_fn)
- where
- (tycon, args, _) = splitAlgTyConApp body_ty
- rep_ty = newTypeRep tycon args
- (wrap_fn, work_fn) = mkWWcoerce rep_ty
+ = case splitNewType_maybe body_ty of
+ Nothing -> (id, id)
+ Just rep_ty -> (mkNote (Coerce body_ty rep_ty),
+ mkNote (Coerce rep_ty body_ty))
\end{code}
mk_unpk_case new_or_data arg unpk_args data_con arg_tycon . wrap_fn,
work_fn . mk_pk_let new_or_data arg data_con tycon_arg_tys unpk_args)
where
- inst_con_arg_tys = dataConArgTys data_con tycon_arg_tys
- (arg_tycon, tycon_arg_tys, data_con)
- = case (splitAlgTyConApp_maybe (idType arg)) of
-
- Just (arg_tycon, tycon_arg_tys, [data_con]) ->
- -- The main event: a single-constructor data type
- (arg_tycon, tycon_arg_tys, data_con)
-
- Just (_, _, data_cons) ->
- pprPanic "mk_ww_arg_processing:"
- (text "not one constr (interface files not consistent/up to date?)"
- $$ (ppr arg <+> ppr (idType arg)))
-
- Nothing ->
- panic "mk_ww_arg_processing: not datatype"
+ (arg_tycon, tycon_arg_tys, data_con, inst_con_arg_tys) = splitProductType "mk_ww" (idType arg)
-- Other cases
other_demand ->
in
returnUs (id_id, new_tup, new_exp_case)
where
- (data_con, tycon, tycon_arg_tys, inst_con_arg_tys) = splitType "mk_cpr_case" ty
+ (tycon, tycon_arg_tys, data_con, inst_con_arg_tys) = splitProductType "mk_cpr_case" ty
from_type = head inst_con_arg_tys
-- if coerced from a function 'look through' to find result type
target_of_from_type = (snd.splitFunTys.snd.splitForAllTys) from_type
in
returnUs (id_id, new_tup, new_exp)
where
- (data_con, tycon, tycon_arg_tys, inst_con_arg_tys) = splitType "mk_cpr_let" ty
+ (tycon, tycon_arg_tys, data_con, inst_con_arg_tys) = splitProductType "mk_cpr_let" ty
from_type = head inst_con_arg_tys
-- if coerced from a function 'look through' to find result type
target_of_from_type = (snd.splitFunTys.snd.splitForAllTys) from_type
-splitType :: String -> Type -> (DataCon, TyCon, [Type], [Type])
-splitType fname ty = (data_con, tycon, tycon_arg_tys, dataConArgTys data_con tycon_arg_tys)
- where
- (data_con, tycon, tycon_arg_tys)
- = case (splitAlgTyConApp_maybe ty) of
- Just (arg_tycon, tycon_arg_tys, [data_con]) ->
- -- The main event: a single-constructor data type
- (data_con, arg_tycon, tycon_arg_tys)
-
- Just (_, _, data_cons) ->
- pprPanic (fname ++ ":")
- (text "not one constr (interface files not consistent/up to date?)"
- $$ ppr ty)
-
- Nothing ->
- pprPanic (fname ++ ":")
- (text "not a datatype" $$ ppr ty)
+splitProductType :: String -> Type -> (TyCon, [Type], DataCon, [Type])
+splitProductType fname ty = case splitProductType_maybe ty of
+ Just stuff -> stuff
+ Nothing -> pprPanic (fname ++ ": not a product") (ppr ty)
\end{code}
import Id ( mkUserLocal, isDataConId_maybe )
import MkId ( mkSpecPragmaId )
import Var ( TyVar, Id, setVarName,
- idType, setIdInfo, idInfo, tyVarKind
+ idType, lazySetIdInfo, idInfo, tyVarKind
)
import TcType ( TcType, TcTyVar, TcTyVarSet, TcThetaType,
tcInstTyVars, zonkTcTyVars,
-- have explicit local definitions, so we get a black hole!
= id
| otherwise
- = id `setIdInfo` new_info
+ = id `lazySetIdInfo` new_info
-- The Id must be returned without a data dependency on maybe_id
where
new_info = -- pprTrace "tcAdd" (ppr id) $
\end{code}
\begin{code}
-tcMonoExpr (HsSCC label expr) res_ty
+tcMonoExpr (HsSCC lbl expr) res_ty
= tcMonoExpr expr res_ty `thenTc` \ (expr', lie) ->
- returnTc (HsSCC label expr', lie)
+ returnTc (HsSCC lbl expr', lie)
tcMonoExpr (HsLet binds expr) res_ty
= tcBindsAndThen
Mini-utils:
\begin{code}
pp_nest_hang :: String -> SDoc -> SDoc
-pp_nest_hang label stuff = nest 2 (hang (text label) 4 stuff)
+pp_nest_hang lbl stuff = nest 2 (hang (text lbl) 4 stuff)
\end{code}
Boring and alphabetical:
-- others:
import Id ( idName, idType, setIdType, omitIfaceSigForId, Id )
-import DataCon ( DataCon, dataConArgTys )
+import DataCon ( DataCon, splitProductType_maybe )
import TcEnv ( tcLookupValueMaybe, tcExtendGlobalValEnv, tcGetValueEnv,
ValueEnv, TcId, tcInstId
)
\begin{code}
maybeBoxedPrimType :: Type -> Maybe (DataCon, Type)
maybeBoxedPrimType ty
- = case splitAlgTyConApp_maybe ty of -- Data type,
- Just (tycon, tys_applied, [data_con]) | isDataTyCon tycon -- with exactly one constructor
- -> case (dataConArgTys data_con tys_applied) of
- [data_con_arg_ty] -- Applied to exactly one type,
- | isUnLiftedType data_con_arg_ty -- which is primitive
- -> Just (data_con, data_con_arg_ty)
- other_cases -> Nothing
+ = case splitProductType_maybe ty of -- Product data type
+ Just (tycon, tys_applied, data_con, [data_con_arg_ty]) -- constr has one arg
+ | isUnLiftedType data_con_arg_ty -- which is primitive
+ -> Just (data_con, data_con_arg_ty)
+
other_cases -> Nothing
\end{code}
zonkTcTypeToType result_ty `thenNF_Tc` \ new_result_ty ->
returnNF_Tc (CCall fun new_args may_gc is_casm new_result_ty)
-zonkExpr (HsSCC label expr)
+zonkExpr (HsSCC lbl expr)
= zonkExpr expr `thenNF_Tc` \ new_expr ->
- returnNF_Tc (HsSCC label new_expr)
+ returnNF_Tc (HsSCC lbl new_expr)
zonkExpr (TyLam tyvars expr)
= mapNF_Tc zonkTcTyVarToTyVar tyvars `thenNF_Tc` \ new_tyvars ->
import CmdLineOpts ( opt_GlasgowExts, opt_AllowUndecidableInstances )
import Class ( classBigSig, Class )
import Var ( idName, idType, Id, TyVar )
-import DataCon ( isNullaryDataCon, dataConArgTys, dataConId )
+import DataCon ( isNullaryDataCon, splitProductType_maybe, dataConId )
import Maybes ( maybeToBool, catMaybes, expectJust )
import MkId ( mkDictFunId )
import Module ( ModuleName )
ty == stringTy ||
byte_arr_thing
where
- byte_arr_thing = case splitAlgTyConApp_maybe ty of
- Just (tycon, ty_args, [data_con]) | isDataTyCon tycon ->
- length data_con_arg_tys == 2 &&
+ byte_arr_thing = case splitProductType_maybe ty of
+ Just (tycon, ty_args, data_con, [data_con_arg_ty1, data_con_arg_ty2]) ->
maybeToBool maybe_arg2_tycon &&
(arg2_tycon == byteArrayPrimTyCon ||
arg2_tycon == mutableByteArrayPrimTyCon)
where
- data_con_arg_tys = dataConArgTys data_con ty_args
- (data_con_arg_ty1 : data_con_arg_ty2 : _) = data_con_arg_tys
- maybe_arg2_tycon = splitTyConApp_maybe data_con_arg_ty2
+ maybe_arg2_tycon = splitTyConApp_maybe data_con_arg_ty2
Just (arg2_tycon,_) = maybe_arg2_tycon
other -> False
isNewTyCon (AlgTyCon {algTyConFlavour = NewType}) = True
isNewTyCon other = False
--- A "product" tycon is non-recursive and has one constructor,
+-- A "product" tycon is non-recursive and has one constructor, and is *not* an unboxed tuple
-- whether DataType or NewType
isProductTyCon (AlgTyCon {dataCons = [c], algTyConRec = NonRecursive}) = True
-isProductTyCon (TupleTyCon {}) = True
+isProductTyCon (TupleTyCon { tyConBoxed = boxed }) = boxed
isProductTyCon other = False
isSynTyCon (SynTyCon {}) = True
splitAlgTyConApp_maybe, splitAlgTyConApp,
mkDictTy, splitDictTy_maybe, isDictTy,
- mkSynTy, isSynTy, deNoteType, repType, newTypeRep,
+ mkSynTy, isSynTy, deNoteType, repType, splitNewType_maybe,
mkUsgTy, isUsgTy{- dont use -}, isNotUsgTy, splitUsgTy, unUsgTy, tyUsg,
tidyType, tidyTypes,
tidyOpenType, tidyOpenTypes,
tidyTyVar, tidyTyVars,
- tidyTopType
+ tidyTopType,
+
+ -- Seq
+ seqType, seqTypes
+
) where
#include "HsVersions.h"
import Unique -- quite a few *Keys
import Util ( thenCmp, mapAccumL, seqList, ($!) )
import Outputable
-
+import UniqSet ( sizeUniqSet ) -- Should come via VarSet
\end{code}
%************************************************************************
mkSynTy syn_tycon tys
= ASSERT( isSynTyCon syn_tycon )
ASSERT( isNotUsgTy body )
+ ASSERT( length tyvars == length tys )
NoteTy (SynNote (TyConApp syn_tycon tys))
(substTy (mkTyVarSubst tyvars tys) body)
where
repType :: Type -> Type
repType (NoteTy _ ty) = repType ty
repType (ForAllTy _ ty) = repType ty
-repType (TyConApp tc tys) | isNewTyCon tc = repType (newTypeRep tc tys)
+repType (TyConApp tc tys) | isNewTyCon tc = repType (new_type_rep tc tys)
repType other_ty = other_ty
-newTypeRep :: TyCon -> [Type] -> Type
+splitNewType_maybe :: Type -> Maybe Type
+-- Find the representation of a newtype, if it is one
+splitNewType_maybe (NoteTy _ ty) = splitNewType_maybe ty
+splitNewType_maybe (TyConApp tc tys) | isNewTyCon tc = case splitNewType_maybe rep_ty of
+ Just rep_ty' -> Just rep_ty'
+ Nothing -> Just rep_ty
+ where
+ rep_ty = new_type_rep tc tys
+
+splitNewType_maybe other = Nothing
+
+new_type_rep :: TyCon -> [Type] -> Type
-- The representation type for (T t1 .. tn), where T is a newtype
-- Looks through one layer only
-newTypeRep tc tys
+new_type_rep tc tys
= ASSERT( isNewTyCon tc )
case splitFunTy_maybe (applyTys (dataConType (head (tyConDataCons tc))) tys) of
Just (rep_ty, _) -> rep_ty
\end{code}
+%************************************************************************
+%* *
+\subsection{Sequencing on types
+%* *
+%************************************************************************
+
+\begin{code}
+seqType :: Type -> ()
+seqType (TyVarTy tv) = tv `seq` ()
+seqType (AppTy t1 t2) = seqType t1 `seq` seqType t2
+seqType (FunTy t1 t2) = seqType t1 `seq` seqType t2
+seqType (NoteTy note t2) = seqNote note `seq` seqType t2
+seqType (TyConApp tc tys) = tc `seq` seqTypes tys
+seqType (ForAllTy tv ty) = tv `seq` seqType ty
+
+seqTypes :: [Type] -> ()
+seqTypes [] = ()
+seqTypes (ty:tys) = seqType ty `seq` seqTypes tys
+
+seqNote :: TyNote -> ()
+seqNote (SynNote ty) = seqType ty
+seqNote (FTVNote set) = sizeUniqSet set `seq` ()
+seqNote (UsgNote usg) = usg `seq` ()
+\end{code}
+
\begin{code}
bcc :: Graph -> Forest [Vertex]
-bcc g = (concat . map bicomps . map (label g dnum)) forest
+bcc g = (concat . map bicomps . map (do_label g dnum)) forest
where forest = dff g
dnum = preArr (bounds g) forest
-label :: Graph -> Table Int -> Tree Vertex -> Tree (Vertex,Int,Int)
-label g dnum (Node v ts) = Node (v,dnum!v,lv) us
- where us = map (label g dnum) ts
+do_label :: Graph -> Table Int -> Tree Vertex -> Tree (Vertex,Int,Int)
+do_label g dnum (Node v ts) = Node (v,dnum!v,lv) us
+ where us = map (do_label g dnum) ts
lv = minimum ([dnum!v] ++ [dnum!w | w <- g!v]
++ [lu | Node (u,du,lu) xs <- us])
trySlurp :: Handle -> Int -> Addr -> IO (Addr, Int)
trySlurp handle sz_i chunk =
-#if __GLASGOW_HASKELL__ >= 303
+#if __GLASGOW_HASKELL__ == 303
+ wantReadableHandle "hGetChar" handle >>= \ handle_ ->
+ let fo = haFO__ handle_ in
+#elif __GLASGOW_HASKELL__ > 303
wantReadableHandle "hGetChar" handle $ \ handle_ ->
let fo = haFO__ handle_ in
#else
reAllocMem ptr sz = do
chunk <- _ccall_ realloc ptr sz
if chunk == nullAddr
-#if __GLASGOW_HASKELL__ < 303
+#ifndef __HASKELL98__
then fail (userError "reAllocMem")
#else
then fail "reAllocMem"