import PrelRules ( primOpRule )
import Rules ( addRule )
import Type ( Type, ThetaType, mkDictTy, mkDictTys, mkTyConApp, mkTyVarTys,
- mkFunTys, mkFunTy, mkSigmaTy,
+ mkFunTys, mkFunTy, mkSigmaTy, splitSigmaTy,
isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType,
- splitFunTys, splitForAllTys
+ splitFunTys, splitForAllTys, mkPredTy
)
import Module ( Module )
import CoreUtils ( exprType, mkInlineMe )
import CoreUnfold ( mkTopUnfolding, mkCompulsoryUnfolding, mkOtherCon )
import Literal ( Literal(..) )
import TyCon ( TyCon, isNewTyCon, tyConTyVars, tyConDataCons,
- tyConTheta, isProductTyCon, isUnboxedTupleTyCon )
+ tyConTheta, isProductTyCon, isDataTyCon )
import Class ( Class, classTyCon, classTyVars, classSelIds )
import Var ( Id, TyVar )
import VarSet ( isEmptyVarSet )
-import Name ( mkDerivedName, mkWiredInName, mkLocalName,
+import Name ( mkWiredInName, mkLocalName,
mkWorkerOcc, mkCCallName,
- Name, NamedThing(..),
+ Name, NamedThing(..), getSrcLoc
)
import OccName ( mkVarOcc )
import PrimOp ( PrimOp(DataToTagOp, CCallOp),
maybeMarkedUnboxed, splitProductType_maybe
)
import Id ( idType, mkId,
- mkVanillaId, mkTemplateLocals,
+ mkVanillaId, mkTemplateLocals, mkTemplateLocalsNum,
mkTemplateLocal, idCprInfo
)
-import IdInfo ( IdInfo, vanillaIdInfo, mkIdInfo,
+import IdInfo ( IdInfo, constantIdInfo, mkIdInfo,
exactArity, setUnfoldingInfo, setCafInfo, setCprInfo,
setArityInfo, setSpecInfo, setTyGenInfo,
mkStrictnessInfo, setStrictnessInfo,
\begin{code}
mkSpecPragmaId occ uniq ty loc
- = mkId (mkLocalName uniq occ loc) ty (mkIdInfo SpecPragmaId)
+ = mkId (mkLocalName uniq occ loc) ty (mkIdInfo SpecPragmaId NoCafRefs)
-- Maybe a SysLocal? But then we'd lose the location
mkDefaultMethodId dm_name rec_c ty
= mkId dm_name ty info
where
- info = vanillaIdInfo `setTyGenInfo` TyGenNever
+ info = constantIdInfo `setTyGenInfo` TyGenNever
-- type is wired-in (see comment at TcClassDcl.tcClassSig), so
-- do not generalise it
+mkWorkerId :: Unique -> Id -> Type -> Id
+-- A worker gets a local name. CoreTidy will globalise it if necessary.
mkWorkerId uniq unwrkr ty
- = mkVanillaId (mkDerivedName mkWorkerOcc (getName unwrkr) uniq) ty
+ = mkVanillaId wkr_name ty
+ where
+ wkr_name = mkLocalName uniq (mkWorkerOcc (getOccName unwrkr)) (getSrcLoc unwrkr)
\end{code}
%************************************************************************
mkDataConId work_name data_con
= mkId work_name (dataConRepType data_con) info
where
- info = mkIdInfo (DataConId data_con)
+ info = mkIdInfo (DataConId data_con) NoCafRefs
`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 = ReturnsCPR
+ | otherwise = NoCPRInfo
+ -- ReturnsCPR is only true for products that are real data types;
+ -- that is, not unboxed tuples or newtypes
\end{code}
The wrapper for a constructor is an ordinary top-level binding that evaluates
wrap_id = mkId (dataConName data_con) wrap_ty info
work_id = dataConId data_con
- info = mkIdInfo (DataConWrapId data_con)
+ info = mkIdInfo (DataConWrapId data_con) NoCafRefs
`setUnfoldingInfo` mkTopUnfolding (mkInlineMe wrap_rhs)
`setCprInfo` cpr_info
-- The Cpr info can be important inside INLINE rhss, where the
`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
`setTyGenInfo` TyGenNever
-- No point generalising its type, since it gets eagerly inlined
-- away anyway
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 = [mkDictTy cls tys | (cls, tys) <- tycon_theta,
+ needed_dict (cls, tys)]
+ 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 => a -> a
+ -- But then we must generat 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 = mkIdInfo (RecordSelId field_label) NoCafRefs
+ `setArityInfo` exactArity arity
`setUnfoldingInfo` unfolding
- `setCafInfo` NoCafRefs
`setTyGenInfo` TyGenNever
-- 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
+ dict_ids = mkTemplateLocalsNum 1 dict_tys
+ field_dict_ids = mkTemplateLocalsNum (n_dict_tys+1) field_dict_tys
+ data_id = mkTemplateLocal arity 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
+ 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)
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)
+ (length arg_ids + 1)
where
- arg_ids = mkTemplateLocals (dataConInstOrigArgTys data_con tyvar_tys)
- -- The first one will shadow data_id, but who cares
+ arg_ids = mkTemplateLocalsNum (arity+1) (dataConInstOrigArgTys data_con tyvar_tys)
+ -- arity+1 avoids all shadowing
maybe_the_arg_id = assocMaybe (field_lbls `zip` arg_ids) field_label
field_lbls = dataConFieldLabels data_con
field_lbl = mkFieldLabel name tycon ty tag
tag = assoc "MkId.mkDictSelId" (classSelIds clas `zip` allFieldLabelTags) sel_id
- info = mkIdInfo (RecordSelId field_lbl)
+ info = mkIdInfo (RecordSelId field_lbl) NoCafRefs
`setArityInfo` exactArity 1
`setUnfoldingInfo` unfolding
- `setCafInfo` NoCafRefs
`setTyGenInfo` TyGenNever
-- We no longer use 'must-inline' on record selectors. They'll
name = mkPrimOpIdName prim_op
id = mkId name ty info
- info = mkIdInfo (PrimOpId prim_op)
+ info = mkIdInfo (PrimOpId prim_op) NoCafRefs
`setSpecInfo` rules
`setArityInfo` exactArity arity
`setStrictnessInfo` strict_info
name = mkCCallName uniq occ_str
prim_op = CCallOp ccall
- info = mkIdInfo (PrimOpId prim_op)
+ info = mkIdInfo (PrimOpId prim_op) NoCafRefs
`setArityInfo` exactArity arity
`setStrictnessInfo` strict_info
= mkId dfun_name dfun_ty info
where
dfun_ty = mkSigmaTy inst_tyvars dfun_theta (mkDictTy clas inst_tys)
- info = vanillaIdInfo `setTyGenInfo` TyGenNever
+ info = mkIdInfo DictFunId MayHaveCafRefs
+ `setTyGenInfo` TyGenNever
-- type is wired-in (see comment at TcClassDcl.tcClassSig), so
-- do not generalise it
+ -- An imported dfun may refer to CAFs, so we assume the worst
{- 1 dec 99: disable the Mark Jones optimisation for the sake
of compatibility with Hugs.
unsafeCoerceId
= pcMiscPrelId unsafeCoerceIdKey pREL_GHC SLIT("unsafeCoerce#") ty info
where
- info = vanillaIdInfo
- `setUnfoldingInfo` mkCompulsoryUnfolding rhs
+ info = constantIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
ty = mkForAllTys [openAlphaTyVar,openBetaTyVar]
getTagId
= pcMiscPrelId getTagIdKey pREL_GHC SLIT("getTag#") ty info
where
- info = vanillaIdInfo
+ info = constantIdInfo
`setUnfoldingInfo` mkCompulsoryUnfolding rhs
-- We don't provide a defn for this; you must inline it
generic_ERROR_ID u n = pc_bottoming_Id u pREL_ERR n errorTy
-- Very useful...
-noCafIdInfo = vanillaIdInfo `setCafInfo` NoCafRefs
+noCafIdInfo = constantIdInfo `setCafInfo` NoCafRefs
(openAlphaTyVar:openBetaTyVar:_) = openAlphaTyVars
openAlphaTy = mkTyVarTy openAlphaTyVar