mkDictFunId, mkDefaultMethodId,
mkDictSelId,
- mkDataConId, mkDataConWrapId,
+ mkDataConIds,
mkRecordSelId,
mkPrimOpId, mkFCallId,
-- And some particular Ids; see below for why they are wired in
wiredInIds, ghcPrimIds,
unsafeCoerceId, realWorldPrimId, voidArgId, nullAddrId, seqId,
+ lazyId, lazyIdUnfolding, lazyIdKey,
mkRuntimeErrorApp,
rEC_CON_ERROR_ID, iRREFUT_PAT_ERROR_ID, rUNTIME_ERROR_ID,
nON_EXHAUSTIVE_GUARDS_ERROR_ID, nO_METHOD_BINDING_ERROR_ID,
- pAT_ERROR_ID
+ pAT_ERROR_ID, eRROR_ID
) where
#include "HsVersions.h"
import BasicTypes ( Arity, StrictnessMark(..), isMarkedUnboxed, isMarkedStrict )
-import TysPrim ( openAlphaTyVars, alphaTyVar, alphaTy, betaTyVar, betaTy,
- intPrimTy, realWorldStatePrimTy, addrPrimTy
+import TysPrim ( openAlphaTyVars, alphaTyVar, alphaTy,
+ realWorldStatePrimTy, addrPrimTy
)
import TysWiredIn ( charTy, mkListTy )
import PrelRules ( primOpRules )
import Rules ( addRule )
+import Type ( TyThing(..) )
import TcType ( Type, ThetaType, mkDictTy, mkPredTys, mkTyConApp,
mkTyVarTys, mkClassPred, tcEqPred,
mkFunTys, mkFunTy, mkSigmaTy, tcSplitSigmaTy,
isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType,
tcSplitFunTys, tcSplitForAllTys, mkPredTy
)
-import Module ( Module )
import CoreUtils ( exprType )
import CoreUnfold ( mkTopUnfolding, mkCompulsoryUnfolding, mkOtherCon )
import Literal ( Literal(..), nullAddrLit )
import Class ( Class, classTyCon, classTyVars, classSelIds )
import Var ( Id, TyVar, Var )
import VarSet ( isEmptyVarSet )
-import Name ( mkWiredInName, mkFCallName, Name )
-import OccName ( mkVarOcc )
-import PrimOp ( PrimOp(DataToTagOp), primOpSig, mkPrimOpIdName )
+import Name ( mkFCallName, mkWiredInName, Name, BuiltInSyntax(..) )
+import OccName ( mkOccFS, varName )
+import PrimOp ( PrimOp, primOpSig, primOpOcc, primOpTag )
import ForeignCall ( ForeignCall )
-import DataCon ( DataCon,
- dataConFieldLabels, dataConRepArity, dataConTyCon,
+import DataCon ( DataCon, DataConIds(..),
+ dataConFieldLabels, dataConRepArity,
dataConArgTys, dataConRepType,
- dataConOrigArgTys,
- dataConName, dataConTheta,
- dataConSig, dataConStrictMarks, dataConWorkId,
+ dataConOrigArgTys, dataConTheta,
+ dataConSig, dataConStrictMarks, dataConExStricts,
splitProductType
)
-import Id ( idType, mkGlobalId, mkVanillaGlobal, mkSysLocal,
- mkTemplateLocals, mkTemplateLocalsNum,
- mkTemplateLocal, idNewStrictness, idName
+import Id ( idType, mkGlobalId, mkVanillaGlobal, mkSysLocal,
+ mkTemplateLocals, mkTemplateLocalsNum, mkExportedLocalId,
+ mkTemplateLocal, idName
)
-import IdInfo ( IdInfo, noCafNoTyGenIdInfo,
- setUnfoldingInfo,
+import IdInfo ( IdInfo, noCafIdInfo, setUnfoldingInfo,
setArityInfo, setSpecInfo, setCafInfo,
- setAllStrictnessInfo,
+ setAllStrictnessInfo, vanillaIdInfo,
GlobalIdDetails(..), CafInfo(..)
)
-import NewDemand ( mkStrictSig, strictSigResInfo, DmdResult(..),
+import NewDemand ( mkStrictSig, DmdResult(..),
mkTopDmdType, topDmd, evalDmd, lazyDmd, retCPR,
Demand(..), Demands(..) )
-import FieldLabel ( mkFieldLabel, fieldLabelName,
- firstFieldLabelTag, allFieldLabelTags, fieldLabelType
+import FieldLabel ( fieldLabelName, firstFieldLabelTag,
+ allFieldLabelTags, fieldLabelType
)
import DmdAnal ( dmdAnalTopRhs )
import CoreSyn
-import Unique ( mkBuiltinUnique )
+import Unique ( mkBuiltinUnique, mkPrimOpIdUnique )
import Maybes
import PrelNames
import Maybe ( isJust )
import Util ( dropList, isSingleton )
import Outputable
+import FastString
import ListSetOps ( assoc, assocMaybe )
import UnicodeUtil ( stringToUtf8 )
import List ( nubBy )
-import Char ( ord )
\end{code}
%************************************************************************
nON_EXHAUSTIVE_GUARDS_ERROR_ID,
nO_METHOD_BINDING_ERROR_ID,
pAT_ERROR_ID,
- rEC_CON_ERROR_ID
+ rEC_CON_ERROR_ID,
+
+ lazyId
] ++ ghcPrimIds
-- These Ids are exported from GHC.Prim
realWorldPrimId,
unsafeCoerceId,
nullAddrId,
- getTagId,
seqId
]
\end{code}
%* *
%************************************************************************
-\begin{code}
-mkDataConId :: Name -> DataCon -> Id
- -- Makes the *worker* for the data constructor; that is, the function
- -- that takes the reprsentation arguments and builds the constructor.
-mkDataConId work_name data_con
- = mkGlobalId (DataConId data_con) work_name (dataConRepType data_con) info
- where
- info = noCafNoTyGenIdInfo
- `setArityInfo` arity
- `setAllStrictnessInfo` Just strict_sig
-
- arity = dataConRepArity data_con
-
- strict_sig = mkStrictSig (mkTopDmdType (replicate arity topDmd) cpr_info)
- -- Notice that we do *not* say the worker is strict
- -- even if the data constructor is declared strict
- -- e.g. data T = MkT !(Int,Int)
- -- Why? Because the *wrapper* is strict (and its unfolding has case
- -- expresssions that do the evals) but the *worker* itself is not.
- -- If we pretend it is strict then when we see
- -- case x of y -> $wMkT y
- -- the simplifier thinks that y is "sure to be evaluated" (because
- -- $wMkT is strict) and drops the case. No, $wMkT is not strict.
- --
- -- When the simplifer sees a pattern
- -- case e of MkT x -> ...
- -- it uses the dataConRepStrictness of MkT to mark x as evaluated;
- -- but that's fine... dataConRepStrictness comes from the data con
- -- not from the worker Id.
-
- tycon = dataConTyCon data_con
- cpr_info | isProductTyCon tycon &&
- isDataTyCon tycon &&
- arity > 0 &&
- arity <= mAX_CPR_SIZE = retCPR
- | otherwise = TopRes
- -- RetCPR is only true for products that are real data types;
- -- that is, not unboxed tuples or [non-recursive] newtypes
-
-mAX_CPR_SIZE :: Arity
-mAX_CPR_SIZE = 10
--- We do not treat very big tuples as CPR-ish:
--- a) for a start we get into trouble because there aren't
--- "enough" unboxed tuple types (a tiresome restriction,
--- but hard to fix),
--- b) more importantly, big unboxed tuples get returned mainly
--- on the stack, and are often then allocated in the heap
--- by the caller. So doing CPR for them may in fact make
--- things worse.
-\end{code}
-
The wrapper for a constructor is an ordinary top-level binding that evaluates
any strict args, unboxes any args that are going to be flattened, and calls
the worker.
Making an explicit case expression allows the simplifier to eliminate
it in the (common) case where the constructor arg is already evaluated.
+
\begin{code}
-mkDataConWrapId data_con
- = mkGlobalId (DataConWrapId data_con) (dataConName data_con) wrap_ty info
- where
- work_id = dataConWorkId data_con
-
- info = noCafNoTyGenIdInfo
- `setUnfoldingInfo` wrap_unf
- -- The NoCaf-ness is set by noCafNoTyGenIdInfo
- `setArityInfo` arity
- -- It's important to specify the arity, so that partial
- -- applications are treated as values
- `setAllStrictnessInfo` Just wrap_sig
-
- wrap_sig = mkStrictSig (mkTopDmdType arg_dmds res_info)
- res_info = strictSigResInfo (idNewStrictness work_id)
- arg_dmds = map mk_dmd strict_marks
- mk_dmd str | isMarkedStrict str = evalDmd
- | otherwise = lazyDmd
- -- The Cpr info can be important inside INLINE rhss, where the
- -- wrapper constructor isn't inlined.
- -- And the argument strictness can be important too; we
- -- may not inline a contructor when it is partially applied.
- -- For example:
- -- data W = C !Int !Int !Int
- -- ...(let w = C x in ...(w p q)...)...
- -- we want to see that w is strict in its two arguments
+mkDataConIds :: Name -> Name -> DataCon -> DataConIds
+ -- Makes the *worker* for the data constructor; that is, the function
+ -- that takes the reprsentation arguments and builds the constructor.
+mkDataConIds wrap_name wkr_name data_con
+ | isNewTyCon tycon
+ = NewDC nt_wrap_id
- wrap_unf | isNewTyCon tycon
- = ASSERT( null ex_tyvars && null ex_dict_args && isSingleton orig_arg_tys )
- -- No existentials on a newtype, but it can have a context
- -- e.g. newtype Eq a => T a = MkT (...)
- mkTopUnfolding $ Note InlineMe $
- mkLams tyvars $ Lam id_arg1 $
- mkNewTypeBody tycon result_ty (Var id_arg1)
-
- | not (any isMarkedStrict strict_marks)
- = mkCompulsoryUnfolding (Var work_id)
- -- The common case. Not only is this efficient,
- -- but it also ensures that the wrapper is replaced
- -- by the worker even when there are no args.
- -- f (:) x
- -- becomes
- -- f $w: x
- -- This is really important in rule matching,
- -- (We could match on the wrappers,
- -- but that makes it less likely that rules will match
- -- when we bring bits of unfoldings together.)
- --
- -- NB: because of this special case, (map (:) ys) turns into
- -- (map $w: ys). The top-level defn for (:) is never used.
- -- This is somewhat of a bore, but I'm currently leaving it
- -- as is, so that there still is a top level curried (:) for
- -- the interpreter to call.
-
- | otherwise
- = mkTopUnfolding $ Note InlineMe $
- mkLams all_tyvars $
- mkLams ex_dict_args $ mkLams id_args $
- foldr mk_case con_app
- (zip (ex_dict_args++id_args) strict_marks) i3 []
-
- con_app i rep_ids = mkApps (Var work_id)
- (map varToCoreExpr (all_tyvars ++ reverse rep_ids))
+ | any isMarkedStrict all_strict_marks -- Algebraic, needs wrapper
+ = AlgDC (Just alg_wrap_id) wrk_id
+ | otherwise -- Algebraic, no wrapper
+ = AlgDC Nothing wrk_id
+ where
(tyvars, _, ex_tyvars, ex_theta, orig_arg_tys, tycon) = dataConSig data_con
- all_tyvars = tyvars ++ ex_tyvars
+ all_tyvars = tyvars ++ ex_tyvars
ex_dict_tys = mkPredTys ex_theta
all_arg_tys = ex_dict_tys ++ orig_arg_tys
-- but now we don't. Instead the type checker just injects these
-- extra constraints where necessary.
- mkLocals i tys = (zipWith mkTemplateLocal [i..i+n-1] tys, i+n)
- where
- n = length tys
+ ----------- Worker (algebraic data types only) --------------
+ wrk_id = mkGlobalId (DataConWorkId data_con) wkr_name
+ (dataConRepType data_con) wkr_info
+
+ wkr_arity = dataConRepArity data_con
+ wkr_info = noCafIdInfo
+ `setArityInfo` wkr_arity
+ `setAllStrictnessInfo` Just wkr_sig
+
+ wkr_sig = mkStrictSig (mkTopDmdType (replicate wkr_arity topDmd) cpr_info)
+ -- Notice that we do *not* say the worker is strict
+ -- even if the data constructor is declared strict
+ -- e.g. data T = MkT !(Int,Int)
+ -- Why? Because the *wrapper* is strict (and its unfolding has case
+ -- expresssions that do the evals) but the *worker* itself is not.
+ -- If we pretend it is strict then when we see
+ -- case x of y -> $wMkT y
+ -- the simplifier thinks that y is "sure to be evaluated" (because
+ -- $wMkT is strict) and drops the case. No, $wMkT is not strict.
+ --
+ -- When the simplifer sees a pattern
+ -- case e of MkT x -> ...
+ -- it uses the dataConRepStrictness of MkT to mark x as evaluated;
+ -- but that's fine... dataConRepStrictness comes from the data con
+ -- not from the worker Id.
+
+ cpr_info | isProductTyCon tycon &&
+ isDataTyCon tycon &&
+ wkr_arity > 0 &&
+ wkr_arity <= mAX_CPR_SIZE = retCPR
+ | otherwise = TopRes
+ -- RetCPR is only true for products that are real data types;
+ -- that is, not unboxed tuples or [non-recursive] newtypes
+
+ ----------- Wrappers for newtypes --------------
+ nt_wrap_id = mkGlobalId (DataConWrapId data_con) wrap_name wrap_ty nt_wrap_info
+ nt_wrap_info = noCafIdInfo -- The NoCaf-ness is set by noCafIdInfo
+ `setArityInfo` 1 -- Arity 1
+ `setUnfoldingInfo` newtype_unf
+ newtype_unf = ASSERT( null ex_tyvars && null ex_theta &&
+ isSingleton orig_arg_tys )
+ -- No existentials on a newtype, but it can have a context
+ -- e.g. newtype Eq a => T a = MkT (...)
+ mkTopUnfolding $ Note InlineMe $
+ mkLams tyvars $ Lam id_arg1 $
+ mkNewTypeBody tycon result_ty (Var id_arg1)
+
+ id_arg1 = mkTemplateLocal 1 (head orig_arg_tys)
+
+ ----------- Wrappers for algebraic data types --------------
+ alg_wrap_id = mkGlobalId (DataConWrapId data_con) wrap_name wrap_ty alg_wrap_info
+ alg_wrap_info = noCafIdInfo -- The NoCaf-ness is set by noCafIdInfo
+ `setArityInfo` alg_arity
+ -- It's important to specify the arity, so that partial
+ -- applications are treated as values
+ `setUnfoldingInfo` alg_unf
+ `setAllStrictnessInfo` Just wrap_sig
+
+ all_strict_marks = dataConExStricts data_con ++ dataConStrictMarks data_con
+ wrap_sig = mkStrictSig (mkTopDmdType arg_dmds cpr_info)
+ arg_dmds = map mk_dmd all_strict_marks
+ mk_dmd str | isMarkedStrict str = evalDmd
+ | otherwise = lazyDmd
+ -- The Cpr info can be important inside INLINE rhss, where the
+ -- wrapper constructor isn't inlined.
+ -- And the argument strictness can be important too; we
+ -- may not inline a contructor when it is partially applied.
+ -- For example:
+ -- data W = C !Int !Int !Int
+ -- ...(let w = C x in ...(w p q)...)...
+ -- we want to see that w is strict in its two arguments
+
+ alg_unf = mkTopUnfolding $ Note InlineMe $
+ mkLams all_tyvars $
+ mkLams ex_dict_args $ mkLams id_args $
+ foldr mk_case con_app
+ (zip (ex_dict_args ++ id_args) all_strict_marks)
+ i3 []
+
+ con_app i rep_ids = mkApps (Var wrk_id)
+ (map varToCoreExpr (all_tyvars ++ reverse rep_ids))
(ex_dict_args,i2) = mkLocals 1 ex_dict_tys
(id_args,i3) = mkLocals i2 orig_arg_tys
- arity = i3-1
- (id_arg1:_) = id_args -- Used for newtype only
-
- strict_marks = dataConStrictMarks data_con
+ alg_arity = i3-1
mk_case
:: (Id, StrictnessMark) -- Arg, strictness
body i' (reverse con_args ++ rep_args))]
where
(con_args, i') = mkLocals i tys
+
+mAX_CPR_SIZE :: Arity
+mAX_CPR_SIZE = 10
+-- We do not treat very big tuples as CPR-ish:
+-- a) for a start we get into trouble because there aren't
+-- "enough" unboxed tuple types (a tiresome restriction,
+-- but hard to fix),
+-- b) more importantly, big unboxed tuples get returned mainly
+-- on the stack, and are often then allocated in the heap
+-- by the caller. So doing CPR for them may in fact make
+-- things worse.
+
+mkLocals i tys = (zipWith mkTemplateLocal [i..i+n-1] tys, i+n)
+ where
+ n = length tys
\end{code}
(not f :: R -> forall a. a->a, which gives the type inference mechanism
problems at call sites)
-Similarly for newtypes
+Similarly for (recursive) newtypes
newtype N = MkN { unN :: forall a. a->a }
- unN :: forall a. N -> a -> a
- unN = /\a -> \n:N -> coerce (a->a) n
+ unN :: forall b. N -> b -> b
+ unN = /\b -> \n:N -> (coerce (forall a. a->a) n)
\begin{code}
mkRecordSelId tycon field_label
-- Assumes that all fields with the same field label have the same type
- --
- -- Annoyingly, we have to pass in the unpackCString# Id, because
- -- we can't conjure it up out of thin air
= sel_id
where
sel_id = mkGlobalId (RecordSelId field_label) (fieldLabelName field_label) selector_ty info
-- Use the demand analyser to work out strictness.
-- With all this unpackery it's not easy!
- info = noCafNoTyGenIdInfo
+ info = noCafIdInfo
`setCafInfo` caf_info
`setArityInfo` arity
`setUnfoldingInfo` mkTopUnfolding rhs_w_str
default_alt | no_default = []
| otherwise = [(DEFAULT, [], error_expr)]
- -- the default branch may have CAF refs, because it calls recSelError etc.
+ -- The default branch may have CAF refs, because it calls recSelError etc.
caf_info | no_default = NoCafRefs
| otherwise = MayHaveCafRefs
mkLams dict_ids $ mkLams field_dict_ids $
Lam data_id $ sel_body
- sel_body | isNewTyCon tycon = mkNewTypeBody tycon field_tau (mk_result data_id)
+ sel_body | isNewTyCon tycon = mk_result (mkNewTypeBody tycon field_ty (Var data_id))
| otherwise = Case (Var data_id) data_id (default_alt ++ the_alts)
- mk_result result_id = mkVarApps (mkVarApps (Var result_id) field_tyvars) field_dict_ids
+ mk_result poly_result = mkVarApps (mkVarApps poly_result field_tyvars) field_dict_ids
-- We pull the field lambdas to the top, so we need to
-- apply them in the body. For example:
-- data T = MkT { foo :: forall a. a->a }
Nothing -> Nothing
Just the_arg_id -> Just (mkReboxingAlt uniqs data_con arg_ids body)
where
- body = mk_result the_arg_id
+ body = mk_result (Var the_arg_id)
where
arg_ids = mkTemplateLocalsNum field_base (dataConOrigArgTys data_con)
-- No need to instantiate; same tyvars in datacon as tycon
+ -- Records can't be existential, so no existential tyvars or dicts
unpack_base = field_base + length arg_ids
uniqs = map mkBuiltinUnique [unpack_base..]
(DataAlt con, args', mkLets binds rhs)
where
- stricts = dataConStrictMarks con
+ stricts = dataConExStricts con ++ dataConStrictMarks con
go [] stricts us = ([], [])
Selecting a field for a dictionary. If there is just one field, then
there's nothing to do.
-ToDo: unify with mkRecordSelId.
+Dictionary selectors may get nested forall-types. Thus:
+
+ class Foo a where
+ op :: forall b. Ord b => a -> b -> b
+
+Then the top-level type for op is
+
+ op :: forall a. Foo a =>
+ forall b. Ord b =>
+ a -> b -> b
+
+This is unlike ordinary record selectors, which have all the for-alls
+at the outside. When dealing with classes it's very convenient to
+recover the original type signature from the class op selector.
\begin{code}
mkDictSelId :: Name -> Class -> Id
mkDictSelId name clas
- = mkGlobalId (RecordSelId field_lbl) name sel_ty info
+ = mkGlobalId (ClassOpId clas) name sel_ty info
where
sel_ty = mkForAllTys tyvars (mkFunTy (idType dict_id) (idType the_arg_id))
-- We can't just say (exprType rhs), because that would give a type
-- But it's type must expose the representation of the dictionary
-- to gat (say) C a -> (a -> a)
- field_lbl = mkFieldLabel name tycon sel_ty tag
- tag = assoc "MkId.mkDictSelId" (map idName (classSelIds clas) `zip` allFieldLabelTags) name
+ tag = assoc "MkId.mkDictSelId" (map idName (classSelIds clas) `zip` allFieldLabelTags) name
- info = noCafNoTyGenIdInfo
+ info = noCafIdInfo
`setArityInfo` 1
`setUnfoldingInfo` mkTopUnfolding rhs
`setAllStrictnessInfo` Just strict_sig
where
(tyvars,arg_tys,res_ty, arity, strict_sig) = primOpSig prim_op
ty = mkForAllTys tyvars (mkFunTys arg_tys res_ty)
- name = mkPrimOpIdName prim_op
+ name = mkWiredInName gHC_PRIM (primOpOcc prim_op)
+ (mkPrimOpIdUnique (primOpTag prim_op))
+ Nothing (AnId id) UserSyntax
id = mkGlobalId (PrimOpId prim_op) name ty info
- info = noCafNoTyGenIdInfo
+ info = noCafIdInfo
`setSpecInfo` rules
`setArityInfo` arity
`setAllStrictnessInfo` Just strict_sig
name = mkFCallName uniq occ_str
- info = noCafNoTyGenIdInfo
+ info = noCafIdInfo
`setArityInfo` arity
`setAllStrictnessInfo` Just strict_sig
that they aren't discarded by the occurrence analyser.
\begin{code}
-mkDefaultMethodId dm_name ty = mkVanillaGlobal dm_name ty noCafNoTyGenIdInfo
+mkDefaultMethodId dm_name ty = mkExportedLocalId dm_name ty
mkDictFunId :: Name -- Name to use for the dict fun;
- -> Class
-> [TyVar]
- -> [Type]
-> ThetaType
+ -> Class
+ -> [Type]
-> Id
-mkDictFunId dfun_name clas inst_tyvars inst_tys dfun_theta
- = mkVanillaGlobal dfun_name dfun_ty noCafNoTyGenIdInfo
+mkDictFunId dfun_name inst_tyvars dfun_theta clas inst_tys
+ = mkExportedLocalId dfun_name dfun_ty
where
dfun_ty = mkSigmaTy inst_tyvars dfun_theta (mkDictTy clas inst_tys)
another gun with which to shoot yourself in the foot.
\begin{code}
+mkWiredInIdName mod fs uniq id
+ = mkWiredInName mod (mkOccFS varName fs) uniq Nothing (AnId id) UserSyntax
+
+unsafeCoerceName = mkWiredInIdName gHC_PRIM FSLIT("unsafeCoerce#") unsafeCoerceIdKey unsafeCoerceId
+nullAddrName = mkWiredInIdName gHC_PRIM FSLIT("nullAddr#") nullAddrIdKey nullAddrId
+seqName = mkWiredInIdName gHC_PRIM FSLIT("seq") seqIdKey seqId
+realWorldName = mkWiredInIdName gHC_PRIM FSLIT("realWorld#") realWorldPrimIdKey realWorldPrimId
+lazyIdName = mkWiredInIdName pREL_BASE FSLIT("lazy") lazyIdKey lazyId
+
+errorName = mkWiredInIdName pREL_ERR FSLIT("error") errorIdKey eRROR_ID
+recSelErrorName = mkWiredInIdName pREL_ERR FSLIT("recSelError") recSelErrorIdKey rEC_SEL_ERROR_ID
+runtimeErrorName = mkWiredInIdName pREL_ERR FSLIT("runtimeError") runtimeErrorIdKey rUNTIME_ERROR_ID
+irrefutPatErrorName = mkWiredInIdName pREL_ERR FSLIT("irrefutPatError") irrefutPatErrorIdKey iRREFUT_PAT_ERROR_ID
+recConErrorName = mkWiredInIdName pREL_ERR FSLIT("recConError") recConErrorIdKey rEC_CON_ERROR_ID
+patErrorName = mkWiredInIdName pREL_ERR FSLIT("patError") patErrorIdKey pAT_ERROR_ID
+noMethodBindingErrorName = mkWiredInIdName pREL_ERR FSLIT("noMethodBindingError")
+ noMethodBindingErrorIdKey nO_METHOD_BINDING_ERROR_ID
+nonExhaustiveGuardsErrorName
+ = mkWiredInIdName pREL_ERR FSLIT("nonExhaustiveGuardsError")
+ nonExhaustiveGuardsErrorIdKey nON_EXHAUSTIVE_GUARDS_ERROR_ID
+\end{code}
+
+\begin{code}
-- unsafeCoerce# :: forall a b. a -> b
unsafeCoerceId
- = pcMiscPrelId unsafeCoerceIdKey gHC_PRIM FSLIT("unsafeCoerce#") ty info
+ = pcMiscPrelId unsafeCoerceName ty info
where
- info = noCafNoTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
+ info = noCafIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
ty = mkForAllTys [openAlphaTyVar,openBetaTyVar]
-- The reason is is here is because we don't provide
-- a way to write this literal in Haskell.
nullAddrId
- = pcMiscPrelId nullAddrIdKey gHC_PRIM FSLIT("nullAddr#") addrPrimTy info
+ = pcMiscPrelId nullAddrName addrPrimTy info
where
- info = noCafNoTyGenIdInfo `setUnfoldingInfo`
+ info = noCafIdInfo `setUnfoldingInfo`
mkCompulsoryUnfolding (Lit nullAddrLit)
seqId
- = pcMiscPrelId seqIdKey gHC_PRIM FSLIT("seq") ty info
+ = pcMiscPrelId seqName ty info
where
- info = noCafNoTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
+ info = noCafIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
- ty = mkForAllTys [alphaTyVar,betaTyVar]
- (mkFunTy alphaTy (mkFunTy betaTy betaTy))
- [x,y] = mkTemplateLocals [alphaTy, betaTy]
- rhs = mkLams [alphaTyVar,betaTyVar,x,y] (Case (Var x) x [(DEFAULT, [], Var y)])
-\end{code}
-
-@getTag#@ is another function which can't be defined in Haskell. It needs to
-evaluate its argument and call the dataToTag# primitive.
-
-\begin{code}
-getTagId
- = pcMiscPrelId getTagIdKey gHC_PRIM FSLIT("getTag#") ty info
+ ty = mkForAllTys [alphaTyVar,openBetaTyVar]
+ (mkFunTy alphaTy (mkFunTy openBetaTy openBetaTy))
+ [x,y] = mkTemplateLocals [alphaTy, openBetaTy]
+ rhs = mkLams [alphaTyVar,openBetaTyVar,x,y] (Case (Var x) x [(DEFAULT, [], Var y)])
+
+-- lazy :: forall a?. a? -> a? (i.e. works for unboxed types too)
+-- Used to lazify pseq: pseq a b = a `seq` lazy b
+-- No unfolding: it gets "inlined" by the worker/wrapper pass
+-- Also, no strictness: by being a built-in Id, it overrides all
+-- the info in PrelBase.hi. This is important, because the strictness
+-- analyser will spot it as strict!
+lazyId
+ = pcMiscPrelId lazyIdName ty info
where
- info = noCafNoTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
- -- We don't provide a defn for this; you must inline it
-
- ty = mkForAllTys [alphaTyVar] (mkFunTy alphaTy intPrimTy)
- [x,y] = mkTemplateLocals [alphaTy,alphaTy]
- rhs = mkLams [alphaTyVar,x] $
- Case (Var x) y [ (DEFAULT, [], mkApps (Var dataToTagId) [Type alphaTy, Var y]) ]
+ info = noCafIdInfo
+ ty = mkForAllTys [alphaTyVar] (mkFunTy alphaTy alphaTy)
-dataToTagId = mkPrimOpId DataToTagOp
+lazyIdUnfolding :: CoreExpr -- Used to expand LazyOp after strictness anal
+lazyIdUnfolding = mkLams [openAlphaTyVar,x] (Var x)
+ where
+ [x] = mkTemplateLocals [openAlphaTy]
\end{code}
@realWorld#@ used to be a magic literal, \tr{void#}. If things get
\begin{code}
realWorldPrimId -- :: State# RealWorld
- = pcMiscPrelId realWorldPrimIdKey gHC_PRIM FSLIT("realWorld#")
- realWorldStatePrimTy
- (noCafNoTyGenIdInfo `setUnfoldingInfo` mkOtherCon [])
+ = pcMiscPrelId realWorldName realWorldStatePrimTy
+ (noCafIdInfo `setUnfoldingInfo` mkOtherCon [])
-- The mkOtherCon makes it look that realWorld# is evaluated
-- which in turn makes Simplify.interestingArg return True,
-- which in turn makes INLINE things applied to realWorld# likely
mkRuntimeErrorApp err_id res_ty err_msg
= mkApps (Var err_id) [Type res_ty, err_string]
where
- err_string = Lit (MachStr (_PK_ (stringToUtf8 err_msg)))
+ err_string = Lit (MachStr (mkFastString (stringToUtf8 err_msg)))
-rEC_SEL_ERROR_ID = mkRuntimeErrorId recSelErrIdKey FSLIT("recSelError")
-rUNTIME_ERROR_ID = mkRuntimeErrorId runtimeErrorIdKey FSLIT("runtimeError")
-
-iRREFUT_PAT_ERROR_ID = mkRuntimeErrorId irrefutPatErrorIdKey FSLIT("irrefutPatError")
-rEC_CON_ERROR_ID = mkRuntimeErrorId recConErrorIdKey FSLIT("recConError")
-nON_EXHAUSTIVE_GUARDS_ERROR_ID = mkRuntimeErrorId nonExhaustiveGuardsErrorIdKey FSLIT("nonExhaustiveGuardsError")
-pAT_ERROR_ID = mkRuntimeErrorId patErrorIdKey FSLIT("patError")
-nO_METHOD_BINDING_ERROR_ID = mkRuntimeErrorId noMethodBindingErrorIdKey FSLIT("noMethodBindingError")
+rEC_SEL_ERROR_ID = mkRuntimeErrorId recSelErrorName
+rUNTIME_ERROR_ID = mkRuntimeErrorId runtimeErrorName
+iRREFUT_PAT_ERROR_ID = mkRuntimeErrorId irrefutPatErrorName
+rEC_CON_ERROR_ID = mkRuntimeErrorId recConErrorName
+pAT_ERROR_ID = mkRuntimeErrorId patErrorName
+nO_METHOD_BINDING_ERROR_ID = mkRuntimeErrorId noMethodBindingErrorName
+nON_EXHAUSTIVE_GUARDS_ERROR_ID = mkRuntimeErrorId nonExhaustiveGuardsErrorName
-- The runtime error Ids take a UTF8-encoded string as argument
-mkRuntimeErrorId key name = pc_bottoming_Id key pREL_ERR name runtimeErrorTy
-runtimeErrorTy = mkSigmaTy [openAlphaTyVar] [] (mkFunTy addrPrimTy openAlphaTy)
+mkRuntimeErrorId name = pc_bottoming_Id name runtimeErrorTy
+runtimeErrorTy = mkSigmaTy [openAlphaTyVar] [] (mkFunTy addrPrimTy openAlphaTy)
\end{code}
\begin{code}
-eRROR_ID = pc_bottoming_Id errorIdKey pREL_ERR FSLIT("error") errorTy
+eRROR_ID = pc_bottoming_Id errorName errorTy
errorTy :: Type
errorTy = mkSigmaTy [openAlphaTyVar] [] (mkFunTys [mkListTy charTy] openAlphaTy)
%************************************************************************
\begin{code}
-pcMiscPrelId :: Unique{-IdKey-} -> Module -> FAST_STRING -> Type -> IdInfo -> Id
-pcMiscPrelId key mod str ty info
- = let
- name = mkWiredInName mod (mkVarOcc str) key
- imp = mkVanillaGlobal name ty info -- the usual case...
- in
- imp
+pcMiscPrelId :: Name -> Type -> IdInfo -> Id
+pcMiscPrelId name ty info
+ = mkVanillaGlobal name ty info
-- We lie and say the thing is imported; otherwise, we get into
-- a mess with dependency analysis; e.g., core2stg may heave in
-- random calls to GHCbase.unpackPS__. If GHCbase is the module
-- being compiled, then it's just a matter of luck if the definition
-- will be in "the right place" to be in scope.
-pc_bottoming_Id key mod name ty
- = pcMiscPrelId key mod name ty bottoming_info
+pc_bottoming_Id name ty
+ = pcMiscPrelId name ty bottoming_info
where
+ bottoming_info = vanillaIdInfo `setAllStrictnessInfo` Just strict_sig
+ -- Do *not* mark them as NoCafRefs, because they can indeed have
+ -- CAF refs. For example, pAT_ERROR_ID calls GHC.Err.untangle,
+ -- which has some CAFs
+ -- In due course we may arrange that these error-y things are
+ -- regarded by the GC as permanently live, in which case we
+ -- can give them NoCaf info. As it is, any function that calls
+ -- any pc_bottoming_Id will itself have CafRefs, which bloats
+ -- SRTs.
+
strict_sig = mkStrictSig (mkTopDmdType [evalDmd] BotRes)
- bottoming_info = noCafNoTyGenIdInfo `setAllStrictnessInfo` Just strict_sig
- -- these "bottom" out, no matter what their arguments
+ -- These "bottom" out, no matter what their arguments
(openAlphaTyVar:openBetaTyVar:_) = openAlphaTyVars
openAlphaTy = mkTyVarTy openAlphaTyVar