import TysPrim ( openAlphaTyVars, alphaTyVar, alphaTy,
intPrimTy, realWorldStatePrimTy
)
-import TysWiredIn ( boolTy, charTy, mkListTy )
-import PrelMods ( pREL_ERR, pREL_GHC )
+import TysWiredIn ( charTy, mkListTy )
+import PrelNames ( pREL_ERR, pREL_GHC )
import PrelRules ( primOpRule )
import Rules ( addRule )
-import Type ( Type, ClassContext, mkDictTy, mkDictTys, mkTyConApp, mkTyVarTys,
- mkFunTys, mkFunTy, mkSigmaTy, classesToPreds,
- isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType, tyVarsOfTypes,
- splitSigmaTy, splitFunTy_maybe,
- splitFunTys, splitForAllTys, unUsgTy,
- mkUsgTy, UsageAnn(..)
+import Type ( Type, ThetaType, mkDictTy, mkDictTys, mkTyConApp, mkTyVarTys,
+ mkFunTys, mkFunTy, mkSigmaTy,
+ isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType,
+ splitFunTys, splitForAllTys
)
-import PprType ( pprParendType )
import Module ( Module )
import CoreUtils ( exprType, mkInlineMe )
import CoreUnfold ( mkTopUnfolding, mkCompulsoryUnfolding, mkOtherCon )
-import Subst ( mkTopTyVarSubst, substClasses )
-import TyCon ( TyCon, isNewTyCon, tyConTyVars, tyConDataCons, isDataTyCon,
+import Literal ( Literal(..) )
+import TyCon ( TyCon, isNewTyCon, tyConTyVars, tyConDataCons,
tyConTheta, isProductTyCon, isUnboxedTupleTyCon )
-import Class ( Class, classBigSig, classTyCon, classTyVars, classSelIds )
+import Class ( Class, classTyCon, classTyVars, classSelIds )
import Var ( Id, TyVar )
import VarSet ( isEmptyVarSet )
-import Name ( mkDerivedName, mkWiredInIdName, mkLocalName,
- mkWorkerOcc, mkSuperDictSelOcc, mkCCallName,
+import Name ( mkDerivedName, mkWiredInName, mkLocalName,
+ mkWorkerOcc, mkCCallName,
Name, NamedThing(..),
)
-import OccName ( mkSrcVarOcc )
+import OccName ( mkVarOcc )
import PrimOp ( PrimOp(DataToTagOp, CCallOp),
primOpSig, mkPrimOpIdName,
CCall, pprCCallOp
)
-import Demand ( wwStrict, wwPrim )
+import Demand ( wwStrict, wwPrim, mkStrictnessInfo )
import DataCon ( DataCon, StrictnessMark(..),
dataConFieldLabels, dataConRepArity, dataConTyCon,
dataConArgTys, dataConRepType, dataConRepStrictness,
+ dataConInstOrigArgTys,
dataConName, dataConTheta,
- dataConSig, dataConStrictMarks, dataConId
+ dataConSig, dataConStrictMarks, dataConId,
+ maybeMarkedUnboxed, splitProductType_maybe
)
import Id ( idType, mkId,
mkVanillaId, mkTemplateLocals,
- mkTemplateLocal, setInlinePragma, idCprInfo
+ mkTemplateLocal, idCprInfo
)
-import IdInfo ( IdInfo, vanillaIdInfo, mkIdInfo,
+import IdInfo ( IdInfo, constantIdInfo, mkIdInfo,
exactArity, setUnfoldingInfo, setCafInfo, setCprInfo,
- setArityInfo, setInlinePragInfo, setSpecInfo,
+ setArityInfo, setSpecInfo, setTyGenInfo,
mkStrictnessInfo, setStrictnessInfo,
- IdFlavour(..), InlinePragInfo(..), CafInfo(..), StrictnessInfo(..), CprInfo(..)
+ IdFlavour(..), CafInfo(..), CprInfo(..), TyGenInfo(..)
)
-import FieldLabel ( FieldLabel, FieldLabelTag, mkFieldLabel, fieldLabelName,
+import FieldLabel ( mkFieldLabel, fieldLabelName,
firstFieldLabelTag, allFieldLabelTags, fieldLabelType
)
import CoreSyn
import Maybes
-import BasicTypes ( Arity )
-import 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}
-- 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]
+ -- 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
-- Maybe a SysLocal? But then we'd lose the location
mkDefaultMethodId dm_name rec_c ty
- = mkVanillaId dm_name ty
+ = 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 uniq unwrkr ty
= mkVanillaId (mkDerivedName mkWorkerOcc (getName unwrkr) uniq) ty
arity = dataConRepArity data_con
- strict_info = StrictnessInfo (dataConRepStrictness data_con) False
+ strict_info = mkStrictnessInfo (dataConRepStrictness data_con, False)
cpr_info | isProductTyCon tycon &&
not (isUnboxedTupleTyCon tycon) &&
-- The wrapper Id ends up in STG code as an argument,
-- sometimes before its definition, so we want to
-- signal that it has no CAFs
+ `setTyGenInfo` TyGenNever
+ -- No point generalising its type, since it gets eagerly inlined
+ -- away anyway
wrap_ty = mkForAllTys all_tyvars $
mkFunTys all_arg_tys
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 contex
+ -- 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)
-{- I nuked this because map (:) xs would create a
- new local lambda for the (:) in core-to-stg.
- There isn't a defn for the worker!
-
| 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
-- becomes
-- f $w: x
-- This is really important in rule matching,
- -- which is a bit sad. (We could match on the wrappers,
+ -- (We could match on the wrappers,
-- but that makes it less likely that rules will match
- -- when we bring bits of unfoldings together
--}
+ -- 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 $
MarkedUnboxed con tys ->
Case (Var arg) arg [(DataAlt con, con_args,
body i' (reverse con_args++rep_args))]
- where n_tys = length tys
- (con_args,i') = mkLocals i tys
+ where
+ (con_args,i') = mkLocals i tys
\end{code}
unN = /\a -> \n:N -> coerce (a->a) n
\begin{code}
-mkRecordSelId tycon field_label
- -- Assumes that all fields with the same field label
- -- have the same type
+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 info
field_ty = fieldLabelType field_label
- field_name = fieldLabelName field_label
data_cons = tyConDataCons tycon
tyvars = tyConTyVars tycon -- These scope over the types in
-- the FieldLabels of constructors of this type
mkFunTys dict_tys $ mkFunTy data_ty field_tau
info = mkIdInfo (RecordSelId field_label)
- `setArityInfo` exactArity 1
+ `setArityInfo` exactArity (1 + length dict_tys)
`setUnfoldingInfo` unfolding
`setCafInfo` NoCafRefs
+ `setTyGenInfo` TyGenNever
-- ToDo: consider adding further IdInfo
unfolding = mkTopUnfolding sel_rhs
default_alt | all isJust alts = [] -- No default needed
| otherwise = [(DEFAULT, [], error_expr)]
- sel_rhs | isNewTyCon tycon = new_sel_rhs
- | otherwise = data_sel_rhs
+ sel_rhs = mkLams tyvars $ mkLams field_tyvars $
+ mkLams dict_ids $ Lam data_id $
+ sel_body
- data_sel_rhs = mkLams tyvars $ mkLams field_tyvars $
- mkLams dict_ids $ Lam data_id $
- Case (Var data_id) data_id (the_alts ++ default_alt)
-
- new_sel_rhs = mkLams tyvars $ mkLams field_tyvars $ Lam data_id $
- Note (Coerce (unUsgTy field_tau) (unUsgTy data_ty)) (Var data_id)
+ 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, arg_ids,
- mkVarApps (Var the_arg_id) field_tyvars)
- 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 = mkApps (Var rEC_SEL_ERROR_ID) [Type (unUsgTy field_tau), mkStringLit full_msg]
- -- preserves invariant that type args are *not* usage-annotated on top. KSW 1999-04.
+ 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}
ToDo: unify with mkRecordSelId.
\begin{code}
+mkDictSelId :: Name -> Class -> Id
mkDictSelId name clas
= sel_id
where
ty = exprType rhs
sel_id = mkId name ty info
- field_lbl = mkFieldLabel name ty tag
+ field_lbl = mkFieldLabel name tycon ty tag
tag = assoc "MkId.mkDictSelId" (classSelIds clas `zip` allFieldLabelTags) sel_id
info = mkIdInfo (RecordSelId field_lbl)
`setArityInfo` exactArity 1
`setUnfoldingInfo` unfolding
`setCafInfo` NoCafRefs
+ `setTyGenInfo` TyGenNever
-- We no longer use 'must-inline' on record selectors. They'll
-- inline like crazy if they scrutinise a constructor
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
+ name = mkPrimOpIdName prim_op
id = mkId name ty info
info = mkIdInfo (PrimOpId prim_op)
`setArityInfo` exactArity arity
`setStrictnessInfo` strict_info
- rules = addRule id emptyCoreRules (primOpRule prim_op)
+ rules = addRule emptyCoreRules id (primOpRule prim_op)
-- For each ccall we manufacture a separate CCallOpId, giving it
-> Class
-> [TyVar]
-> [Type]
- -> ClassContext
+ -> 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
+ = mkId dfun_name dfun_ty info
where
- (class_tyvars, sc_theta, _, _) = classBigSig clas
- sc_theta' = substClasses (mkTopTyVarSubst class_tyvars inst_tys) sc_theta
-
- dfun_theta = classesToPreds inst_decl_theta
+ dfun_ty = mkSigmaTy inst_tyvars dfun_theta (mkDictTy clas inst_tys)
+ info = constantIdInfo `setTyGenInfo` TyGenNever
+ -- type is wired-in (see comment at TcClassDcl.tcClassSig), so
+ -- do not generalise it
{- 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
-- instance Wob b => Baz T b where..
-- Now sc_theta' has Foo T
-}
- dfun_ty = mkSigmaTy inst_tyvars dfun_theta (mkDictTy clas inst_tys)
-
- not_const (clas, tys) = not (isEmptyVarSet (tyVarsOfTypes tys))
\end{code}
unsafeCoerceId
= pcMiscPrelId unsafeCoerceIdKey pREL_GHC SLIT("unsafeCoerce#") ty info
where
- info = vanillaIdInfo
- `setUnfoldingInfo` mkCompulsoryUnfolding rhs
+ info = constantIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
ty = mkForAllTys [openAlphaTyVar,openBetaTyVar]
getTagId
= pcMiscPrelId getTagIdKey pREL_GHC SLIT("getTag#") ty info
where
- info = vanillaIdInfo
+ info = constantIdInfo
`setUnfoldingInfo` mkCompulsoryUnfolding rhs
-- We don't provide a defn for this; you must inline it
\begin{code}
eRROR_ID
= pc_bottoming_Id errorIdKey pREL_ERR SLIT("error") errorTy
-rEC_SEL_ERROR_ID
- = generic_ERROR_ID recSelErrIdKey SLIT("patError")
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
pcMiscPrelId :: Unique{-IdKey-} -> Module -> FAST_STRING -> Type -> IdInfo -> Id
pcMiscPrelId key mod str ty info
= let
- name = mkWiredInIdName key mod (mkSrcVarOcc str) imp
+ name = mkWiredInName mod (mkVarOcc str) key
imp = mkId name ty info -- the usual case...
in
imp
generic_ERROR_ID u n = pc_bottoming_Id u pREL_ERR n errorTy
-- Very useful...
-noCafIdInfo = vanillaIdInfo `setCafInfo` NoCafRefs
+noCafIdInfo = constantIdInfo `setCafInfo` NoCafRefs
(openAlphaTyVar:openBetaTyVar:_) = openAlphaTyVars
openAlphaTy = mkTyVarTy openAlphaTyVar
openBetaTy = mkTyVarTy openBetaTyVar
errorTy :: Type
-errorTy = mkUsgTy UsMany $
- mkSigmaTy [openAlphaTyVar] [] (mkFunTys [mkUsgTy UsOnce (mkListTy charTy)]
- (mkUsgTy UsMany openAlphaTy))
+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.