mkDictSelId,
mkDataConId, mkDataConWrapId,
- mkRecordSelId,
- mkPrimOpId, mkCCallOpId,
+ mkRecordSelId, rebuildConArgs,
+ mkPrimOpId, mkFCallId,
-- And some particular Ids; see below for why they are wired in
wiredInIds,
#include "HsVersions.h"
-import BasicTypes ( Arity )
+import BasicTypes ( Arity, StrictnessMark(..), isMarkedUnboxed, isMarkedStrict )
import TysPrim ( openAlphaTyVars, alphaTyVar, alphaTy,
intPrimTy, realWorldStatePrimTy
)
import PrelNames ( pREL_ERR, pREL_GHC )
import PrelRules ( primOpRule )
import Rules ( addRule )
-import Type ( Type, ThetaType, mkDictTy, mkPredTys, mkTyConApp, mkTyVarTys,
- 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 CoreUnfold ( mkTopUnfolding, mkCompulsoryUnfolding, mkOtherCon )
import Literal ( Literal(..) )
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 )
-import Name ( mkWiredInName, mkCCallName, Name )
+import Name ( mkWiredInName, mkFCallName, Name )
import OccName ( mkVarOcc )
-import PrimOp ( PrimOp(DataToTagOp, CCallOp),
- primOpSig, mkPrimOpIdName,
- CCall, pprCCallOp
- )
-import Demand ( wwStrict, wwPrim, mkStrictnessInfo )
-import DataCon ( DataCon, StrictnessMark(..),
+import PrimOp ( PrimOp(DataToTagOp), primOpSig, mkPrimOpIdName )
+import ForeignCall ( ForeignCall )
+import DataCon ( DataCon,
dataConFieldLabels, dataConRepArity, dataConTyCon,
dataConArgTys, dataConRepType, dataConRepStrictness,
dataConInstOrigArgTys,
dataConName, dataConTheta,
dataConSig, dataConStrictMarks, dataConId,
- maybeMarkedUnboxed, splitProductType_maybe
+ splitProductType
)
-import Id ( idType, mkGlobalId, mkVanillaGlobal,
+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,
+ mkNewStrictnessInfo, setNewStrictnessInfo,
GlobalIdDetails(..), CafInfo(..), CprInfo(..),
CgInfo(..), setCgArity
)
+import NewDemand ( mkStrictSig, strictSigResInfo, DmdResult(..),
+ mkTopDmdType, topDmd, evalDmd )
import FieldLabel ( mkFieldLabel, fieldLabelName,
firstFieldLabelTag, allFieldLabelTags, fieldLabelType
)
import CoreSyn
+import Unique ( mkBuiltinUnique )
import Maybes
import PrelNames
import Maybe ( isJust )
-- 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
+ = id
where
+ id = mkGlobalId (DataConId data_con) work_name (dataConRepType data_con) info
info = noCafNoTyGenIdInfo
- `setCgArity` arity
- `setArityInfo` exactArity arity
- `setStrictnessInfo` strict_info
- `setCprInfo` cpr_info
+ `setCgArity` arity
+ `setArityInfo` arity
+ `setNewStrictnessInfo` Just strict_sig
arity = dataConRepArity data_con
-
- strict_info = mkStrictnessInfo (dataConRepStrictness data_con, False)
+ strict_sig = mkStrictSig id arity (mkTopDmdType (dataConRepStrictness data_con) cpr_info)
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
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
+ `setArityInfo` arity
-- It's important to specify the arity, so that partial
-- applications are treated as values
+ `setNewStrictnessInfo` Just wrap_sig
wrap_ty = mkForAllTys all_tyvars $
mkFunTys all_arg_tys
result_ty
- cpr_info = idCprInfo work_id
+ res_info = strictSigResInfo (idNewStrictness work_id)
+ wrap_sig = mkStrictSig wrap_id arity (mkTopDmdType (replicate arity topDmd) res_info)
+ -- The Cpr info can be important inside INLINE rhss, where the
+ -- wrapper constructor isn't inlined
+ -- But we are sloppy about the argument demands, because we expect
+ -- to inline the constructor very vigorously.
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 $
+ mkNewTypeBody tycon result_ty id_arg1
- 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
+ | 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.
(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
+ :: (Id, StrictnessMark) -- Arg, strictness
+ -> (Int -> [Id] -> CoreExpr) -- Body
+ -> Int -- Next rep arg id
+ -> [Id] -- Rep args so far, reversed
-> CoreExpr
mk_case (arg,strict) body i rep_args
= case strict of
| 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
+ MarkedUnboxed
+ -> 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
\end{code}
-- 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
arity = 1 + n_dict_tys + n_field_dict_tys
info = noCafNoTyGenIdInfo
`setCgInfo` (CgInfo arity caf_info)
- `setArityInfo` exactArity arity
+ `setArityInfo` arity
`setUnfoldingInfo` unfolding
-- ToDo: consider adding further IdInfo
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 data_id
+ | otherwise = Case (Var data_id) data_id (default_alt ++ the_alts)
mk_maybe_alt data_con
= case maybe_the_arg_id of
Nothing -> Nothing
- Just the_arg_id -> Just (DataAlt data_con, real_args, expr)
+ 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
- strict_marks = dataConStrictMarks data_con
- (expr, real_args) = rebuildConArgs data_con arg_ids strict_marks body
- (length arg_ids + 1)
+ body = mkVarApps (mkVarApps (Var the_arg_id) field_tyvars) field_dict_ids
+ strict_marks = dataConStrictMarks data_con
+ (binds, real_args) = rebuildConArgs arg_ids strict_marks
+ (map mkBuiltinUnique [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
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).
+-- This rather ugly function converts the unpacked data con
+-- arguments back into their packed form.
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')
+ :: [Id] -- Source-level args
+ -> [StrictnessMark] -- Strictness annotations (per-arg)
+ -> [Unique] -- Uniques for the new Ids
+ -> ([CoreBind], [Id]) -- A binding for each source-level arg, plus
+ -- a list of the representation-level arguments
+-- e.g. data T = MkT Int !Int
+--
+-- rebuild [x::Int, y::Int] [Not, Unbox]
+-- = ([ y = I# t ], [x,t])
+
+rebuildConArgs [] stricts us = ([], [])
+
+-- Type variable case
+rebuildConArgs (arg:args) stricts us
+ | isTyVar arg
+ = let (binds, args') = rebuildConArgs args stricts us
+ in (binds, arg:args')
+
+-- Term variable case
+rebuildConArgs (arg:args) (str:stricts) us
+ | isMarkedUnboxed str
+ = let
+ arg_ty = idType arg
+
+ (_, tycon_args, pack_con, con_arg_tys)
+ = 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)
+ con_app = mkConApp pack_con (map Type tycon_args ++ map Var unpacked_args)
+ in
+ (NonRec arg con_app : binds, unpacked_args ++ args')
+
+ | otherwise
+ = let (binds, args') = rebuildConArgs args stricts us
+ in (binds, arg:args')
\end{code}
\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
+ `setArityInfo` 1
`setUnfoldingInfo` unfolding
-- We no longer use 'must-inline' on record selectors. They'll
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) 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_id
+ | isRecursiveTyCon tycon -- Recursive case; use a coerce
+ = Note (Coerce result_ty (idType result_id)) (Var result_id)
+ | otherwise -- Normal case
+ = Var result_id
\end{code}
info = noCafNoTyGenIdInfo
`setSpecInfo` rules
`setCgArity` arity
- `setArityInfo` exactArity arity
- `setStrictnessInfo` strict_info
+ `setArityInfo` arity
+ `setNewStrictnessInfo` Just (mkNewStrictnessInfo id arity strict_info NoCPRInfo)
+ -- Until we modify the primop generation code
rules = maybe emptyCoreRules (addRule emptyCoreRules id)
(primOpRule prim_op)
-- 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
+mkFCallId :: Unique -> ForeignCall -> Type -> Id
+mkFCallId uniq fcall 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
+ id
where
- occ_str = showSDocIface (braces (pprCCallOp ccall <+> ppr ty))
+ id = mkGlobalId (FCallId fcall) name ty info
+ occ_str = showSDocIface (braces (ppr fcall <+> 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
+ name = mkFCallName uniq occ_str
info = noCafNoTyGenIdInfo
- `setCgArity` arity
- `setArityInfo` exactArity arity
- `setStrictnessInfo` strict_info
+ `setCgArity` arity
+ `setArityInfo` arity
+ `setNewStrictnessInfo` 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 id arity (mkTopDmdType (replicate arity evalDmd) TopRes)
\end{code}
-- will be in "the right place" to be in scope.
pc_bottoming_Id key mod name ty
- = pcMiscPrelId key mod name ty bottoming_info
+ = id
where
- bottoming_info = noCafNoTyGenIdInfo
- `setStrictnessInfo` mkStrictnessInfo ([wwStrict], True)
-
+ id = pcMiscPrelId key mod name ty bottoming_info
+ arity = 1
+ strict_sig = mkStrictSig id arity (mkTopDmdType [evalDmd] BotRes)
+ bottoming_info = noCafNoTyGenIdInfo `setNewStrictnessInfo` Just strict_sig
-- these "bottom" out, no matter what their arguments
generic_ERROR_ID u n = pc_bottoming_Id u pREL_ERR n errorTy