[project @ 1999-11-29 17:34:14 by simonpj]
[ghc-hetmet.git] / ghc / compiler / basicTypes / MkId.lhs
index 216538e..158cc3d 100644 (file)
@@ -1,5 +1,5 @@
 %
-% (c) The AQUA Project, Glasgow University, 1994-1996
+% (c) The AQUA Project, Glasgow University, 1998
 %
 \section[StdIdInfo]{Standard unfoldings}
 
@@ -13,101 +13,132 @@ have a standard form, namely:
 
 \begin{code}
 module MkId (
-       mkImportedId,
-       mkUserId,
-       mkUserLocal, mkSysLocal, 
+       mkSpecPragmaId, mkWorkerId,
 
-       mkDataCon, mkTupleCon,
-
-       mkDictFunId,
-       mkMethodSelId, mkSuperDictSelId, mkDefaultMethodId,
+       mkDictFunId, mkDefaultMethodId,
+       mkDictSelId,
 
+       mkDataConId,
        mkRecordSelId,
-
-       mkPrimitiveId, 
-       mkWorkerId
-
+       mkNewTySelId,
+       mkPrimitiveId,
+
+       -- 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,
+       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"
 
-import {-# SOURCE #-} CoreUnfold ( mkUnfolding )
 
-import Type
-import CoreSyn
-import Literal
-import TysWiredIn      ( tupleCon )
-import Name            ( mkLocalName, mkSysLocalName, mkCompoundName, 
-                         occNameString, Name, OccName, NamedThing(..)
+import TysPrim         ( openAlphaTyVars, alphaTyVar, alphaTy, 
+                         intPrimTy, realWorldStatePrimTy
+                       )
+import TysWiredIn      ( boolTy, charTy, mkListTy )
+import PrelMods                ( pREL_ERR, pREL_GHC )
+import Type            ( Type, ThetaType,
+                         mkDictTy, mkTyConApp, mkTyVarTys, mkFunTys, mkFunTy, mkSigmaTy,
+                         isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfTypes,
+                         splitSigmaTy, splitFunTy_maybe, splitAlgTyConApp,
+                         splitFunTys, splitForAllTys, unUsgTy,
+                         mkUsgTy, UsageAnn(..)
+                       )
+import Module          ( Module )
+import CoreUnfold      ( mkTopUnfolding, mkCompulsoryUnfolding )
+import Subst           ( mkTopTyVarSubst, substTheta )
+import TyCon           ( TyCon, isNewTyCon, tyConDataCons, isDataTyCon )
+import Class           ( Class, classBigSig, classTyCon, classTyVars, classSelIds )
+import Var             ( Id, TyVar )
+import VarSet          ( isEmptyVarSet )
+import Const           ( Con(..) )
+import Name            ( mkDerivedName, mkWiredInIdName, mkLocalName, 
+                         mkWorkerOcc, mkSuperDictSelOcc,
+                         Name, NamedThing(..),
                        )
-import Id              ( idType, fIRST_TAG,
-                         mkTemplateLocals, mkId, mkVanillaId,
-                         dataConStrictMarks, dataConFieldLabels, dataConArgTys,
-                         recordSelectorFieldLabel, dataConSig,
-                         StrictnessMark(..),
-                         Id, IdDetails(..), GenId
+import OccName         ( mkSrcVarOcc )
+import PrimOp          ( PrimOp(DataToTagOp), primOpSig, mkPrimOpIdName )
+import Demand          ( wwStrict )
+import DataCon         ( DataCon, StrictnessMark(..), dataConStrictMarks, dataConFieldLabels, 
+                         dataConArgTys, dataConSig, dataConRawArgTys
                        )
-import IdInfo          ( noIdInfo,
-                         exactArity, setUnfoldingInfo, 
+import Id              ( idType, mkId,
+                         mkVanillaId, mkTemplateLocals,
+                         mkTemplateLocal, setInlinePragma
+                       )
+import IdInfo          ( vanillaIdInfo, mkIdInfo,
+                         exactArity, setUnfoldingInfo, setCafInfo,
                          setArityInfo, setInlinePragInfo,
-                         InlinePragInfo(..), IdInfo
+                         mkStrictnessInfo, setStrictnessInfo,
+                         IdFlavour(..), InlinePragInfo(..), CafInfo(..), IdInfo
                        )
-import Class           ( Class, classBigSig, classTyCon )
 import FieldLabel      ( FieldLabel, FieldLabelTag, mkFieldLabel, fieldLabelName, 
                          firstFieldLabelTag, allFieldLabelTags
                        )
-import TyVar           ( TyVar )
-import TyCon           ( TyCon, isNewTyCon, tyConDataCons, isDataTyCon )
-import PrelVals                ( rEC_SEL_ERROR_ID )
+import CoreSyn
 import Maybes
-import SrcLoc          ( SrcLoc )
 import BasicTypes      ( Arity )
-import Unique          ( Unique )
+import Unique
 import Maybe            ( isJust )
 import Outputable
 import Util            ( assoc )
+import List            ( nub )
 \end{code}             
 
 
 %************************************************************************
 %*                                                                     *
-\subsection{Easy ones}
+\subsection{Wired in Ids}
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
-mkImportedId :: Name -> ty -> IdInfo -> GenId ty
-mkImportedId name ty info = mkId name ty (VanillaId True) info
-
--- SysLocal: for an Id being created by the compiler out of thin air...
--- UserLocal: an Id with a name the user might recognize...
-mkSysLocal  :: FAST_STRING -> Unique -> (GenType flexi) -> SrcLoc -> GenId (GenType flexi)
-mkUserLocal :: OccName     -> Unique -> (GenType flexi) -> SrcLoc -> GenId (GenType flexi)
-
-mkSysLocal str uniq ty loc
-  = mkVanillaId (mkSysLocalName uniq str loc) ty noIdInfo
+wiredInIds
+  = [  -- These error-y things are wired in because we don't yet have
+       -- a way to express in an interface file that the result type variable
+       -- 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]
+
+      aBSENT_ERROR_ID
+    , eRROR_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 two can't be defined in Haskell
+    , realWorldPrimId
+    , unsafeCoerceId
+    , getTagId
+    ]
+\end{code}
 
-mkUserLocal occ uniq ty loc
-  = mkVanillaId (mkLocalName uniq occ loc) ty noIdInfo
+%************************************************************************
+%*                                                                     *
+\subsection{Easy ones}
+%*                                                                     *
+%************************************************************************
 
-mkUserId :: Name -> GenType flexi -> GenId (GenType flexi)
-mkUserId name ty
-  = mkVanillaId name ty noIdInfo
+\begin{code}
+mkSpecPragmaId occ uniq ty loc
+  = mkId (mkLocalName uniq occ loc) ty (mkIdInfo SpecPragmaId)
+       -- Maybe a SysLocal?  But then we'd lose the location
 
 mkDefaultMethodId dm_name rec_c ty
-  = mkVanillaId dm_name ty noIdInfo
+  = mkVanillaId dm_name ty
 
-mkDictFunId dfun_name full_ty clas itys
-  = mkVanillaId dfun_name full_ty noIdInfo
-
-mkWorkerId uniq unwrkr ty info
-  = mkVanillaId name ty info
-  where
-    name           = mkCompoundName name_fn uniq (getName unwrkr)
-    name_fn wkr_str = SLIT("$w") _APPEND_ wkr_str
+mkWorkerId uniq unwrkr ty
+  = mkVanillaId (mkDerivedName mkWorkerOcc (getName unwrkr) uniq) ty
 \end{code}
 
-
 %************************************************************************
 %*                                                                     *
 \subsection{Data constructors}
@@ -115,34 +146,16 @@ mkWorkerId uniq unwrkr ty info
 %************************************************************************
 
 \begin{code}
-mkDataCon :: Name
-         -> [StrictnessMark] -> [FieldLabel]
-         -> [TyVar] -> ThetaType
-         -> [TyVar] -> ThetaType
-         -> [TauType] -> TyCon
-         -> Id
-  -- can get the tag and all the pieces of the type from the Type
-
-mkDataCon name stricts fields tvs ctxt con_tvs con_ctxt args_tys tycon
-  = ASSERT(length stricts == length args_tys)
-    data_con
-  where
-    -- NB: data_con self-recursion; should be OK as tags are not
-    -- looked at until late in the game.
-    data_con = mkId name data_con_ty details (dataConInfo data_con)
-    details  = AlgConId data_con_tag stricts fields tvs ctxt con_tvs con_ctxt args_tys tycon
-
-    data_con_tag    = assoc "mkDataCon" (data_con_family `zip` [fIRST_TAG..]) data_con
-    data_con_family = tyConDataCons tycon
-    data_con_ty     = mkSigmaTy (tvs++con_tvs) (ctxt++con_ctxt)
-                               (mkFunTys args_tys (mkTyConApp tycon (mkTyVarTys tvs)))
-
-
-mkTupleCon :: Arity -> Name -> Type -> Id
-mkTupleCon arity name ty 
-  = con_id
+mkDataConId :: DataCon -> Id
+mkDataConId data_con
+  = mkId (getName data_con)
+        id_ty
+        (dataConInfo data_con)
   where
-    con_id = mkId name ty (TupleConId arity) (dataConInfo con_id)
+    (tyvars, theta, ex_tyvars, ex_theta, arg_tys, tycon) = dataConSig data_con
+    id_ty = mkSigmaTy (tyvars ++ ex_tyvars) 
+                     (theta ++ ex_theta)
+                     (mkFunTys arg_tys (mkTyConApp tycon (mkTyVarTys tyvars)))
 \end{code}
 
 We're going to build a constructor that looks like:
@@ -164,53 +177,88 @@ Notice that
 * We have to check that we can construct Data dictionaries for
   the types a and Int.  Once we've done that we can throw d1 away too.
 
-* We use (case p of ...) to evaluate p, rather than "seq" because
+* We use (case p of q -> ...) to evaluate p, rather than "seq" because
   all that matters is that the arguments are evaluated.  "seq" is 
   very careful to preserve evaluation order, which we don't need
   to be here.
 
+  You might think that we could simply give constructors some strictness
+  info, like PrimOps, and let CoreToStg do the let-to-case transformation.
+  But we don't do that because in the case of primops and functions strictness
+  is a *property* not a *requirement*.  In the case of constructors we need to
+  do something active to evaluate the argument.
+
+  Making an explicit case expression allows the simplifier to eliminate
+  it in the (common) case where the constructor arg is already evaluated.
+
 \begin{code}
-dataConInfo :: Id -> IdInfo
-
-dataConInfo con_id
-  = setInlinePragInfo IWantToBeINLINEd $
-               -- Always inline constructors if possible
-    setArityInfo (exactArity (length locals)) $
-    setUnfoldingInfo unfolding $
-    noIdInfo
+dataConInfo :: DataCon -> IdInfo
+
+dataConInfo data_con
+  = mkIdInfo (ConstantId (DataCon data_con))
+    `setArityInfo` exactArity (n_dicts + n_ex_dicts + n_id_args)
+    `setUnfoldingInfo` unfolding
   where
-        unfolding = mkUnfolding con_rhs
+        unfolding = mkTopUnfolding (Note InlineMe con_rhs)
+       -- The dictionary constructors of a class don't get a binding,
+       -- but they are always saturated, so they should always be inlined.
 
-       (tyvars, theta, con_tyvars, con_theta, arg_tys, tycon) = dataConSig con_id
+       (tyvars, theta, ex_tyvars, ex_theta, orig_arg_tys, tycon) 
+          = dataConSig data_con
+       rep_arg_tys = dataConRawArgTys data_con
+       all_tyvars   = tyvars ++ ex_tyvars
 
        dict_tys     = [mkDictTy clas tys | (clas,tys) <- theta]
-       con_dict_tys = [mkDictTy clas tys | (clas,tys) <- con_theta]
+       ex_dict_tys  = [mkDictTy clas tys | (clas,tys) <- ex_theta]
+
        n_dicts      = length dict_tys
+       n_ex_dicts   = length ex_dict_tys
+       n_id_args    = length orig_arg_tys
+       n_rep_args   = length rep_arg_tys
+
        result_ty    = mkTyConApp tycon (mkTyVarTys tyvars)
 
-       locals        = mkTemplateLocals (dict_tys ++ con_dict_tys ++ arg_tys)
-       data_args     = drop n_dicts locals
-       (data_arg1:_) = data_args               -- Used for newtype only
-       strict_marks  = dataConStrictMarks con_id
-       strict_args   = [arg | (arg,MarkedStrict) <- data_args `zip` strict_marks]
-               -- NB: we can't call mkTemplateLocals twice, because it
-               -- always starts from the same unique.
-
-       con_app | isNewTyCon tycon 
-               = ASSERT( length arg_tys == 1)
-                 Note (Coerce result_ty (head arg_tys)) (Var data_arg1)
-               | otherwise
-               = Con con_id (map TyArg (mkTyVarTys tyvars) ++ map VarArg data_args)
+       mkLocals i n tys   = (zipWith mkTemplateLocal [i..i+n-1] tys, i+n)
+       (dict_args, i1)    = mkLocals 1  n_dicts    dict_tys
+       (ex_dict_args,i2)  = mkLocals i1 n_ex_dicts ex_dict_tys
+       (id_args,i3)       = mkLocals i2 n_id_args  orig_arg_tys
 
-       con_rhs = mkTyLam tyvars $
-                 mkValLam locals $
-                 foldr mk_case con_app strict_args
+       (id_arg1:_) = id_args           -- Used for newtype only
+       strict_marks  = dataConStrictMarks data_con
 
-       mk_case arg body | isUnpointedType (idType arg)
-                        = body                 -- "!" on unboxed arg does nothing
-                        | otherwise
-                        = Case (Var arg) (AlgAlts [] (BindDefault arg body))
-                               -- This case shadows "arg" but that's fine
+       con_app i rep_ids
+                | isNewTyCon tycon 
+               = ASSERT( length orig_arg_tys == 1 )
+                 Note (Coerce result_ty (head orig_arg_tys)) (Var id_arg1)
+               | otherwise
+               = mkConApp data_con 
+                       (map Type (mkTyVarTys all_tyvars) ++ 
+                        map Var (reverse rep_ids))
+
+       con_rhs = 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 []
+
+       mk_case 
+          :: (Id, StrictnessMark)      -- arg, strictness
+          -> (Int -> [Id] -> CoreExpr) -- body
+          -> Int                       -- next rep arg id
+          -> [Id]                      -- rep args so far
+          -> CoreExpr
+       mk_case (arg,strict) body i rep_args
+         = case strict of
+               NotMarkedStrict -> body i (arg:rep_args)
+               MarkedStrict 
+                  | isUnLiftedType (idType arg) -> body i (arg:rep_args)
+                  | otherwise ->
+                       Case (Var arg) arg [(DEFAULT,[], body i (arg:rep_args))]
+
+               MarkedUnboxed con tys ->
+                  Case (Var arg) arg [(DataCon con, con_args,
+                                       body i' (reverse con_args++rep_args))]
+                  where n_tys = length tys
+                        (con_args,i') = mkLocals i (length tys) tys
 \end{code}
 
 
@@ -236,15 +284,15 @@ mkRecordSelId field_label selector_ty
   = ASSERT( null theta && isDataTyCon tycon )
     sel_id
   where
-    sel_id = mkId (fieldLabelName field_label) selector_ty
-                 (RecordSelId field_label) info
+    sel_id = mkId (fieldLabelName field_label) selector_ty info
 
-    info = exactArity 1        `setArityInfo` (
-          unfolding    `setUnfoldingInfo`
-          noIdInfo)
+    info = mkIdInfo (RecordSelId field_label)
+          `setArityInfo`       exactArity 1
+          `setUnfoldingInfo`   unfolding       
+          
        -- ToDo: consider adding further IdInfo
 
-    unfolding = mkUnfolding sel_rhs
+    unfolding = mkTopUnfolding sel_rhs
 
     (tyvars, theta, tau)  = splitSigmaTy selector_ty
     (data_ty,rhs_ty)      = expectJust "StdIdInfoRec" (splitFunTy_maybe tau)
@@ -254,58 +302,69 @@ mkRecordSelId field_label selector_ty
        
     [data_id] = mkTemplateLocals [data_ty]
     alts      = map mk_maybe_alt data_cons
-    sel_rhs   = mkTyLam tyvars $
-               mkValLam [data_id] $
-               Case (Var data_id) 
-                        -- if any of the constructors don't have the label, ...
-                    (if any (not . isJust) alts then
-                          AlgAlts (catMaybes alts) 
-                                  (BindDefault data_id error_expr)
-                     else
-                          AlgAlts (catMaybes alts) NoDefault)
+    the_alts  = catMaybes alts
+    default_alt | all isJust alts = [] -- No default needed
+               | otherwise       = [(DEFAULT, [], error_expr)]
+
+    sel_rhs   = mkLams tyvars $ Lam data_id $
+               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 (data_con, arg_ids, Var the_arg_id)
+               Just the_arg_id -> Just (DataCon data_con, arg_ids, Var the_arg_id)
          where
            arg_ids          = mkTemplateLocals (dataConArgTys 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 = mkApp (Var rEC_SEL_ERROR_ID) [rhs_ty] [LitArg msg_lit]
+    error_expr = mkApps (Var rEC_SEL_ERROR_ID) [Type (unUsgTy rhs_ty), mkStringLit full_msg]
+       -- preserves invariant that type args are *not* usage-annotated on top.  KSW 1999-04.
     full_msg   = showSDoc (sep [text "No match in record selector", ppr sel_id]) 
-    msg_lit    = NoRepStr (_PK_ full_msg)
 \end{code}
 
 
 %************************************************************************
 %*                                                                     *
-\subsection{Dictionary selectors}
+\subsection{Newtype field selectors}
 %*                                                                     *
 %************************************************************************
 
+Possibly overkill to do it this way:
+
 \begin{code}
-mkSuperDictSelId :: Unique -> Class -> FieldLabelTag -> Type -> Id
-       -- The FieldLabelTag says which superclass is selected
-       -- So, for 
-       --      class (C a, C b) => Foo a b where ...
-       -- we get superclass selectors
-       --      Foo_sc1, Foo_sc2
-
-mkSuperDictSelId uniq clas index ty
-  = mkDictSelId name clas ty
+mkNewTySelId field_label selector_ty = sel_id
   where
-    name    = mkCompoundName name_fn uniq (getName clas)
-    name_fn clas_str = clas_str _APPEND_ SLIT("_sc") _APPEND_ (_PK_ (show index))
+    sel_id = mkId (fieldLabelName field_label) selector_ty info
+                 
+
+    info = mkIdInfo (RecordSelId field_label)
+          `setArityInfo`       exactArity 1    
+          `setUnfoldingInfo`   unfolding
+          
+       -- ToDo: consider adding further IdInfo
 
-       -- For method selectors the clean thing to do is
-       -- to give the method selector the same name as the class op itself.
-mkMethodSelId name clas ty
-  = mkDictSelId name clas ty
+    unfolding = mkTopUnfolding sel_rhs
+
+    (tyvars, theta, tau)  = splitSigmaTy selector_ty
+    (data_ty,rhs_ty)      = expectJust "StdIdInfoRec" (splitFunTy_maybe tau)
+                                       -- tau is of form (T a b c -> field-type)
+    (tycon, _, data_cons) = splitAlgTyConApp data_ty
+    tyvar_tys            = mkTyVarTys tyvars
+       
+    [data_id] = mkTemplateLocals [data_ty]
+    sel_rhs   = mkLams tyvars $ Lam data_id $
+               Note (Coerce (unUsgTy rhs_ty) (unUsgTy data_ty)) (Var data_id)
 \end{code}
 
+
+%************************************************************************
+%*                                                                     *
+\subsection{Dictionary selectors}
+%*                                                                     *
+%************************************************************************
+
 Selecting a field for a dictionary.  If there is just one field, then
 there's nothing to do.
 
@@ -313,17 +372,19 @@ there's nothing to do.
 mkDictSelId name clas ty
   = sel_id
   where
-    sel_id    = mkId name ty (RecordSelId field_lbl) info
+    sel_id    = mkId name ty info
     field_lbl = mkFieldLabel name ty tag
-    tag       = assoc "MkId.mkDictSelId" ((sc_sel_ids ++ op_sel_ids) `zip` allFieldLabelTags) sel_id
+    tag       = assoc "MkId.mkDictSelId" (classSelIds clas `zip` allFieldLabelTags) sel_id
 
-    info      = setInlinePragInfo IWantToBeINLINEd $
-               setUnfoldingInfo  unfolding noIdInfo
-       -- The always-inline thing means we don't need any other IdInfo
+    info      = mkIdInfo (RecordSelId field_lbl)
+               `setUnfoldingInfo`  unfolding
+               
+       -- We no longer use 'must-inline' on record selectors.  They'll
+       -- inline like crazy if they scrutinise a constructor
 
-    unfolding = mkUnfolding rhs
+    unfolding = mkTopUnfolding rhs
 
-    (tyvars, _, sc_sel_ids, op_sel_ids, defms) = classBigSig clas
+    tyvars  = classTyVars clas
 
     tycon      = classTyCon clas
     [data_con] = tyConDataCons tycon
@@ -334,11 +395,11 @@ mkDictSelId name clas ty
     dict_ty    = mkDictTy clas tyvar_tys
     (dict_id:arg_ids) = mkTemplateLocals (dict_ty : arg_tys)
 
-    rhs | isNewTyCon tycon = mkLam tyvars [dict_id] $
+    rhs | isNewTyCon tycon = mkLams tyvars $ Lam dict_id $
                             Note (Coerce (head arg_tys) dict_ty) (Var dict_id)
-       | otherwise        = mkLam tyvars [dict_id] $
-                            Case (Var dict_id) $
-                            AlgAlts [(data_con, arg_ids, Var the_arg_id)] NoDefault
+       | otherwise        = mkLams tyvars $ Lam dict_id $
+                            Case (Var dict_id) dict_id
+                                 [(DataCon data_con, arg_ids, Var the_arg_id)]
 \end{code}
 
 
@@ -348,40 +409,230 @@ mkDictSelId name clas ty
 %*                                                                     *
 %************************************************************************
 
-
 \begin{code}
-mkPrimitiveId name ty prim_op 
-  = mkId name ty (PrimitiveId prim_op) info
+mkPrimitiveId :: PrimOp -> Id
+mkPrimitiveId prim_op 
+  = id
   where
-
-    info = setUnfoldingInfo unfolding $
-          setInlinePragInfo IMustBeINLINEd $
-               -- The pragma @IMustBeINLINEd@ says that this Id absolutely 
+    (tyvars,arg_tys,res_ty) = primOpSig prim_op
+    ty   = mkForAllTys tyvars (mkFunTys arg_tys res_ty)
+    name = mkPrimOpIdName prim_op id
+    id   = mkId name ty info
+               
+    info = mkIdInfo (ConstantId (PrimOp prim_op))
+          `setUnfoldingInfo`   unfolding
+
+    unfolding = mkCompulsoryUnfolding rhs
+               -- The mkCompulsoryUnfolding says that this Id absolutely 
                -- must be inlined.  It's only used for primitives, 
                -- because we don't want to make a closure for each of them.
-          noIdInfo
 
-    unfolding = mkUnfolding rhs
+    args = mkTemplateLocals arg_tys
+    rhs =  mkLams tyvars $ mkLams args $
+          mkPrimApp prim_op (map Type (mkTyVarTys tyvars) ++ map Var args)
+\end{code}
 
-    (tyvars, tau) = splitForAllTys ty
-    (arg_tys, _)  = splitFunTys tau
 
-    args = mkTemplateLocals arg_tys
-    rhs =  mkLam tyvars args $
-          Prim prim_op
-               ([TyArg (mkTyVarTy tv) | tv <- tyvars] ++ 
-                [VarArg v | v <- args])
+%************************************************************************
+%*                                                                     *
+\subsection{DictFuns}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+mkDictFunId :: Name            -- Name to use for the dict fun;
+           -> Class 
+           -> [TyVar]
+           -> [Type]
+           -> ThetaType
+           -> Id
+
+mkDictFunId dfun_name clas inst_tyvars inst_tys inst_decl_theta
+  = mkVanillaId dfun_name dfun_ty
+  where
+    (class_tyvars, sc_theta, _, _) = classBigSig clas
+    sc_theta' = substTheta (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
+                               -- expose the constant methods.
+
+                  other -> nub (inst_decl_theta ++ filter not_const sc_theta')
+                               -- Otherwise we pass the superclass dictionaries to
+                               -- the dictionary function; the Mark Jones optimisation.
+                               --
+                               -- NOTE the "nub".  I got caught by this one:
+                               --   class Monad m => MonadT t m where ...
+                               --   instance Monad m => MonadT (EnvT env) m where ...
+                               -- Here, the inst_decl_theta has (Monad m); but so
+                               -- does the sc_theta'!
+                               --
+                               -- NOTE the "not_const".  I got caught by this one too:
+                               --   class Foo a => Baz a b where ...
+                               --   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}
+
+
+%************************************************************************
+%*                                                                     *
+\subsection{Un-definable}
+%*                                                                     *
+%************************************************************************
+
+These two can't be defined in Haskell.
+
+unsafeCoerce# isn't so much a PrimOp as a phantom identifier, that
+just gets expanded into a type coercion wherever it occurs.  Hence we
+add it as a built-in Id with an unfolding here.
+
+The type variables we use here are "open" type variables: this means
+they can unify with both unlifted and lifted types.  Hence we provide
+another gun with which to shoot yourself in the foot.
+
+\begin{code}
+unsafeCoerceId
+  = pcMiscPrelId unsafeCoerceIdKey pREL_GHC SLIT("unsafeCoerce#") ty info
+  where
+    info = vanillaIdInfo
+          `setUnfoldingInfo` mkCompulsoryUnfolding rhs
+          
+
+    ty  = mkForAllTys [openAlphaTyVar,openBetaTyVar]
+                     (mkFunTy openAlphaTy openBetaTy)
+    [x] = mkTemplateLocals [openAlphaTy]
+    rhs = mkLams [openAlphaTyVar,openBetaTyVar,x] $
+         Note (Coerce openBetaTy openAlphaTy) (Var x)
+\end{code}
+
+
+@getTag#@ is another function which can't be defined in Haskell.  It needs to
+evaluate its argument and call the dataToTag# primitive.
+
+\begin{code}
+getTagId
+  = pcMiscPrelId getTagIdKey pREL_GHC SLIT("getTag#") ty info
+  where
+    info = vanillaIdInfo
+          `setUnfoldingInfo`   mkCompulsoryUnfolding rhs
+       -- We don't provide a defn for this; you must inline it
+
+    ty = mkForAllTys [alphaTyVar] (mkFunTy alphaTy intPrimTy)
+    [x,y] = mkTemplateLocals [alphaTy,alphaTy]
+    rhs = mkLams [alphaTyVar,x] $
+         Case (Var x) y [ (DEFAULT, [], 
+                  Con (PrimOp DataToTagOp) [Type alphaTy, Var y]) ]
+\end{code}
+
+@realWorld#@ used to be a magic literal, \tr{void#}.  If things get
+nasty as-is, change it back to a literal (@Literal@).
+
+\begin{code}
+realWorldPrimId        -- :: State# RealWorld
+  = pcMiscPrelId realWorldPrimIdKey pREL_GHC SLIT("realWorld#")
+                realWorldStatePrimTy
+                noCafIdInfo
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
+\subsection[PrelVals-error-related]{@error@ and friends; @trace@}
+%*                                                                     *
+%************************************************************************
+
+GHC randomly injects these into the code.
+
+@patError@ is just a version of @error@ for pattern-matching
+failures.  It knows various ``codes'' which expand to longer
+strings---this saves space!
+
+@absentErr@ is a thing we put in for ``absent'' arguments.  They jolly
+well shouldn't be yanked on, but if one is, then you will get a
+friendly message from @absentErr@ (rather than a totally random
+crash).
+
+@parError@ is a special version of @error@ which the compiler does
+not know to be a bottoming Id.  It is used in the @_par_@ and @_seq_@
+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
+rEC_SEL_ERROR_ID
+  = generic_ERROR_ID recSelErrIdKey SLIT("patError")
+pAT_ERROR_ID
+  = generic_ERROR_ID patErrorIdKey SLIT("patError")
+rEC_CON_ERROR_ID
+  = generic_ERROR_ID recConErrorIdKey SLIT("recConError")
+rEC_UPD_ERROR_ID
+  = generic_ERROR_ID recUpdErrorIdKey SLIT("recUpdError")
+iRREFUT_PAT_ERROR_ID
+  = generic_ERROR_ID irrefutPatErrorIdKey SLIT("irrefutPatError")
+nON_EXHAUSTIVE_GUARDS_ERROR_ID
+  = generic_ERROR_ID nonExhaustiveGuardsErrorIdKey SLIT("nonExhaustiveGuardsError")
+nO_METHOD_BINDING_ERROR_ID
+  = generic_ERROR_ID noMethodBindingErrorIdKey SLIT("noMethodBindingError")
+
+aBSENT_ERROR_ID
+  = pc_bottoming_Id absentErrorIdKey pREL_ERR SLIT("absentErr")
+       (mkSigmaTy [openAlphaTyVar] [] openAlphaTy)
+
+pAR_ERROR_ID
+  = pcMiscPrelId parErrorIdKey pREL_ERR SLIT("parError")
+    (mkSigmaTy [openAlphaTyVar] [] openAlphaTy) noCafIdInfo
+
 \end{code}
 
 
 %************************************************************************
 %*                                                                     *
-\subsection{Catch-all}
+\subsection{Utilities}
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
-addStandardIdInfo id
-  = pprTrace "addStandardIdInfo missing:" (ppr id) id
+pcMiscPrelId :: Unique{-IdKey-} -> Module -> FAST_STRING -> Type -> IdInfo -> Id
+pcMiscPrelId key mod str ty info
+  = let
+       name = mkWiredInIdName key mod (mkSrcVarOcc str) imp
+       imp  = mkId name ty info -- the usual case...
+    in
+    imp
+    -- We lie and say the thing is imported; otherwise, we get into
+    -- a mess with dependency analysis; e.g., core2stg may heave in
+    -- random calls to GHCbase.unpackPS__.  If GHCbase is the module
+    -- being compiled, then it's just a matter of luck if the definition
+    -- will be in "the right place" to be in scope.
+
+pc_bottoming_Id key mod name ty
+ = pcMiscPrelId key mod name ty bottoming_info
+ where
+    bottoming_info = noCafIdInfo 
+                    `setStrictnessInfo` mkStrictnessInfo ([wwStrict], True)
+                    
+       -- these "bottom" out, no matter what their arguments
+
+generic_ERROR_ID u n = pc_bottoming_Id u pREL_ERR n errorTy
+
+-- Very useful...
+noCafIdInfo = vanillaIdInfo `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))
+    -- 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.
 \end{code}