[project @ 2001-05-24 15:10:19 by dsyme]
[ghc-hetmet.git] / ghc / compiler / stgSyn / StgSyn.lhs
index 2f0fc0b..5168292 100644 (file)
@@ -10,7 +10,7 @@ suited to spineless tagless code generation.
 
 \begin{code}
 module StgSyn (
-       GenStgArg(..),
+       GenStgArg(..), 
        GenStgLiveVars,
 
        GenStgBinding(..), GenStgExpr(..), GenStgRhs(..),
@@ -18,9 +18,8 @@ module StgSyn (
 
        UpdateFlag(..), isUpdatable,
 
-       StgBinderInfo(..),
-       stgArgOcc, stgUnsatOcc, stgStdHeapOcc, stgNoUpdHeapOcc,
-       stgNormalOcc, stgFakeFunAppOcc,
+       StgBinderInfo,
+       noBinderInfo, stgSatOcc, stgUnsatOcc, satCallsOnly,
        combineStgBinderInfo,
 
        -- a set of synonyms for the most common (only :-) parameterisation
@@ -28,14 +27,18 @@ module StgSyn (
        StgBinding, StgExpr, StgRhs,
        StgCaseAlts, StgCaseDefault,
 
+       -- StgOp
+       StgOp(..),
+
        -- SRTs
        SRT(..), noSRT,
 
-       pprStgBinding, pprStgBindings, pprStgBindingsWithSRTs,
-       getArgPrimRep,
+       -- utils
+       stgBindHasCafRefs,  stgRhsArity, getArgPrimRep, 
        isLitLitArg, isDllConApp, isStgTypeArg,
-       stgArity, stgArgType,
-       collectFinalStgBinders
+       stgArgType, stgBinders,
+
+       pprStgBinding, pprStgBindings, pprStgBindingsWithSRTs, pprStgAlts
 
 #ifdef DEBUG
        , pprStgLVs
@@ -45,14 +48,21 @@ module StgSyn (
 #include "HsVersions.h"
 
 import CostCentre      ( CostCentreStack, CostCentre )
+import VarSet          ( IdSet, isEmptyVarSet )
+import Var             ( isId )
 import Id              ( Id, idName, idPrimRep, idType )
 import Name            ( isDllName )
 import Literal         ( Literal, literalType, isLitLitLit, literalPrimRep )
+import ForeignCall     ( ForeignCall )
 import DataCon         ( DataCon, dataConName )
 import PrimOp          ( PrimOp )
 import Outputable
+import Util             ( count )
 import Type             ( Type )
+import TyCon            ( TyCon )
 import UniqSet         ( isEmptyUniqSet, uniqSetToList, UniqSet )
+import Unique          ( Unique )
+import CmdLineOpts     ( opt_SccProfilingOn )
 \end{code}
 
 %************************************************************************
@@ -66,10 +76,16 @@ are the boring things [except note the @GenStgRhs@], parameterised
 with respect to binder and occurrence information (just as in
 @CoreSyn@):
 
+There is one SRT for each group of bindings.
+
 \begin{code}
 data GenStgBinding bndr occ
-  = StgNonRec  bndr (GenStgRhs bndr occ)
-  | StgRec     [(bndr, GenStgRhs bndr occ)]
+  = StgNonRec  SRT bndr (GenStgRhs bndr occ)
+  | StgRec     SRT [(bndr, GenStgRhs bndr occ)]
+
+stgBinders :: GenStgBinding bndr occ -> [bndr]
+stgBinders (StgNonRec _ b _) = [b]
+stgBinders (StgRec _ bs)     = map fst bs
 \end{code}
 
 %************************************************************************
@@ -97,6 +113,7 @@ isStgTypeArg other       = False
 
 isDllArg :: StgArg -> Bool
        -- Does this argument refer to something in a different DLL?
+isDllArg (StgTypeArg v)   = False
 isDllArg (StgVarArg v)   = isDllName (idName v)
 isDllArg (StgLitArg lit) = isLitLitLit lit
 
@@ -110,6 +127,7 @@ stgArgType :: StgArg -> Type
        -- Very half baked becase we have lost the type arguments
 stgArgType (StgVarArg v)   = idType v
 stgArgType (StgLitArg lit) = literalType lit
+stgArgType (StgTypeArg lit) = panic "stgArgType called on stgTypeArg"
 \end{code}
 
 %************************************************************************
@@ -157,7 +175,7 @@ constructors, primitives, and literals.
   | StgConApp  DataCon
                [GenStgArg occ] -- Saturated
 
-  | StgPrimApp PrimOp
+  | StgOpApp   StgOp           -- Primitive op or foreign call
                [GenStgArg occ] -- Saturated
                Type            -- Result type; we need to know the result type
                                -- so that we can assign result registers.
@@ -175,7 +193,7 @@ it encodes (\x -> e) as (let f = \x -> e in f)
 \begin{code}
   | StgLam
        Type            -- Type of whole lambda (useful when making a binder for it)
-       [Id]
+       [bndr]
        StgExpr         -- Body of lambda
 \end{code}
 
@@ -349,10 +367,9 @@ data GenStgRhs bndr occ
   = StgRhsClosure
        CostCentreStack         -- CCS to be attached (default is CurrentCCS)
        StgBinderInfo           -- Info about how this binder is used (see below)
-       SRT                     -- The closures's SRT
        [occ]                   -- non-global free vars; a list, rather than
                                -- a set, because order is important
-       UpdateFlag              -- ReEntrant | Updatable | SingleEntry
+       !UpdateFlag             -- ReEntrant | Updatable | SingleEntry
        [bndr]                  -- arguments; if empty, then not a function;
                                -- as above, order is important.
        (GenStgExpr bndr occ)   -- body
@@ -381,47 +398,50 @@ The second flavour of right-hand-side is for constructors (simple but important)
        [GenStgArg occ] -- args
 \end{code}
 
+\begin{code}
+stgRhsArity :: StgRhs -> Int
+stgRhsArity (StgRhsClosure _ _ _ _ bndrs _) = count isId bndrs
+  -- The arity never includes type parameters, so
+  -- when keeping type arguments and binders in the Stg syntax 
+  -- (opt_KeepStgTypes) we have to fliter out the type binders.
+stgRhsArity (StgRhsCon _ _ _) = 0
+\end{code}
+
+\begin{code}
+stgBindHasCafRefs :: GenStgBinding bndr occ -> Bool
+stgBindHasCafRefs (StgNonRec srt _ rhs)
+  = nonEmptySRT srt || rhsIsUpdatable rhs
+stgBindHasCafRefs (StgRec srt binds)
+  = nonEmptySRT srt || any rhsIsUpdatable (map snd binds)
+
+rhsIsUpdatable (StgRhsClosure _ _ _ upd _ _) = isUpdatable upd
+rhsIsUpdatable _ = False
+\end{code}
+
 Here's the @StgBinderInfo@ type, and its combining op:
 \begin{code}
 data StgBinderInfo
   = NoStgBinderInfo
-  | StgBinderInfo
-       Bool            -- At least one occurrence as an argument
-
-       Bool            -- At least one occurrence in an unsaturated application
-
-       Bool            -- This thing (f) has at least occurrence of the form:
-                       --    x = [..] \u [] -> f a b c
-                       -- where the application is saturated
+  | SatCallsOnly       -- All occurrences are *saturated* *function* calls
+                       -- This means we don't need to build an info table and 
+                       -- slow entry code for the thing
+                       -- Thunks never get this value
 
-       Bool            -- Ditto for non-updatable x.
+noBinderInfo = NoStgBinderInfo
+stgUnsatOcc  = NoStgBinderInfo
+stgSatOcc    = SatCallsOnly
 
-       Bool            -- At least one fake application occurrence, that is
-                       -- an StgApp f args where args is an empty list
-                       -- This is due to the fact that we do not have a
-                       -- StgVar constructor.
-                       -- Used by the lambda lifter.
-                       -- True => "at least one unsat app" is True too
-
-stgArgOcc        = StgBinderInfo True  False False False False
-stgUnsatOcc      = StgBinderInfo False True  False False False
-stgStdHeapOcc    = StgBinderInfo False False True  False False
-stgNoUpdHeapOcc  = StgBinderInfo False False False True  False
-stgNormalOcc     = StgBinderInfo False False False False False
--- [Andre] can't think of a good name for the last one.
-stgFakeFunAppOcc = StgBinderInfo False True  False False True
+satCallsOnly :: StgBinderInfo -> Bool
+satCallsOnly SatCallsOnly    = True
+satCallsOnly NoStgBinderInfo = False
 
 combineStgBinderInfo :: StgBinderInfo -> StgBinderInfo -> StgBinderInfo
+combineStgBinderInfo SatCallsOnly SatCallsOnly = SatCallsOnly
+combineStgBinderInfo info1 info2              = NoStgBinderInfo
 
-combineStgBinderInfo NoStgBinderInfo info2 = info2
-combineStgBinderInfo info1 NoStgBinderInfo = info1
-combineStgBinderInfo (StgBinderInfo arg1 unsat1 std_heap1 upd_heap1 fkap1)
-                    (StgBinderInfo arg2 unsat2 std_heap2 upd_heap2 fkap2)
-  = StgBinderInfo (arg1      || arg2)
-                 (unsat1    || unsat2)
-                 (std_heap1 || std_heap2)
-                 (upd_heap1 || upd_heap2)
-                 (fkap1     || fkap2)
+--------------
+pp_binder_info NoStgBinderInfo = empty
+pp_binder_info SatCallsOnly    = ptext SLIT("sat-only")
 \end{code}
 
 %************************************************************************
@@ -432,9 +452,33 @@ combineStgBinderInfo (StgBinderInfo arg1 unsat1 std_heap1 upd_heap1 fkap1)
 
 Just like in @CoreSyntax@ (except no type-world stuff).
 
+* Algebraic cases are done using
+       StgAlgAlts (Just tc) alts deflt
+
+* Polymorphic cases, or case of a function type, are done using
+       StgAlgAlts Nothing [] (StgBindDefault e)
+
+* Primitive cases are done using 
+       StgPrimAlts tc alts deflt
+
+We thought of giving polymorphic cases their own constructor,
+but we get a bit more code sharing this way
+
+The type constructor in StgAlgAlts/StgPrimAlts is guaranteed not
+to be abstract; that is, we can see its representation.  This is
+important because the code generator uses it to determine return
+conventions etc.  But it's not trivial where there's a moduule loop 
+involved, because some versions of a type constructor might not have
+all the constructors visible.  So mkStgAlgAlts (in CoreToStg) ensures
+that it gets the TyCon from the constructors or literals (which are
+guaranteed to have the Real McCoy) rather than from the scrutinee type.
+
 \begin{code}
 data GenStgCaseAlts bndr occ
-  = StgAlgAlts Type    -- so we can find out things about constructor family
+  = StgAlgAlts (Maybe TyCon)                   -- Just tc => scrutinee type is 
+                                               --            an algebraic data type
+                                               -- Nothing => scrutinee type is a type
+                                               --            variable or function type
                [(DataCon,                      -- alts: data constructor,
                  [bndr],                       -- constructor's parameters,
                  [Bool],                       -- "use mask", same length as
@@ -443,7 +487,8 @@ data GenStgCaseAlts bndr occ
                                                -- used in the ...
                  GenStgExpr bndr occ)] -- ...right-hand side.
                (GenStgCaseDefault bndr occ)
-  | StgPrimAlts        Type    -- so we can find out things about constructor family
+
+  | StgPrimAlts        TyCon
                [(Literal,                      -- alts: unboxed literal,
                  GenStgExpr bndr occ)] -- rhs.
                (GenStgCaseDefault bndr occ)
@@ -500,6 +545,26 @@ isUpdatable Updatable   = True
 
 %************************************************************************
 %*                                                                      *
+\subsubsection{StgOp}
+%*                                                                      *
+%************************************************************************
+
+An StgOp allows us to group together PrimOps and ForeignCalls.
+It's quite useful to move these around together, notably
+in StgOpApp and COpStmt.
+
+\begin{code}
+data StgOp = StgPrimOp  PrimOp
+
+          | StgFCallOp ForeignCall Unique
+               -- The Unique is occasionally needed by the C pretty-printer
+               -- (which lacks a unique supply), notably when generating a
+               -- typedef for foreign-export-dynamic
+\end{code}
+
+
+%************************************************************************
+%*                                                                      *
 \subsubsection[Static Reference Tables]{@SRT@}
 %*                                                                      *
 %************************************************************************
@@ -508,40 +573,28 @@ There is one SRT per top-level function group.  Each local binding and
 case expression within this binding group has a subrange of the whole
 SRT, expressed as an offset and length.
 
+In CoreToStg we collect the list of CafRefs at each SRT site, which is later 
+converted into the length and offset form by the SRT pass.
+
 \begin{code}
 data SRT = NoSRT
-         | SRT !Int{-offset-} !Int{-length-}
+        | SRTEntries IdSet                     -- generated by CoreToStg
+         | SRT !Int{-offset-} !Int{-length-}   -- generated by computeSRTs
 
 noSRT :: SRT
 noSRT = NoSRT
 
+nonEmptySRT NoSRT           = False
+nonEmptySRT (SRTEntries vs) = not (isEmptyVarSet vs)
+nonEmptySRT _               = True
+
 pprSRT (NoSRT) = ptext SLIT("_no_srt_")
+pprSRT (SRTEntries ids) = text "SRT:" <> ppr ids
 pprSRT (SRT off len) = parens (ppr off <> comma <> ppr len)
 \end{code}
 
 %************************************************************************
 %*                                                                     *
-\subsection[Stg-utility-functions]{Utility functions}
-%*                                                                     *
-%************************************************************************
-
-
-For doing interfaces, we want the exported top-level Ids from the
-final pre-codegen STG code, so as to be sure we have the
-latest/greatest pragma info.
-
-\begin{code}
-collectFinalStgBinders
-       :: [StgBinding] -- input program
-       -> [Id]
-
-collectFinalStgBinders [] = []
-collectFinalStgBinders (StgNonRec b _ : binds) = b : collectFinalStgBinders binds
-collectFinalStgBinders (StgRec bs     : binds) = map fst bs ++ collectFinalStgBinders binds
-\end{code}
-
-%************************************************************************
-%*                                                                     *
 \subsection[Stg-pretty-printing]{Pretty-printing}
 %*                                                                     *
 %************************************************************************
@@ -553,13 +606,14 @@ hoping he likes terminators instead...  Ditto for case alternatives.
 pprGenStgBinding :: (Outputable bndr, Outputable bdee, Ord bdee)
                 => GenStgBinding bndr bdee -> SDoc
 
-pprGenStgBinding (StgNonRec bndr rhs)
-  = hang (hsep [ppr bndr, equals])
-        4 ((<>) (ppr rhs) semi)
+pprGenStgBinding (StgNonRec srt bndr rhs)
+  = pprMaybeSRT srt $$ hang (hsep [ppr bndr, equals])
+                       4 ((<>) (ppr rhs) semi)
 
-pprGenStgBinding (StgRec pairs)
+pprGenStgBinding (StgRec srt pairs)
   = vcat ((ifPprDebug (ptext SLIT("{- StgRec (begin) -}"))) :
-             (map (ppr_bind) pairs) ++ [(ifPprDebug (ptext SLIT("{- StgRec (end) -}")))])
+          pprMaybeSRT srt :
+          (map (ppr_bind) pairs) ++ [(ifPprDebug (ptext SLIT("{- StgRec (end) -}")))])
   where
     ppr_bind (bndr, expr)
       = hang (hsep [ppr bndr, equals])
@@ -624,8 +678,8 @@ pprStgExpr (StgApp func args)
 pprStgExpr (StgConApp con args)
   = hsep [ ppr con, brackets (interppSP args)]
 
-pprStgExpr (StgPrimApp op args _)
-  = hsep [ ppr op, brackets (interppSP args)]
+pprStgExpr (StgOpApp op args _)
+  = hsep [ pprStgOp op, brackets (interppSP args)]
 
 pprStgExpr (StgLam _ bndrs body)
   =sep [ char '\\' <+> ppr bndrs <+> ptext SLIT("->"),
@@ -641,7 +695,8 @@ pprStgExpr (StgLam _ bndrs body)
 --
 -- Very special!  Suspicious! (SLPJ)
 
-pprStgExpr (StgLet (StgNonRec bndr (StgRhsClosure cc bi srt free_vars upd_flag args rhs))
+{-
+pprStgExpr (StgLet srt (StgNonRec bndr (StgRhsClosure cc bi free_vars upd_flag args rhs))
                        expr@(StgLet _ _))
   = ($$)
       (hang (hcat [ptext SLIT("let { "), ppr bndr, ptext SLIT(" = "),
@@ -652,12 +707,14 @@ pprStgExpr (StgLet (StgNonRec bndr (StgRhsClosure cc bi srt free_vars upd_flag a
                          interppSP args, char ']'])
            8 (sep [hsep [ppr rhs, ptext SLIT("} in")]]))
       (ppr expr)
+-}
 
 -- special case: let ... in let ...
 
 pprStgExpr (StgLet bind expr@(StgLet _ _))
   = ($$)
-      (sep [hang (ptext SLIT("let {")) 2 (hsep [pprGenStgBinding bind, ptext SLIT("} in")])])
+      (sep [hang (ptext SLIT("let {"))
+               2 (hsep [pprGenStgBinding bind, ptext SLIT("} in")])])
       (ppr expr)
 
 -- general case
@@ -695,31 +752,34 @@ pprStgExpr (StgCase expr lvs_whole lvs_rhss bndr srt alts)
                    ptext SLIT("]; rhs lvs: ["), interppSP (uniqSetToList lvs_rhss),
                    ptext SLIT("]; "),
                    pprMaybeSRT srt])),
-          nest 2 (ppr_alts alts),
+          nest 2 (pprStgAlts alts),
           char '}']
   where
-    ppr_default StgNoDefault = empty
-    ppr_default (StgBindDefault expr)
-      = hang (hsep [ptext SLIT("DEFAULT"), ptext SLIT("->")]) 4 (ppr expr)
-
-    pp_ty (StgAlgAlts  ty _ _) = ppr ty
-    pp_ty (StgPrimAlts ty _ _) = ppr ty
+    pp_ty (StgAlgAlts  maybe_tycon _ _) = ppr maybe_tycon
+    pp_ty (StgPrimAlts tycon       _ _) = ppr tycon
 
-    ppr_alts (StgAlgAlts ty alts deflt)
+pprStgAlts (StgAlgAlts _ alts deflt)
       = vcat [ vcat (map (ppr_bxd_alt) alts),
-                  ppr_default deflt ]
+              pprStgDefault deflt ]
       where
        ppr_bxd_alt (con, params, use_mask, expr)
          = hang (hsep [ppr con, interppSP params, ptext SLIT("->")])
                   4 ((<>) (ppr expr) semi)
 
-    ppr_alts (StgPrimAlts ty alts deflt)
+pprStgAlts (StgPrimAlts _ alts deflt)
       = vcat [ vcat (map (ppr_ubxd_alt) alts),
-                  ppr_default deflt ]
+              pprStgDefault deflt ]
       where
        ppr_ubxd_alt (lit, expr)
          = hang (hsep [ppr lit, ptext SLIT("->")])
                 4 ((<>) (ppr expr) semi)
+
+pprStgDefault StgNoDefault         = empty
+pprStgDefault (StgBindDefault expr) = hang (hsep [ptext SLIT("DEFAULT"), ptext SLIT("->")]) 
+                                        4 (ppr expr)
+
+pprStgOp (StgPrimOp  op)   = ppr op
+pprStgOp (StgFCallOp op _) = ppr op
 \end{code}
 
 \begin{code}
@@ -737,20 +797,18 @@ pprStgRhs :: (Outputable bndr, Outputable bdee, Ord bdee)
          => GenStgRhs bndr bdee -> SDoc
 
 -- special case
-pprStgRhs (StgRhsClosure cc bi srt [free_var] upd_flag [{-no args-}] (StgApp func []))
+pprStgRhs (StgRhsClosure cc bi [free_var] upd_flag [{-no args-}] (StgApp func []))
   = hcat [ ppr cc,
           pp_binder_info bi,
-          pprMaybeSRT srt,
           brackets (ifPprDebug (ppr free_var)),
           ptext SLIT(" \\"), ppr upd_flag, ptext SLIT(" [] "), ppr func ]
 
 -- general case
-pprStgRhs (StgRhsClosure cc bi srt free_vars upd_flag args body)
-  = hang (hcat [ppr cc,
+pprStgRhs (StgRhsClosure cc bi free_vars upd_flag args body)
+  = hang (hsep [if opt_SccProfilingOn then ppr cc else empty,
                pp_binder_info bi,
-               pprMaybeSRT srt,
-               brackets (ifPprDebug (interppSP free_vars)),
-               ptext SLIT(" \\"), ppr upd_flag, brackets (interppSP args)])
+               ifPprDebug (brackets (interppSP free_vars)),
+               char '\\' <> ppr upd_flag, brackets (interppSP args)])
         4 (ppr body)
 
 pprStgRhs (StgRhsCon cc con args)
@@ -758,30 +816,5 @@ pprStgRhs (StgRhsCon cc con args)
           space, ppr con, ptext SLIT("! "), brackets (interppSP args)]
 
 pprMaybeSRT (NoSRT) = empty
-pprMaybeSRT srt     = ptext SLIT(" srt: ") <> pprSRT srt
-
---------------
-
-pp_binder_info NoStgBinderInfo = empty
-
--- cases so boring that we print nothing
-pp_binder_info (StgBinderInfo True b c d e) = empty
-
--- general case
-pp_binder_info (StgBinderInfo a b c d e)
-  = getPprStyle $ \ sty -> 
-    if userStyle sty then
-       empty
-    else
-       parens (hsep (punctuate comma (map ppr [a,b,c,d,e])))
-\end{code}
-
-Collect @IdInfo@ stuff that is most easily just snaffled straight
-from the STG bindings.
-
-\begin{code}
-stgArity :: StgRhs -> Int
-
-stgArity (StgRhsCon _ _ _)              = 0 -- it's a constructor, fully applied
-stgArity (StgRhsClosure _ _ _ _ _ args _ ) = length args
+pprMaybeSRT srt     = ptext SLIT("srt: ") <> pprSRT srt
 \end{code}