mkPrimOpId, mkFCallId,
-- And some particular Ids; see below for why they are wired in
- wiredInIds,
- unsafeCoerceId, realWorldPrimId, 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
+ wiredInIds, ghcPrimIds,
+ 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
#include "HsVersions.h"
tcSplitFunTys, tcSplitForAllTys, mkPredTy
)
import Module ( Module )
-import CoreUtils ( mkInlineMe )
+import CoreUtils ( exprType )
import CoreUnfold ( mkTopUnfolding, mkCompulsoryUnfolding, mkOtherCon )
import Literal ( Literal(..), nullAddrLit )
import TyCon ( TyCon, isNewTyCon, tyConTyVars, tyConDataCons,
)
import IdInfo ( IdInfo, noCafNoTyGenIdInfo,
setUnfoldingInfo,
- setArityInfo, setSpecInfo, setCgInfo, setCafInfo,
- mkNewStrictnessInfo, setNewStrictnessInfo,
- GlobalIdDetails(..), CafInfo(..), CprInfo(..),
- CgInfo
+ setArityInfo, setSpecInfo, setCafInfo,
+ setAllStrictnessInfo,
+ GlobalIdDetails(..), CafInfo(..)
)
import NewDemand ( mkStrictSig, strictSigResInfo, DmdResult(..),
- mkTopDmdType, topDmd, evalDmd, Demand(..), Keepity(..) )
+ mkTopDmdType, topDmd, evalDmd, lazyDmd,
+ Demand(..), Demands(..) )
import FieldLabel ( mkFieldLabel, fieldLabelName,
firstFieldLabelTag, allFieldLabelTags, fieldLabelType
)
import Maybes
import PrelNames
import Maybe ( isJust )
+import Util ( dropList, isSingleton )
import Outputable
import ListSetOps ( assoc, assocMaybe )
import UnicodeUtil ( stringToUtf8 )
-- 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
- , pAR_ERROR_ID
- , pAT_ERROR_ID
- , rEC_CON_ERROR_ID
- , rEC_UPD_ERROR_ID
-
- -- These can't be defined in Haskell, but they have
+ aBSENT_ERROR_ID,
+ eRROR_ID,
+ eRROR_CSTRING_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
+ ] ++ ghcPrimIds
+
+-- These Ids are exported from GHC.Prim
+ghcPrimIds
+ = [ -- These can't be defined in Haskell, but they have
-- perfectly reasonable unfoldings in Core
- , realWorldPrimId
- , unsafeCoerceId
- , nullAddrId
- , getTagId
- , seqId
+ realWorldPrimId,
+ unsafeCoerceId,
+ nullAddrId,
+ getTagId,
+ seqId
]
\end{code}
where
info = noCafNoTyGenIdInfo
`setArityInfo` arity
- `setNewStrictnessInfo` Just strict_sig
+ `setAllStrictnessInfo` Just strict_sig
arity = dataConRepArity data_con
work_id = dataConId data_con
info = noCafNoTyGenIdInfo
- `setUnfoldingInfo` mkTopUnfolding (mkInlineMe wrap_rhs)
+ `setUnfoldingInfo` wrap_unf
-- The NoCaf-ness is set by noCafNoTyGenIdInfo
`setArityInfo` arity
-- It's important to specify the arity, so that partial
-- applications are treated as values
- `setNewStrictnessInfo` Just wrap_sig
+ `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 = Eval
- | otherwise = Lazy
+ mk_dmd str | isMarkedStrict str = evalDmd
+ | otherwise = lazyDmd
-- The Cpr info can be important inside INLINE rhss, where the
- -- wrapper constructor isn't inlined
+ -- 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:
-- ...(let w = C x in ...(w p q)...)...
-- we want to see that w is strict in its two arguments
- wrap_rhs | isNewTyCon tycon
- = ASSERT( null ex_tyvars && null ex_dict_args && length orig_arg_tys == 1 )
+ 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 (...)
+ mkTopUnfolding $ Note InlineMe $
mkLams tyvars $ mkLams dict_args $ Lam id_arg1 $
- mkNewTypeBody tycon result_ty 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 []
`setCafInfo` caf_info
`setArityInfo` arity
`setUnfoldingInfo` mkTopUnfolding rhs_w_str
- `setNewStrictnessInfo` Just strict_sig
+ `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
mkLams dict_ids $ mkLams field_dict_ids $
Lam data_id $ sel_body
- sel_body | isNewTyCon tycon = mkNewTypeBody tycon field_tau data_id
+ 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..])
(_, 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)
+ unpacked_args = zipWith (mkSysLocal FSLIT("rb")) us con_arg_tys
+ (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 con_app : binds, unpacked_args ++ args')
info = noCafNoTyGenIdInfo
`setArityInfo` 1
`setUnfoldingInfo` mkTopUnfolding rhs
- `setNewStrictnessInfo` Just strict_sig
+ `setAllStrictnessInfo` Just strict_sig
-- We no longer use 'must-inline' on record selectors. They'll
-- inline like crazy if they scrutinise a constructor
-- 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 = Eval
- | otherwise = Seq Drop [ if the_arg_id == id then Eval else Abs
- | id <- arg_ids ]
+ arg_dmd | isNewTyCon tycon = evalDmd
+ | otherwise = Eval (Prod [ if the_arg_id == id then evalDmd else Abs
+ | id <- arg_ids ])
tyvars = classTyVars clas
(dict_id:arg_ids) = mkTemplateLocals (mkPredTy pred : arg_tys)
rhs | isNewTyCon tycon = mkLams tyvars $ Lam dict_id $
- mkNewTypeBody tycon (head arg_tys) 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_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 (idType result_id)) (Var result_id)
+ = Note (Coerce result_ty (exprType result_expr)) result_expr
| otherwise -- Normal case
- = Var result_id
+ = result_expr
\end{code}
mkPrimOpId prim_op
= id
where
- (tyvars,arg_tys,res_ty, arity, strict_info) = primOpSig prim_op
+ (tyvars,arg_tys,res_ty, arity, strict_sig) = primOpSig prim_op
ty = mkForAllTys tyvars (mkFunTys arg_tys res_ty)
name = mkPrimOpIdName prim_op
id = mkGlobalId (PrimOpId prim_op) name ty info
info = noCafNoTyGenIdInfo
`setSpecInfo` rules
`setArityInfo` arity
- `setNewStrictnessInfo` Just (mkNewStrictnessInfo id arity strict_info NoCPRInfo)
- -- Until we modify the primop generation code
+ `setAllStrictnessInfo` Just strict_sig
rules = foldl (addRule id) emptyCoreRules (primOpRules prim_op)
info = noCafNoTyGenIdInfo
`setArityInfo` arity
- `setNewStrictnessInfo` Just strict_sig
+ `setAllStrictnessInfo` Just strict_sig
(_, tau) = tcSplitForAllTys ty
(arg_tys, _) = tcSplitFunTys tau
\begin{code}
-- unsafeCoerce# :: forall a b. a -> b
unsafeCoerceId
- = pcMiscPrelId unsafeCoerceIdKey pREL_GHC SLIT("unsafeCoerce#") ty info
+ = pcMiscPrelId unsafeCoerceIdKey gHC_PRIM FSLIT("unsafeCoerce#") ty info
where
info = noCafNoTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
-- 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
+ = pcMiscPrelId nullAddrIdKey gHC_PRIM FSLIT("nullAddr#") addrPrimTy info
where
info = noCafNoTyGenIdInfo `setUnfoldingInfo`
mkCompulsoryUnfolding (Lit nullAddrLit)
seqId
- = pcMiscPrelId seqIdKey pREL_GHC SLIT("seq") ty info
+ = pcMiscPrelId seqIdKey gHC_PRIM FSLIT("seq") ty info
where
info = noCafNoTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
\begin{code}
getTagId
- = pcMiscPrelId getTagIdKey pREL_GHC SLIT("getTag#") ty info
+ = pcMiscPrelId getTagIdKey gHC_PRIM FSLIT("getTag#") ty info
where
info = noCafNoTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
-- We don't provide a defn for this; you must inline it
@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#")
+ = pcMiscPrelId realWorldPrimIdKey gHC_PRIM FSLIT("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
+
+voidArgId -- :: State# RealWorld
+ = mkSysLocal FSLIT("void") voidArgIdKey realWorldStatePrimTy
\end{code}
\begin{code}
eRROR_ID
- = pc_bottoming_Id errorIdKey pREL_ERR SLIT("error") errorTy
+ = pc_bottoming_Id errorIdKey pREL_ERR FSLIT("error") errorTy
eRROR_CSTRING_ID
- = pc_bottoming_Id errorCStringIdKey pREL_ERR SLIT("errorCString")
+ = pc_bottoming_Id errorCStringIdKey pREL_ERR FSLIT("errorCString")
(mkSigmaTy [openAlphaTyVar] [] (mkFunTy addrPrimTy openAlphaTy))
pAT_ERROR_ID
- = generic_ERROR_ID patErrorIdKey SLIT("patError")
+ = generic_ERROR_ID patErrorIdKey FSLIT("patError")
rEC_SEL_ERROR_ID
- = generic_ERROR_ID recSelErrIdKey SLIT("recSelError")
+ = generic_ERROR_ID recSelErrIdKey FSLIT("recSelError")
rEC_CON_ERROR_ID
- = generic_ERROR_ID recConErrorIdKey SLIT("recConError")
+ = generic_ERROR_ID recConErrorIdKey FSLIT("recConError")
rEC_UPD_ERROR_ID
- = generic_ERROR_ID recUpdErrorIdKey SLIT("recUpdError")
+ = generic_ERROR_ID recUpdErrorIdKey FSLIT("recUpdError")
iRREFUT_PAT_ERROR_ID
- = generic_ERROR_ID irrefutPatErrorIdKey SLIT("irrefutPatError")
+ = generic_ERROR_ID irrefutPatErrorIdKey FSLIT("irrefutPatError")
nON_EXHAUSTIVE_GUARDS_ERROR_ID
- = generic_ERROR_ID nonExhaustiveGuardsErrorIdKey SLIT("nonExhaustiveGuardsError")
+ = generic_ERROR_ID nonExhaustiveGuardsErrorIdKey FSLIT("nonExhaustiveGuardsError")
nO_METHOD_BINDING_ERROR_ID
- = generic_ERROR_ID noMethodBindingErrorIdKey SLIT("noMethodBindingError")
+ = generic_ERROR_ID noMethodBindingErrorIdKey FSLIT("noMethodBindingError")
aBSENT_ERROR_ID
- = pc_bottoming_Id absentErrorIdKey pREL_ERR SLIT("absentErr")
+ = pc_bottoming_Id absentErrorIdKey pREL_ERR FSLIT("absentErr")
(mkSigmaTy [openAlphaTyVar] [] openAlphaTy)
pAR_ERROR_ID
- = pcMiscPrelId parErrorIdKey pREL_ERR SLIT("parError")
+ = pcMiscPrelId parErrorIdKey pREL_ERR FSLIT("parError")
(mkSigmaTy [openAlphaTyVar] [] openAlphaTy) noCafNoTyGenIdInfo
\end{code}
= pcMiscPrelId key mod name ty bottoming_info
where
strict_sig = mkStrictSig (mkTopDmdType [evalDmd] BotRes)
- bottoming_info = noCafNoTyGenIdInfo `setNewStrictnessInfo` Just strict_sig
+ 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