[project @ 2002-03-05 14:18:53 by simonmar]
[ghc-hetmet.git] / ghc / compiler / basicTypes / MkId.lhs
index 5e1165c..11dcc39 100644 (file)
@@ -21,36 +21,36 @@ module MkId (
        mkPrimOpId, mkFCallId,
 
        -- 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
+       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"
 
 
-import BasicTypes      ( Arity )
-import TysPrim         ( openAlphaTyVars, alphaTyVar, alphaTy, 
-                         intPrimTy, realWorldStatePrimTy
+import BasicTypes      ( Arity, StrictnessMark(..), isMarkedUnboxed, isMarkedStrict )
+import TysPrim         ( openAlphaTyVars, alphaTyVar, alphaTy, betaTyVar, betaTy,
+                         intPrimTy, realWorldStatePrimTy, addrPrimTy
                        )
 import TysWiredIn      ( charTy, mkListTy )
-import PrelNames       ( pREL_ERR, pREL_GHC )
-import PrelRules       ( primOpRule )
+import PrelRules       ( primOpRules )
 import Rules           ( addRule )
-import Type            ( Type, ThetaType, mkDictTy, mkPredTys, mkTyConApp,
-                         mkTyVarTys, repType, isNewType,
-                         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 CoreUtils       ( exprType )
 import CoreUnfold      ( mkTopUnfolding, mkCompulsoryUnfolding, mkOtherCon )
-import Literal         ( Literal(..) )
+import Literal         ( Literal(..), nullAddrLit )
 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 )
@@ -58,11 +58,9 @@ import Name          ( mkWiredInName, mkFCallName, Name )
 import OccName         ( mkVarOcc )
 import PrimOp          ( PrimOp(DataToTagOp), primOpSig, mkPrimOpIdName )
 import ForeignCall     ( ForeignCall )
-import Demand          ( wwStrict, wwPrim, mkStrictnessInfo, 
-                         StrictnessMark(..), isMarkedUnboxed, isMarkedStrict )
 import DataCon         ( DataCon, 
                          dataConFieldLabels, dataConRepArity, dataConTyCon,
-                         dataConArgTys, dataConRepType, dataConRepStrictness, 
+                         dataConArgTys, dataConRepType, 
                          dataConInstOrigArgTys,
                           dataConName, dataConTheta,
                          dataConSig, dataConStrictMarks, dataConId,
@@ -70,23 +68,27 @@ import DataCon              ( DataCon,
                        )
 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,
-                         GlobalIdDetails(..), CafInfo(..), CprInfo(..), 
-                         CgInfo(..), setCgArity
+                         setUnfoldingInfo, 
+                         setArityInfo, setSpecInfo, setCafInfo,
+                         setAllStrictnessInfo,
+                         GlobalIdDetails(..), CafInfo(..)
                        )
+import NewDemand       ( mkStrictSig, strictSigResInfo, DmdResult(..),
+                         mkTopDmdType, topDmd, evalDmd, lazyDmd, 
+                         Demand(..), Demands(..) )
 import FieldLabel      ( mkFieldLabel, fieldLabelName, 
                          firstFieldLabelTag, allFieldLabelTags, fieldLabelType
                        )
+import DmdAnal         ( dmdAnalTopRhs )
 import CoreSyn
 import Unique          ( mkBuiltinUnique )
 import Maybes
 import PrelNames
 import Maybe            ( isJust )
+import Util             ( dropList, isSingleton )
 import Outputable
 import ListSetOps      ( assoc, assocMaybe )
 import UnicodeUtil      ( stringToUtf8 )
@@ -107,23 +109,30 @@ wiredInIds
        -- 
        -- [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 three can't be defined in Haskell
-    , realWorldPrimId
-    , unsafeCoerceId
-    , getTagId
+       -- 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
+    ] ++ 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
     ]
 \end{code}
 
@@ -141,23 +150,36 @@ mkDataConId work_name data_con
   = mkGlobalId (DataConId data_con) work_name (dataConRepType data_con) info
   where
     info = noCafNoTyGenIdInfo
-          `setCgArity`         arity
-          `setArityInfo`       exactArity arity
-          `setStrictnessInfo`  strict_info
-          `setCprInfo`         cpr_info
-
-    arity = dataConRepArity data_con
-
-    strict_info = mkStrictnessInfo (dataConRepStrictness data_con, False)
+          `setArityInfo`               arity
+          `setAllStrictnessInfo`       Just strict_sig
+
+    arity      = dataConRepArity data_con
+
+    strict_sig = mkStrictSig (mkTopDmdType (replicate arity topDmd) cpr_info)
+       -- 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)
+       -- Why?  Because the *wrapper* is strict (and its unfolding has case
+       -- expresssions that do the evals) but the *worker* itself is not.
+       -- If we pretend it is strict then when we see
+       --      case x of y -> $wMkT y
+       -- the simplifier thinks that y is "sure to be evaluated" (because
+       -- $wMkT is strict) and drops the case.  No, $wMkT is not strict.
+       --
+       -- When the simplifer sees a pattern 
+       --      case e of MkT x -> ...
+       -- it uses the dataConRepStrictness of MkT to mark x as evaluated;
+       -- but that's fine... dataConRepStrictness comes from the data con
+       -- not from the worker Id.
 
     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
