[project @ 2001-07-25 07:42:23 by simonpj]
[ghc-hetmet.git] / ghc / compiler / basicTypes / MkId.lhs
index e5a2a49..761eef8 100644 (file)
@@ -17,13 +17,13 @@ module MkId (
        mkDictSelId,
 
        mkDataConId, mkDataConWrapId,
-       mkRecordSelId,
-       mkPrimOpId, mkCCallOpId,
+       mkRecordSelId, rebuildConArgs,
+       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,
+       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
@@ -31,56 +31,59 @@ module MkId (
 #include "HsVersions.h"
 
 
+import BasicTypes      ( Arity, StrictnessMark(..), isMarkedUnboxed, isMarkedStrict )
 import TysPrim         ( openAlphaTyVars, alphaTyVar, alphaTy, 
-                         intPrimTy, realWorldStatePrimTy
+                         intPrimTy, realWorldStatePrimTy, addrPrimTy
                        )
 import TysWiredIn      ( charTy, mkListTy )
-import PrelNames       ( pREL_ERR, pREL_GHC )
 import PrelRules       ( primOpRule )
 import Rules           ( addRule )
-import Type            ( Type, ThetaType, mkDictTy, mkDictTys, mkTyConApp, mkTyVarTys,
-                         mkFunTys, mkFunTy, mkSigmaTy, splitSigmaTy, 
+import TcType          ( Type, ThetaType, mkDictTy, mkPredTys, mkTyConApp,
+                         mkTyVarTys, mkClassPred, tcEqPred,
+                         mkFunTys, mkFunTy, mkSigmaTy, tcSplitSigmaTy, 
                          isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType,
-                         splitFunTys, splitForAllTys, mkPredTy
+                         tcSplitFunTys, tcSplitForAllTys, mkPredTy
                        )
 import Module          ( Module )
 import CoreUtils       ( exprType, mkInlineMe )
 import CoreUnfold      ( mkTopUnfolding, mkCompulsoryUnfolding, mkOtherCon )
 import Literal         ( Literal(..) )
 import TyCon           ( TyCon, isNewTyCon, tyConTyVars, tyConDataCons,
-                          tyConTheta, isProductTyCon, isDataTyCon )
+                          tyConTheta, isProductTyCon, isDataTyCon, isRecursiveTyCon )
 import Class           ( Class, classTyCon, classTyVars, classSelIds )
 import Var             ( Id, TyVar )
 import VarSet          ( isEmptyVarSet )
-import Name            ( mkWiredInName, mkCCallName, Name )
+import Name            ( mkWiredInName, mkFCallName, Name )
 import OccName         ( mkVarOcc )
-import PrimOp          ( PrimOp(DataToTagOp, CCallOp), 
-                         primOpSig, mkPrimOpIdName,
-                         CCall, pprCCallOp
-                       )
-import Demand          ( wwStrict, wwPrim, mkStrictnessInfo )
-import DataCon         ( DataCon, StrictnessMark(..), 
+import PrimOp          ( PrimOp(DataToTagOp), primOpSig, mkPrimOpIdName )
+import ForeignCall     ( ForeignCall )
+import DataCon         ( DataCon, 
                          dataConFieldLabels, dataConRepArity, dataConTyCon,
                          dataConArgTys, dataConRepType, dataConRepStrictness, 
                          dataConInstOrigArgTys,
                           dataConName, dataConTheta,
                          dataConSig, dataConStrictMarks, dataConId,
-                         maybeMarkedUnboxed, splitProductType_maybe
+                         splitProductType
                        )
-import Id              ( idType, mkGlobalId, mkVanillaGlobal,
+import Id              ( idType, mkGlobalId, mkVanillaGlobal, mkSysLocal,
+                         mkLocalIdWithInfo, setIdNoDiscard,
                          mkTemplateLocals, mkTemplateLocalsNum,
-                         mkTemplateLocal, idCprInfo
+                         mkTemplateLocal, idNewStrictness, idName
                        )
-import IdInfo          ( IdInfo, vanillaIdInfo, noTyGenIdInfo, noCafOrTyGenIdInfo,
-                         exactArity, setUnfoldingInfo, setCafInfo, setCprInfo,
-                         setArityInfo, setSpecInfo, 
-                         mkStrictnessInfo, setStrictnessInfo,
-                         GlobalIdDetails(..), CafInfo(..), CprInfo(..)
+import IdInfo          ( IdInfo, noCafNoTyGenIdInfo,
+                         exactArity, setUnfoldingInfo, setCprInfo,
+                         setArityInfo, setSpecInfo,  setCgInfo,
+                         mkNewStrictnessInfo, setNewStrictnessInfo,
+                         GlobalIdDetails(..), CafInfo(..), CprInfo(..), 
+                         CgInfo(..), setCgArity
                        )
+import NewDemand       ( mkStrictSig, strictSigResInfo, DmdResult(..),
+                         mkTopDmdType, topDmd, evalDmd )
 import FieldLabel      ( mkFieldLabel, fieldLabelName, 
                          firstFieldLabelTag, allFieldLabelTags, fieldLabelType
                        )
 import CoreSyn
+import Unique          ( mkBuiltinUnique )
 import Maybes
 import PrelNames
 import Maybe            ( isJust )
@@ -109,6 +112,7 @@ wiredInIds
 
       aBSENT_ERROR_ID
     , eRROR_ID
+    , eRROR_CSTRING_ID
     , iRREFUT_PAT_ERROR_ID
     , nON_EXHAUSTIVE_GUARDS_ERROR_ID
     , nO_METHOD_BINDING_ERROR_ID
@@ -117,7 +121,7 @@ wiredInIds
     , rEC_CON_ERROR_ID
     , rEC_UPD_ERROR_ID
 
-       -- These two can't be defined in Haskell
+       -- These three can't be defined in Haskell
     , realWorldPrimId
     , unsafeCoerceId
     , getTagId
@@ -135,24 +139,36 @@ mkDataConId :: Name -> DataCon -> Id
        -- Makes the *worker* for the data constructor; that is, the function
        -- that takes the reprsentation arguments and builds the constructor.
 mkDataConId work_name data_con
-  = mkGlobalId (DataConId data_con) work_name (dataConRepType data_con) info
+  = id 
   where
-    info = noCafOrTyGenIdInfo
-          `setArityInfo`       exactArity arity
-          `setStrictnessInfo`  strict_info
-          `setCprInfo`         cpr_info
+    id = mkGlobalId (DataConId data_con) work_name (dataConRepType data_con) info
+    info = noCafNoTyGenIdInfo
+          `setCgArity`                 arity
+          `setArityInfo`               arity
+          `setNewStrictnessInfo`       Just strict_sig
 
     arity = dataConRepArity data_con
-
-    strict_info = mkStrictnessInfo (dataConRepStrictness data_con, False)
+    strict_sig = mkStrictSig id arity (mkTopDmdType (dataConRepStrictness data_con) cpr_info)
 
     tycon = dataConTyCon data_con
     cpr_info | isProductTyCon tycon && 
               isDataTyCon tycon    &&
-              arity > 0                = ReturnsCPR
-            | otherwise                = NoCPRInfo
-       -- ReturnsCPR is only true for products that are real data types;
-       -- that is, not unboxed tuples or newtypes
+              arity > 0            &&
+              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
+-- We do not treat very big tuples as CPR-ish:
+--     a) for a start we get into trouble because there aren't 
+--        "enough" unboxed tuple types (a tiresome restriction, 
+--        but hard to fix), 
+--     b) more importantly, big unboxed tuples get returned mainly
+--        on the stack, and are often then allocated in the heap
+--        by the caller.  So doing CPR for them may in fact make
+--        things worse.
 \end{code}
 
 The wrapper for a constructor is an ordinary top-level binding that evaluates
@@ -199,30 +215,34 @@ mkDataConWrapId data_con
     wrap_id = mkGlobalId (DataConWrapId data_con) (dataConName data_con) wrap_ty info
     work_id = dataConId data_con
 
-    info = noCafOrTyGenIdInfo
+    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
-          `setArityInfo`       exactArity arity
+          `setCgArity`         arity
+               -- 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
 
     wrap_ty = mkForAllTys all_tyvars $
              mkFunTys all_arg_tys
              result_ty
 
-    cpr_info = idCprInfo work_id
+    res_info = strictSigResInfo (idNewStrictness work_id)
+    wrap_sig = mkStrictSig wrap_id arity (mkTopDmdType (replicate arity topDmd) res_info)
+       -- The Cpr info can be important inside INLINE rhss, where the
+       -- wrapper constructor isn't inlined
+       -- But we are sloppy about the argument demands, because we expect 
+       -- to inline the constructor very vigorously.
 
     wrap_rhs | isNewTyCon tycon
             = ASSERT( null ex_tyvars && null ex_dict_args && length orig_arg_tys == 1 )
                -- No existentials on a newtype, but it can have a context
                -- e.g.         newtype Eq a => T a = MkT (...)
+               mkLams tyvars $ mkLams dict_args $ Lam id_arg1 $ 
+               mkNewTypeBody tycon result_ty id_arg1
 
-              mkLams tyvars $ mkLams dict_args $ Lam id_arg1 $
-              Note (Coerce result_ty (head orig_arg_tys)) (Var id_arg1)
-
-            | null dict_args && all not_marked_strict strict_marks
+            | null dict_args && not (any isMarkedStrict strict_marks)
             = Var work_id      -- The common case.  Not only is this efficient,
                                -- but it also ensures that the wrapper is replaced
                                -- by the worker even when there are no args.
@@ -253,8 +273,8 @@ mkDataConWrapId data_con
     (tyvars, theta, ex_tyvars, ex_theta, orig_arg_tys, tycon) = dataConSig data_con
     all_tyvars   = tyvars ++ ex_tyvars
 
-    dict_tys     = mkDictTys theta
-    ex_dict_tys  = mkDictTys ex_theta
+    dict_tys     = mkPredTys theta
+    ex_dict_tys  = mkPredTys ex_theta
     all_arg_tys  = dict_tys ++ ex_dict_tys ++ orig_arg_tys
     result_ty    = mkTyConApp tycon (mkTyVarTys tyvars)
 
@@ -269,15 +289,12 @@ mkDataConWrapId data_con
     (id_arg1:_)   = id_args            -- Used for newtype only
 
     strict_marks  = dataConStrictMarks data_con
-    not_marked_strict NotMarkedStrict = True
-    not_marked_strict other          = False
-
 
     mk_case 
-          :: (Id, StrictnessMark)      -- arg, strictness
-          -> (Int -> [Id] -> CoreExpr) -- body
-          -> Int                       -- next rep arg id
-          -> [Id]                      -- rep args so far
+          :: (Id, StrictnessMark)      -- Arg, strictness
+          -> (Int -> [Id] -> CoreExpr) -- Body
+          -> Int                       -- Next rep arg id
+          -> [Id]                      -- Rep args so far, reversed
           -> CoreExpr
     mk_case (arg,strict) body i rep_args
          = case strict of
@@ -287,11 +304,13 @@ mkDataConWrapId data_con
                   | otherwise ->
                        Case (Var arg) arg [(DEFAULT,[], body i (arg:rep_args))]
 
-               MarkedUnboxed con tys ->
-                  Case (Var arg) arg [(DataAlt con, con_args,
-                                       body i' (reverse con_args++rep_args))]
-                  where 
-                       (con_args,i') = mkLocals i tys
+               MarkedUnboxed
+                  -> case splitProductType "do_unbox" (idType arg) of
+                          (tycon, tycon_args, con, tys) ->
+                                  Case (Var arg) arg [(DataAlt con, con_args,
+                                       body i' (reverse con_args ++ rep_args))]
+                             where 
+                               (con_args, i') = mkLocals i tys
 \end{code}
 
 
@@ -357,13 +376,13 @@ mkRecordSelId tycon field_label unpack_id unpackUtf8_id
 
     tycon_theta        = tyConTheta tycon      -- The context on the data decl
                                        --   eg data (Eq a, Ord b) => T a b = ...
-    dict_tys  = [mkDictTy cls tys | (cls, tys) <- tycon_theta, 
-                                   needed_dict (cls, tys)]
-    needed_dict pred = or [ pred `elem` (dataConTheta dc) 
-                         | (DataAlt dc, _, _) <- the_alts]
+    dict_tys  = [mkPredTy pred | pred <- tycon_theta, 
+                                needed_dict pred]
+    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 
@@ -393,9 +412,9 @@ mkRecordSelId tycon field_label unpack_id unpackUtf8_id
                   mkFunTy data_ty field_tau
       
     arity = 1 + n_dict_tys + n_field_dict_tys
-    info = noTyGenIdInfo
-          `setCafInfo`         caf_info
-          `setArityInfo`       exactArity arity
+    info = noCafNoTyGenIdInfo
+          `setCgInfo`          (CgInfo arity caf_info)
+          `setArityInfo`       arity
           `setUnfoldingInfo`   unfolding       
        -- ToDo: consider adding further IdInfo
 
@@ -428,20 +447,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 data_id
+            | otherwise        = Case (Var data_id) data_id (default_alt ++ the_alts)
 
     mk_maybe_alt data_con 
          = case maybe_the_arg_id of
                Nothing         -> Nothing
-               Just the_arg_id -> Just (DataAlt data_con, real_args, expr)
+               Just the_arg_id -> Just (DataAlt data_con, real_args, mkLets binds body)
                  where
-                   body              = mkVarApps (mkVarApps (Var the_arg_id) field_tyvars) field_dict_ids
-                   strict_marks      = dataConStrictMarks data_con
-                   (expr, real_args) = rebuildConArgs data_con arg_ids strict_marks body
-                                                      (length arg_ids + 1)
+                   body               = mkVarApps (mkVarApps (Var the_arg_id) field_tyvars) field_dict_ids
+                   strict_marks       = dataConStrictMarks data_con
+                   (binds, real_args) = rebuildConArgs arg_ids strict_marks
+                                                       (map mkBuiltinUnique [unpack_base..])
        where
             arg_ids = mkTemplateLocalsNum field_base (dataConInstOrigArgTys data_con tyvar_tys)
+
+           unpack_base = field_base + length arg_ids
+
                                -- arity+1 avoids all shadowing
            maybe_the_arg_id  = assocMaybe (field_lbls `zip` arg_ids) field_label
            field_lbls        = dataConFieldLabels data_con
@@ -460,41 +482,46 @@ mkRecordSelId tycon field_label unpack_id unpackUtf8_id
     full_msg   = showSDoc (sep [text "No match in record selector", ppr sel_id]) 
 
 
--- this rather ugly function converts the unpacked data con arguments back into
--- their packed form.  It is almost the same as the version in DsUtils, except that
--- we use template locals here rather than newDsId (ToDo: merge these).
+-- This rather ugly function converts the unpacked data con 
+-- arguments back into their packed form.
 
 rebuildConArgs
-  :: DataCon                           -- the con we're matching on
-  -> [Id]                              -- the source-level args
-  -> [StrictnessMark]                  -- the strictness annotations (per-arg)
-  -> CoreExpr                          -- the body
-  -> Int                               -- template local
-  -> (CoreExpr, [Id])
-
-rebuildConArgs con [] stricts body i = (body, [])
-rebuildConArgs con (arg:args) stricts body i | isTyVar arg
-  = let (body', args') = rebuildConArgs con args stricts body i
-    in  (body',arg:args')
-rebuildConArgs con (arg:args) (str:stricts) body i
-  = case maybeMarkedUnboxed str of
-       Just (pack_con1, _) -> 
-           case splitProductType_maybe (idType arg) of
-               Just (_, tycon_args, pack_con, con_arg_tys) ->
-                   ASSERT( pack_con == pack_con1 )
-                   let unpacked_args = zipWith mkTemplateLocal [i..] con_arg_tys
-                       (body', real_args) = rebuildConArgs con args stricts body 
-                                               (i + length con_arg_tys)
-                   in
-                   (
-                        Let (NonRec arg (mkConApp pack_con 
-                                                 (map Type tycon_args ++
-                                                  map Var  unpacked_args))) body', 
-                        unpacked_args ++ real_args
-                   )
-
-       _ -> let (body', args') = rebuildConArgs con args stricts body i
-            in  (body', arg:args')
+  :: [Id]                      -- Source-level args
+  -> [StrictnessMark]          -- Strictness annotations (per-arg)
+  -> [Unique]                  -- Uniques for the new Ids
+  -> ([CoreBind], [Id])                -- A binding for each source-level arg, plus
+                               -- a list of the representation-level arguments 
+-- e.g.   data T = MkT Int !Int
+--
+-- rebuild [x::Int, y::Int] [Not, Unbox]
+--  = ([ y = I# t ], [x,t])
+
+rebuildConArgs []        stricts us = ([], [])
+
+-- Type variable case
+rebuildConArgs (arg:args) stricts us 
+  | isTyVar arg
+  = let (binds, args') = rebuildConArgs args stricts us
+    in  (binds, arg:args')
+
+-- Term variable case
+rebuildConArgs (arg:args) (str:stricts) us
+  | isMarkedUnboxed str
+  = let
+       arg_ty  = idType arg
+
+       (_, tycon_args, pack_con, con_arg_tys)
+                = splitProductType "rebuildConArgs" arg_ty
+
+       unpacked_args  = zipWith (mkSysLocal SLIT("rb")) us con_arg_tys
+       (binds, args') = rebuildConArgs args stricts (drop (length con_arg_tys) us)
+       con_app        = mkConApp pack_con (map Type tycon_args ++ map Var unpacked_args)
+    in
+    (NonRec arg con_app : binds, unpacked_args ++ args')
+
+  | otherwise
+  = let (binds, args') = rebuildConArgs args stricts us
+    in  (binds, arg:args')
 \end{code}
 
 
@@ -512,15 +539,21 @@ 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
-
-    info      = noCafOrTyGenIdInfo
-               `setArityInfo`      exactArity 1
+    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`      1
                `setUnfoldingInfo`  unfolding
                
        -- We no longer use 'must-inline' on record selectors.  They'll
@@ -536,14 +569,20 @@ 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) dict_id
        | otherwise        = mkLams tyvars $ Lam dict_id $
                             Case (Var dict_id) dict_id
                                  [(DataAlt data_con, arg_ids, Var the_arg_id)]
+
+mkNewTypeBody tycon result_ty result_id
+  | isRecursiveTyCon tycon     -- Recursive case; use a coerce
+  = Note (Coerce result_ty (idType result_id)) (Var result_id)
+  | otherwise                  -- Normal case
+  = Var result_id
 \end{code}
 
 
@@ -563,12 +602,15 @@ mkPrimOpId prim_op
     name = mkPrimOpIdName prim_op
     id   = mkGlobalId (PrimOpId prim_op) name ty info
                
-    info = noCafOrTyGenIdInfo
+    info = noCafNoTyGenIdInfo
           `setSpecInfo`        rules
-          `setArityInfo`       exactArity arity
-          `setStrictnessInfo`  strict_info
+          `setCgArity`         arity
+          `setArityInfo`       arity
+          `setNewStrictnessInfo`       Just (mkNewStrictnessInfo id arity strict_info NoCPRInfo)
+       -- Until we modify the primop generation code
 
-    rules = addRule emptyCoreRules id (primOpRule prim_op)
+    rules = maybe emptyCoreRules (addRule emptyCoreRules id)
+               (primOpRule prim_op)
 
 
 -- For each ccall we manufacture a separate CCallOpId, giving it
@@ -580,28 +622,29 @@ mkPrimOpId prim_op
 -- details of the ccall, type and all.  This means that the interface 
 -- file reader can reconstruct a suitable Id
 
-mkCCallOpId :: Unique -> CCall -> Type -> Id
-mkCCallOpId uniq ccall ty
+mkFCallId :: Unique -> ForeignCall -> Type -> Id
+mkFCallId uniq fcall ty
   = ASSERT( isEmptyVarSet (tyVarsOfType ty) )
        -- A CCallOpId should have no free type variables; 
        -- when doing substitutions won't substitute over it
-    mkGlobalId (PrimOpId prim_op) name ty info
+    id
   where
-    occ_str = showSDocIface (braces (pprCCallOp ccall <+> ppr ty))
+    id = mkGlobalId (FCallId fcall) name ty info
+    occ_str = showSDocIface (braces (ppr fcall <+> ppr ty))
        -- The "occurrence name" of a ccall is the full info about the
        -- ccall; it is encoded, but may have embedded spaces etc!
 
-    name    = mkCCallName uniq occ_str
-    prim_op = CCallOp ccall
+    name = mkFCallName uniq occ_str
 
-    info = noCafOrTyGenIdInfo
-          `setArityInfo`       exactArity arity
-          `setStrictnessInfo`  strict_info
+    info = noCafNoTyGenIdInfo
+          `setCgArity`                 arity
+          `setArityInfo`               arity
+          `setNewStrictnessInfo`       Just strict_sig
 
-    (_, tau)    = splitForAllTys ty
-    (arg_tys, _) = splitFunTys tau
+    (_, tau)    = tcSplitForAllTys ty
+    (arg_tys, _) = tcSplitFunTys tau
     arity       = length arg_tys
-    strict_info  = mkStrictnessInfo (take arity (repeat wwPrim), False)
+    strict_sig   = mkStrictSig id arity (mkTopDmdType (replicate arity evalDmd) TopRes)
 \end{code}
 
 
@@ -613,7 +656,7 @@ mkCCallOpId uniq ccall ty
 
 \begin{code}
 mkDefaultMethodId dm_name ty
-  = mkVanillaGlobal dm_name ty noTyGenIdInfo
+  = mkVanillaGlobal dm_name ty noCafNoTyGenIdInfo
 
 mkDictFunId :: Name            -- Name to use for the dict fun;
            -> Class 
@@ -623,12 +666,21 @@ mkDictFunId :: Name               -- Name to use for the dict fun;
            -> Id
 
 mkDictFunId dfun_name clas inst_tyvars inst_tys dfun_theta
-  = mkVanillaGlobal dfun_name dfun_ty noTyGenIdInfo
+  = setIdNoDiscard (mkLocalIdWithInfo dfun_name dfun_ty noCafNoTyGenIdInfo)
+       -- NB: It's important that dict funs are *local* Ids
+       -- This ensures that they are taken to account by free-variable finding
+       -- and dependency analysis (e.g. CoreFVs.exprFreeVars).  
+       -- In particular, if they are globals, the
+       -- specialiser floats dict uses above their defns, which prevents
+       -- good simplifications happening.
+       --
+       -- It's OK for them to be locals, because we form the instance-env to
+       -- pass on to the next module (md_insts) in CoreTidy, afer tdying
+       -- and globalising the top-level Ids.
+       --
+       -- BUT Make sure it's an exported Id (setIdNoDiscard) so that it's not dropped!
   where
     dfun_ty = mkSigmaTy inst_tyvars dfun_theta (mkDictTy clas inst_tys)
-    info     = noTyGenIdInfo
-             -- 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.
@@ -680,7 +732,7 @@ another gun with which to shoot yourself in the foot.
 unsafeCoerceId
   = pcMiscPrelId unsafeCoerceIdKey pREL_GHC SLIT("unsafeCoerce#") ty info
   where
-    info = noCafOrTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
+    info = noCafNoTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
           
 
     ty  = mkForAllTys [openAlphaTyVar,openBetaTyVar]
@@ -698,7 +750,7 @@ evaluate its argument and call the dataToTag# primitive.
 getTagId
   = pcMiscPrelId getTagIdKey pREL_GHC SLIT("getTag#") ty info
   where
-    info = noCafOrTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
+    info = noCafNoTyGenIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
        -- We don't provide a defn for this; you must inline it
 
     ty = mkForAllTys [alphaTyVar] (mkFunTy alphaTy intPrimTy)
@@ -716,7 +768,7 @@ nasty as-is, change it back to a literal (@Literal@).
 realWorldPrimId        -- :: State# RealWorld
   = pcMiscPrelId realWorldPrimIdKey pREL_GHC SLIT("realWorld#")
                 realWorldStatePrimTy
-                (noCafOrTyGenIdInfo `setUnfoldingInfo` mkOtherCon [])
+                (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
@@ -748,6 +800,9 @@ 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
+eRROR_CSTRING_ID
+  = pc_bottoming_Id errorCStringIdKey pREL_ERR SLIT("errorCString") 
+                   (mkSigmaTy [openAlphaTyVar] [] (mkFunTy addrPrimTy openAlphaTy))
 pAT_ERROR_ID
   = generic_ERROR_ID patErrorIdKey SLIT("patError")
 rEC_SEL_ERROR_ID
@@ -769,7 +824,7 @@ aBSENT_ERROR_ID
 
 pAR_ERROR_ID
   = pcMiscPrelId parErrorIdKey pREL_ERR SLIT("parError")
-    (mkSigmaTy [openAlphaTyVar] [] openAlphaTy) noCafOrTyGenIdInfo
+    (mkSigmaTy [openAlphaTyVar] [] openAlphaTy) noCafNoTyGenIdInfo
 \end{code}
 
 
@@ -794,11 +849,12 @@ pcMiscPrelId key mod str ty info
     -- will be in "the right place" to be in scope.
 
 pc_bottoming_Id key mod name ty
- = pcMiscPrelId key mod name ty bottoming_info
+ = id
  where
-    bottoming_info = noCafOrTyGenIdInfo 
-                    `setStrictnessInfo` mkStrictnessInfo ([wwStrict], True)
-                    
+    id = pcMiscPrelId key mod name ty bottoming_info
+    arity         = 1
+    strict_sig    = mkStrictSig id arity (mkTopDmdType [evalDmd] BotRes)
+    bottoming_info = noCafNoTyGenIdInfo `setNewStrictnessInfo` Just strict_sig
        -- these "bottom" out, no matter what their arguments
 
 generic_ERROR_ID u n = pc_bottoming_Id u pREL_ERR n errorTy