\begin{code}
module MkId (
mkDictFunId, mkDefaultMethodId,
- mkDictSelId,
+ mkDictSelId,
mkDataConId, mkDataConWrapId,
- mkRecordSelId, rebuildConArgs,
+ mkRecordSelId,
mkPrimOpId, mkFCallId,
+ mkReboxingAlt, mkNewTypeBody,
+
-- And some particular Ids; see below for why they are wired in
wiredInIds, ghcPrimIds,
- unsafeCoerceId, realWorldPrimId, voidArgId, nullAddrId,
- eRROR_ID, eRROR_CSTRING_ID, rEC_SEL_ERROR_ID, pAT_ERROR_ID,
- rEC_CON_ERROR_ID, rEC_UPD_ERROR_ID, iRREFUT_PAT_ERROR_ID,
+ 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,
- aBSENT_ERROR_ID, pAR_ERROR_ID
+ pAT_ERROR_ID
) where
#include "HsVersions.h"
isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType,
tcSplitFunTys, tcSplitForAllTys, mkPredTy
)
-import Module ( Module )
import CoreUtils ( exprType )
import CoreUnfold ( mkTopUnfolding, mkCompulsoryUnfolding, mkOtherCon )
import Literal ( Literal(..), nullAddrLit )
import TyCon ( TyCon, isNewTyCon, tyConTyVars, tyConDataCons,
tyConTheta, isProductTyCon, isDataTyCon, isRecursiveTyCon )
import Class ( Class, classTyCon, classTyVars, classSelIds )
-import Var ( Id, TyVar )
+import Var ( Id, TyVar, Var )
import VarSet ( isEmptyVarSet )
-import Name ( mkWiredInName, mkFCallName, Name )
-import OccName ( mkVarOcc )
+import Name ( mkFCallName, Name )
import PrimOp ( PrimOp(DataToTagOp), primOpSig, mkPrimOpIdName )
import ForeignCall ( ForeignCall )
import DataCon ( DataCon,
dataConFieldLabels, dataConRepArity, dataConTyCon,
dataConArgTys, dataConRepType,
- dataConInstOrigArgTys,
+ dataConOrigArgTys,
dataConName, dataConTheta,
- dataConSig, dataConStrictMarks, dataConId,
+ dataConSig, dataConStrictMarks, dataConWorkId,
splitProductType
)
import Id ( idType, mkGlobalId, mkVanillaGlobal, mkSysLocal,
mkTemplateLocals, mkTemplateLocalsNum,
mkTemplateLocal, idNewStrictness, idName
)
-import IdInfo ( IdInfo, noCafNoTyGenIdInfo,
+import IdInfo ( IdInfo, noCafIdInfo, hasCafIdInfo,
setUnfoldingInfo,
setArityInfo, setSpecInfo, setCafInfo,
setAllStrictnessInfo,
GlobalIdDetails(..), CafInfo(..)
)
import NewDemand ( mkStrictSig, strictSigResInfo, DmdResult(..),
- mkTopDmdType, topDmd, evalDmd, lazyDmd,
+ mkTopDmdType, topDmd, evalDmd, lazyDmd, retCPR,
Demand(..), Demands(..) )
import FieldLabel ( mkFieldLabel, fieldLabelName,
firstFieldLabelTag, allFieldLabelTags, fieldLabelType
import Maybe ( isJust )
import Util ( dropList, isSingleton )
import Outputable
+import FastString
import ListSetOps ( assoc, assocMaybe )
import UnicodeUtil ( stringToUtf8 )
-import Char ( ord )
+import List ( nubBy )
\end{code}
%************************************************************************
-- error-reporting functions that they have an 'open'
-- result type. -- sof 1/99]
- aBSENT_ERROR_ID,
- eRROR_ID,
- eRROR_CSTRING_ID,
+ eRROR_ID, -- This one isn't used anywhere else in the compiler
+ -- But we still need it in wiredInIds so that when GHC
+ -- compiles a program that mentions 'error' we don't
+ -- import its type from the interface file; we just get
+ -- the Id defined here. Which has an 'open-tyvar' type.
+
+ rUNTIME_ERROR_ID,
iRREFUT_PAT_ERROR_ID,
nON_EXHAUSTIVE_GUARDS_ERROR_ID,
nO_METHOD_BINDING_ERROR_ID,
- pAR_ERROR_ID,
pAT_ERROR_ID,
rEC_CON_ERROR_ID,
- rEC_UPD_ERROR_ID
+
+ lazyId
] ++ ghcPrimIds
-- These Ids are exported from GHC.Prim
mkDataConId work_name data_con
= mkGlobalId (DataConId data_con) work_name (dataConRepType data_con) info
where
- info = noCafNoTyGenIdInfo
+ info = noCafIdInfo
`setArityInfo` arity
`setAllStrictnessInfo` Just strict_sig
cpr_info | isProductTyCon tycon &&
isDataTyCon tycon &&
arity > 0 &&
- arity <= mAX_CPR_SIZE = RetCPR
+ 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
mkDataConWrapId data_con
= mkGlobalId (DataConWrapId data_con) (dataConName data_con) wrap_ty info
where
- work_id = dataConId data_con
+ work_id = dataConWorkId data_con
- info = noCafNoTyGenIdInfo
+ info = noCafIdInfo
`setUnfoldingInfo` wrap_unf
- -- The NoCaf-ness is set by noCafNoTyGenIdInfo
+ -- The NoCaf-ness is set by noCafIdInfo
`setArityInfo` arity
-- It's important to specify the arity, so that partial
-- applications are treated as values
`setAllStrictnessInfo` Just wrap_sig
- wrap_ty = mkForAllTys all_tyvars (mkFunTys all_arg_tys result_ty)
-
wrap_sig = mkStrictSig (mkTopDmdType arg_dmds res_info)
res_info = strictSigResInfo (idNewStrictness work_id)
- arg_dmds = [Abs | d <- dict_args] ++ map mk_dmd strict_marks
+ 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
-- No existentials on a newtype, but it can have a context
-- e.g. newtype Eq a => T a = MkT (...)
mkTopUnfolding $ Note InlineMe $
- mkLams tyvars $ mkLams dict_args $ Lam id_arg1 $
+ mkLams tyvars $ Lam id_arg1 $
mkNewTypeBody tycon result_ty (Var id_arg1)
- | null dict_args && not (any isMarkedStrict strict_marks)
+ | 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
| otherwise
= mkTopUnfolding $ Note InlineMe $
- mkLams all_tyvars $ mkLams dict_args $
+ 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))
- (tyvars, theta, ex_tyvars, ex_theta, orig_arg_tys, tycon) = dataConSig data_con
+ (tyvars, _, ex_tyvars, ex_theta, orig_arg_tys, tycon) = dataConSig data_con
all_tyvars = tyvars ++ ex_tyvars
- dict_tys = mkPredTys theta
ex_dict_tys = mkPredTys ex_theta
- all_arg_tys = dict_tys ++ ex_dict_tys ++ orig_arg_tys
+ all_arg_tys = ex_dict_tys ++ orig_arg_tys
result_ty = mkTyConApp tycon (mkTyVarTys tyvars)
+ wrap_ty = mkForAllTys all_tyvars (mkFunTys all_arg_tys result_ty)
+ -- We used to include the stupid theta in the wrapper's args
+ -- 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
- (dict_args, i1) = mkLocals 1 dict_tys
- (ex_dict_args,i2) = mkLocals i1 ex_dict_tys
+ (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
(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 unpack_id unpackUtf8_id
+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
data_ty = mkTyConApp tycon tyvar_tys
tyvar_tys = mkTyVarTys tyvars
- tycon_theta = tyConTheta tycon -- The context on the data decl
+ -- Very tiresomely, the selectors are (unnecessarily!) overloaded over
+ -- just the dictionaries in the types of the constructors that contain
+ -- the relevant field. [The Report says that pattern matching on a
+ -- constructor gives the same constraints as applying it.] Urgh.
+ --
+ -- However, not all data cons have all constraints (because of
+ -- TcTyDecls.thinContext). So we need to find all the data cons
+ -- involved in the pattern match and take the union of their constraints.
+ --
+ -- NB: this code relies on the fact that DataCons are quantified over
+ -- the identical type variables as their parent TyCon
+ tycon_theta = tyConTheta tycon -- The context on the data decl
-- eg data (Eq a, Ord b) => T a b = ...
- dict_tys = [mkPredTy pred | pred <- tycon_theta,
- needed_dict pred]
- needed_dict pred = or [ tcEqPred pred p
- | (DataAlt dc, _, _) <- the_alts, p <- dataConTheta dc]
- n_dict_tys = length dict_tys
+ needed_preds = [pred | (DataAlt dc, _, _) <- the_alts, pred <- dataConTheta dc]
+ dict_tys = map mkPredTy (nubBy tcEqPred needed_preds)
+ n_dict_tys = length dict_tys
(field_tyvars,field_theta,field_tau) = tcSplitSigmaTy field_ty
field_dict_tys = map mkPredTy field_theta
-- Note that this is exactly the type we'd infer from a user defn
-- op (R op) = op
- -- Very tiresomely, the selectors are (unnecessarily!) overloaded over
- -- just the dictionaries in the types of the constructors that contain
- -- the relevant field. Urgh.
- -- NB: this code relies on the fact that DataCons are quantified over
- -- the identical type variables as their parent TyCon
-
selector_ty :: Type
selector_ty = mkForAllTys tyvars $ mkForAllTys field_tyvars $
mkFunTys dict_tys $ mkFunTys field_dict_tys $
-- 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 }
-- foo = /\a. \t:T. case t of { MkT f -> f a }
mk_maybe_alt data_con
- = case maybe_the_arg_id of
+ = case maybe_the_arg_id of
Nothing -> Nothing
- Just the_arg_id -> Just (DataAlt data_con, real_args, mkLets binds body)
- where
- body = mk_result the_arg_id
- strict_marks = dataConStrictMarks data_con
- (binds, real_args) = rebuildConArgs arg_ids strict_marks
- (map mkBuiltinUnique [unpack_base..])
+ Just the_arg_id -> Just (mkReboxingAlt uniqs data_con arg_ids body)
+ where
+ body = mk_result (Var the_arg_id)
where
- arg_ids = mkTemplateLocalsNum field_base (dataConInstOrigArgTys data_con tyvar_tys)
+ arg_ids = mkTemplateLocalsNum field_base (dataConOrigArgTys data_con)
+ -- No need to instantiate; same tyvars in datacon as tycon
unpack_base = field_base + length arg_ids
+ uniqs = map mkBuiltinUnique [unpack_base..]
-- arity+1 avoids all shadowing
maybe_the_arg_id = assocMaybe (field_lbls `zip` arg_ids) field_label
field_lbls = dataConFieldLabels data_con
- error_expr = mkApps (Var rEC_SEL_ERROR_ID) [Type field_tau, err_string]
- err_string
- | all safeChar full_msg
- = App (Var unpack_id) (Lit (MachStr (_PK_ full_msg)))
- | otherwise
- = App (Var unpackUtf8_id) (Lit (MachStr (_PK_ (stringToUtf8 (map ord full_msg)))))
- where
- safeChar c = c >= '\1' && c <= '\xFF'
- -- TODO: Putting this Unicode stuff here is ugly. Find a better
- -- generic place to make string literals. This logic is repeated
- -- in DsUtils.
+ error_expr = mkRuntimeErrorApp rEC_SEL_ERROR_ID field_tau full_msg
full_msg = showSDoc (sep [text "No match in record selector", ppr sel_id])
--- This rather ugly function converts the unpacked data con
--- arguments back into their packed form.
-
-rebuildConArgs
- :: [Id] -- Source-level args
- -> [StrictnessMark] -- Strictness annotations (per-arg)
- -> [Unique] -- Uniques for the new Ids
- -> ([CoreBind], [Id]) -- A binding for each source-level arg, plus
- -- a list of the representation-level arguments
--- e.g. data T = MkT Int !Int
+-- (mkReboxingAlt us con xs rhs) basically constructs the case
+-- alternative (con, xs, rhs)
+-- but it does the reboxing necessary to construct the *source*
+-- arguments, xs, from the representation arguments ys.
+-- For example:
+-- data T = MkT !(Int,Int) Bool
+--
+-- mkReboxingAlt MkT [x,b] r
+-- = (DataAlt MkT, [y::Int,z::Int,b], let x = (y,z) in r)
--
--- rebuild [x::Int, y::Int] [Not, Unbox]
--- = ([ y = I# t ], [x,t])
+-- mkDataAlt should really be in DataCon, but it can't because
+-- it manipulates CoreSyn.
-rebuildConArgs [] stricts us = ([], [])
+mkReboxingAlt
+ :: [Unique] -- Uniques for the new Ids
+ -> DataCon
+ -> [Var] -- Source-level args
+ -> CoreExpr -- RHS
+ -> CoreAlt
--- Type variable case
-rebuildConArgs (arg:args) stricts us
- | isTyVar arg
- = let (binds, args') = rebuildConArgs args stricts us
- in (binds, arg:args')
+mkReboxingAlt us con args rhs
+ | not (any isMarkedUnboxed stricts)
+ = (DataAlt con, args, rhs)
--- Term variable case
-rebuildConArgs (arg:args) (str:stricts) us
- | isMarkedUnboxed str
+ | otherwise
= let
- arg_ty = idType arg
-
- (_, tycon_args, pack_con, con_arg_tys)
- = splitProductType "rebuildConArgs" arg_ty
-
- unpacked_args = zipWith (mkSysLocal FSLIT("rb")) us con_arg_tys
- (binds, args') = rebuildConArgs args stricts (dropList con_arg_tys us)
- con_app = mkConApp pack_con (map Type tycon_args ++ map Var unpacked_args)
+ (binds, args') = go args stricts us
in
- (NonRec arg con_app : binds, unpacked_args ++ args')
+ (DataAlt con, args', mkLets binds rhs)
- | otherwise
- = let (binds, args') = rebuildConArgs args stricts us
- in (binds, arg:args')
+ where
+ stricts = dataConStrictMarks con
+
+ go [] stricts us = ([], [])
+
+ -- Type variable case
+ go (arg:args) stricts us
+ | isTyVar arg
+ = let (binds, args') = go args stricts us
+ in (binds, arg:args')
+
+ -- Term variable case
+ go (arg:args) (str:stricts) us
+ | isMarkedUnboxed str
+ = let
+ (_, tycon_args, pack_con, con_arg_tys)
+ = splitProductType "mkReboxingAlt" (idType arg)
+
+ unpacked_args = zipWith (mkSysLocal FSLIT("rb")) us con_arg_tys
+ (binds, args') = go args stricts (dropList con_arg_tys us)
+ con_app = mkConApp pack_con (map Type tycon_args ++ map Var unpacked_args)
+ in
+ (NonRec arg con_app : binds, unpacked_args ++ args')
+
+ | otherwise
+ = let (binds, args') = go args stricts us
+ in (binds, arg:args')
\end{code}
field_lbl = mkFieldLabel name tycon sel_ty tag
tag = assoc "MkId.mkDictSelId" (map idName (classSelIds clas) `zip` allFieldLabelTags) name
- info = noCafNoTyGenIdInfo
+ info = noCafIdInfo
`setArityInfo` 1
`setUnfoldingInfo` mkTopUnfolding rhs
`setAllStrictnessInfo` Just strict_sig
name = mkPrimOpIdName prim_op
id = mkGlobalId (PrimOpId prim_op) name ty info
- info = noCafNoTyGenIdInfo
+ info = noCafIdInfo
`setSpecInfo` rules
`setArityInfo` arity
`setAllStrictnessInfo` Just strict_sig
-- when doing substitutions won't substitute over it
mkGlobalId (FCallId fcall) name ty info
where
- occ_str = showSDocIface (braces (ppr fcall <+> ppr ty))
+ occ_str = showSDoc (braces (ppr fcall <+> ppr ty))
-- The "occurrence name" of a ccall is the full info about the
-- ccall; it is encoded, but may have embedded spaces etc!
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 = mkVanillaGlobal dm_name ty noCafIdInfo
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
+ = mkVanillaGlobal dfun_name dfun_ty noCafIdInfo
where
dfun_ty = mkSigmaTy inst_tyvars dfun_theta (mkDictTy clas inst_tys)
%* *
%************************************************************************
-These Ids can't be defined in Haskell. They could be defined in
-unfoldings in PrelGHC.hi-boot, but we'd have to ensure that they
-were definitely, definitely inlined, because there is no curried
-identifier for them. That's what mkCompulsoryUnfolding does.
-If we had a way to get a compulsory unfolding from an interface file,
-we could do that, but we don't right now.
+These Ids can't be defined in Haskell. They could be defined in
+unfoldings in the wired-in GHC.Prim interface file, but we'd have to
+ensure that they were definitely, definitely inlined, because there is
+no curried identifier for them. That's what mkCompulsoryUnfolding
+does. If we had a way to get a compulsory unfolding from an interface
+file, we could do that, but we don't right now.
unsafeCoerce# isn't so much a PrimOp as a phantom identifier, that
just gets expanded into a type coercion wherever it occurs. Hence we
\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)])
+
+-- 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 = noCafIdInfo
+ ty = mkForAllTys [alphaTyVar] (mkFunTy alphaTy alphaTy)
+
+lazyIdUnfolding :: CoreExpr -- Used to expand LazyOp after strictness anal
+lazyIdUnfolding = mkLams [openAlphaTyVar,x] (Var x)
+ where
+ [x] = mkTemplateLocals [openAlphaTy]
\end{code}
@getTag#@ is another function which can't be defined in Haskell. It needs to
\begin{code}
getTagId
- = pcMiscPrelId getTagIdKey gHC_PRIM FSLIT("getTag#") ty info
+ = pcMiscPrelId getTagName ty info
where
- info = noCafNoTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
+ info = noCafIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
-- We don't provide a defn for this; you must inline it
ty = mkForAllTys [alphaTyVar] (mkFunTy alphaTy intPrimTy)
\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
templates, but we don't ever expect to generate code for it.
\begin{code}
-eRROR_ID
- = pc_bottoming_Id errorIdKey pREL_ERR FSLIT("error") errorTy
-eRROR_CSTRING_ID
- = pc_bottoming_Id errorCStringIdKey pREL_ERR FSLIT("errorCString")
- (mkSigmaTy [openAlphaTyVar] [] (mkFunTy addrPrimTy openAlphaTy))
-pAT_ERROR_ID
- = generic_ERROR_ID patErrorIdKey FSLIT("patError")
-rEC_SEL_ERROR_ID
- = generic_ERROR_ID recSelErrIdKey FSLIT("recSelError")
-rEC_CON_ERROR_ID
- = generic_ERROR_ID recConErrorIdKey FSLIT("recConError")
-rEC_UPD_ERROR_ID
- = generic_ERROR_ID recUpdErrorIdKey FSLIT("recUpdError")
-iRREFUT_PAT_ERROR_ID
- = generic_ERROR_ID irrefutPatErrorIdKey FSLIT("irrefutPatError")
-nON_EXHAUSTIVE_GUARDS_ERROR_ID
- = generic_ERROR_ID nonExhaustiveGuardsErrorIdKey FSLIT("nonExhaustiveGuardsError")
-nO_METHOD_BINDING_ERROR_ID
- = generic_ERROR_ID noMethodBindingErrorIdKey FSLIT("noMethodBindingError")
-
-aBSENT_ERROR_ID
- = pc_bottoming_Id absentErrorIdKey pREL_ERR FSLIT("absentErr")
- (mkSigmaTy [openAlphaTyVar] [] openAlphaTy)
-
-pAR_ERROR_ID
- = pcMiscPrelId parErrorIdKey pREL_ERR FSLIT("parError")
- (mkSigmaTy [openAlphaTyVar] [] openAlphaTy) noCafNoTyGenIdInfo
+mkRuntimeErrorApp
+ :: Id -- Should be of type (forall a. Addr# -> a)
+ -- where Addr# points to a UTF8 encoded string
+ -> Type -- The type to instantiate 'a'
+ -> String -- The string to print
+ -> CoreExpr
+
+mkRuntimeErrorApp err_id res_ty err_msg
+ = mkApps (Var err_id) [Type res_ty, err_string]
+ where
+ err_string = Lit (MachStr (mkFastString (stringToUtf8 err_msg)))
+
+rEC_SEL_ERROR_ID = mkRuntimeErrorId recSelErrorName
+rUNTIME_ERROR_ID = mkRuntimeErrorId runtimeErrorName
+iRREFUT_PAT_ERROR_ID = mkRuntimeErrorId irrefutPatErrorName
+rEC_CON_ERROR_ID = mkRuntimeErrorId recConErrorName
+nON_EXHAUSTIVE_GUARDS_ERROR_ID = mkRuntimeErrorId nonExhaustiveGuardsErrorName
+pAT_ERROR_ID = mkRuntimeErrorId patErrorName
+nO_METHOD_BINDING_ERROR_ID = mkRuntimeErrorId noMethodBindingErrorName
+
+-- The runtime error Ids take a UTF8-encoded string as argument
+mkRuntimeErrorId name = pc_bottoming_Id name runtimeErrorTy
+runtimeErrorTy = mkSigmaTy [openAlphaTyVar] [] (mkFunTy addrPrimTy openAlphaTy)
+\end{code}
+
+\begin{code}
+eRROR_ID = pc_bottoming_Id errorName errorTy
+
+errorTy :: Type
+errorTy = mkSigmaTy [openAlphaTyVar] [] (mkFunTys [mkListTy charTy] openAlphaTy)
+ -- Notice the openAlphaTyVar. It says that "error" can be applied
+ -- to unboxed as well as boxed types. This is OK because it never
+ -- returns, so the return type is irrelevant.
\end{code}
%************************************************************************
\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
- strict_sig = mkStrictSig (mkTopDmdType [evalDmd] BotRes)
- bottoming_info = noCafNoTyGenIdInfo `setAllStrictnessInfo` Just strict_sig
- -- these "bottom" out, no matter what their arguments
+ bottoming_info = hasCafIdInfo `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.
-generic_ERROR_ID u n = pc_bottoming_Id u pREL_ERR n errorTy
+ strict_sig = mkStrictSig (mkTopDmdType [evalDmd] BotRes)
+ -- These "bottom" out, no matter what their arguments
(openAlphaTyVar:openBetaTyVar:_) = openAlphaTyVars
openAlphaTy = mkTyVarTy openAlphaTyVar
openBetaTy = mkTyVarTy openBetaTyVar
-
-errorTy :: Type
-errorTy = mkSigmaTy [openAlphaTyVar] [] (mkFunTys [mkListTy charTy]
- openAlphaTy)
- -- Notice the openAlphaTyVar. It says that "error" can be applied
- -- to unboxed as well as boxed types. This is OK because it never
- -- returns, so the return type is irrelevant.
\end{code}