[project @ 1998-03-19 23:54:49 by simonpj]
[ghc-hetmet.git] / ghc / compiler / simplStg / SimplStg.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1995
3 %
4 \section[SimplStg]{Driver for simplifying @STG@ programs}
5
6 \begin{code}
7 module SimplStg ( stg2stg ) where
8
9 #include "HsVersions.h"
10
11 import StgSyn
12
13 import LambdaLift       ( liftProgram )
14 import Name             ( isLocallyDefined )
15 import UniqSet          ( UniqSet(..), mapUniqSet )
16 import CostCentre       ( CostCentre )
17 import SCCfinal         ( stgMassageForProfiling )
18 import StgLint          ( lintStgBindings )
19 import StgStats         ( showStgStats )
20 import StgVarInfo       ( setStgVarInfo )
21 import UpdAnal          ( updateAnalyse )
22
23 import CmdLineOpts      ( opt_SccGroup, --Not used:opt_EnsureSplittableC,
24                           opt_StgDoLetNoEscapes, opt_D_verbose_stg2stg,
25                           opt_DoStgLinting,
26                           StgToDo(..)
27                         )
28 import Id               ( nullIdEnv, lookupIdEnv, addOneToIdEnv,
29                           growIdEnvList, isNullIdEnv, IdEnv,
30                           GenId{-instance Eq/Outputable -}, Id
31                         )
32 import Maybes           ( maybeToBool )
33 import ErrUtils         ( doIfSet )
34 import UniqSupply       ( splitUniqSupply, UniqSupply )
35 import Util             ( mapAccumL, panic, assertPanic )
36 import IO               ( hPutStr, stderr )
37 import Outputable
38 import GlaExts          ( trace )
39 \end{code}
40
41 \begin{code}
42 stg2stg :: [StgToDo]            -- spec of what stg-to-stg passes to do
43         -> FAST_STRING          -- module name (profiling only)
44         -> UniqSupply           -- a name supply
45         -> [StgBinding]         -- input...
46         -> IO
47             ([StgBinding],      -- output program...
48              ([CostCentre],     -- local cost-centres that need to be decl'd
49               [CostCentre]))    -- "extern" cost-centres
50
51 stg2stg stg_todos module_name us binds
52   = case (splitUniqSupply us)   of { (us4now, us4later) ->
53
54     doIfSet do_verbose_stg2stg
55         (printErrs (text "VERBOSE STG-TO-STG:" $$
56                     text "*** Core2Stg:" $$
57                     vcat (map ppr (setStgVarInfo False binds)))) >>
58
59         -- Do the main business!
60     foldl_mn do_stg_pass (binds, us4now, ([],[])) stg_todos
61                 >>= \ (processed_binds, _, cost_centres) ->
62
63         --      Do essential wind-up
64
65 {- Nuked for now        SLPJ Dec 96
66
67         -- Essential wind-up: part (a), saturate RHSs
68         -- This must occur *after* elimIndirections, because elimIndirections
69         -- can change things' arities.  Consider:
70         --      x_local = f x
71         --      x_global = \a -> x_local a
72         -- Then elimIndirections will change the program to
73         --      x_global = f x
74         -- and lo and behold x_global's arity has changed!
75     case (satStgRhs processed_binds us4later) of { saturated_binds ->
76 -}
77
78         -- Essential wind-up: part (b), do setStgVarInfo. It has to
79         -- happen regardless, because the code generator uses its
80         -- decorations.
81         --
82         -- Why does it have to happen last?  Because earlier passes
83         -- may move things around, which would change the live-var
84         -- info.  Also, setStgVarInfo decides about let-no-escape
85         -- things, which in turn do a better job if arities are
86         -- correct, which is done by satStgRhs.
87         --
88
89     return (setStgVarInfo do_let_no_escapes processed_binds, cost_centres)
90    }
91   where
92     do_let_no_escapes  = opt_StgDoLetNoEscapes
93     do_verbose_stg2stg = opt_D_verbose_stg2stg
94
95 {-
96     (do_unlocalising, unlocal_tag) 
97      = case opt_EnsureSplittableC of
98          Just tag -> (True, _PK_ tag)
99          Nothing  -> (False, panic "tag")
100 -}
101     grp_name  = case (opt_SccGroup) of
102                   Just xx -> _PK_ xx
103                   Nothing -> module_name -- default: module name
104
105     -------------
106     stg_linter = if False --LATER: opt_DoStgLinting (ToDo)
107                  then lintStgBindings
108                  else ( \ whodunnit binds -> binds )
109
110     -------------------------------------------
111     do_stg_pass (binds, us, ccs) to_do
112       = let
113             (us1, us2) = splitUniqSupply us
114         in
115         case to_do of
116           StgDoStaticArgs ->  panic "STG static argument transformation deleted"
117
118           StgDoUpdateAnalysis ->
119              ASSERT(null (fst ccs) && null (snd ccs))
120              _scc_ "StgUpdAnal"
121                 -- NB We have to do setStgVarInfo first!  (There's one
122                 -- place free-var info is used) But no let-no-escapes,
123                 -- because update analysis doesn't care.
124              end_pass us2 "UpdAnal" ccs (updateAnalyse (setStgVarInfo False binds))
125
126           D_stg_stats ->
127              trace (showStgStats binds)
128              end_pass us2 "StgStats" ccs binds
129
130           StgDoLambdaLift ->
131              _scc_ "StgLambdaLift"
132                 -- NB We have to do setStgVarInfo first!
133              let
134                 binds3 = liftProgram module_name us1 (setStgVarInfo do_let_no_escapes binds)
135              in
136              end_pass us2 "LambdaLift" ccs binds3
137
138           StgDoMassageForProfiling ->
139              _scc_ "ProfMassage"
140              let
141                  (collected_CCs, binds3)
142                    = stgMassageForProfiling module_name grp_name us1 binds
143              in
144              end_pass us2 "ProfMassage" collected_CCs binds3
145
146     end_pass us2 what ccs binds2
147       = -- report verbosely, if required
148         (if do_verbose_stg2stg then
149             hPutStr stderr (showSDoc
150               (text ("*** "++what++":") $$ vcat (map ppr binds2)
151             ))
152          else return ()) >>
153         let
154             linted_binds = stg_linter what binds2
155         in
156         return (linted_binds, us2, ccs)
157             -- return: processed binds
158             --         UniqueSupply for the next guy to use
159             --         cost-centres to be declared/registered (specialised)
160             --         add to description of what's happened (reverse order)
161
162 -- here so it can be inlined...
163 foldl_mn f z []     = return z
164 foldl_mn f z (x:xs) = f z x     >>= \ zz ->
165                      foldl_mn f zz xs
166 \end{code}