X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2FbasicTypes%2FMkId.lhs;h=a6404455e84b4f06bbdae0aa8bc3f1f202097e24;hb=fcd0198ba7ad41ba2be19faf258663e6371f627e;hp=a385e8b645c7d76ec7c630a24f9e123ba89fa135;hpb=5e0ea427646a5474dd7c659b0713c6a62d8c99c7;p=ghc-hetmet.git diff --git a/compiler/basicTypes/MkId.lhs b/compiler/basicTypes/MkId.lhs index a385e8b..a640445 100644 --- a/compiler/basicTypes/MkId.lhs +++ b/compiler/basicTypes/MkId.lhs @@ -1,7 +1,7 @@ % +% (c) The University of Glasgow 2006 % (c) The AQUA Project, Glasgow University, 1998 % -\section[StdIdInfo]{Standard unfoldings} This module contains definitions for the IdInfo for things that have a standard form, namely: @@ -18,7 +18,7 @@ module MkId ( mkDataConIds, mkRecordSelId, - mkPrimOpId, mkFCallId, + mkPrimOpId, mkFCallId, mkTickBoxOpId, mkBinaryTickBoxOpId, mkReboxingAlt, wrapNewTypeBody, unwrapNewTypeBody, mkUnpackCase, mkProductBox, @@ -38,66 +38,41 @@ module MkId ( #include "HsVersions.h" - -import BasicTypes ( Arity, StrictnessMark(..), isMarkedUnboxed, isMarkedStrict ) -import Rules ( mkSpecInfo ) -import TysPrim ( openAlphaTyVars, alphaTyVar, alphaTy, - realWorldStatePrimTy, addrPrimTy - ) -import TysWiredIn ( charTy, mkListTy ) -import PrelRules ( primOpRules ) -import Type ( TyThing(..), mkForAllTy, tyVarsOfTypes, - newTyConInstRhs, mkTopTvSubst, substTyVar ) -import TcGadt ( gadtRefine, refineType, emptyRefinement ) -import HsBinds ( ExprCoFn(..), isIdCoercion ) -import Coercion ( mkSymCoercion, mkUnsafeCoercion, isEqPred ) -import TcType ( Type, ThetaType, mkDictTy, mkPredTys, mkPredTy, - mkTyConApp, mkTyVarTys, mkClassPred, isPredTy, - mkFunTys, mkFunTy, mkSigmaTy, tcSplitSigmaTy, tcEqType, - isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType, - tcSplitFunTys, tcSplitForAllTys, dataConsStupidTheta - ) -import CoreUtils ( exprType, dataConOrigInstPat, mkCoerce ) -import CoreUnfold ( mkTopUnfolding, mkCompulsoryUnfolding ) -import Literal ( nullAddrLit, mkStringLit ) -import TyCon ( TyCon, isNewTyCon, tyConDataCons, FieldLabel, - tyConStupidTheta, isProductTyCon, isDataTyCon, isRecursiveTyCon, - newTyConCo ) -import Class ( Class, classTyCon, classSelIds ) -import Var ( Id, TyVar, Var, setIdType ) -import VarSet ( isEmptyVarSet, subVarSet, varSetElems ) -import Name ( mkFCallName, mkWiredInName, Name, BuiltInSyntax(..)) -import OccName ( mkOccNameFS, varName ) -import PrimOp ( PrimOp, primOpSig, primOpOcc, primOpTag ) -import ForeignCall ( ForeignCall ) -import DataCon ( DataCon, DataConIds(..), dataConTyCon, dataConUnivTyVars, - dataConFieldLabels, dataConRepArity, dataConResTys, - dataConRepArgTys, dataConRepType, dataConFullSig, - dataConStrictMarks, dataConExStricts, - splitProductType, isVanillaDataCon, dataConFieldType, - deepSplitProductType - ) -import Id ( idType, mkGlobalId, mkVanillaGlobal, mkSysLocal, - mkTemplateLocals, mkTemplateLocalsNum, mkExportedLocalId, - mkTemplateLocal, idName - ) -import IdInfo ( IdInfo, noCafIdInfo, setUnfoldingInfo, - setArityInfo, setSpecInfo, setCafInfo, - setAllStrictnessInfo, vanillaIdInfo, - GlobalIdDetails(..), CafInfo(..) - ) -import NewDemand ( mkStrictSig, DmdResult(..), - mkTopDmdType, topDmd, evalDmd, lazyDmd, retCPR, - Demand(..), Demands(..) ) -import DmdAnal ( dmdAnalTopRhs ) +import Rules +import TysPrim +import TysWiredIn +import PrelRules +import Type +import TcGadt +import HsBinds +import Coercion +import TcType +import CoreUtils +import CoreUnfold +import Literal +import TyCon +import Class +import VarSet +import Name +import OccName +import PrimOp +import ForeignCall +import DataCon +import Id +import Var ( Var, TyVar) +import IdInfo +import NewDemand +import DmdAnal import CoreSyn -import Unique ( mkBuiltinUnique, mkPrimOpIdUnique ) +import Unique import Maybes import PrelNames -import Util ( dropList, isSingleton ) +import BasicTypes hiding ( SuccessFlag(..) ) +import Util import Outputable import FastString -import ListSetOps ( assoc, minusList ) +import ListSetOps +import Module \end{code} %************************************************************************ @@ -187,22 +162,48 @@ Notice that Making an explicit case expression allows the simplifier to eliminate it in the (common) case where the constructor arg is already evaluated. +[Wrappers for data instance tycons] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In the case of data instances, the wrapper also applies the coercion turning +the representation type into the family instance type to cast the result of +the wrapper. For example, consider the declarations + + data family Map k :: * -> * + data instance Map (a, b) v = MapPair (Map a (Pair b v)) + +The tycon to which the datacon MapPair belongs gets a unique internal name of +the form :R123Map, and we call it the representation tycon. In contrast, Map +is the family tycon (accessible via tyConFamInst_maybe). The wrapper and work +of MapPair get the types + + $WMapPair :: forall a b v. Map a (Map a b v) -> Map (a, b) v + $wMapPair :: forall a b v. Map a (Map a b v) -> :R123Map a b v + +which implies that the wrapper code will have to apply the coercion moving +between representation and family type. It is accessible via +tyConFamilyCoercion_maybe and has kind + + Co123Map a b v :: {Map (a, b) v :=: :R123Map a b v} + +This coercion is conditionally applied by wrapFamInstBody. \begin{code} mkDataConIds :: Name -> Name -> DataCon -> DataConIds mkDataConIds wrap_name wkr_name data_con | isNewTyCon tycon - = DCIds Nothing nt_work_id -- Newtype, only has a worker + = DCIds Nothing nt_work_id -- Newtype, only has a worker - | any isMarkedStrict all_strict_marks -- Algebraic, needs wrapper - || not (null eq_spec) + | any isMarkedStrict all_strict_marks -- Algebraic, needs wrapper + || not (null eq_spec) -- NB: LoadIface.ifaceDeclSubBndrs + || isFamInstTyCon tycon -- depends on this test = DCIds (Just alg_wrap_id) wrk_id - | otherwise -- Algebraic, no wrapper + | otherwise -- Algebraic, no wrapper = DCIds Nothing wrk_id where - (univ_tvs, ex_tvs, eq_spec, theta, orig_arg_tys) = dataConFullSig data_con - tycon = dataConTyCon data_con + (univ_tvs, ex_tvs, eq_spec, + theta, orig_arg_tys) = dataConFullSig data_con + tycon = dataConTyCon data_con ----------- Wrapper -------------- -- We used to include the stupid theta in the wrapper's args @@ -210,9 +211,23 @@ mkDataConIds wrap_name wkr_name data_con -- extra constraints where necessary. wrap_tvs = (univ_tvs `minusList` map fst eq_spec) ++ ex_tvs subst = mkTopTvSubst eq_spec + famSubst = ASSERT( length (tyConTyVars tycon ) == + length (mkTyVarTys univ_tvs) ) + zipTopTvSubst (tyConTyVars tycon) (mkTyVarTys univ_tvs) + -- substitution mapping the type constructor's type + -- arguments to the universals of the data constructor + -- (crucial when type checking interfaces) dict_tys = mkPredTys theta result_ty_args = map (substTyVar subst) univ_tvs - result_ty = mkTyConApp tycon result_ty_args + result_ty = case tyConFamInst_maybe tycon of + -- ordinary constructor + Nothing -> mkTyConApp tycon result_ty_args + -- family instance constructor + Just (familyTyCon, + instTys) -> + mkTyConApp familyTyCon ( substTys subst + . substTys famSubst + $ instTys) wrap_ty = mkForAllTys wrap_tvs $ mkFunTys dict_tys $ mkFunTys orig_arg_tys $ result_ty -- NB: watch out here if you allow user-written equality @@ -232,6 +247,7 @@ mkDataConIds wrap_name wkr_name data_con -- even if arity = 0 wkr_sig = mkStrictSig (mkTopDmdType (replicate wkr_arity topDmd) cpr_info) + -- Note [Data-con worker strictness] -- 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) @@ -256,7 +272,7 @@ mkDataConIds wrap_name wkr_name data_con -- RetCPR is only true for products that are real data types; -- that is, not unboxed tuples or [non-recursive] newtypes - ----------- Wrappers for newtypes -------------- + ----------- Workers for newtypes -------------- nt_work_id = mkGlobalId (DataConWrapId data_con) wkr_name wrap_ty nt_work_info nt_work_info = noCafIdInfo -- The NoCaf-ness is set by noCafIdInfo `setArityInfo` 1 -- Arity 1 @@ -302,10 +318,11 @@ mkDataConIds wrap_name wkr_name data_con (zip (dict_args ++ id_args) all_strict_marks) i3 [] - con_app _ rep_ids = Var wrk_id `mkTyApps` result_ty_args - `mkVarApps` ex_tvs - `mkTyApps` map snd eq_spec - `mkVarApps` reverse rep_ids + con_app _ rep_ids = wrapFamInstBody tycon result_ty_args $ + Var wrk_id `mkTyApps` result_ty_args + `mkVarApps` ex_tvs + `mkTyApps` map snd eq_spec + `mkVarApps` reverse rep_ids (dict_args,i2) = mkLocals 1 dict_tys (id_args,i3) = mkLocals i2 orig_arg_tys @@ -344,6 +361,18 @@ mAX_CPR_SIZE = 10 mkLocals i tys = (zipWith mkTemplateLocal [i..i+n-1] tys, i+n) where n = length tys + +-- If the type constructor is a representation type of a data instance, wrap +-- the expression into a cast adjusting the expression type, which is an +-- instance of the representation type, to the corresponding instance of the +-- family instance type. +-- +wrapFamInstBody :: TyCon -> [Type] -> CoreExpr -> CoreExpr +wrapFamInstBody tycon args result_expr + | Just co_con <- tyConFamilyCoercion_maybe tycon + = mkCoerce (mkSymCoercion (mkTyConApp co_con args)) result_expr + | otherwise + = result_expr \end{code} @@ -565,14 +594,14 @@ mkRecordSelId tycon field_label -- T1 b' (c : [b]=[b']) (x:Maybe b') -- -> x `cast` Maybe (sym (right c)) - Succeeded refinement = gadtRefine emptyRefinement ex_tvs co_tvs - (co_fn, res_ty) = refineType refinement (idType the_arg_id) + -- Generate the refinement for b'=b, -- and apply to (Maybe b'), to get (Maybe b) - - rhs = case co_fn of - ExprCoFn co -> Cast (Var the_arg_id) co - id_co -> ASSERT(isIdCoercion id_co) Var the_arg_id + Succeeded refinement = gadtRefine emptyRefinement ex_tvs co_tvs + the_arg_id_ty = idType the_arg_id + (rhs, res_ty) = case refineType refinement the_arg_id_ty of + Just (co, res_ty) -> (Cast (Var the_arg_id) co, res_ty) + Nothing -> (Var the_arg_id, the_arg_id_ty) field_vs = filter (not . isPredTy . idType) arg_vs the_arg_id = assoc "mkRecordSelId:mk_alt" (field_lbls `zip` field_vs) field_label @@ -792,15 +821,28 @@ wrapNewTypeBody :: TyCon -> [Type] -> CoreExpr -> CoreExpr -- If a coercion constructor is prodivided in the newtype, then we use -- it, otherwise the wrap/unwrap are both no-ops -- +-- If the we are dealing with a newtype instance, we have a second coercion +-- identifying the family instance with the constructor of the newtype +-- instance. This coercion is applied in any case (ie, composed with the +-- coercion constructor of the newtype or applied by itself). +-- wrapNewTypeBody tycon args result_expr - | Just co_con <- newTyConCo tycon - = mkCoerce (mkSymCoercion (mkTyConApp co_con args)) result_expr - | otherwise - = result_expr + = wrapFamInstBody tycon args inner + where + inner + | Just co_con <- newTyConCo_maybe tycon + = mkCoerce (mkSymCoercion (mkTyConApp co_con args)) result_expr + | otherwise + = result_expr +-- When unwrapping, we do *not* apply any family coercion, because this will +-- be done via a CoPat by the type checker. We have to do it this way as +-- computing the right type arguments for the coercion requires more than just +-- a spliting operation (cf, TcPat.tcConPat). +-- unwrapNewTypeBody :: TyCon -> [Type] -> CoreExpr -> CoreExpr unwrapNewTypeBody tycon args result_expr - | Just co_con <- newTyConCo tycon + | Just co_con <- newTyConCo_maybe tycon = mkCoerce (mkTyConApp co_con args) result_expr | otherwise = result_expr @@ -824,7 +866,7 @@ mkPrimOpId prim_op ty = mkForAllTys tyvars (mkFunTys arg_tys res_ty) name = mkWiredInName gHC_PRIM (primOpOcc prim_op) (mkPrimOpIdUnique (primOpTag prim_op)) - Nothing (AnId id) UserSyntax + (AnId id) UserSyntax id = mkGlobalId (PrimOpId prim_op) name ty info info = noCafIdInfo @@ -862,6 +904,38 @@ mkFCallId uniq fcall ty (arg_tys, _) = tcSplitFunTys tau arity = length arg_tys strict_sig = mkStrictSig (mkTopDmdType (replicate arity evalDmd) TopRes) + +mkTickBoxOpId :: Unique + -> Module + -> TickBoxId + -> Id +mkTickBoxOpId uniq mod ix = mkGlobalId (TickBoxOpId tickbox) name ty info + where + tickbox = TickBox mod ix + occ_str = showSDoc (braces (ppr tickbox)) + name = mkTickBoxOpName uniq occ_str + info = noCafIdInfo + ty = realWorldStatePrimTy + +mkBinaryTickBoxOpId + :: Unique + -> Module + -> TickBoxId + -> TickBoxId + -> Id +mkBinaryTickBoxOpId uniq mod ixT ixF = mkGlobalId (TickBoxOpId tickbox) name ty info + where + tickbox = BinaryTickBox mod ixT ixF + occ_str = showSDoc (braces (ppr tickbox)) + name = mkTickBoxOpName uniq occ_str + info = noCafIdInfo + `setArityInfo` arity + `setAllStrictnessInfo` Just strict_sig + ty = mkFunTy boolTy boolTy + + arity = 1 + strict_sig = mkStrictSig (mkTopDmdType (replicate arity evalDmd) TopRes) + --- ?? mkStrictSig (mkTopDmdType [seqDmd] TopRes) \end{code} @@ -963,7 +1037,7 @@ another gun with which to shoot yourself in the foot. \begin{code} mkWiredInIdName mod fs uniq id - = mkWiredInName mod (mkOccNameFS varName fs) uniq Nothing (AnId id) UserSyntax + = mkWiredInName mod (mkOccNameFS varName fs) uniq (AnId id) UserSyntax unsafeCoerceName = mkWiredInIdName gHC_PRIM FSLIT("unsafeCoerce#") unsafeCoerceIdKey unsafeCoerceId nullAddrName = mkWiredInIdName gHC_PRIM FSLIT("nullAddr#") nullAddrIdKey nullAddrId @@ -996,8 +1070,7 @@ unsafeCoerceId (mkFunTy openAlphaTy openBetaTy) [x] = mkTemplateLocals [openAlphaTy] rhs = mkLams [openAlphaTyVar,openBetaTyVar,x] $ --- Note (Coerce openBetaTy openAlphaTy) (Var x) - Cast (Var x) (mkUnsafeCoercion openAlphaTy openBetaTy) + Cast (Var x) (mkUnsafeCoercion openAlphaTy openBetaTy) -- nullAddr# :: Addr# -- The reason is is here is because we don't provide @@ -1155,9 +1228,5 @@ pc_bottoming_Id name ty strict_sig = mkStrictSig (mkTopDmdType [evalDmd] BotRes) -- These "bottom" out, no matter what their arguments - -(openAlphaTyVar:openBetaTyVar:_) = openAlphaTyVars -openAlphaTy = mkTyVarTy openAlphaTyVar -openBetaTy = mkTyVarTy openBetaTyVar \end{code}