[project @ 1997-03-14 07:52:06 by simonpj]
[ghc-hetmet.git] / ghc / compiler / simplStg / SimplStg.lhs
index efa5679..7e38837 100644 (file)
@@ -15,23 +15,26 @@ import StgSyn
 
 import LambdaLift      ( liftProgram )
 import Name            ( isLocallyDefined )
+import UniqSet          ( UniqSet(..), mapUniqSet )
 import SCCfinal                ( stgMassageForProfiling )
 import StgLint         ( lintStgBindings )
 import StgStats                ( showStgStats )
 import StgVarInfo      ( setStgVarInfo )
 import UpdAnal         ( updateAnalyse )
 
-import CmdLineOpts     ( opt_EnsureSplittableC, opt_SccGroup,
+import CmdLineOpts     ( opt_SccGroup, --Not used:opt_EnsureSplittableC,
                          opt_StgDoLetNoEscapes, opt_D_verbose_stg2stg,
+                         opt_DoStgLinting,
                          StgToDo(..)
                        )
 import Id              ( nullIdEnv, lookupIdEnv, addOneToIdEnv,
                          growIdEnvList, isNullIdEnv, SYN_IE(IdEnv),
+                         setIdVisibility,
                          GenId{-instance Eq/Outputable -}
                        )
 import Maybes          ( maybeToBool )
 import PprType         ( GenType{-instance Outputable-} )
-import Pretty          ( ppShow, ppAbove, ppAboves, ppStr )
+import Pretty          ( ppShow, ppAbove, ppAboves, ppStr, ppPStr )
 import UniqSupply      ( splitUniqSupply )
 import Util            ( mapAccumL, panic, assertPanic )
 
@@ -54,7 +57,7 @@ stg2stg stg_todos module_name ppr_style us binds
     (if do_verbose_stg2stg then
        hPutStr stderr "VERBOSE STG-TO-STG:\n" >>
        hPutStr stderr (ppShow 1000
-       (ppAbove (ppStr ("*** Core2Stg:"))
+       (ppAbove (ppPStr SLIT("*** Core2Stg:"))
                 (ppAboves (map (ppr ppr_style) (setStgVarInfo False binds)))
        ))
      else return ()) >>
@@ -66,6 +69,7 @@ stg2stg stg_todos module_name ppr_style us binds
        --      Do essential wind-up
 
 {- Nuked for now       SLPJ Dec 96
+
        -- Essential wind-up: part (a), saturate RHSs
        -- This must occur *after* elimIndirections, because elimIndirections
        -- can change things' arities.  Consider:
@@ -74,7 +78,6 @@ stg2stg stg_todos module_name ppr_style us binds
        -- Then elimIndirections will change the program to
        --      x_global = f x
        -- and lo and behold x_global's arity has changed!
-
     case (satStgRhs processed_binds us4later) of { saturated_binds ->
 -}
 
@@ -89,13 +92,20 @@ stg2stg stg_todos module_name ppr_style us binds
        -- correct, which is done by satStgRhs.
        --
 
-{-     Done in Core now.  Nuke soon. SLPJ Nov 96
+{- 
+       Done in Core now.  Nuke soon. SLPJ Nov 96
+
+   No, STG passes may introduce toplevel bindings which
+   have to be globalised here (later than Core anyway) -- SOF 2/97
+
+   Yes, lambda lifting now does the Right Thing.
+
     let
                -- ToDo: provide proper flag control!
        binds_to_mangle
          = if not do_unlocalising
-           then saturated_binds
-           else snd (unlocaliseStgBinds unlocal_tag nullIdEnv no_ind_binds)
+           then processed_binds
+           else snd (unlocaliseStgBinds unlocal_tag nullIdEnv processed_binds)
     in
 -}
 
@@ -105,12 +115,18 @@ stg2stg stg_todos module_name ppr_style us binds
     do_let_no_escapes  = opt_StgDoLetNoEscapes
     do_verbose_stg2stg = opt_D_verbose_stg2stg
 
+{-
+    (do_unlocalising, unlocal_tag) 
+     = case opt_EnsureSplittableC of
+         Just tag -> (True, _PK_ tag)
+         Nothing  -> (False, panic "tag")
+-}
     grp_name  = case (opt_SccGroup) of
                  Just xx -> _PK_ xx
                  Nothing -> module_name -- default: module name
 
     -------------
-    stg_linter = if False -- LATER: switch_is_on DoCoreLinting -- ToDo: DoStgLinting flag
+    stg_linter = if False --LATER: opt_DoStgLinting (ToDo)
                 then lintStgBindings ppr_style
                 else ( \ whodunnit binds -> binds )
 
@@ -138,7 +154,7 @@ stg2stg stg_todos module_name ppr_style us binds
             _scc_ "StgLambdaLift"
                -- NB We have to do setStgVarInfo first!
             let
-               binds3 = liftProgram us1 (setStgVarInfo do_let_no_escapes binds)
+               binds3 = liftProgram module_name us1 (setStgVarInfo do_let_no_escapes binds)
             in
             end_pass us2 "LambdaLift" ccs binds3
 
@@ -173,4 +189,154 @@ foldl_mn f z (x:xs) = f z x       >>= \ zz ->
                     foldl_mn f zz xs
 \end{code}
 
+%************************************************************************
+%*                                                                     *
+\subsection[SimplStg-unlocalise]{Unlocalisation in STG code}
+%*                                                                     *
+%************************************************************************
+
+The idea of all this ``unlocalise'' stuff is that in certain (prelude
+only) modules we split up the .hc file into lots of separate little
+files, which are separately compiled by the C compiler.  That gives
+lots of little .o files.  The idea is that if you happen to mention
+one of them you don't necessarily pull them all in.  (Pulling in a
+piece you don't need can be v bad, because it may mention other pieces
+you don't need either, and so on.)
+
+Sadly, splitting up .hc files means that local names (like s234) are
+now globally visible, which can lead to clashes between two .hc
+files. So unlocaliseWhatnot goes through making all the local things
+into global things, essentially by giving them full names so when they
+are printed they'll have their module name too.  Pretty revolting
+really.
+
+\begin{code}
+type UnlocalEnv = IdEnv Id
 
+lookup_uenv :: UnlocalEnv -> Id -> Id
+lookup_uenv env id =  case lookupIdEnv env id of
+                       Nothing     -> id
+                       Just new_id -> new_id
+unlocaliseStgBinds :: FAST_STRING
+                   -> UnlocalEnv
+                   -> [StgBinding] 
+                  -> (UnlocalEnv, [StgBinding])
+unlocaliseStgBinds mod uenv []       = (uenv, [])
+unlocaliseStgBinds mod uenv (b : bs) =
+  case unlocal_top_bind mod uenv b        of { (new_uenv, new_b) ->
+  case unlocaliseStgBinds mod new_uenv bs of { (uenv3, new_bs) ->
+    (uenv3, new_b : new_bs)
+  }}
+
+------------------
+unlocal_top_bind :: FAST_STRING 
+                -> UnlocalEnv 
+                -> StgBinding 
+                -> (UnlocalEnv, StgBinding)
+unlocal_top_bind mod uenv bind@(StgNonRec binder _) =
+ let
+  new_uenv =
+   case lookupIdEnv uenv binder of
+    Just global -> uenv
+    Nothing     -> new_env
+     where
+      new_env    = addOneToIdEnv uenv binder new_global
+      new_global = setIdVisibility mod binder
+ in
+ (new_uenv, renameTopStgBind (lookup_uenv new_uenv) bind)
+
+unlocal_top_bind mod uenv bind@(StgRec pairs) =
+ let
+  new_env binder uenv =
+    case lookupIdEnv uenv binder of
+      Just global -> uenv
+      Nothing     -> env'
+        where
+         env'       = addOneToIdEnv uenv binder new_global
+         new_global = setIdVisibility mod binder
+
+  uenv' = foldr (new_env) uenv (map (fst) pairs)
+ in
+ (uenv', renameTopStgBind (lookup_uenv uenv') bind)
+
+\end{code}
+
+@renameTopStgBind@ renames top level binders and all occurrences thereof.
+
+\begin{code}
+renameTopStgBind :: (Id -> Id) -> StgBinding -> StgBinding
+renameTopStgBind fn (StgNonRec b rhs) = StgNonRec (fn b) (mapStgBindeesRhs fn rhs)
+renameTopStgBind fn (StgRec pairs)    = StgRec [ (fn b, mapStgBindeesRhs fn r) | (b, r) <- pairs ]
+\end{code}
+
+This utility function simply applies the given function to every
+bindee in the program.
+
+\begin{code}
+mapStgBindeesBind :: (Id -> Id) -> StgBinding -> StgBinding
+mapStgBindeesBind fn (StgNonRec b rhs) = StgNonRec b (mapStgBindeesRhs fn rhs)
+mapStgBindeesBind fn (StgRec pairs)    = StgRec [ (b, mapStgBindeesRhs fn r) | (b, r) <- pairs ]
+
+------------------
+mapStgBindeesRhs :: (Id -> Id) -> StgRhs -> StgRhs
+mapStgBindeesRhs fn (StgRhsClosure cc bi fvs u args expr)
+  = StgRhsClosure 
+       cc bi 
+       (map fn fvs) 
+       u 
+       (map fn args) 
+       (mapStgBindeesExpr fn expr)
+
+mapStgBindeesRhs fn (StgRhsCon cc con atoms)
+  = StgRhsCon cc con (map (mapStgBindeesArg fn) atoms)
+
+------------------
+mapStgBindeesExpr :: (Id -> Id) -> StgExpr -> StgExpr
+
+mapStgBindeesExpr fn (StgApp f args lvs)
+  = StgApp (mapStgBindeesArg fn f) 
+          (map (mapStgBindeesArg fn) args) 
+          (mapUniqSet fn lvs)
+
+mapStgBindeesExpr fn (StgCon con atoms lvs)
+  = StgCon con (map (mapStgBindeesArg fn) atoms) (mapUniqSet fn lvs)
+
+mapStgBindeesExpr fn (StgPrim op atoms lvs)
+  = StgPrim op (map (mapStgBindeesArg fn) atoms) (mapUniqSet fn lvs)
+
+mapStgBindeesExpr fn (StgLet bind expr)
+  = StgLet (mapStgBindeesBind fn bind) (mapStgBindeesExpr fn expr)
+
+mapStgBindeesExpr fn (StgLetNoEscape lvs rhss_lvs bind body)
+  = StgLetNoEscape (mapUniqSet fn lvs) (mapUniqSet fn rhss_lvs)
+                  (mapStgBindeesBind fn bind) (mapStgBindeesExpr fn body)
+
+mapStgBindeesExpr fn (StgSCC ty label expr)
+  = StgSCC ty label (mapStgBindeesExpr fn expr)
+
+mapStgBindeesExpr fn (StgCase expr lvs1 lvs2 uniq alts)
+  = StgCase (mapStgBindeesExpr fn expr)
+           (mapUniqSet fn lvs1)
+           (mapUniqSet fn lvs2)
+           uniq
+           (mapStgBindeesAlts alts)
+  where
+    mapStgBindeesAlts (StgAlgAlts ty alts deflt)
+      = StgAlgAlts ty (map mapStgBindeesBoxed_alt alts) (mapStgBindeesDeflt deflt)
+      where
+       mapStgBindeesBoxed_alt (c,ps,use_mask,expr) = (c,ps,use_mask,mapStgBindeesExpr fn expr)
+
+    mapStgBindeesAlts (StgPrimAlts ty alts deflt)
+      = StgPrimAlts ty (map mapStgBindeesunboxed_alt alts) (mapStgBindeesDeflt deflt)
+      where
+       mapStgBindeesunboxed_alt (l,expr) = (l,mapStgBindeesExpr fn expr)
+
+    mapStgBindeesDeflt StgNoDefault                = StgNoDefault
+    mapStgBindeesDeflt (StgBindDefault b used expr) = StgBindDefault b used (mapStgBindeesExpr fn expr)
+
+------------------
+mapStgBindeesArg :: (Id -> Id) -> StgArg -> StgArg
+mapStgBindeesArg fn a@(StgLitArg _)   = a
+mapStgBindeesArg fn a@(StgConArg _)   = a
+mapStgBindeesArg fn a@(StgVarArg id)  = StgVarArg (fn id)
+\end{code}