\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,
- unsafeCoerceId, realWorldPrimId,
- eRROR_ID, eRROR_CSTRING_ID, rEC_SEL_ERROR_ID, pAT_ERROR_ID, rEC_CON_ERROR_ID,
- rEC_UPD_ERROR_ID, iRREFUT_PAT_ERROR_ID, nON_EXHAUSTIVE_GUARDS_ERROR_ID,
- nO_METHOD_BINDING_ERROR_ID, aBSENT_ERROR_ID, pAR_ERROR_ID
+ 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
) where
#include "HsVersions.h"
isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType,
tcSplitFunTys, tcSplitForAllTys, mkPredTy
)
-import Module ( Module )
-import CoreUtils ( mkInlineMe )
+import CoreUtils ( exprType )
import CoreUnfold ( mkTopUnfolding, mkCompulsoryUnfolding, mkOtherCon )
-import Literal ( Literal(..) )
+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, setCgInfo,
- mkNewStrictnessInfo, setNewStrictnessInfo,
- GlobalIdDetails(..), CafInfo(..), CprInfo(..),
- CgInfo(..), setCgArity
+ setArityInfo, setSpecInfo, setCafInfo,
+ setAllStrictnessInfo,
+ GlobalIdDetails(..), CafInfo(..)
)
import NewDemand ( mkStrictSig, strictSigResInfo, DmdResult(..),
- mkTopDmdType, topDmd, evalDmd, Demand(..), Keepity(..) )
+ mkTopDmdType, topDmd, evalDmd, lazyDmd, retCPR,
+ Demand(..), Demands(..) )
import FieldLabel ( mkFieldLabel, fieldLabelName,
firstFieldLabelTag, allFieldLabelTags, fieldLabelType
)
import Maybes
import PrelNames
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}
%************************************************************************
--
-- [The interface file format now carry such information, but there's
-- no way yet of expressing at the definition site for these
- -- error-reporting
- -- functions that they have an 'open' result type. -- sof 1/99]
-
- aBSENT_ERROR_ID
- , eRROR_ID
- , eRROR_CSTRING_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
-
- -- These three can't be defined in Haskell
- , realWorldPrimId
- , unsafeCoerceId
- , getTagId
- , seqId
+ -- error-reporting functions that they have an 'open'
+ -- result type. -- sof 1/99]
+
+ 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,
+ pAT_ERROR_ID,
+ rEC_CON_ERROR_ID,
+
+ lazyId
+ ] ++ ghcPrimIds
+
+-- These Ids are exported from GHC.Prim
+ghcPrimIds
+ = [ -- These can't be defined in Haskell, but they have
+ -- perfectly reasonable unfoldings in Core
+ realWorldPrimId,
+ unsafeCoerceId,
+ nullAddrId,
+ getTagId,
+ seqId
]
\end{code}
mkDataConId work_name data_con
= mkGlobalId (DataConId data_con) work_name (dataConRepType data_con) info
where
- info = noCafNoTyGenIdInfo
- `setCgArity` arity
+ info = noCafIdInfo
`setArityInfo` arity
- `setNewStrictnessInfo` Just strict_sig
+ `setAllStrictnessInfo` Just strict_sig
arity = dataConRepArity data_con
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
- `setUnfoldingInfo` mkTopUnfolding (mkInlineMe wrap_rhs)
- `setCgArity` arity
- -- The NoCaf-ness is set by noCafNoTyGenIdInfo
+ info = noCafIdInfo
+ `setUnfoldingInfo` wrap_unf
+ -- The NoCaf-ness is set by noCafIdInfo
`setArityInfo` arity
-- It's important to specify the arity, so that partial
-- applications are treated as values
- `setNewStrictnessInfo` Just wrap_sig
-
- wrap_ty = mkForAllTys all_tyvars (mkFunTys all_arg_tys result_ty)
+ `setAllStrictnessInfo` Just wrap_sig
+ wrap_sig = mkStrictSig (mkTopDmdType arg_dmds res_info)
res_info = strictSigResInfo (idNewStrictness work_id)
- wrap_sig = mkStrictSig (mkTopDmdType (replicate arity topDmd) res_info)
+ 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
- -- But we are sloppy about the argument demands, because we expect
- -- to inline the constructor very vigorously.
-
- wrap_rhs | isNewTyCon tycon
- = ASSERT( null ex_tyvars && null ex_dict_args && length orig_arg_tys == 1 )
+ -- 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
+
+ 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 (...)
- mkLams tyvars $ mkLams dict_args $ Lam id_arg1 $
- mkNewTypeBody tycon result_ty id_arg1
-
- | null dict_args && not (any isMarkedStrict strict_marks)
- = 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.)
+ 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), and thence into (map (\x xs. $w: x xs) ys)
- -- in core-to-stg. The top-level defn for (:) is never used.
+ -- (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
- = mkLams all_tyvars $ mkLams dict_args $
+ = 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))
- (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
- `setCgInfo` CgInfo arity caf_info
+ info = noCafIdInfo
+ `setCafInfo` caf_info
`setArityInfo` arity
`setUnfoldingInfo` mkTopUnfolding rhs_w_str
- `setNewStrictnessInfo` Just strict_sig
- -- Unfolding and strictness added by dmdAnalTopId
+ `setAllStrictnessInfo` Just strict_sig
-- Allocate Ids. We do it a funny way round because field_dict_tys is
-- almost always empty. Also note that we use length_tycon_theta
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 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 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 :: forall a. T -> 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 = mkVarApps (mkVarApps (Var the_arg_id) field_tyvars) field_dict_ids
- 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
--
--- rebuild [x::Int, y::Int] [Not, Unbox]
--- = ([ y = I# t ], [x,t])
+-- mkReboxingAlt MkT [x,b] r
+-- = (DataAlt MkT, [y::Int,z::Int,b], let x = (y,z) in r)
+--
+-- 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 SLIT("rb")) us con_arg_tys
- (binds, args') = rebuildConArgs args stricts (drop (length 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
- `setCgArity` 1
+ info = noCafIdInfo
`setArityInfo` 1
`setUnfoldingInfo` mkTopUnfolding rhs
- `setNewStrictnessInfo` Just strict_sig
+ `setAllStrictnessInfo` Just strict_sig
-- We no longer use 'must-inline' on record selectors. They'll
-- inline like crazy if they scrutinise a constructor
-- It's worth giving one, so that absence info etc is generated
-- even if the selector isn't inlined
strict_sig = mkStrictSig (mkTopDmdType [arg_dmd] TopRes)
- arg_dmd | isNewTyCon tycon = Eval
- | otherwise = Seq Drop [ if the_arg_id == id then Eval else Abs
- | id <- arg_ids ]
+ arg_dmd | isNewTyCon tycon = evalDmd
+ | otherwise = Eval (Prod [ if the_arg_id == id then evalDmd else Abs
+ | id <- arg_ids ])
tyvars = classTyVars clas
(dict_id:arg_ids) = mkTemplateLocals (mkPredTy pred : arg_tys)
rhs | isNewTyCon tycon = mkLams tyvars $ Lam dict_id $
- mkNewTypeBody tycon (head arg_tys) dict_id
+ mkNewTypeBody tycon (head arg_tys) (Var dict_id)
| otherwise = mkLams tyvars $ Lam dict_id $
Case (Var dict_id) dict_id
[(DataAlt data_con, arg_ids, Var the_arg_id)]
-mkNewTypeBody tycon result_ty result_id
+mkNewTypeBody tycon result_ty result_expr
+ -- Adds a coerce where necessary
+ -- Used for both wrapping and unwrapping
| isRecursiveTyCon tycon -- Recursive case; use a coerce
- = Note (Coerce result_ty (idType result_id)) (Var result_id)
+ = Note (Coerce result_ty (exprType result_expr)) result_expr
| otherwise -- Normal case
- = Var result_id
+ = result_expr
\end{code}
mkPrimOpId prim_op
= id
where
- (tyvars,arg_tys,res_ty, arity, strict_info) = primOpSig prim_op
+ (tyvars,arg_tys,res_ty, arity, strict_sig) = primOpSig prim_op
ty = mkForAllTys tyvars (mkFunTys arg_tys res_ty)
name = mkPrimOpIdName prim_op
id = mkGlobalId (PrimOpId prim_op) name ty info
- info = noCafNoTyGenIdInfo
+ info = noCafIdInfo
`setSpecInfo` rules
- `setCgArity` arity
`setArityInfo` arity
- `setNewStrictnessInfo` Just (mkNewStrictnessInfo id arity strict_info NoCPRInfo)
- -- Until we modify the primop generation code
+ `setAllStrictnessInfo` Just strict_sig
rules = foldl (addRule id) emptyCoreRules (primOpRules prim_op)
-- 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
- `setCgArity` arity
+ info = noCafIdInfo
`setArityInfo` arity
- `setNewStrictnessInfo` Just strict_sig
+ `setAllStrictnessInfo` Just strict_sig
(_, tau) = tcSplitForAllTys ty
(arg_tys, _) = tcSplitFunTys tau
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. Thats 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
another gun with which to shoot yourself in the foot.
\begin{code}
+-- unsafeCoerce# :: forall a b. a -> b
unsafeCoerceId
- = pcMiscPrelId unsafeCoerceIdKey pREL_GHC SLIT("unsafeCoerce#") ty info
+ = pcMiscPrelId unsafeCoerceName ty info
where
- info = noCafNoTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
+ info = noCafIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
ty = mkForAllTys [openAlphaTyVar,openBetaTyVar]
rhs = mkLams [openAlphaTyVar,openBetaTyVar,x] $
Note (Coerce openBetaTy openAlphaTy) (Var x)
+-- nullAddr# :: Addr#
+-- The reason is is here is because we don't provide
+-- a way to write this literal in Haskell.
+nullAddrId
+ = pcMiscPrelId nullAddrName addrPrimTy info
+ where
+ info = noCafIdInfo `setUnfoldingInfo`
+ mkCompulsoryUnfolding (Lit nullAddrLit)
+
seqId
- = pcMiscPrelId seqIdKey pREL_GHC SLIT("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] (Case (Var x) x [(DEFAULT, [], Var y)])
+ 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 pREL_GHC SLIT("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)
@realWorld#@ used to be a magic literal, \tr{void#}. If things get
nasty as-is, change it back to a literal (@Literal@).
+voidArgId is a Local Id used simply as an argument in functions
+where we just want an arg to avoid having a thunk of unlifted type.
+E.g.
+ x = \ void :: State# RealWorld -> (# p, q #)
+
+This comes up in strictness analysis
+
\begin{code}
realWorldPrimId -- :: State# RealWorld
- = pcMiscPrelId realWorldPrimIdKey pREL_GHC SLIT("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
-- to be inlined
+
+voidArgId -- :: State# RealWorld
+ = mkSysLocal FSLIT("void") voidArgIdKey realWorldStatePrimTy
\end{code}
templates, but we don't ever expect to generate code for it.
\begin{code}
-eRROR_ID
- = pc_bottoming_Id errorIdKey pREL_ERR SLIT("error") errorTy
-eRROR_CSTRING_ID
- = pc_bottoming_Id errorCStringIdKey pREL_ERR SLIT("errorCString")
- (mkSigmaTy [openAlphaTyVar] [] (mkFunTy addrPrimTy openAlphaTy))
-pAT_ERROR_ID
- = generic_ERROR_ID patErrorIdKey SLIT("patError")
-rEC_SEL_ERROR_ID
- = generic_ERROR_ID recSelErrIdKey SLIT("recSelError")
-rEC_CON_ERROR_ID
- = generic_ERROR_ID recConErrorIdKey SLIT("recConError")
-rEC_UPD_ERROR_ID
- = generic_ERROR_ID recUpdErrorIdKey SLIT("recUpdError")
-iRREFUT_PAT_ERROR_ID
- = generic_ERROR_ID irrefutPatErrorIdKey SLIT("irrefutPatError")
-nON_EXHAUSTIVE_GUARDS_ERROR_ID
- = generic_ERROR_ID nonExhaustiveGuardsErrorIdKey SLIT("nonExhaustiveGuardsError")
-nO_METHOD_BINDING_ERROR_ID
- = generic_ERROR_ID noMethodBindingErrorIdKey SLIT("noMethodBindingError")
-
-aBSENT_ERROR_ID
- = pc_bottoming_Id absentErrorIdKey pREL_ERR SLIT("absentErr")
- (mkSigmaTy [openAlphaTyVar] [] openAlphaTy)
-
-pAR_ERROR_ID
- = pcMiscPrelId parErrorIdKey pREL_ERR SLIT("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
-
- arity = 1
- strict_sig = mkStrictSig (mkTopDmdType [evalDmd] BotRes)
- bottoming_info = noCafNoTyGenIdInfo `setNewStrictnessInfo` 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}