[project @ 2001-06-13 17:12:21 by rrt]
[ghc-hetmet.git] / ghc / compiler / basicTypes / MkId.lhs
index c2809e3..5e1165c 100644 (file)
@@ -17,8 +17,8 @@ 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,
@@ -39,7 +39,8 @@ import TysWiredIn     ( charTy, mkListTy )
 import PrelNames       ( pREL_ERR, pREL_GHC )
 import PrelRules       ( primOpRule )
 import Rules           ( addRule )
-import Type            ( Type, ThetaType, mkDictTy, mkPredTys, mkTyConApp, mkTyVarTys,
+import Type            ( Type, ThetaType, mkDictTy, mkPredTys, mkTyConApp,
+                         mkTyVarTys, repType, isNewType,
                          mkFunTys, mkFunTy, mkSigmaTy, splitSigmaTy, 
                          isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType,
                          splitFunTys, splitForAllTys, mkPredTy
@@ -53,22 +54,21 @@ import TyCon                ( TyCon, isNewTyCon, tyConTyVars, tyConDataCons,
 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 Demand          ( wwStrict, wwPrim, mkStrictnessInfo, 
+                         StrictnessMark(..), isMarkedUnboxed, isMarkedStrict )
+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,
                          mkTemplateLocals, mkTemplateLocalsNum,
                          mkTemplateLocal, idCprInfo
                        )
@@ -83,6 +83,7 @@ import FieldLabel     ( mkFieldLabel, fieldLabelName,
                          firstFieldLabelTag, allFieldLabelTags, fieldLabelType
                        )
 import CoreSyn
+import Unique          ( mkBuiltinUnique )
 import Maybes
 import PrelNames
 import Maybe            ( isJust )
@@ -239,7 +240,7 @@ mkDataConWrapId data_con
               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.
@@ -286,15 +287,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
@@ -304,11 +302,25 @@ 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
+                  | 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
+                          (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}
 
 
@@ -451,14 +463,17 @@ mkRecordSelId tycon field_label unpack_id unpackUtf8_id
     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
@@ -477,41 +492,55 @@ 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
+       prod_ty | isNewType arg_ty = repType arg_ty
+               | otherwise        = arg_ty
+
+       (_, tycon_args, pack_con, con_arg_tys)
+                = splitProductType "rebuildConArgs" prod_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)
+    in
+    (NonRec arg coerce : binds, unpacked_args ++ args')
+
+  | otherwise
+  = let (binds, args') = rebuildConArgs args stricts us
+    in  (binds, arg:args')
 \end{code}
 
 
@@ -600,19 +629,18 @@ 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
+    mkGlobalId (FCallId fcall) name ty info
   where
-    occ_str = showSDocIface (braces (pprCCallOp ccall <+> ppr ty))
+    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