\begin{code}
module MkId (
- mkSpecPragmaId, mkWorkerId,
-
mkDictFunId, mkDefaultMethodId,
mkDictSelId,
#include "HsVersions.h"
+import BasicTypes ( Arity )
import TysPrim ( openAlphaTyVars, alphaTyVar, alphaTy,
intPrimTy, realWorldStatePrimTy
)
-import TysWiredIn ( boolTy, charTy, mkListTy )
+import TysWiredIn ( charTy, mkListTy )
import PrelNames ( pREL_ERR, pREL_GHC )
import PrelRules ( primOpRule )
import Rules ( addRule )
-import Type ( Type, ThetaType, mkDictTy, mkDictTys, mkTyConApp, mkTyVarTys,
- mkFunTys, mkFunTy, mkSigmaTy, classesToPreds,
- isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType, tyVarsOfTypes,
- splitSigmaTy, splitFunTy_maybe,
- splitFunTys, splitForAllTys, unUsgTy,
- mkUsgTy, UsageAnn(..)
+import Type ( Type, ThetaType, mkDictTy, mkPredTys, mkTyConApp, mkTyVarTys,
+ mkFunTys, mkFunTy, mkSigmaTy, splitSigmaTy,
+ isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType,
+ splitFunTys, splitForAllTys, mkPredTy
)
import Module ( Module )
import CoreUtils ( exprType, mkInlineMe )
import CoreUnfold ( mkTopUnfolding, mkCompulsoryUnfolding, mkOtherCon )
import Literal ( Literal(..) )
-import TyCon ( TyCon, isNewTyCon, tyConTyVars, tyConDataCons, isDataTyCon,
- tyConTheta, isProductTyCon, isUnboxedTupleTyCon )
-import Class ( Class, classBigSig, classTyCon, classTyVars, classSelIds )
+import TyCon ( TyCon, isNewTyCon, tyConTyVars, tyConDataCons,
+ tyConTheta, isProductTyCon, isDataTyCon )
+import Class ( Class, classTyCon, classTyVars, classSelIds )
import Var ( Id, TyVar )
import VarSet ( isEmptyVarSet )
-import Name ( mkDerivedName, mkWiredInIdName, mkLocalName,
- mkWorkerOcc, mkSuperDictSelOcc, mkCCallName,
- Name, NamedThing(..),
- )
-import OccName ( mkSrcVarOcc )
+import Name ( mkWiredInName, mkCCallName, Name )
+import OccName ( mkVarOcc )
import PrimOp ( PrimOp(DataToTagOp, CCallOp),
primOpSig, mkPrimOpIdName,
CCall, pprCCallOp
dataConSig, dataConStrictMarks, dataConId,
maybeMarkedUnboxed, splitProductType_maybe
)
-import Id ( idType, mkId,
- mkVanillaId, mkTemplateLocals,
- mkTemplateLocal, setInlinePragma, idCprInfo
+import Id ( idType, mkGlobalId, mkVanillaGlobal,
+ mkTemplateLocals, mkTemplateLocalsNum,
+ mkTemplateLocal, idCprInfo
)
-import IdInfo ( IdInfo, vanillaIdInfo, mkIdInfo,
- exactArity, setUnfoldingInfo, setCafInfo, setCprInfo,
- setArityInfo, setInlinePragInfo, setSpecInfo,
+import IdInfo ( IdInfo, noCafNoTyGenIdInfo,
+ exactArity, setUnfoldingInfo, setCprInfo,
+ setArityInfo, setSpecInfo, setCgInfo,
mkStrictnessInfo, setStrictnessInfo,
- IdFlavour(..), InlinePragInfo(..), CafInfo(..), StrictnessInfo(..), CprInfo(..)
+ GlobalIdDetails(..), CafInfo(..), CprInfo(..),
+ CgInfo(..), setCgArity
)
-import FieldLabel ( FieldLabel, FieldLabelTag, mkFieldLabel, fieldLabelName,
+import FieldLabel ( mkFieldLabel, fieldLabelName,
firstFieldLabelTag, allFieldLabelTags, fieldLabelType
)
import CoreSyn
import Char ( ord )
\end{code}
-
%************************************************************************
%* *
\subsection{Wired in Ids}
, rEC_CON_ERROR_ID
, rEC_UPD_ERROR_ID
- -- These two can't be defined in Haskell
+ -- These three can't be defined in Haskell
, realWorldPrimId
, unsafeCoerceId
, getTagId
%************************************************************************
%* *
-\subsection{Easy ones}
-%* *
-%************************************************************************
-
-\begin{code}
-mkSpecPragmaId occ uniq ty loc
- = mkId (mkLocalName uniq occ loc) ty (mkIdInfo SpecPragmaId)
- -- Maybe a SysLocal? But then we'd lose the location
-
-mkDefaultMethodId dm_name rec_c ty
- = mkVanillaId dm_name ty
-
-mkWorkerId uniq unwrkr ty
- = mkVanillaId (mkDerivedName mkWorkerOcc (getName unwrkr) uniq) ty
-\end{code}
-
-%************************************************************************
-%* *
\subsection{Data constructors}
%* *
%************************************************************************
-- 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
- = mkId work_name (dataConRepType data_con) info
+ = mkGlobalId (DataConId data_con) work_name (dataConRepType data_con) info
where
- info = mkIdInfo (DataConId data_con)
+ info = noCafNoTyGenIdInfo
+ `setCgArity` arity
`setArityInfo` exactArity arity
`setStrictnessInfo` strict_info
`setCprInfo` cpr_info
strict_info = mkStrictnessInfo (dataConRepStrictness data_con, False)
+ tycon = dataConTyCon data_con
cpr_info | isProductTyCon tycon &&
- not (isUnboxedTupleTyCon tycon) &&
- arity > 0 = ReturnsCPR
- | otherwise = NoCPRInfo
- where
- tycon = dataConTyCon data_con
- -- Newtypes don't have a worker at all
- --
- -- If we are a product with 0 args we must be void(like)
- -- We can't create an unboxed tuple with 0 args for this
- -- and since Void has only one, constant value it should
- -- just mean returning a pointer to a pre-existing cell.
- -- So we won't really gain from doing anything fancy
- -- and we treat this case as Top.
+ isDataTyCon tycon &&
+ arity > 0 &&
+ arity <= mAX_CPR_SIZE = ReturnsCPR
+ | otherwise = NoCPRInfo
+ -- ReturnsCPR is only true for products that are real data types;
+ -- that is, not unboxed tuples or 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
mkDataConWrapId data_con
= wrap_id
where
- wrap_id = mkId (dataConName data_con) wrap_ty info
+ wrap_id = mkGlobalId (DataConWrapId data_con) (dataConName data_con) wrap_ty info
work_id = dataConId data_con
- info = mkIdInfo (DataConWrapId data_con)
+ info = noCafNoTyGenIdInfo
`setUnfoldingInfo` mkTopUnfolding (mkInlineMe wrap_rhs)
`setCprInfo` cpr_info
-- The Cpr info can be important inside INLINE rhss, where the
-- wrapper constructor isn't inlined
+ `setCgArity` arity
+ -- The NoCaf-ness is set by noCafNoTyGenIdInfo
`setArityInfo` exactArity arity
-- It's important to specify the arity, so that partial
-- applications are treated as values
- `setCafInfo` NoCafRefs
- -- The wrapper Id ends up in STG code as an argument,
- -- sometimes before its definition, so we want to
- -- signal that it has no CAFs
wrap_ty = mkForAllTys all_tyvars $
mkFunTys all_arg_tys
(tyvars, theta, ex_tyvars, ex_theta, orig_arg_tys, tycon) = dataConSig data_con
all_tyvars = tyvars ++ ex_tyvars
- dict_tys = mkDictTys theta
- ex_dict_tys = mkDictTys ex_theta
+ dict_tys = mkPredTys theta
+ ex_dict_tys = mkPredTys ex_theta
all_arg_tys = dict_tys ++ ex_dict_tys ++ orig_arg_tys
result_ty = mkTyConApp tycon (mkTyVarTys tyvars)
-- we can't conjure it up out of thin air
= sel_id
where
- sel_id = mkId (fieldLabelName field_label) selector_ty info
-
+ sel_id = mkGlobalId (RecordSelId field_label) (fieldLabelName field_label) selector_ty info
field_ty = fieldLabelType field_label
data_cons = tyConDataCons tycon
tyvars = tyConTyVars tycon -- These scope over the types in
-- the FieldLabels of constructors of this type
- tycon_theta = tyConTheta tycon -- The context on the data decl
- -- eg data (Eq a, Ord b) => T a b = ...
- (field_tyvars,field_tau) = splitForAllTys field_ty
-
data_ty = mkTyConApp tycon tyvar_tys
tyvar_tys = mkTyVarTys tyvars
+ 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 [ pred `elem` (dataConTheta dc)
+ | (DataAlt dc, _, _) <- the_alts]
+ n_dict_tys = length dict_tys
+
+ (field_tyvars,field_theta,field_tau) = splitSigmaTy field_ty
+ field_dict_tys = map mkPredTy field_theta
+ n_field_dict_tys = length field_dict_tys
+ -- If the field has a universally quantified type we have to
+ -- be a bit careful. Suppose we have
+ -- data R = R { op :: forall a. Foo a => a -> a }
+ -- Then we can't give op the type
+ -- op :: R -> forall a. Foo a => a -> a
+ -- because the typechecker doesn't understand foralls to the
+ -- right of an arrow. The "right" type to give it is
+ -- op :: forall a. Foo a => R -> a -> a
+ -- But then we must generate the right unfolding too:
+ -- op = /\a -> \dfoo -> \ r ->
+ -- case r of
+ -- R op -> op a dfoo
+ -- 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
- dict_tys = [mkDictTy cls tys | (cls, tys) <- tycon_theta, needed_dict (cls, tys)]
- needed_dict pred = or [ pred `elem` (dataConTheta dc)
- | (DataAlt dc, _, _) <- the_alts]
selector_ty :: Type
selector_ty = mkForAllTys tyvars $ mkForAllTys field_tyvars $
- mkFunTys dict_tys $ mkFunTy data_ty field_tau
+ mkFunTys dict_tys $ mkFunTys field_dict_tys $
+ mkFunTy data_ty field_tau
- info = mkIdInfo (RecordSelId field_label)
- `setArityInfo` exactArity (1 + length dict_tys)
+ arity = 1 + n_dict_tys + n_field_dict_tys
+ info = noCafNoTyGenIdInfo
+ `setCgInfo` (CgInfo arity caf_info)
+ `setArityInfo` exactArity arity
`setUnfoldingInfo` unfolding
- `setCafInfo` NoCafRefs
-- ToDo: consider adding further IdInfo
unfolding = mkTopUnfolding sel_rhs
-
- (data_id:dict_ids) = mkTemplateLocals (data_ty:dict_tys)
+ -- 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
+ -- rather than n_dict_tys, because the latter gives an infinite loop:
+ -- n_dict tys depends on the_alts, which depens on arg_ids, which depends
+ -- on arity, which depends on n_dict tys. Sigh! Mega sigh!
+ field_dict_base = length tycon_theta + 1
+ dict_id_base = field_dict_base + n_field_dict_tys
+ field_base = dict_id_base + 1
+ dict_ids = mkTemplateLocalsNum 1 dict_tys
+ field_dict_ids = mkTemplateLocalsNum field_dict_base field_dict_tys
+ data_id = mkTemplateLocal dict_id_base data_ty
+
alts = map mk_maybe_alt data_cons
the_alts = catMaybes alts
- default_alt | all isJust alts = [] -- No default needed
- | otherwise = [(DEFAULT, [], error_expr)]
- sel_rhs = mkLams tyvars $ mkLams field_tyvars $
- mkLams dict_ids $ Lam data_id $
- sel_body
+ no_default = all isJust alts -- No default needed
+ default_alt | no_default = []
+ | otherwise = [(DEFAULT, [], error_expr)]
- sel_body | isNewTyCon tycon = Note (Coerce (unUsgTy field_tau) (unUsgTy data_ty)) (Var data_id)
+ -- the default branch may have CAF refs, because it calls recSelError etc.
+ caf_info | no_default = NoCafRefs
+ | otherwise = MayHaveCafRefs
+
+ sel_rhs = mkLams tyvars $ mkLams field_tyvars $
+ mkLams dict_ids $ mkLams field_dict_ids $
+ Lam data_id $ sel_body
+
+ sel_body | isNewTyCon tycon = Note (Coerce field_tau data_ty) (Var data_id)
| otherwise = Case (Var data_id) data_id (the_alts ++ default_alt)
mk_maybe_alt data_con
Nothing -> Nothing
Just the_arg_id -> Just (DataAlt data_con, real_args, expr)
where
- body = mkVarApps (Var the_arg_id) field_tyvars
+ body = mkVarApps (mkVarApps (Var the_arg_id) field_tyvars) field_dict_ids
strict_marks = dataConStrictMarks data_con
(expr, real_args) = rebuildConArgs data_con arg_ids strict_marks body
- (length arg_ids + 1)
+ unpack_base
where
- arg_ids = mkTemplateLocals (dataConInstOrigArgTys data_con tyvar_tys)
- -- The first one will shadow data_id, but who cares
+ arg_ids = mkTemplateLocalsNum field_base (dataConInstOrigArgTys data_con tyvar_tys)
+
+ unpack_base = field_base + length arg_ids
+
+ -- 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 (unUsgTy field_tau), err_string]
- -- preserves invariant that type args are *not* usage-annotated on top. KSW 1999-04.
+ 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)))
= sel_id
where
ty = exprType rhs
- sel_id = mkId name ty info
+ sel_id = mkGlobalId (RecordSelId field_lbl) name ty info
field_lbl = mkFieldLabel name tycon ty tag
tag = assoc "MkId.mkDictSelId" (classSelIds clas `zip` allFieldLabelTags) sel_id
- info = mkIdInfo (RecordSelId field_lbl)
+ info = noCafNoTyGenIdInfo
+ `setCgArity` 1
`setArityInfo` exactArity 1
`setUnfoldingInfo` unfolding
- `setCafInfo` NoCafRefs
-- We no longer use 'must-inline' on record selectors. They'll
-- inline like crazy if they scrutinise a constructor
where
(tyvars,arg_tys,res_ty, arity, strict_info) = primOpSig prim_op
ty = mkForAllTys tyvars (mkFunTys arg_tys res_ty)
- name = mkPrimOpIdName prim_op id
- id = mkId name ty info
+ name = mkPrimOpIdName prim_op
+ id = mkGlobalId (PrimOpId prim_op) name ty info
- info = mkIdInfo (PrimOpId prim_op)
+ info = noCafNoTyGenIdInfo
`setSpecInfo` rules
+ `setCgArity` arity
`setArityInfo` exactArity arity
`setStrictnessInfo` strict_info
- rules = addRule id emptyCoreRules (primOpRule prim_op)
+ rules = maybe emptyCoreRules (addRule emptyCoreRules id)
+ (primOpRule prim_op)
-- For each ccall we manufacture a separate CCallOpId, giving it
= ASSERT( isEmptyVarSet (tyVarsOfType ty) )
-- A CCallOpId should have no free type variables;
-- when doing substitutions won't substitute over it
- mkId name ty info
+ mkGlobalId (PrimOpId prim_op) name ty info
where
occ_str = showSDocIface (braces (pprCCallOp ccall <+> ppr ty))
-- The "occurrence name" of a ccall is the full info about the
name = mkCCallName uniq occ_str
prim_op = CCallOp ccall
- info = mkIdInfo (PrimOpId prim_op)
+ info = noCafNoTyGenIdInfo
+ `setCgArity` arity
`setArityInfo` exactArity arity
`setStrictnessInfo` strict_info
%************************************************************************
%* *
-\subsection{DictFuns}
+\subsection{DictFuns and default methods}
%* *
%************************************************************************
\begin{code}
+mkDefaultMethodId dm_name ty
+ = mkVanillaGlobal dm_name ty noCafNoTyGenIdInfo
+
mkDictFunId :: Name -- Name to use for the dict fun;
-> Class
-> [TyVar]
-> Id
mkDictFunId dfun_name clas inst_tyvars inst_tys dfun_theta
- = mkVanillaId dfun_name dfun_ty
+ = mkVanillaGlobal dfun_name dfun_ty noCafNoTyGenIdInfo
where
dfun_ty = mkSigmaTy inst_tyvars dfun_theta (mkDictTy clas inst_tys)
unsafeCoerceId
= pcMiscPrelId unsafeCoerceIdKey pREL_GHC SLIT("unsafeCoerce#") ty info
where
- info = vanillaIdInfo
- `setUnfoldingInfo` mkCompulsoryUnfolding rhs
+ info = noCafNoTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
ty = mkForAllTys [openAlphaTyVar,openBetaTyVar]
getTagId
= pcMiscPrelId getTagIdKey pREL_GHC SLIT("getTag#") ty info
where
- info = vanillaIdInfo
- `setUnfoldingInfo` mkCompulsoryUnfolding rhs
+ info = noCafNoTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
-- We don't provide a defn for this; you must inline it
ty = mkForAllTys [alphaTyVar] (mkFunTy alphaTy intPrimTy)
realWorldPrimId -- :: State# RealWorld
= pcMiscPrelId realWorldPrimIdKey pREL_GHC SLIT("realWorld#")
realWorldStatePrimTy
- (noCafIdInfo `setUnfoldingInfo` mkOtherCon [])
+ (noCafNoTyGenIdInfo `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
pAR_ERROR_ID
= pcMiscPrelId parErrorIdKey pREL_ERR SLIT("parError")
- (mkSigmaTy [openAlphaTyVar] [] openAlphaTy) noCafIdInfo
-
+ (mkSigmaTy [openAlphaTyVar] [] openAlphaTy) noCafNoTyGenIdInfo
\end{code}
pcMiscPrelId :: Unique{-IdKey-} -> Module -> FAST_STRING -> Type -> IdInfo -> Id
pcMiscPrelId key mod str ty info
= let
- name = mkWiredInIdName key mod (mkSrcVarOcc str) imp
- imp = mkId name ty info -- the usual case...
+ name = mkWiredInName mod (mkVarOcc str) key
+ imp = mkVanillaGlobal name ty info -- the usual case...
in
imp
-- We lie and say the thing is imported; otherwise, we get into
pc_bottoming_Id key mod name ty
= pcMiscPrelId key mod name ty bottoming_info
where
- bottoming_info = noCafIdInfo
+ bottoming_info = noCafNoTyGenIdInfo
`setStrictnessInfo` mkStrictnessInfo ([wwStrict], True)
-
+
-- these "bottom" out, no matter what their arguments
generic_ERROR_ID u n = pc_bottoming_Id u pREL_ERR n errorTy
--- Very useful...
-noCafIdInfo = vanillaIdInfo `setCafInfo` NoCafRefs
-
(openAlphaTyVar:openBetaTyVar:_) = openAlphaTyVars
openAlphaTy = mkTyVarTy openAlphaTyVar
openBetaTy = mkTyVarTy openBetaTyVar
errorTy :: Type
-errorTy = mkUsgTy UsMany $
- mkSigmaTy [openAlphaTyVar] [] (mkFunTys [mkUsgTy UsOnce (mkListTy charTy)]
- (mkUsgTy UsMany openAlphaTy))
+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.