X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FbasicTypes%2FMkId.lhs;h=dae32dfeb5d14f9e4b6de22fefcc53fd6d60d2e8;hb=5cf73eab6ec5df0abe330e107cbe969d41e38d30;hp=669be86bdd6f833147c7bfc50c2c8bc649b1dec6;hpb=3160f854580e6d8df412c8cd34d93bae27175d67;p=ghc-hetmet.git diff --git a/ghc/compiler/basicTypes/MkId.lhs b/ghc/compiler/basicTypes/MkId.lhs index 669be86..dae32df 100644 --- a/ghc/compiler/basicTypes/MkId.lhs +++ b/ghc/compiler/basicTypes/MkId.lhs @@ -13,81 +13,117 @@ have a standard form, namely: \begin{code} module MkId ( - mkSpecPragmaId, mkWorkerId, - mkDictFunId, mkDefaultMethodId, - mkMethodSelId, mkSuperDictSelId, + mkDictSelId, - mkDataConId, + mkDataConId, mkDataConWrapId, mkRecordSelId, - mkNewTySelId, - mkPrimitiveId + 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 TysWiredIn ( boolTy ) -import Type ( Type, ThetaType, - mkDictTy, mkTyConApp, mkTyVarTys, mkFunTys, mkFunTy, mkSigmaTy, - isUnLiftedType, substTopTheta, - splitSigmaTy, splitFunTy_maybe, splitAlgTyConApp, - splitFunTys, splitForAllTys +import BasicTypes ( Arity ) +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, mkPredTys, mkTyConApp, mkTyVarTys, + mkFunTys, mkFunTy, mkSigmaTy, splitSigmaTy, + isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType, + splitFunTys, splitForAllTys, mkPredTy ) -import TyCon ( TyCon, isNewTyCon, tyConDataCons, isDataTyCon ) -import Class ( Class, classBigSig, classTyCon ) -import Var ( Id, TyVar, VarDetails(..), mkId ) -import VarEnv ( zipVarEnv ) -import Const ( Con(..) ) -import Name ( mkDerivedName, mkWiredInIdName, - mkWorkerOcc, mkSuperDictSelOcc, - Name, NamedThing(..), +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, mkCCallName, Name ) +import OccName ( mkVarOcc ) +import PrimOp ( PrimOp(DataToTagOp, CCallOp), + primOpSig, mkPrimOpIdName, + CCall, pprCCallOp ) -import PrimOp ( PrimOp, primOpType, primOpOcc, primOpUniq ) -import DataCon ( DataCon, dataConStrictMarks, dataConFieldLabels, - dataConArgTys, dataConSig +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 Id ( idType, - mkUserLocal, mkVanillaId, mkTemplateLocals, - setInlinePragma +import Id ( idType, mkGlobalId, mkVanillaGlobal, + mkTemplateLocals, mkTemplateLocalsNum, + mkTemplateLocal, idCprInfo ) -import IdInfo ( noIdInfo, - exactArity, setUnfoldingInfo, - setArityInfo, setInlinePragInfo, - InlinePragInfo(..), IdInfo +import IdInfo ( IdInfo, noCafNoTyGenIdInfo, + exactArity, setUnfoldingInfo, setCprInfo, + setArityInfo, setSpecInfo, setCgInfo, + mkStrictnessInfo, setStrictnessInfo, + GlobalIdDetails(..), CafInfo(..), CprInfo(..), + CgInfo(..), setCgArity ) -import FieldLabel ( FieldLabel, FieldLabelTag, mkFieldLabel, fieldLabelName, - firstFieldLabelTag, allFieldLabelTags +import FieldLabel ( mkFieldLabel, fieldLabelName, + firstFieldLabelTag, allFieldLabelTags, fieldLabelType ) import CoreSyn -import PrelVals ( rEC_SEL_ERROR_ID ) -import PrelMods ( pREL_GHC ) import Maybes -import BasicTypes ( Arity, StrictnessMark(..) ) -import Unique ( Unique ) +import PrelNames import Maybe ( isJust ) import Outputable -import Util ( assoc ) -import List ( nub ) +import ListSetOps ( assoc, assocMaybe ) +import UnicodeUtil ( stringToUtf8 ) +import Char ( ord ) \end{code} - %************************************************************************ %* * -\subsection{Easy ones} +\subsection{Wired in Ids} %* * %************************************************************************ \begin{code} -mkSpecPragmaId occ uniq ty - = mkUserLocal occ uniq ty `setInlinePragma` IAmASpecPragmaId - -mkDefaultMethodId dm_name rec_c ty - = mkVanillaId dm_name ty - -mkWorkerId uniq unwrkr ty - = mkVanillaId (mkDerivedName mkWorkerOcc (getName unwrkr) uniq) ty +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 three can't be defined in Haskell + , realWorldPrimId + , unsafeCoerceId + , getTagId + ] \end{code} %************************************************************************ @@ -97,19 +133,47 @@ mkWorkerId uniq unwrkr ty %************************************************************************ \begin{code} -mkDataConId :: DataCon -> Id -mkDataConId data_con - = mkId (getName data_con) - id_ty - (ConstantId (DataCon data_con)) - (dataConInfo data_con) +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 + = mkGlobalId (DataConId data_con) work_name (dataConRepType data_con) info where - (tyvars, theta, ex_tyvars, ex_theta, arg_tys, tycon) = dataConSig data_con - id_ty = mkSigmaTy (tyvars ++ ex_tyvars) - (theta ++ ex_theta) - (mkFunTys arg_tys (mkTyConApp tycon (mkTyVarTys tyvars))) + info = noCafNoTyGenIdInfo + `setCgArity` arity + `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 && + 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 +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 @@ -129,53 +193,122 @@ Notice that * 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 :: DataCon -> IdInfo - -dataConInfo data_con - = setInlinePragInfo IMustBeINLINEd $ - -- Always inline constructors; we won't create a binding for them - setArityInfo (exactArity (length locals)) $ - setUnfoldingInfo unfolding $ - noIdInfo +mkDataConWrapId data_con + = wrap_id where - unfolding = mkUnfolding con_rhs - - (tyvars, theta, ex_tyvars, ex_theta, arg_tys, tycon) = dataConSig data_con - all_tyvars = tyvars ++ ex_tyvars - - dict_tys = [mkDictTy clas tys | (clas,tys) <- theta] - ex_dict_tys = [mkDictTy clas tys | (clas,tys) <- ex_theta] - n_dicts = length dict_tys - result_ty = mkTyConApp tycon (mkTyVarTys tyvars) - - locals = mkTemplateLocals (dict_tys ++ ex_dict_tys ++ arg_tys) - data_args = drop n_dicts locals - (data_arg1:_) = data_args -- Used for newtype only - strict_marks = dataConStrictMarks data_con - 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 - = mkConApp data_con (map Type (mkTyVarTys all_tyvars) ++ map Var data_args) - - con_rhs = mkLams all_tyvars $ mkLams locals $ - foldr mk_case con_app strict_args - - mk_case arg body | isUnLiftedType (idType arg) - = body -- "!" on unboxed arg does nothing - | otherwise - = Case (Var arg) arg [(DEFAULT,[],body)] - -- This case shadows "arg" but that's fine + wrap_id = mkGlobalId (DataConWrapId data_con) (dataConName data_con) wrap_ty info + work_id = dataConId 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 + + 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 = 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) + + 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} @@ -196,82 +329,192 @@ We're going to build a record selector unfolding that looks like this: T2 ... x ... -> x other -> error "..." -\begin{code} -mkRecordSelId field_label selector_ty - = ASSERT( null theta && isDataTyCon tycon ) - sel_id - where - sel_id = mkId (fieldLabelName field_label) selector_ty - (RecordSelId field_label) info +Similarly for newtypes - info = exactArity 1 `setArityInfo` ( - unfolding `setUnfoldingInfo` - noIdInfo) - -- ToDo: consider adding further IdInfo + newtype N a = MkN { unN :: a->a } - unfolding = mkUnfolding 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 + unN :: N a -> a -> a + unN n = coerce (a->a) n - [data_id] = mkTemplateLocals [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)] +We need to take a little care if the field has a polymorphic type: - sel_rhs = mkLams tyvars $ Lam data_id $ - Case (Var data_id) data_id (the_alts ++ default_alt) + data R = R { f :: forall a. a->a } - mk_maybe_alt data_con - = case maybe_the_arg_id of - Nothing -> Nothing - Just the_arg_id -> Just (DataCon data_con, arg_ids, Var the_arg_id) - where - arg_ids = mkTemplateLocals (dataConArgTys 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 = mkApps (Var rEC_SEL_ERROR_ID) [Type rhs_ty, mkStringLit full_msg] - full_msg = showSDoc (sep [text "No match in record selector", ppr sel_id]) -\end{code} +Then we want + f :: forall a. R -> a -> a + f = /\ a \ r = case r of + R f -> f a -%************************************************************************ -%* * -\subsection{Newtype field selectors} -%* * -%************************************************************************ +(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 } -Possibly overkill to do it this way: + unN :: forall a. N -> a -> a + unN = /\a -> \n:N -> coerce (a->a) n \begin{code} -mkNewTySelId field_label selector_ty = 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 = 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 + 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 + + selector_ty :: Type + selector_ty = mkForAllTys tyvars $ mkForAllTys field_tyvars $ + mkFunTys dict_tys $ mkFunTys field_dict_tys $ + mkFunTy data_ty field_tau + + arity = 1 + n_dict_tys + n_field_dict_tys + info = noCafNoTyGenIdInfo + `setCgInfo` (CgInfo arity caf_info) + `setArityInfo` exactArity arity + `setUnfoldingInfo` unfolding -- 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] - sel_rhs = mkLams tyvars $ Lam data_id $ - Note (Coerce rhs_ty data_ty) (Var data_id) + -- 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 + + no_default = all isJust alts -- No default needed + default_alt | no_default = [] + | otherwise = [(DEFAULT, [], error_expr)] + + -- 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 + = case maybe_the_arg_id of + Nothing -> Nothing + Just the_arg_id -> Just (DataAlt data_con, real_args, expr) + where + 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 + unpack_base + where + 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 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]) + + +-- 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} @@ -281,45 +524,32 @@ mkNewTySelId field_label selector_ty = sel_id %* * %************************************************************************ -\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 = mkDerivedName (mkSuperDictSelOcc index) (getName clas) uniq - - -- 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 - - info = setInlinePragInfo IMustBeINLINEd $ - setUnfoldingInfo unfolding noIdInfo - -- The always-inline thing means we don't need any other IdInfo - -- We need "Must" inline because we don't create any bindigs for - -- the selectors. + ty = exprType rhs + 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 = noCafNoTyGenIdInfo + `setCgArity` 1 + `setArityInfo` exactArity 1 + `setUnfoldingInfo` unfolding + + -- 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 @@ -334,7 +564,7 @@ mkDictSelId name clas ty Note (Coerce (head arg_tys) dict_ty) (Var dict_id) | otherwise = mkLams tyvars $ Lam dict_id $ Case (Var dict_id) dict_id - [(DataCon data_con, arg_ids, Var the_arg_id)] + [(DataAlt data_con, arg_ids, Var the_arg_id)] \end{code} @@ -344,51 +574,71 @@ mkDictSelId name clas ty %* * %************************************************************************ - \begin{code} -mkPrimitiveId :: PrimOp -> Id -mkPrimitiveId prim_op +mkPrimOpId :: PrimOp -> Id +mkPrimOpId prim_op = id where - occ_name = primOpOcc prim_op - key = primOpUniq prim_op - ty = primOpType prim_op - name = mkWiredInIdName key pREL_GHC occ_name id - id = mkId name ty (ConstantId (PrimOp prim_op)) info + (tyvars,arg_tys,res_ty, arity, strict_info) = primOpSig prim_op + ty = mkForAllTys tyvars (mkFunTys arg_tys res_ty) + name = mkPrimOpIdName prim_op + id = mkGlobalId (PrimOpId prim_op) name ty info - 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 - - (tyvars, tau) = splitForAllTys ty - (arg_tys, _) = splitFunTys tau - - args = mkTemplateLocals arg_tys - rhs = mkLams tyvars $ mkLams args $ - mkPrimApp prim_op (map Type (mkTyVarTys tyvars) ++ map Var args) -\end{code} - -\end{code} - -\begin{code} -dyadic_fun_ty ty = mkFunTys [ty, ty] ty -monadic_fun_ty ty = ty `mkFunTy` ty -compare_fun_ty ty = mkFunTys [ty, ty] boolTy + info = noCafNoTyGenIdInfo + `setSpecInfo` rules + `setCgArity` arity + `setArityInfo` exactArity arity + `setStrictnessInfo` strict_info + + rules = maybe emptyCoreRules (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 + 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 + -- ccall; it is encoded, but may have embedded spaces etc! + + name = mkCCallName uniq occ_str + prim_op = CCallOp ccall + + info = noCafNoTyGenIdInfo + `setCgArity` arity + `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} +\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] @@ -396,18 +646,24 @@ mkDictFunId :: Name -- Name to use for the dict fun; -> ThetaType -> Id -mkDictFunId dfun_name clas inst_tyvars inst_tys inst_decl_theta - = mkVanillaId dfun_name dfun_ty +mkDictFunId dfun_name clas inst_tyvars inst_tys dfun_theta + = mkVanillaGlobal dfun_name dfun_ty noCafNoTyGenIdInfo where - (class_tyvars, sc_theta, _, _, _) = classBigSig clas - sc_theta' = substTopTheta (zipVarEnv class_tyvars inst_tys) sc_theta + dfun_ty = mkSigmaTy inst_tyvars dfun_theta (mkDictTy clas inst_tys) + +{- 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 ++ sc_theta') + other -> nub (inst_decl_theta ++ filter not_const sc_theta') -- Otherwise we pass the superclass dictionaries to -- the dictionary function; the Mark Jones optimisation. -- @@ -416,6 +672,167 @@ mkDictFunId dfun_name clas inst_tyvars inst_tys inst_decl_theta -- 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} - dfun_ty = mkSigmaTy inst_tyvars dfun_theta (mkDictTy clas inst_tys) + +%************************************************************************ +%* * +\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. + +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 = noCafNoTyGenIdInfo `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 = noCafNoTyGenIdInfo `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 + (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 + -- 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) noCafNoTyGenIdInfo +\end{code} + + +%************************************************************************ +%* * +\subsection{Utilities} +%* * +%************************************************************************ + +\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 + -- 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 = 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 + +(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} +