[project @ 2001-07-23 10:54:46 by simonpj]
[ghc-hetmet.git] / ghc / compiler / basicTypes / MkId.lhs
index 23376f4..b3c6be3 100644 (file)
@@ -18,7 +18,7 @@ module MkId (
 
        mkDataConId, mkDataConWrapId,
        mkRecordSelId, rebuildConArgs,
-       mkPrimOpId, mkCCallOpId,
+       mkPrimOpId, mkFCallId,
 
        -- And some particular Ids; see below for why they are wired in
        wiredInIds,
@@ -31,7 +31,7 @@ module MkId (
 #include "HsVersions.h"
 
 
-import BasicTypes      ( Arity )
+import BasicTypes      ( Arity, StrictnessMark(..), isMarkedUnboxed, isMarkedStrict )
 import TysPrim         ( openAlphaTyVars, alphaTyVar, alphaTy, 
                          intPrimTy, realWorldStatePrimTy
                        )
@@ -39,29 +39,25 @@ import TysWiredIn   ( charTy, mkListTy )
 import PrelNames       ( pREL_ERR, pREL_GHC )
 import PrelRules       ( primOpRule )
 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 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, 
-                         StrictnessMark(..), isMarkedUnboxed, isMarkedStrict )
+import PrimOp          ( PrimOp(DataToTagOp), primOpSig, mkPrimOpIdName )
+import ForeignCall     ( ForeignCall )
 import DataCon         ( DataCon, 
                          dataConFieldLabels, dataConRepArity, dataConTyCon,
                          dataConArgTys, dataConRepType, dataConRepStrictness, 
@@ -72,15 +68,17 @@ 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,
+                         mkNewStrictnessInfo, setNewStrictnessInfo,
                          GlobalIdDetails(..), CafInfo(..), CprInfo(..), 
                          CgInfo(..), setCgArity
                        )
+import NewDemand       ( mkStrictSig, strictSigResInfo, DmdResult(..),
+                         mkTopDmdType, topDmd, evalDmd )
 import FieldLabel      ( mkFieldLabel, fieldLabelName, 
                          firstFieldLabelTag, allFieldLabelTags, fieldLabelType
                        )
@@ -140,26 +138,25 @@ 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
+    id = mkGlobalId (DataConId data_con) work_name (dataConRepType data_con) info
     info = noCafNoTyGenIdInfo
-          `setCgArity`         arity
-          `setArityInfo`       exactArity arity
-          `setStrictnessInfo`  strict_info
-          `setCprInfo`         cpr_info
+          `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            &&
-              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
@@ -219,28 +216,30 @@ mkDataConWrapId 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
                -- 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
+          `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 $
-              Note (Coerce result_ty (head orig_arg_tys)) (Var id_arg1)
+               mkLams tyvars $ mkLams dict_args $ Lam id_arg1 $ 
+               mkNewTypeBody tycon result_ty id_arg1
 
             | null dict_args && not (any isMarkedStrict strict_marks)
             = Var work_id      -- The common case.  Not only is this efficient,
@@ -305,24 +304,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}
 
 
@@ -390,11 +377,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 
@@ -426,7 +413,7 @@ mkRecordSelId tycon field_label unpack_id unpackUtf8_id
     arity = 1 + n_dict_tys + n_field_dict_tys
     info = noCafNoTyGenIdInfo
           `setCgInfo`          (CgInfo arity caf_info)
-          `setArityInfo`       exactArity arity
+          `setArityInfo`       arity
           `setUnfoldingInfo`   unfolding       
        -- ToDo: consider adding further IdInfo
 
@@ -459,8 +446,8 @@ 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
@@ -521,24 +508,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)
+       (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 coerce : binds, unpacked_args ++ args')
+    (NonRec arg con_app : binds, unpacked_args ++ args')
 
   | otherwise
   = let (binds, args') = rebuildConArgs args stricts us
@@ -560,16 +538,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
+    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
+               `setArityInfo`      1
                `setUnfoldingInfo`  unfolding
                
        -- We no longer use 'must-inline' on record selectors.  They'll
@@ -585,14 +568,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}
 
 
@@ -615,8 +604,9 @@ mkPrimOpId prim_op
     info = noCafNoTyGenIdInfo
           `setSpecInfo`        rules
           `setCgArity`         arity
-          `setArityInfo`       exactArity arity
-          `setStrictnessInfo`  strict_info
+          `setArityInfo`       arity
+          `setNewStrictnessInfo`       Just (mkNewStrictnessInfo id arity strict_info NoCPRInfo)
+       -- Until we modify the primop generation code
 
     rules = maybe emptyCoreRules (addRule emptyCoreRules id)
                (primOpRule prim_op)
@@ -631,29 +621,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 = noCafNoTyGenIdInfo
-          `setCgArity`         arity
-          `setArityInfo`       exactArity arity
-          `setStrictnessInfo`  strict_info
+          `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}
 
 
@@ -843,11 +833,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 = noCafNoTyGenIdInfo 
-                    `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