@@ -210,57 +232,64 @@ Notice that
 
 \begin{code}
 mkDataConWrapId data_con
-  = wrap_id
+  = mkGlobalId (DataConWrapId data_con) (dataConName data_con) wrap_ty info
   where
-    wrap_id = mkGlobalId (DataConWrapId data_con) (dataConName data_con) wrap_ty info
     work_id = dataConId data_con
 
     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
+          `setUnfoldingInfo`   wrap_unf
                -- 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
-
-    wrap_ty = mkForAllTys all_tyvars $
-             mkFunTys all_arg_tys
-             result_ty
-
-    cpr_info = idCprInfo work_id
-
-    wrap_rhs | isNewTyCon tycon
-            = ASSERT( null ex_tyvars && null ex_dict_args && length orig_arg_tys == 1 )
+          `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 = evalDmd
+              | otherwise          = lazyDmd
+       -- The Cpr info can be important inside INLINE rhss, where the
+       -- 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:
+       --      data W = C !Int !Int !Int
+       --      ...(let w = C x in ...(w p q)...)...
+       -- we want to see that w is strict in its two arguments
+
+    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 (...)
-
-              mkLams tyvars $ mkLams dict_args $ Lam id_arg1 $
-              Note (Coerce result_ty (head orig_arg_tys)) (Var id_arg1)
+               mkTopUnfolding $ Note InlineMe $
+               mkLams tyvars $ mkLams dict_args $ Lam 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 []
@@ -303,24 +332,12 @@ mkDataConWrapId data_con
                        Case (Var arg) arg [(DEFAULT,[], body i (arg:rep_args))]
 
                MarkedUnboxed
-                  | isNewType arg_ty ->
-                       Let (NonRec coerced_arg 
-                               (Note (Coerce rep_ty arg_ty) (Var arg)))
-                             (do_unbox coerced_arg rep_ty i')
-                  | otherwise ->
-                       do_unbox arg arg_ty i
-                 where
-                   ([coerced_arg],i') = mkLocals i [rep_ty]
-                   arg_ty = idType arg
-                   rep_ty = repType arg_ty
-
-                   do_unbox arg ty i = 
-                       case splitProductType "do_unbox" ty of
+                  -> 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
+                               (con_args, i') = mkLocals i tys
 \end{code}
 
 
@@ -388,11 +405,11 @@ mkRecordSelId tycon field_label unpack_id unpackUtf8_id
                                        --   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 
@@ -422,13 +439,16 @@ mkRecordSelId tycon field_label unpack_id unpackUtf8_id
                   mkFunTy data_ty field_tau
       
     arity = 1 + n_dict_tys + n_field_dict_tys
-    info = noCafNoTyGenIdInfo
-          `setCgInfo`          (CgInfo arity caf_info)
-          `setArityInfo`       exactArity arity
-          `setUnfoldingInfo`   unfolding       
-       -- ToDo: consider adding further IdInfo
 
-    unfolding = mkTopUnfolding sel_rhs
+    (strict_sig, rhs_w_str) = dmdAnalTopRhs sel_rhs
+       -- Use the demand analyser to work out strictness.
+       -- With all this unpackery it's not easy!
+
+    info = noCafNoTyGenIdInfo
+          `setCafInfo`           caf_info
+          `setArityInfo`         arity
+          `setUnfoldingInfo`     mkTopUnfolding rhs_w_str
+          `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
@@ -457,15 +477,23 @@ mkRecordSelId tycon field_label unpack_id unpackUtf8_id
              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 (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..])
