X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FbasicTypes%2FMkId.lhs;h=c112a2ab0e2a9f3da88a009885325a47689e3a47;hb=53ce311e219dcccf4d205f573c16e23a5c44265e;hp=5e1165c2eccd324307fdc51c7457f0badc5bc662;hpb=f16228e47dbaf4c5eb710bf507b3b61bc5ad7122;p=ghc-hetmet.git diff --git a/ghc/compiler/basicTypes/MkId.lhs b/ghc/compiler/basicTypes/MkId.lhs index 5e1165c..c112a2a 100644 --- a/ghc/compiler/basicTypes/MkId.lhs +++ b/ghc/compiler/basicTypes/MkId.lhs @@ -22,8 +22,8 @@ module MkId ( -- 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, + unsafeCoerceId, realWorldPrimId, voidArgId, nullAddrId, + eRROR_ID, eRROR_CSTRING_ID, rEC_SEL_ERROR_ID, pAT_ERROR_ID, rEC_CON_ERROR_ID, rEC_UPD_ERROR_ID, iRREFUT_PAT_ERROR_ID, nON_EXHAUSTIVE_GUARDS_ERROR_ID, nO_METHOD_BINDING_ERROR_ID, aBSENT_ERROR_ID, pAR_ERROR_ID ) where @@ -31,26 +31,25 @@ module MkId ( #include "HsVersions.h" -import BasicTypes ( Arity ) -import TysPrim ( openAlphaTyVars, alphaTyVar, alphaTy, - intPrimTy, realWorldStatePrimTy +import BasicTypes ( Arity, StrictnessMark(..), isMarkedUnboxed, isMarkedStrict ) +import TysPrim ( openAlphaTyVars, alphaTyVar, alphaTy, betaTyVar, betaTy, + intPrimTy, realWorldStatePrimTy, addrPrimTy ) import TysWiredIn ( charTy, mkListTy ) -import PrelNames ( pREL_ERR, pREL_GHC ) -import PrelRules ( primOpRule ) +import PrelRules ( primOpRules ) import Rules ( addRule ) -import Type ( Type, ThetaType, mkDictTy, mkPredTys, mkTyConApp, - mkTyVarTys, repType, isNewType, - mkFunTys, mkFunTy, mkSigmaTy, splitSigmaTy, +import TcType ( Type, ThetaType, mkDictTy, mkPredTys, mkTyConApp, + mkTyVarTys, mkClassPred, tcEqPred, + mkFunTys, mkFunTy, mkSigmaTy, tcSplitSigmaTy, isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType, - splitFunTys, splitForAllTys, mkPredTy + tcSplitFunTys, tcSplitForAllTys, mkPredTy ) import Module ( Module ) -import CoreUtils ( exprType, mkInlineMe ) +import CoreUtils ( exprType ) import CoreUnfold ( mkTopUnfolding, mkCompulsoryUnfolding, mkOtherCon ) -import Literal ( Literal(..) ) +import Literal ( Literal(..), nullAddrLit ) import TyCon ( TyCon, isNewTyCon, tyConTyVars, tyConDataCons, - tyConTheta, isProductTyCon, isDataTyCon ) + tyConTheta, isProductTyCon, isDataTyCon, isRecursiveTyCon ) import Class ( Class, classTyCon, classTyVars, classSelIds ) import Var ( Id, TyVar ) import VarSet ( isEmptyVarSet ) @@ -58,11 +57,9 @@ import Name ( mkWiredInName, mkFCallName, Name ) import OccName ( mkVarOcc ) import PrimOp ( PrimOp(DataToTagOp), primOpSig, mkPrimOpIdName ) import ForeignCall ( ForeignCall ) -import Demand ( wwStrict, wwPrim, mkStrictnessInfo, - StrictnessMark(..), isMarkedUnboxed, isMarkedStrict ) import DataCon ( DataCon, dataConFieldLabels, dataConRepArity, dataConTyCon, - dataConArgTys, dataConRepType, dataConRepStrictness, + dataConArgTys, dataConRepType, dataConInstOrigArgTys, dataConName, dataConTheta, dataConSig, dataConStrictMarks, dataConId, @@ -70,23 +67,27 @@ import DataCon ( DataCon, ) import Id ( idType, mkGlobalId, mkVanillaGlobal, mkSysLocal, mkTemplateLocals, mkTemplateLocalsNum, - mkTemplateLocal, idCprInfo + mkTemplateLocal, idNewStrictness, idName ) import IdInfo ( IdInfo, noCafNoTyGenIdInfo, - exactArity, setUnfoldingInfo, setCprInfo, - setArityInfo, setSpecInfo, setCgInfo, - mkStrictnessInfo, setStrictnessInfo, - GlobalIdDetails(..), CafInfo(..), CprInfo(..), - CgInfo(..), setCgArity + setUnfoldingInfo, + setArityInfo, setSpecInfo, setCafInfo, + newStrictnessFromOld, setAllStrictnessInfo, + GlobalIdDetails(..), CafInfo(..), CprInfo(..) ) +import NewDemand ( mkStrictSig, strictSigResInfo, DmdResult(..), + mkTopDmdType, topDmd, evalDmd, lazyDmd, + Demand(..), Demands(..) ) import FieldLabel ( mkFieldLabel, fieldLabelName, firstFieldLabelTag, allFieldLabelTags, fieldLabelType ) +import DmdAnal ( dmdAnalTopRhs ) import CoreSyn import Unique ( mkBuiltinUnique ) import Maybes import PrelNames import Maybe ( isJust ) +import Util ( dropList, isSingleton ) import Outputable import ListSetOps ( assoc, assocMaybe ) import UnicodeUtil ( stringToUtf8 ) @@ -107,11 +108,12 @@ wiredInIds -- -- [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] + -- error-reporting functions that they have an 'open' + -- result type. -- sof 1/99] aBSENT_ERROR_ID , eRROR_ID + , eRROR_CSTRING_ID , iRREFUT_PAT_ERROR_ID , nON_EXHAUSTIVE_GUARDS_ERROR_ID , nO_METHOD_BINDING_ERROR_ID @@ -120,10 +122,13 @@ wiredInIds , rEC_CON_ERROR_ID , rEC_UPD_ERROR_ID - -- These three can't be defined in Haskell + -- These can't be defined in Haskell, but they have + -- perfectly reasonable unfoldings in Core , realWorldPrimId , unsafeCoerceId + , nullAddrId , getTagId + , seqId ] \end{code} @@ -141,23 +146,36 @@ mkDataConId work_name data_con = mkGlobalId (DataConId data_con) work_name (dataConRepType data_con) info where info = noCafNoTyGenIdInfo - `setCgArity` arity - `setArityInfo` exactArity arity - `setStrictnessInfo` strict_info - `setCprInfo` cpr_info - - arity = dataConRepArity data_con - - strict_info = mkStrictnessInfo (dataConRepStrictness data_con, False) + `setArityInfo` arity + `setAllStrictnessInfo` Just strict_sig + + arity = dataConRepArity data_con + + strict_sig = mkStrictSig (mkTopDmdType (replicate arity topDmd) cpr_info) + -- Notice that we do *not* say the worker is strict + -- even if the data constructor is declared strict + -- e.g. data T = MkT !(Int,Int) + -- Why? Because the *wrapper* is strict (and its unfolding has case + -- expresssions that do the evals) but the *worker* itself is not. + -- If we pretend it is strict then when we see + -- case x of y -> $wMkT y + -- the simplifier thinks that y is "sure to be evaluated" (because + -- $wMkT is strict) and drops the case. No, $wMkT is not strict. + -- + -- When the simplifer sees a pattern + -- case e of MkT x -> ... + -- it uses the dataConRepStrictness of MkT to mark x as evaluated; + -- but that's fine... dataConRepStrictness comes from the data con + -- not from the worker Id. 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 + arity <= mAX_CPR_SIZE = RetCPR + | otherwise = TopRes + -- RetCPR is only true for products that are real data types; + -- that is, not unboxed tuples or [non-recursive] newtypes mAX_CPR_SIZE :: Arity mAX_CPR_SIZE = 10 @@ -210,57 +228,64 @@ Notice that \begin{code} mkDataConWrapId data_con - = wrap_id + = mkGlobalId (DataConWrapId data_con) (dataConName data_con) wrap_ty info where - 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 + `setUnfoldingInfo` wrap_unf -- The NoCaf-ness is set by noCafNoTyGenIdInfo - `setArityInfo` exactArity arity + `setArityInfo` 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 ) + `setAllStrictnessInfo` Just wrap_sig + + wrap_ty = mkForAllTys all_tyvars (mkFunTys all_arg_tys result_ty) + + wrap_sig = mkStrictSig (mkTopDmdType arg_dmds res_info) + res_info = strictSigResInfo (idNewStrictness work_id) + arg_dmds = [Abs | d <- dict_args] ++ map mk_dmd strict_marks + mk_dmd str | isMarkedStrict str = evalDmd + | otherwise = lazyDmd + -- The Cpr info can be important inside INLINE rhss, where the + -- wrapper constructor isn't inlined. + -- And the argument strictness can be important too; we + -- may not inline a contructor when it is partially applied. + -- For example: + -- data W = C !Int !Int !Int + -- ...(let w = C x in ...(w p q)...)... + -- we want to see that w is strict in its two arguments + + wrap_unf | isNewTyCon tycon + = ASSERT( null ex_tyvars && null ex_dict_args && isSingleton orig_arg_tys ) -- No existentials on a newtype, but it can have a context -- e.g. newtype Eq a => T a = MkT (...) - - mkLams tyvars $ mkLams dict_args $ Lam id_arg1 $ - Note (Coerce result_ty (head orig_arg_tys)) (Var id_arg1) + mkTopUnfolding $ Note InlineMe $ + mkLams tyvars $ mkLams dict_args $ Lam id_arg1 $ + mkNewTypeBody tycon result_ty (Var id_arg1) | null dict_args && not (any isMarkedStrict strict_marks) - = Var work_id -- The common case. Not only is this efficient, - -- but it also ensures that the wrapper is replaced - -- by the worker even when there are no args. - -- f (:) x - -- becomes - -- f $w: x - -- This is really important in rule matching, - -- (We could match on the wrappers, - -- but that makes it less likely that rules will match - -- when we bring bits of unfoldings together.) + = mkCompulsoryUnfolding (Var work_id) + -- The common case. Not only is this efficient, + -- but it also ensures that the wrapper is replaced + -- by the worker even when there are no args. + -- f (:) x + -- becomes + -- f $w: x + -- This is really important in rule matching, + -- (We could match on the wrappers, + -- but that makes it less likely that rules will match + -- when we bring bits of unfoldings together.) -- -- NB: because of this special case, (map (:) ys) turns into - -- (map $w: ys), and thence into (map (\x xs. $w: x xs) ys) - -- in core-to-stg. The top-level defn for (:) is never used. + -- (map $w: ys). The top-level defn for (:) is never used. -- This is somewhat of a bore, but I'm currently leaving it -- as is, so that there still is a top level curried (:) for -- the interpreter to call. | otherwise - = mkLams all_tyvars $ mkLams dict_args $ + = mkTopUnfolding $ Note InlineMe $ + mkLams all_tyvars $ mkLams dict_args $ mkLams ex_dict_args $ mkLams id_args $ foldr mk_case con_app (zip (ex_dict_args++id_args) strict_marks) i3 [] @@ -303,24 +328,12 @@ mkDataConWrapId data_con Case (Var arg) arg [(DEFAULT,[], body i (arg:rep_args))] MarkedUnboxed - | isNewType arg_ty -> - Let (NonRec coerced_arg - (Note (Coerce rep_ty arg_ty) (Var arg))) - (do_unbox coerced_arg rep_ty i') - | otherwise -> - do_unbox arg arg_ty i - where - ([coerced_arg],i') = mkLocals i [rep_ty] - arg_ty = idType arg - rep_ty = repType arg_ty - - do_unbox arg ty i = - case splitProductType "do_unbox" ty of + -> case splitProductType "do_unbox" (idType arg) of (tycon, tycon_args, con, tys) -> Case (Var arg) arg [(DataAlt con, con_args, body i' (reverse con_args ++ rep_args))] where - (con_args, i') = mkLocals i tys + (con_args, i') = mkLocals i tys \end{code} @@ -388,11 +401,11 @@ mkRecordSelId tycon field_label unpack_id unpackUtf8_id -- 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] + needed_dict pred = or [ tcEqPred pred p + | (DataAlt dc, _, _) <- the_alts, p <- dataConTheta dc] n_dict_tys = length dict_tys - (field_tyvars,field_theta,field_tau) = splitSigmaTy field_ty + (field_tyvars,field_theta,field_tau) = tcSplitSigmaTy 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 @@ -422,13 +435,16 @@ mkRecordSelId tycon field_label unpack_id unpackUtf8_id 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 = mkTopUnfolding sel_rhs + (strict_sig, rhs_w_str) = dmdAnalTopRhs sel_rhs + -- Use the demand analyser to work out strictness. + -- With all this unpackery it's not easy! + + info = noCafNoTyGenIdInfo + `setCafInfo` caf_info + `setArityInfo` arity + `setUnfoldingInfo` mkTopUnfolding rhs_w_str + `setAllStrictnessInfo` Just strict_sig -- Allocate Ids. We do it a funny way round because field_dict_tys is -- almost always empty. Also note that we use length_tycon_theta @@ -457,15 +473,23 @@ mkRecordSelId tycon field_label unpack_id unpackUtf8_id 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) + sel_body | isNewTyCon tycon = mkNewTypeBody tycon field_tau (mk_result data_id) + | otherwise = Case (Var data_id) data_id (default_alt ++ the_alts) + + mk_result result_id = mkVarApps (mkVarApps (Var result_id) field_tyvars) field_dict_ids + -- We pull the field lambdas to the top, so we need to + -- apply them in the body. For example: + -- data T = MkT { foo :: forall a. a->a } + -- + -- foo :: forall a. T -> a -> a + -- foo = /\a. \t:T. case t of { MkT f -> f a } mk_maybe_alt data_con = case maybe_the_arg_id of Nothing -> Nothing Just the_arg_id -> Just (DataAlt data_con, real_args, mkLets binds body) where - body = mkVarApps (mkVarApps (Var the_arg_id) field_tyvars) field_dict_ids + body = mk_result the_arg_id strict_marks = dataConStrictMarks data_con (binds, real_args) = rebuildConArgs arg_ids strict_marks (map mkBuiltinUnique [unpack_base..]) @@ -519,24 +543,15 @@ rebuildConArgs (arg:args) (str:stricts) us | isMarkedUnboxed str = let arg_ty = idType arg - prod_ty | isNewType arg_ty = repType arg_ty - | otherwise = arg_ty (_, tycon_args, pack_con, con_arg_tys) - = splitProductType "rebuildConArgs" prod_ty + = splitProductType "rebuildConArgs" arg_ty unpacked_args = zipWith (mkSysLocal SLIT("rb")) us con_arg_tys - - (binds, args') = rebuildConArgs args stricts - (drop (length con_arg_tys) us) - - coerce | isNewType arg_ty = Note (Coerce arg_ty prod_ty) con_app - | otherwise = con_app - - con_app = mkConApp pack_con (map Type tycon_args ++ - map Var unpacked_args) + (binds, args') = rebuildConArgs args stricts (dropList con_arg_tys us) + con_app = mkConApp pack_con (map Type tycon_args ++ map Var unpacked_args) in - (NonRec arg coerce : binds, unpacked_args ++ args') + (NonRec arg con_app : binds, unpacked_args ++ args') | otherwise = let (binds, args') = rebuildConArgs args stricts us @@ -558,22 +573,34 @@ ToDo: unify with mkRecordSelId. \begin{code} mkDictSelId :: Name -> Class -> Id mkDictSelId name clas - = sel_id + = mkGlobalId (RecordSelId field_lbl) name sel_ty info where - 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 + sel_ty = mkForAllTys tyvars (mkFunTy (idType dict_id) (idType the_arg_id)) + -- We can't just say (exprType rhs), because that would give a type + -- C a -> C a + -- for a single-op class (after all, the selector is the identity) + -- But it's type must expose the representation of the dictionary + -- to gat (say) C a -> (a -> a) + + field_lbl = mkFieldLabel name tycon sel_ty tag + tag = assoc "MkId.mkDictSelId" (map idName (classSelIds clas) `zip` allFieldLabelTags) name info = noCafNoTyGenIdInfo - `setCgArity` 1 - `setArityInfo` exactArity 1 - `setUnfoldingInfo` unfolding - + `setArityInfo` 1 + `setUnfoldingInfo` mkTopUnfolding rhs + `setAllStrictnessInfo` Just strict_sig + -- We no longer use 'must-inline' on record selectors. They'll -- inline like crazy if they scrutinise a constructor - unfolding = mkTopUnfolding rhs + -- The strictness signature is of the form U(AAAVAAAA) -> T + -- where the V depends on which item we are selecting + -- It's worth giving one, so that absence info etc is generated + -- even if the selector isn't inlined + strict_sig = mkStrictSig (mkTopDmdType [arg_dmd] TopRes) + arg_dmd | isNewTyCon tycon = evalDmd + | otherwise = Eval (Prod [ if the_arg_id == id then evalDmd else Abs + | id <- arg_ids ]) tyvars = classTyVars clas @@ -583,14 +610,22 @@ mkDictSelId name clas arg_tys = dataConArgTys data_con tyvar_tys the_arg_id = arg_ids !! (tag - firstFieldLabelTag) - dict_ty = mkDictTy clas tyvar_tys - (dict_id:arg_ids) = mkTemplateLocals (dict_ty : arg_tys) + pred = mkClassPred clas tyvar_tys + (dict_id:arg_ids) = mkTemplateLocals (mkPredTy pred : arg_tys) - rhs | isNewTyCon tycon = mkLams tyvars $ Lam dict_id $ - Note (Coerce (head arg_tys) dict_ty) (Var dict_id) + rhs | isNewTyCon tycon = mkLams tyvars $ Lam dict_id $ + mkNewTypeBody tycon (head arg_tys) (Var dict_id) | otherwise = mkLams tyvars $ Lam dict_id $ Case (Var dict_id) dict_id [(DataAlt data_con, arg_ids, Var the_arg_id)] + +mkNewTypeBody tycon result_ty result_expr + -- Adds a coerce where necessary + -- Used for both wrapping and unwrapping + | isRecursiveTyCon tycon -- Recursive case; use a coerce + = Note (Coerce result_ty (exprType result_expr)) result_expr + | otherwise -- Normal case + = result_expr \end{code} @@ -612,12 +647,11 @@ mkPrimOpId prim_op info = noCafNoTyGenIdInfo `setSpecInfo` rules - `setCgArity` arity - `setArityInfo` exactArity arity - `setStrictnessInfo` strict_info + `setArityInfo` arity + `setAllStrictnessInfo` Just (newStrictnessFromOld name arity strict_info NoCPRInfo) + -- Until we modify the primop generation code - rules = maybe emptyCoreRules (addRule emptyCoreRules id) - (primOpRule prim_op) + rules = foldl (addRule id) emptyCoreRules (primOpRules prim_op) -- For each ccall we manufacture a separate CCallOpId, giving it @@ -643,14 +677,13 @@ mkFCallId uniq fcall ty name = mkFCallName uniq occ_str info = noCafNoTyGenIdInfo - `setCgArity` arity - `setArityInfo` exactArity arity - `setStrictnessInfo` strict_info + `setArityInfo` arity + `setAllStrictnessInfo` Just strict_sig - (_, tau) = splitForAllTys ty - (arg_tys, _) = splitFunTys tau + (_, tau) = tcSplitForAllTys ty + (arg_tys, _) = tcSplitFunTys tau arity = length arg_tys - strict_info = mkStrictnessInfo (take arity (repeat wwPrim), False) + strict_sig = mkStrictSig (mkTopDmdType (replicate arity evalDmd) TopRes) \end{code} @@ -660,9 +693,34 @@ mkFCallId uniq fcall ty %* * %************************************************************************ +Important notes about dict funs and default methods +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Dict funs and default methods are *not* ImplicitIds. Their definition +involves user-written code, so we can't figure out their strictness etc +based on fixed info, as we can for constructors and record selectors (say). + +We build them as GlobalIds, but when in the module where they are +bound, we turn the Id at the *binding site* into an exported LocalId. +This ensures that they are taken to account by free-variable finding +and dependency analysis (e.g. CoreFVs.exprFreeVars). The simplifier +will propagate the LocalId to all occurrence sites. + +Why shouldn't they be bound as GlobalIds? Because, in particular, if +they are globals, the specialiser floats dict uses above their defns, +which prevents good simplifications happening. Also the strictness +analyser treats a occurrence of a GlobalId as imported and assumes it +contains strictness in its IdInfo, which isn't true if the thing is +bound in the same module as the occurrence. + +It's OK for dfuns to be LocalIds, because we form the instance-env to +pass on to the next module (md_insts) in CoreTidy, afer tidying +and globalising the top-level Ids. + +BUT make sure they are *exported* LocalIds (setIdLocalExported) so +that they aren't discarded by the occurrence analyser. + \begin{code} -mkDefaultMethodId dm_name ty - = mkVanillaGlobal dm_name ty noCafNoTyGenIdInfo +mkDefaultMethodId dm_name ty = mkVanillaGlobal dm_name ty noCafNoTyGenIdInfo mkDictFunId :: Name -- Name to use for the dict fun; -> Class @@ -712,7 +770,12 @@ mkDictFunId dfun_name clas inst_tyvars inst_tys dfun_theta %* * %************************************************************************ -These two can't be defined in Haskell. +These Ids can't be defined in Haskell. They could be defined in +unfoldings in PrelGHC.hi-boot, but we'd have to ensure that they +were definitely, definitely inlined, because there is no curried +identifier for them. That's what mkCompulsoryUnfolding does. +If we had a way to get a compulsory unfolding from an interface file, +we could do that, but we don't right now. unsafeCoerce# isn't so much a PrimOp as a phantom identifier, that just gets expanded into a type coercion wherever it occurs. Hence we @@ -723,6 +786,7 @@ they can unify with both unlifted and lifted types. Hence we provide another gun with which to shoot yourself in the foot. \begin{code} +-- unsafeCoerce# :: forall a b. a -> b unsafeCoerceId = pcMiscPrelId unsafeCoerceIdKey pREL_GHC SLIT("unsafeCoerce#") ty info where @@ -734,8 +798,27 @@ unsafeCoerceId [x] = mkTemplateLocals [openAlphaTy] rhs = mkLams [openAlphaTyVar,openBetaTyVar,x] $ Note (Coerce openBetaTy openAlphaTy) (Var x) -\end{code} +-- nullAddr# :: Addr# +-- The reason is is here is because we don't provide +-- a way to write this literal in Haskell. +nullAddrId + = pcMiscPrelId nullAddrIdKey pREL_GHC SLIT("nullAddr#") addrPrimTy info + where + info = noCafNoTyGenIdInfo `setUnfoldingInfo` + mkCompulsoryUnfolding (Lit nullAddrLit) + +seqId + = pcMiscPrelId seqIdKey pREL_GHC SLIT("seq") ty info + where + info = noCafNoTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs + + + ty = mkForAllTys [alphaTyVar,betaTyVar] + (mkFunTy alphaTy (mkFunTy betaTy betaTy)) + [x,y] = mkTemplateLocals [alphaTy, betaTy] + rhs = mkLams [alphaTyVar,betaTyVar,x,y] (Case (Var x) x [(DEFAULT, [], Var y)]) +\end{code} @getTag#@ is another function which can't be defined in Haskell. It needs to evaluate its argument and call the dataToTag# primitive. @@ -758,6 +841,13 @@ dataToTagId = mkPrimOpId DataToTagOp @realWorld#@ used to be a magic literal, \tr{void#}. If things get nasty as-is, change it back to a literal (@Literal@). +voidArgId is a Local Id used simply as an argument in functions +where we just want an arg to avoid having a thunk of unlifted type. +E.g. + x = \ void :: State# RealWorld -> (# p, q #) + +This comes up in strictness analysis + \begin{code} realWorldPrimId -- :: State# RealWorld = pcMiscPrelId realWorldPrimIdKey pREL_GHC SLIT("realWorld#") @@ -767,6 +857,9 @@ realWorldPrimId -- :: State# RealWorld -- which in turn makes Simplify.interestingArg return True, -- which in turn makes INLINE things applied to realWorld# likely -- to be inlined + +voidArgId -- :: State# RealWorld + = mkSysLocal SLIT("void") voidArgIdKey realWorldStatePrimTy \end{code} @@ -794,6 +887,9 @@ templates, but we don't ever expect to generate code for it. \begin{code} eRROR_ID = pc_bottoming_Id errorIdKey pREL_ERR SLIT("error") errorTy +eRROR_CSTRING_ID + = pc_bottoming_Id errorCStringIdKey pREL_ERR SLIT("errorCString") + (mkSigmaTy [openAlphaTyVar] [] (mkFunTy addrPrimTy openAlphaTy)) pAT_ERROR_ID = generic_ERROR_ID patErrorIdKey SLIT("patError") rEC_SEL_ERROR_ID @@ -842,9 +938,8 @@ pcMiscPrelId key mod str ty info pc_bottoming_Id key mod name ty = pcMiscPrelId key mod name ty bottoming_info where - bottoming_info = noCafNoTyGenIdInfo - `setStrictnessInfo` mkStrictnessInfo ([wwStrict], True) - + strict_sig = mkStrictSig (mkTopDmdType [evalDmd] BotRes) + bottoming_info = noCafNoTyGenIdInfo `setAllStrictnessInfo` Just strict_sig -- these "bottom" out, no matter what their arguments generic_ERROR_ID u n = pc_bottoming_Id u pREL_ERR n errorTy