%
-% (c) The AQUA Project, Glasgow University, 1994-1996
+% (c) The AQUA Project, Glasgow University, 1998
%
\section[StdIdInfo]{Standard unfoldings}
\begin{code}
module MkId (
- mkImportedId,
- mkUserId,
- mkUserLocal, mkSysLocal,
- mkSpecPragmaId,
+ mkSpecPragmaId, mkWorkerId,
- mkDataCon, mkTupleCon,
-
- mkDictFunId,
- mkMethodSelId, mkSuperDictSelId, mkDefaultMethodId,
+ mkDictFunId, mkDefaultMethodId,
+ mkDictSelId,
+ mkDataConId, mkDataConWrapId,
mkRecordSelId,
-
- mkPrimitiveId,
- mkWorkerId
-
+ mkPrimOpId, mkCCallOpId,
+
+ -- And some particular Ids; see below for why they are wired in
+ wiredInIds,
+ unsafeCoerceId, realWorldPrimId,
+ eRROR_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
) where
#include "HsVersions.h"
-import {-# SOURCE #-} CoreUnfold ( mkUnfolding )
-import Type
-import CoreSyn
-import Literal
-import TysWiredIn ( tupleCon )
-import Name ( mkLocalName, mkSysLocalName, mkCompoundName,
- occNameString, Name, OccName, NamedThing(..)
+import TysPrim ( openAlphaTyVars, alphaTyVar, alphaTy,
+ intPrimTy, realWorldStatePrimTy
+ )
+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,
+ isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType,
+ splitFunTys, splitForAllTys
+ )
+import Module ( Module )
+import CoreUtils ( exprType, mkInlineMe )
+import CoreUnfold ( mkTopUnfolding, mkCompulsoryUnfolding, mkOtherCon )
+import Literal ( Literal(..) )
+import TyCon ( TyCon, isNewTyCon, tyConTyVars, tyConDataCons,
+ tyConTheta, isProductTyCon, isDataTyCon )
+import Class ( Class, classTyCon, classTyVars, classSelIds )
+import Var ( Id, TyVar )
+import VarSet ( isEmptyVarSet )
+import Name ( mkWiredInName, mkLocalName,
+ mkWorkerOcc, mkCCallName,
+ Name, NamedThing(..), getSrcLoc
+ )
+import OccName ( mkVarOcc )
+import PrimOp ( PrimOp(DataToTagOp, CCallOp),
+ primOpSig, mkPrimOpIdName,
+ CCall, pprCCallOp
)
-import Id ( idType, fIRST_TAG,
- mkTemplateLocals, mkId, mkVanillaId,
- dataConStrictMarks, dataConFieldLabels, dataConArgTys,
- recordSelectorFieldLabel, dataConSig,
- StrictnessMark(..),
- Id, IdDetails(..), GenId
+import Demand ( wwStrict, wwPrim, mkStrictnessInfo )
+import DataCon ( DataCon, StrictnessMark(..),
+ dataConFieldLabels, dataConRepArity, dataConTyCon,
+ dataConArgTys, dataConRepType, dataConRepStrictness,
+ dataConInstOrigArgTys,
+ dataConName, dataConTheta,
+ dataConSig, dataConStrictMarks, dataConId,
+ maybeMarkedUnboxed, splitProductType_maybe
)
-import IdInfo ( noIdInfo,
- exactArity, setUnfoldingInfo,
- setArityInfo, setInlinePragInfo,
- InlinePragInfo(..), IdInfo
+import Id ( idType, mkId,
+ mkVanillaId, mkTemplateLocals,
+ mkTemplateLocal, idCprInfo
)
-import Class ( Class, classBigSig, classTyCon )
-import FieldLabel ( FieldLabel, FieldLabelTag, mkFieldLabel, fieldLabelName,
- firstFieldLabelTag, allFieldLabelTags
+import IdInfo ( IdInfo, constantIdInfo, mkIdInfo,
+ exactArity, setUnfoldingInfo, setCafInfo, setCprInfo,
+ setArityInfo, setSpecInfo, setTyGenInfo,
+ mkStrictnessInfo, setStrictnessInfo,
+ IdFlavour(..), CafInfo(..), CprInfo(..), TyGenInfo(..)
)
-import TyVar ( TyVar )
-import TyCon ( TyCon, isNewTyCon, tyConDataCons, isDataTyCon )
-import PrelVals ( rEC_SEL_ERROR_ID )
+import FieldLabel ( mkFieldLabel, fieldLabelName,
+ firstFieldLabelTag, allFieldLabelTags, fieldLabelType
+ )
+import CoreSyn
import Maybes
-import SrcLoc ( SrcLoc )
-import BasicTypes ( Arity )
-import Unique ( Unique )
+import PrelNames
import Maybe ( isJust )
import Outputable
-import Util ( assoc )
+import ListSetOps ( assoc, assocMaybe )
+import UnicodeUtil ( stringToUtf8 )
+import Char ( ord )
\end{code}
%************************************************************************
%* *
-\subsection{Easy ones}
+\subsection{Wired in Ids}
%* *
%************************************************************************
\begin{code}
-mkImportedId :: Name -> ty -> IdInfo -> GenId ty
-mkImportedId name ty info = mkId name ty (VanillaId True) info
-
--- SysLocal: for an Id being created by the compiler out of thin air...
--- UserLocal: an Id with a name the user might recognize...
-mkSysLocal :: FAST_STRING -> Unique -> (GenType flexi) -> SrcLoc -> GenId (GenType flexi)
-mkUserLocal :: OccName -> Unique -> (GenType flexi) -> SrcLoc -> GenId (GenType flexi)
-
-mkSysLocal str uniq ty loc
- = mkVanillaId (mkSysLocalName uniq str loc) ty noIdInfo
+wiredInIds
+ = [ -- These error-y things are wired in because we don't yet have
+ -- a way to express in an interface file that the result type variable
+ -- is 'open'; that is can be unified with an unboxed type
+ --
+ -- [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
+ , 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 two can't be defined in Haskell
+ , realWorldPrimId
+ , unsafeCoerceId
+ , getTagId
+ ]
+\end{code}
-mkUserLocal occ uniq ty loc
- = mkVanillaId (mkLocalName uniq occ loc) ty noIdInfo
+%************************************************************************
+%* *
+\subsection{Easy ones}
+%* *
+%************************************************************************
+\begin{code}
mkSpecPragmaId occ uniq ty loc
- = mkId (mkLocalName uniq occ loc) ty SpecPragmaId noIdInfo
-
-mkUserId :: Name -> GenType flexi -> GenId (GenType flexi)
-mkUserId name ty
- = mkVanillaId name ty noIdInfo
+ = 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
- = mkVanillaId dm_name ty noIdInfo
-
-mkDictFunId dfun_name full_ty clas itys
- = mkVanillaId dfun_name full_ty noIdInfo
-
-mkWorkerId uniq unwrkr ty info
- = mkVanillaId name ty info
+ = mkId dm_name ty info
+ where
+ 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 wkr_name ty
where
- name = mkCompoundName name_fn uniq (getName unwrkr)
- name_fn wkr_str = SLIT("$w") _APPEND_ wkr_str
+ wkr_name = mkLocalName uniq (mkWorkerOcc (getOccName unwrkr)) (getSrcLoc unwrkr)
\end{code}
-
%************************************************************************
%* *
\subsection{Data constructors}
%************************************************************************
\begin{code}
-mkDataCon :: Name
- -> [StrictnessMark] -> [FieldLabel]
- -> [TyVar] -> ThetaType
- -> [TyVar] -> ThetaType
- -> [TauType] -> TyCon
- -> Id
- -- can get the tag and all the pieces of the type from the Type
-
-mkDataCon name stricts fields tvs ctxt con_tvs con_ctxt args_tys tycon
- = ASSERT(length stricts == length args_tys)
- data_con
- where
- -- NB: data_con self-recursion; should be OK as tags are not
- -- looked at until late in the game.
- data_con = mkId name data_con_ty details (dataConInfo data_con)
- details = AlgConId data_con_tag stricts fields tvs ctxt con_tvs con_ctxt args_tys tycon
-
- data_con_tag = assoc "mkDataCon" (data_con_family `zip` [fIRST_TAG..]) data_con
- data_con_family = tyConDataCons tycon
- data_con_ty = mkSigmaTy (tvs++con_tvs) (ctxt++con_ctxt)
- (mkFunTys args_tys (mkTyConApp tycon (mkTyVarTys tvs)))
-
-
-mkTupleCon :: Arity -> Name -> Type -> Id
-mkTupleCon arity name ty
- = con_id
+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
+ = mkId work_name (dataConRepType data_con) info
where
- con_id = mkId name ty (TupleConId arity) (dataConInfo con_id)
+ info = mkIdInfo (DataConId data_con) NoCafRefs
+ `setArityInfo` exactArity arity
+ `setStrictnessInfo` strict_info
+ `setCprInfo` cpr_info
+
+ arity = dataConRepArity data_con
+
+ strict_info = mkStrictnessInfo (dataConRepStrictness data_con, False)
+
+ tycon = dataConTyCon data_con
+ cpr_info | isProductTyCon tycon &&
+ 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
+any strict args, unboxes any args that are going to be flattened, and calls
+the worker.
+
We're going to build a constructor that looks like:
data (Data a, C b) => T a b = T1 !a !Int b
* We have to check that we can construct Data dictionaries for
the types a and Int. Once we've done that we can throw d1 away too.
-* We use (case p of ...) to evaluate p, rather than "seq" because
+* We use (case p of q -> ...) to evaluate p, rather than "seq" because
all that matters is that the arguments are evaluated. "seq" is
very careful to preserve evaluation order, which we don't need
to be here.
+ You might think that we could simply give constructors some strictness
+ info, like PrimOps, and let CoreToStg do the let-to-case transformation.
+ But we don't do that because in the case of primops and functions strictness
+ is a *property* not a *requirement*. In the case of constructors we need to
+ do something active to evaluate the argument.
+
+ Making an explicit case expression allows the simplifier to eliminate
+ it in the (common) case where the constructor arg is already evaluated.
+
\begin{code}
-dataConInfo :: Id -> IdInfo
-
-dataConInfo con_id
- = setInlinePragInfo IWantToBeINLINEd $
- -- Always inline constructors if possible
- setArityInfo (exactArity (length locals)) $
- setUnfoldingInfo unfolding $
- noIdInfo
+mkDataConWrapId data_con
+ = wrap_id
where
- unfolding = mkUnfolding con_rhs
-
- (tyvars, theta, con_tyvars, con_theta, arg_tys, tycon) = dataConSig con_id
-
- dict_tys = [mkDictTy clas tys | (clas,tys) <- theta]
- con_dict_tys = [mkDictTy clas tys | (clas,tys) <- con_theta]
- n_dicts = length dict_tys
- result_ty = mkTyConApp tycon (mkTyVarTys tyvars)
-
- locals = mkTemplateLocals (dict_tys ++ con_dict_tys ++ arg_tys)
- data_args = drop n_dicts locals
- (data_arg1:_) = data_args -- Used for newtype only
- strict_marks = dataConStrictMarks con_id
- strict_args = [arg | (arg,MarkedStrict) <- data_args `zip` strict_marks]
- -- NB: we can't call mkTemplateLocals twice, because it
- -- always starts from the same unique.
-
- con_app | isNewTyCon tycon
- = ASSERT( length arg_tys == 1)
- Note (Coerce result_ty (head arg_tys)) (Var data_arg1)
- | otherwise
- = Con con_id (map TyArg (mkTyVarTys tyvars) ++ map VarArg data_args)
-
- con_rhs = mkTyLam tyvars $
- mkValLam locals $
- foldr mk_case con_app strict_args
-
- mk_case arg body | isUnpointedType (idType arg)
- = body -- "!" on unboxed arg does nothing
- | otherwise
- = Case (Var arg) (AlgAlts [] (BindDefault arg body))
- -- This case shadows "arg" but that's fine
+ wrap_id = mkId (dataConName data_con) wrap_ty info
+ work_id = dataConId 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
+ -- wrapper constructor isn't inlined
+ `setArityInfo` exactArity arity
+ -- It's important to specify the arity, so that partial
+ -- applications are treated as values
+ `setTyGenInfo` TyGenNever
+ -- No point generalising its type, since it gets eagerly inlined
+ -- away anyway
+
+ wrap_ty = mkForAllTys all_tyvars $
+ mkFunTys all_arg_tys
+ result_ty
+
+ cpr_info = idCprInfo work_id
+
+ wrap_rhs | isNewTyCon tycon
+ = ASSERT( null ex_tyvars && null ex_dict_args && length orig_arg_tys == 1 )
+ -- 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 $
+ Note (Coerce result_ty (head orig_arg_tys)) (Var id_arg1)
+
+ | null dict_args && all not_marked_strict 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.)
+ --
+ -- 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.
+ -- 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 $
+ 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
+ all_tyvars = tyvars ++ ex_tyvars
+
+ dict_tys = mkDictTys theta
+ ex_dict_tys = mkDictTys ex_theta
+ all_arg_tys = dict_tys ++ ex_dict_tys ++ orig_arg_tys
+ result_ty = mkTyConApp tycon (mkTyVarTys tyvars)
+
+ 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
+ (id_args,i3) = mkLocals i2 orig_arg_tys
+ arity = i3-1
+ (id_arg1:_) = id_args -- Used for newtype only
+
+ strict_marks = dataConStrictMarks data_con
+ not_marked_strict NotMarkedStrict = True
+ not_marked_strict other = False
+
+
+ mk_case
+ :: (Id, StrictnessMark) -- arg, strictness
+ -> (Int -> [Id] -> CoreExpr) -- body
+ -> Int -- next rep arg id
+ -> [Id] -- rep args so far
+ -> CoreExpr
+ mk_case (arg,strict) body i rep_args
+ = case strict of
+ NotMarkedStrict -> body i (arg:rep_args)
+ MarkedStrict
+ | isUnLiftedType (idType arg) -> body i (arg:rep_args)
+ | otherwise ->
+ Case (Var arg) arg [(DEFAULT,[], body i (arg:rep_args))]
+
+ MarkedUnboxed con tys ->
+ Case (Var arg) arg [(DataAlt con, con_args,
+ body i' (reverse con_args++rep_args))]
+ where
+ (con_args,i') = mkLocals i tys
\end{code}
T2 ... x ... -> x
other -> error "..."
+Similarly for newtypes
+
+ newtype N a = MkN { unN :: a->a }
+
+ unN :: N a -> a -> a
+ unN n = coerce (a->a) n
+
+We need to take a little care if the field has a polymorphic type:
+
+ data R = R { f :: forall a. a->a }
+
+Then we want
+
+ f :: forall a. R -> a -> a
+ f = /\ a \ r = case r of
+ R f -> f a
+
+(not f :: R -> forall a. a->a, which gives the type inference mechanism
+problems at call sites)
+
+Similarly for newtypes
+
+ newtype N = MkN { unN :: forall a. a->a }
+
+ unN :: forall a. N -> a -> a
+ unN = /\a -> \n:N -> coerce (a->a) n
+
\begin{code}
-mkRecordSelId field_label selector_ty
- = ASSERT( null theta && isDataTyCon tycon )
- sel_id
+mkRecordSelId tycon field_label unpack_id unpackUtf8_id
+ -- 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 = mkId (fieldLabelName field_label) selector_ty
- (RecordSelId field_label) info
-
- info = exactArity 1 `setArityInfo` (
- unfolding `setUnfoldingInfo`
- noIdInfo)
+ sel_id = mkId (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
+
+ -- 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
+
+ info = mkIdInfo (RecordSelId field_label) NoCafRefs
+ `setArityInfo` exactArity (1 + length dict_tys)
+ `setUnfoldingInfo` unfolding
+ `setTyGenInfo` TyGenNever
-- ToDo: consider adding further IdInfo
- unfolding = mkUnfolding sel_rhs
+ unfolding = mkTopUnfolding sel_rhs
- (tyvars, theta, tau) = splitSigmaTy selector_ty
- (data_ty,rhs_ty) = expectJust "StdIdInfoRec" (splitFunTy_maybe tau)
- -- tau is of form (T a b c -> field-type)
- (tycon, _, data_cons) = splitAlgTyConApp data_ty
- tyvar_tys = mkTyVarTys tyvars
- [data_id] = mkTemplateLocals [data_ty]
+ (data_id:dict_ids) = mkTemplateLocals (data_ty:dict_tys)
alts = map mk_maybe_alt data_cons
- sel_rhs = mkTyLam tyvars $
- mkValLam [data_id] $
- Case (Var data_id)
- -- if any of the constructors don't have the label, ...
- (if any (not . isJust) alts then
- AlgAlts (catMaybes alts)
- (BindDefault data_id error_expr)
- else
- AlgAlts (catMaybes alts) NoDefault)
+ 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_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
= case maybe_the_arg_id of
Nothing -> Nothing
- Just the_arg_id -> Just (data_con, arg_ids, Var the_arg_id)
- where
- arg_ids = mkTemplateLocals (dataConArgTys data_con tyvar_tys)
+ Just the_arg_id -> Just (DataAlt data_con, real_args, expr)
+ where
+ body = mkVarApps (Var the_arg_id) field_tyvars
+ strict_marks = dataConStrictMarks data_con
+ (expr, real_args) = rebuildConArgs data_con arg_ids strict_marks body
+ (length arg_ids + 1)
+ where
+ arg_ids = mkTemplateLocals (dataConInstOrigArgTys data_con tyvar_tys)
-- The first one will shadow data_id, but who cares
- field_lbls = dataConFieldLabels data_con
- maybe_the_arg_id = assocMaybe (field_lbls `zip` arg_ids) field_label
-
- error_expr = mkApp (Var rEC_SEL_ERROR_ID) [rhs_ty] [LitArg msg_lit]
+ 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.
full_msg = showSDoc (sep [text "No match in record selector", ppr sel_id])
- msg_lit = NoRepStr (_PK_ full_msg)
+
+
+-- this rather ugly function converts the unpacked data con arguments back into
+-- their packed form. It is almost the same as the version in DsUtils, except that
+-- we use template locals here rather than newDsId (ToDo: merge these).
+
+rebuildConArgs
+ :: DataCon -- the con we're matching on
+ -> [Id] -- the source-level args
+ -> [StrictnessMark] -- the strictness annotations (per-arg)
+ -> CoreExpr -- the body
+ -> Int -- template local
+ -> (CoreExpr, [Id])
+
+rebuildConArgs con [] stricts body i = (body, [])
+rebuildConArgs con (arg:args) stricts body i | isTyVar arg
+ = let (body', args') = rebuildConArgs con args stricts body i
+ in (body',arg:args')
+rebuildConArgs con (arg:args) (str:stricts) body i
+ = case maybeMarkedUnboxed str of
+ Just (pack_con1, _) ->
+ case splitProductType_maybe (idType arg) of
+ Just (_, tycon_args, pack_con, con_arg_tys) ->
+ ASSERT( pack_con == pack_con1 )
+ let unpacked_args = zipWith mkTemplateLocal [i..] con_arg_tys
+ (body', real_args) = rebuildConArgs con args stricts body
+ (i + length con_arg_tys)
+ in
+ (
+ Let (NonRec arg (mkConApp pack_con
+ (map Type tycon_args ++
+ map Var unpacked_args))) body',
+ unpacked_args ++ real_args
+ )
+
+ _ -> let (body', args') = rebuildConArgs con args stricts body i
+ in (body', arg:args')
\end{code}
%* *
%************************************************************************
-\begin{code}
-mkSuperDictSelId :: Unique -> Class -> FieldLabelTag -> Type -> Id
- -- The FieldLabelTag says which superclass is selected
- -- So, for
- -- class (C a, C b) => Foo a b where ...
- -- we get superclass selectors
- -- Foo_sc1, Foo_sc2
-
-mkSuperDictSelId uniq clas index ty
- = mkDictSelId name clas ty
- where
- name = mkCompoundName name_fn uniq (getName clas)
- name_fn clas_str = clas_str _APPEND_ SLIT("_sc") _APPEND_ (_PK_ (show index))
-
- -- For method selectors the clean thing to do is
- -- to give the method selector the same name as the class op itself.
-mkMethodSelId name clas ty
- = mkDictSelId name clas ty
-\end{code}
-
Selecting a field for a dictionary. If there is just one field, then
-there's nothing to do.
+there's nothing to do.
+
+ToDo: unify with mkRecordSelId.
\begin{code}
-mkDictSelId name clas ty
+mkDictSelId :: Name -> Class -> Id
+mkDictSelId name clas
= sel_id
where
- sel_id = mkId name ty (RecordSelId field_lbl) info
- field_lbl = mkFieldLabel name ty tag
- tag = assoc "MkId.mkDictSelId" ((sc_sel_ids ++ op_sel_ids) `zip` allFieldLabelTags) sel_id
+ ty = exprType rhs
+ sel_id = mkId name ty info
+ field_lbl = mkFieldLabel name tycon ty tag
+ tag = assoc "MkId.mkDictSelId" (classSelIds clas `zip` allFieldLabelTags) sel_id
- info = setInlinePragInfo IWantToBeINLINEd $
- setUnfoldingInfo unfolding noIdInfo
- -- The always-inline thing means we don't need any other IdInfo
+ info = mkIdInfo (RecordSelId field_lbl) NoCafRefs
+ `setArityInfo` exactArity 1
+ `setUnfoldingInfo` unfolding
+ `setTyGenInfo` TyGenNever
+
+ -- We no longer use 'must-inline' on record selectors. They'll
+ -- inline like crazy if they scrutinise a constructor
- unfolding = mkUnfolding rhs
+ unfolding = mkTopUnfolding rhs
- (tyvars, _, sc_sel_ids, op_sel_ids, defms) = classBigSig clas
+ tyvars = classTyVars clas
tycon = classTyCon clas
[data_con] = tyConDataCons tycon
dict_ty = mkDictTy clas tyvar_tys
(dict_id:arg_ids) = mkTemplateLocals (dict_ty : arg_tys)
- rhs | isNewTyCon tycon = mkLam tyvars [dict_id] $
+ rhs | isNewTyCon tycon = mkLams tyvars $ Lam dict_id $
Note (Coerce (head arg_tys) dict_ty) (Var dict_id)
- | otherwise = mkLam tyvars [dict_id] $
- Case (Var dict_id) $
- AlgAlts [(data_con, arg_ids, Var the_arg_id)] NoDefault
+ | otherwise = mkLams tyvars $ Lam dict_id $
+ Case (Var dict_id) dict_id
+ [(DataAlt data_con, arg_ids, Var the_arg_id)]
\end{code}
%* *
%************************************************************************
+\begin{code}
+mkPrimOpId :: PrimOp -> Id
+mkPrimOpId prim_op
+ = id
+ 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 = mkId name ty info
+
+ info = mkIdInfo (PrimOpId prim_op) NoCafRefs
+ `setSpecInfo` rules
+ `setArityInfo` exactArity arity
+ `setStrictnessInfo` strict_info
+
+ rules = addRule emptyCoreRules id (primOpRule prim_op)
+
+
+-- For each ccall we manufacture a separate CCallOpId, giving it
+-- a fresh unique, a type that is correct for this particular ccall,
+-- and a CCall structure that gives the correct details about calling
+-- convention etc.
+--
+-- The *name* of this Id is a local name whose OccName gives the full
+-- details of the ccall, type and all. This means that the interface
+-- file reader can reconstruct a suitable Id
+
+mkCCallOpId :: Unique -> CCall -> Type -> Id
+mkCCallOpId uniq ccall ty
+ = ASSERT( isEmptyVarSet (tyVarsOfType ty) )
+ -- A CCallOpId should have no free type variables;
+ -- when doing substitutions won't substitute over it
+ mkId name ty info
+ where
+ occ_str = showSDocIface (braces (pprCCallOp ccall <+> 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 = mkCCallName uniq occ_str
+ prim_op = CCallOp ccall
+
+ info = mkIdInfo (PrimOpId prim_op) NoCafRefs
+ `setArityInfo` exactArity arity
+ `setStrictnessInfo` strict_info
+
+ (_, tau) = splitForAllTys ty
+ (arg_tys, _) = splitFunTys tau
+ arity = length arg_tys
+ strict_info = mkStrictnessInfo (take arity (repeat wwPrim), False)
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{DictFuns}
+%* *
+%************************************************************************
\begin{code}
-mkPrimitiveId name ty prim_op
- = mkId name ty (PrimitiveId prim_op) info
+mkDictFunId :: Name -- Name to use for the dict fun;
+ -> Class
+ -> [TyVar]
+ -> [Type]
+ -> ThetaType
+ -> Id
+
+mkDictFunId dfun_name clas inst_tyvars inst_tys dfun_theta
+ = mkId dfun_name dfun_ty info
where
+ dfun_ty = mkSigmaTy inst_tyvars dfun_theta (mkDictTy clas inst_tys)
+ 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.
+ See `types/InstEnv' for a discussion related to this.
+
+ (class_tyvars, sc_theta, _, _) = classBigSig clas
+ not_const (clas, tys) = not (isEmptyVarSet (tyVarsOfTypes tys))
+ sc_theta' = substClasses (mkTopTyVarSubst class_tyvars inst_tys) sc_theta
+ dfun_theta = case inst_decl_theta of
+ [] -> [] -- If inst_decl_theta is empty, then we don't
+ -- want to have any dict arguments, so that we can
+ -- expose the constant methods.
+
+ other -> nub (inst_decl_theta ++ filter not_const sc_theta')
+ -- Otherwise we pass the superclass dictionaries to
+ -- the dictionary function; the Mark Jones optimisation.
+ --
+ -- NOTE the "nub". I got caught by this one:
+ -- class Monad m => MonadT t m where ...
+ -- instance Monad m => MonadT (EnvT env) m where ...
+ -- Here, the inst_decl_theta has (Monad m); but so
+ -- does the sc_theta'!
+ --
+ -- NOTE the "not_const". I got caught by this one too:
+ -- class Foo a => Baz a b where ...
+ -- instance Wob b => Baz T b where..
+ -- Now sc_theta' has Foo T
+-}
+\end{code}
- info = setUnfoldingInfo unfolding $
- setInlinePragInfo IMustBeINLINEd $
- -- The pragma @IMustBeINLINEd@ says that this Id absolutely
- -- must be inlined. It's only used for primitives,
- -- because we don't want to make a closure for each of them.
- noIdInfo
- unfolding = mkUnfolding rhs
+%************************************************************************
+%* *
+\subsection{Un-definable}
+%* *
+%************************************************************************
+
+These two can't be defined in Haskell.
+
+unsafeCoerce# isn't so much a PrimOp as a phantom identifier, that
+just gets expanded into a type coercion wherever it occurs. Hence we
+add it as a built-in Id with an unfolding here.
- (tyvars, tau) = splitForAllTys ty
- (arg_tys, _) = splitFunTys tau
+The type variables we use here are "open" type variables: this means
+they can unify with both unlifted and lifted types. Hence we provide
+another gun with which to shoot yourself in the foot.
+
+\begin{code}
+unsafeCoerceId
+ = pcMiscPrelId unsafeCoerceIdKey pREL_GHC SLIT("unsafeCoerce#") ty info
+ where
+ info = constantIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
+
+
+ ty = mkForAllTys [openAlphaTyVar,openBetaTyVar]
+ (mkFunTy openAlphaTy openBetaTy)
+ [x] = mkTemplateLocals [openAlphaTy]
+ rhs = mkLams [openAlphaTyVar,openBetaTyVar,x] $
+ Note (Coerce openBetaTy openAlphaTy) (Var x)
+\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 pREL_GHC SLIT("getTag#") ty info
+ where
+ info = constantIdInfo
+ `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]) ]
+
+dataToTagId = mkPrimOpId DataToTagOp
+\end{code}
+
+@realWorld#@ used to be a magic literal, \tr{void#}. If things get
+nasty as-is, change it back to a literal (@Literal@).
+
+\begin{code}
+realWorldPrimId -- :: State# RealWorld
+ = pcMiscPrelId realWorldPrimIdKey pREL_GHC SLIT("realWorld#")
+ 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
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[PrelVals-error-related]{@error@ and friends; @trace@}
+%* *
+%************************************************************************
+
+GHC randomly injects these into the code.
+
+@patError@ is just a version of @error@ for pattern-matching
+failures. It knows various ``codes'' which expand to longer
+strings---this saves space!
+
+@absentErr@ is a thing we put in for ``absent'' arguments. They jolly
+well shouldn't be yanked on, but if one is, then you will get a
+friendly message from @absentErr@ (rather than a totally random
+crash).
+
+@parError@ is a special version of @error@ which the compiler does
+not know to be a bottoming Id. It is used in the @_par_@ and @_seq_@
+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
+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) noCafIdInfo
- args = mkTemplateLocals arg_tys
- rhs = mkLam tyvars args $
- Prim prim_op
- ([TyArg (mkTyVarTy tv) | tv <- tyvars] ++
- [VarArg v | v <- args])
\end{code}
%************************************************************************
%* *
-\subsection{Catch-all}
+\subsection{Utilities}
%* *
%************************************************************************
\begin{code}
-addStandardIdInfo id
- = pprTrace "addStandardIdInfo missing:" (ppr id) id
+pcMiscPrelId :: Unique{-IdKey-} -> Module -> FAST_STRING -> Type -> IdInfo -> Id
+pcMiscPrelId key mod str ty info
+ = let
+ name = mkWiredInName mod (mkVarOcc str) key
+ imp = mkId name ty info -- the usual case...
+ in
+ imp
+ -- 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
+ where
+ bottoming_info = noCafIdInfo
+ `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 = constantIdInfo `setCafInfo` NoCafRefs
+
+(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}