@@ -519,24 +547,15 @@ rebuildConArgs (arg:args) (str:stricts) us
   | isMarkedUnboxed str
   = let
        arg_ty  = idType arg
-       prod_ty | isNewType arg_ty = repType arg_ty
-               | otherwise        = arg_ty
 
        (_, tycon_args, pack_con, con_arg_tys)
-                = splitProductType "rebuildConArgs" prod_ty
+                = 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)
-
-       coerce | isNewType arg_ty = Note (Coerce arg_ty prod_ty) con_app
-              | otherwise        = con_app
-
-       con_app        = mkConApp pack_con (map Type tycon_args ++ 
-                                           map Var  unpacked_args)
+       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 coerce : binds, unpacked_args ++ args')
+    (NonRec arg con_app : binds, unpacked_args ++ args')
 
   | otherwise
   = let (binds, args') = rebuildConArgs args stricts us
@@ -558,22 +577,34 @@ ToDo: unify with mkRecordSelId.
 \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
-               `setUnfoldingInfo`  unfolding
-               
+               `setArityInfo`          1
+               `setUnfoldingInfo`      mkTopUnfolding rhs
+               `setAllStrictnessInfo`  Just strict_sig
+
        -- We no longer use 'must-inline' on record selectors.  They'll
        -- inline like crazy if they scrutinise a constructor
 
-    unfolding = mkTopUnfolding rhs
+       -- The strictness signature is of the form U(AAAVAAAA) -> T
+       -- where the V depends on which item we are selecting
+       -- 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 = evalDmd
+           | otherwise        = Eval (Prod [ if the_arg_id == id then evalDmd else Abs
+                                           | id <- arg_ids ])
 
     tyvars  = classTyVars clas
 
@@ -583,14 +614,22 @@ mkDictSelId name clas
     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) (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_expr
+       -- Adds a coerce where necessary
+       -- Used for both wrapping and unwrapping
+  | isRecursiveTyCon tycon     -- Recursive case; use a coerce
+  = Note (Coerce result_ty (exprType result_expr)) result_expr
+  | otherwise                  -- Normal case
+  = result_expr
 \end{code}
 
 
@@ -605,19 +644,17 @@ mkPrimOpId :: PrimOp -> Id
 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
-          `setCgArity`         arity
-          `setArityInfo`       exactArity arity
-          `setStrictnessInfo`  strict_info
+          `setArityInfo`       arity
+          `setAllStrictnessInfo` Just strict_sig
 
-    rules = maybe emptyCoreRules (addRule emptyCoreRules id)
-               (primOpRule prim_op)
+    rules = foldl (addRule id) emptyCoreRules (primOpRules prim_op)
 
 
 -- For each ccall we manufacture a separate CCallOpId, giving it
@@ -643,14 +680,13 @@ mkFCallId uniq fcall ty
     name = mkFCallName uniq occ_str
 
     info = noCafNoTyGenIdInfo
-          `setCgArity`         arity
-          `setArityInfo`       exactArity arity
-          `setStrictnessInfo`  strict_info
+          `setArityInfo`               arity
+          `setAllStrictnessInfo`       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 (mkTopDmdType (replicate arity evalDmd) TopRes)
 \end{code}
 
 
@@ -660,9 +696,34 @@ mkFCallId uniq fcall ty
 %*                                                                     *
 %************************************************************************
 
+Important notes about dict funs and default methods
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Dict funs and default methods are *not* ImplicitIds.  Their definition
+involves user-written code, so we can't figure out their strictness etc
+based on fixed info, as we can for constructors and record selectors (say).
+
+We build them as GlobalIds, but when in the module where they are
+bound, we turn the Id at the *binding site* into an exported LocalId.
+This ensures that they are taken to account by free-variable finding
+and dependency analysis (e.g. CoreFVs.exprFreeVars).   The simplifier
+will propagate the LocalId to all occurrence sites. 
+
+Why shouldn't they be bound as GlobalIds?  Because, in particular, if
+they are globals, the specialiser floats dict uses above their defns,
+which prevents good simplifications happening.  Also the strictness
+analyser treats a occurrence of a GlobalId as imported and assumes it
+contains strictness in its IdInfo, which isn't true if the thing is
+bound in the same module as the occurrence.
+
+It's OK for dfuns to be LocalIds, because we form the instance-env to
+pass on to the next module (md_insts) in CoreTidy, afer tidying
+and globalising the top-level Ids.
+
+BUT make sure they are *exported* LocalIds (setIdLocalExported) so 
+that they aren't discarded by the occurrence analyser.
+
 \begin{code}
-mkDefaultMethodId dm_name ty
-  = mkVanillaGlobal dm_name ty noCafNoTyGenIdInfo
+mkDefaultMethodId dm_name ty = mkVanillaGlobal dm_name ty noCafNoTyGenIdInfo
 
 mkDictFunId :: Name            -- Name to use for the dict fun;
            -> Class 
@@ -712,7 +773,12 @@ mkDictFunId dfun_name clas inst_tyvars inst_tys dfun_theta
 %*                                                                     *
 %************************************************************************
 
-These two can't be defined in Haskell.
+These Ids can't be defined in Haskell.  They could be defined in 
+unfoldings in PrelGHC.hi-boot, but we'd have to ensure that they
+were definitely, definitely inlined, because there is no curried
+identifier for them.  That's what mkCompulsoryUnfolding does.
+If we had a way to get a compulsory unfolding from an interface file,
+we could do that, but we don't right now.
 
 unsafeCoerce# isn't so much a PrimOp as a phantom identifier, that
 just gets expanded into a type coercion wherever it occurs.  Hence we
@@ -723,8 +789,9 @@ they can unify with both unlifted and lifted types.  Hence we provide
 another gun with which to shoot yourself in the foot.
 
 \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
           
@@ -734,15 +801,34 @@ unsafeCoerceId
     [x] = mkTemplateLocals [openAlphaTy]
     rhs = mkLams [openAlphaTyVar,openBetaTyVar,x] $
          Note (Coerce openBetaTy openAlphaTy) (Var x)
-\end{code}
 
+-- nullAddr# :: Addr#
+-- The reason is is here is because we don't provide 
+-- a way to write this literal in Haskell.
+nullAddrId 
+  = pcMiscPrelId nullAddrIdKey gHC_PRIM FSLIT("nullAddr#") addrPrimTy info
+  where
+    info = noCafNoTyGenIdInfo `setUnfoldingInfo` 
+          mkCompulsoryUnfolding (Lit nullAddrLit)
+
+seqId
+  = pcMiscPrelId seqIdKey gHC_PRIM FSLIT("seq") ty info
+  where
+    info = noCafNoTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
+          
+
+    ty  = mkForAllTys [alphaTyVar,betaTyVar]
+                     (mkFunTy alphaTy (mkFunTy betaTy betaTy))
+    [x,y] = mkTemplateLocals [alphaTy, betaTy]
+    rhs = mkLams [alphaTyVar,betaTyVar,x,y] (Case (Var x) x [(DEFAULT, [], Var y)])
+\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
+  = 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
@@ -758,15 +844,25 @@ dataToTagId = mkPrimOpId DataToTagOp
 @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}
 
 
@@ -793,28 +889,31 @@ 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
+  = pc_bottoming_Id errorIdKey pREL_ERR FSLIT("error") errorTy
+eRROR_CSTRING_ID
+  = 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}
 
@@ -842,9 +941,8 @@ pcMiscPrelId key mod str ty info
 pc_bottoming_Id key mod name ty
  = pcMiscPrelId key mod name ty bottoming_info
  where
-    bottoming_info = noCafNoTyGenIdInfo 
-                    `setStrictnessInfo` mkStrictnessInfo ([wwStrict], True)
-
+    strict_sig    = mkStrictSig (mkTopDmdType [evalDmd] BotRes)
+    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