[project @ 2000-11-24 09:51:38 by simonpj]
[ghc-hetmet.git] / ghc / compiler / simplStg / SimplStg.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1998
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 CostCentre       ( CostCentre, CostCentreStack )
15 import SCCfinal         ( stgMassageForProfiling )
16 import StgLint          ( lintStgBindings )
17 import StgStats         ( showStgStats )
18 import StgVarInfo       ( setStgVarInfo )
19 import SRT              ( computeSRTs )
20
21 import CmdLineOpts      ( DynFlags, DynFlag(..), dopt, 
22                           opt_StgDoLetNoEscapes,
23                           StgToDo(..), dopt_StgToDo
24                         )
25 import Id               ( Id )
26 import Module           ( Module )
27 import ErrUtils         ( doIfSet_dyn, dumpIfSet_dyn, showPass )
28 import UniqSupply       ( mkSplitUniqSupply, splitUniqSupply, UniqSupply )
29 import IO               ( hPutStr, stdout )
30 import Outputable
31 \end{code}
32
33 \begin{code}
34 stg2stg :: DynFlags             -- includes spec of what stg-to-stg passes to do
35         -> Module               -- module name (profiling only)
36         -> UniqSupply           -- a name supply
37         -> [StgBinding]         -- input...
38         -> IO
39             ([(StgBinding,[Id])],  -- output program...
40              ([CostCentre],        -- local cost-centres that need to be decl'd
41               [CostCentre],        -- "extern" cost-centres
42               [CostCentreStack]))  -- pre-defined "singleton" cost centre stacks
43
44 stg2stg dflags module_name us binds
45   = do  { showPass dflags "Stg2Stg"
46         ; us <- mkSplitUniqSupply 'g'
47
48         ; doIfSet_dyn dflags Opt_D_verbose_stg2stg 
49                       (printDump (text "VERBOSE STG-TO-STG:"))
50
51         ; (binds', us', ccs) <- end_pass us "Core2Stg" ([],[],[]) binds
52
53                 -- Do the main business!
54         ; (processed_binds, _, cost_centres) 
55                 <- foldl_mn do_stg_pass (binds', us', ccs)
56                             (dopt_StgToDo dflags)
57
58                 -- Do essential wind-up
59         -- Essential wind-up: part (b), do setStgVarInfo. It has to
60         -- happen regardless, because the code generator uses its
61         -- decorations.
62         --
63         -- Why does it have to happen last?  Because earlier passes
64         -- may move things around, which would change the live-var
65         -- info.  Also, setStgVarInfo decides about let-no-escape
66         -- things, which in turn do a better job if arities are
67         -- correct, which is done by satStgRhs.
68         --
69
70         ; let annotated_binds = setStgVarInfo opt_StgDoLetNoEscapes processed_binds
71               srt_binds       = computeSRTs annotated_binds
72
73         ; dumpIfSet_dyn dflags Opt_D_dump_stg "STG syntax:" 
74                         (pprStgBindingsWithSRTs srt_binds)
75
76         ; return (srt_binds, cost_centres)
77    }
78
79   where
80     stg_linter = if dopt Opt_DoStgLinting dflags
81                  then lintStgBindings
82                  else ( \ whodunnit binds -> binds )
83
84     -------------------------------------------
85     do_stg_pass (binds, us, ccs) to_do
86       = let
87             (us1, us2) = splitUniqSupply us
88         in
89         case to_do of
90           StgDoStaticArgs ->  panic "STG static argument transformation deleted"
91
92           D_stg_stats ->
93              trace (showStgStats binds)
94              end_pass us2 "StgStats" ccs binds
95
96           StgDoLambdaLift ->
97              _scc_ "StgLambdaLift"
98                 -- NB We have to do setStgVarInfo first!
99              let
100                 binds3 = liftProgram module_name us1 (setStgVarInfo opt_StgDoLetNoEscapes binds)
101              in
102              end_pass us2 "LambdaLift" ccs binds3
103
104           StgDoMassageForProfiling ->
105              _scc_ "ProfMassage"
106              let
107                  (collected_CCs, binds3)
108                    = stgMassageForProfiling module_name us1 binds
109              in
110              end_pass us2 "ProfMassage" collected_CCs binds3
111
112     end_pass us2 what ccs binds2
113       = -- report verbosely, if required
114         (if dopt Opt_D_verbose_stg2stg dflags then
115             hPutStr stdout (showSDoc
116               (text ("*** "++what++":") $$ vcat (map ppr binds2)
117             ))
118          else return ()) >>
119         let
120             linted_binds = stg_linter what binds2
121         in
122         return (linted_binds, us2, ccs)
123             -- return: processed binds
124             --         UniqueSupply for the next guy to use
125             --         cost-centres to be declared/registered (specialised)
126             --         add to description of what's happened (reverse order)
127
128 -- here so it can be inlined...
129 foldl_mn f z []     = return z
130 foldl_mn f z (x:xs) = f z x     >>= \ zz ->
131                      foldl_mn f zz xs
132 \end{code}