NCG debugging cleanup
[ghc-hetmet.git] / compiler / nativeGen / AsmCodeGen.lhs
1 -- -----------------------------------------------------------------------------
2 --
3 -- (c) The University of Glasgow 1993-2004
4 -- 
5 -- This is the top-level module in the native code generator.
6 --
7 -- -----------------------------------------------------------------------------
8
9 \begin{code}
10 module AsmCodeGen ( nativeCodeGen ) where
11
12 #include "HsVersions.h"
13 #include "nativeGen/NCG.h"
14
15 import MachInstrs
16 import MachRegs
17 import MachCodeGen
18 import PprMach
19 import RegAllocInfo
20 import NCGMonad
21 import PositionIndependentCode
22 import RegAllocLinear
23 import RegAllocStats
24 import RegLiveness
25 import RegCoalesce
26 import qualified RegAllocColor  as Color
27 import qualified GraphColor     as Color
28
29 import Cmm
30 import CmmOpt           ( cmmMiniInline, cmmMachOpFold )
31 import PprCmm           ( pprStmt, pprCmms, pprCmm )
32 import MachOp
33 import CLabel
34
35 import UniqFM
36 import Unique           ( Unique, getUnique )
37 import UniqSupply
38 import FastTypes
39 import List             ( groupBy, sortBy )
40 import ErrUtils         ( dumpIfSet_dyn )
41 import DynFlags
42 import StaticFlags      ( opt_Static, opt_PIC )
43 import Util
44 import Config           ( cProjectVersion )
45 import Module
46
47 import Digraph
48 import qualified Pretty
49 import Outputable
50 import FastString
51 import UniqSet
52
53 -- DEBUGGING ONLY
54 --import OrdList
55
56 import Data.List
57 import Data.Int
58 import Data.Word
59 import Data.Bits
60 import Data.Maybe
61 import GHC.Exts
62 import Control.Monad
63
64 {-
65 The native-code generator has machine-independent and
66 machine-dependent modules.
67
68 This module ("AsmCodeGen") is the top-level machine-independent
69 module.  Before entering machine-dependent land, we do some
70 machine-independent optimisations (defined below) on the
71 'CmmStmts's.
72
73 We convert to the machine-specific 'Instr' datatype with
74 'cmmCodeGen', assuming an infinite supply of registers.  We then use
75 a machine-independent register allocator ('regAlloc') to rejoin
76 reality.  Obviously, 'regAlloc' has machine-specific helper
77 functions (see about "RegAllocInfo" below).
78
79 Finally, we order the basic blocks of the function so as to minimise
80 the number of jumps between blocks, by utilising fallthrough wherever
81 possible.
82
83 The machine-dependent bits break down as follows:
84
85   * ["MachRegs"]  Everything about the target platform's machine
86     registers (and immediate operands, and addresses, which tend to
87     intermingle/interact with registers).
88
89   * ["MachInstrs"]  Includes the 'Instr' datatype (possibly should
90     have a module of its own), plus a miscellany of other things
91     (e.g., 'targetDoubleSize', 'smStablePtrTable', ...)
92
93   * ["MachCodeGen"]  is where 'Cmm' stuff turns into
94     machine instructions.
95
96   * ["PprMach"] 'pprInstr' turns an 'Instr' into text (well, really
97     a 'Doc').
98
99   * ["RegAllocInfo"] In the register allocator, we manipulate
100     'MRegsState's, which are 'BitSet's, one bit per machine register.
101     When we want to say something about a specific machine register
102     (e.g., ``it gets clobbered by this instruction''), we set/unset
103     its bit.  Obviously, we do this 'BitSet' thing for efficiency
104     reasons.
105
106     The 'RegAllocInfo' module collects together the machine-specific
107     info needed to do register allocation.
108
109    * ["RegisterAlloc"] The (machine-independent) register allocator.
110 -}
111
112 -- -----------------------------------------------------------------------------
113 -- Top-level of the native codegen
114
115 -- NB. We *lazilly* compile each block of code for space reasons.
116
117 --------------------
118 nativeCodeGen :: DynFlags -> Module -> ModLocation -> [RawCmm] -> UniqSupply -> IO Pretty.Doc
119 nativeCodeGen dflags mod modLocation cmms us
120   = let (res, _) = initUs us $
121            cgCmm (concat (map add_split cmms))
122
123         cgCmm :: [RawCmmTop] -> UniqSM ( [CmmNativeGenDump], Pretty.Doc, [CLabel])
124         cgCmm tops = 
125            lazyMapUs (cmmNativeGen dflags) tops  `thenUs` \ results -> 
126            case unzip3 results of { (dump,docs,imps) ->
127            returnUs (dump, my_vcat docs, concat imps)
128            }
129     in 
130     case res of { (dump, insn_sdoc, imports) -> do
131
132     cmmNativeGenDump dflags mod modLocation dump
133
134     return (insn_sdoc Pretty.$$ dyld_stubs imports
135
136 #if HAVE_SUBSECTIONS_VIA_SYMBOLS
137                 -- On recent versions of Darwin, the linker supports
138                 -- dead-stripping of code and data on a per-symbol basis.
139                 -- There's a hack to make this work in PprMach.pprNatCmmTop.
140             Pretty.$$ Pretty.text ".subsections_via_symbols"
141 #endif
142 #if HAVE_GNU_NONEXEC_STACK
143                 -- On recent GNU ELF systems one can mark an object file
144                 -- as not requiring an executable stack. If all objects
145                 -- linked into a program have this note then the program
146                 -- will not use an executable stack, which is good for
147                 -- security. GHC generated code does not need an executable
148                 -- stack so add the note in:
149             Pretty.$$ Pretty.text ".section .note.GNU-stack,\"\",@progbits"
150 #endif
151 #if !defined(darwin_TARGET_OS)
152                 -- And just because every other compiler does, lets stick in
153                 -- an identifier directive: .ident "GHC x.y.z"
154             Pretty.$$ let compilerIdent = Pretty.text "GHC" Pretty.<+>
155                                           Pretty.text cProjectVersion
156                        in Pretty.text ".ident" Pretty.<+>
157                           Pretty.doubleQuotes compilerIdent
158 #endif
159             )
160    }
161
162   where
163
164     add_split (Cmm tops)
165         | dopt Opt_SplitObjs dflags = split_marker : tops
166         | otherwise                 = tops
167
168     split_marker = CmmProc [] mkSplitMarkerLabel [] []
169
170          -- Generate "symbol stubs" for all external symbols that might
171          -- come from a dynamic library.
172 {-    dyld_stubs imps = Pretty.vcat $ map pprDyldSymbolStub $
173                                     map head $ group $ sort imps-}
174                                     
175         -- (Hack) sometimes two Labels pretty-print the same, but have
176         -- different uniques; so we compare their text versions...
177     dyld_stubs imps 
178         | needImportedSymbols
179           = Pretty.vcat $
180             (pprGotDeclaration :) $
181             map (pprImportedSymbol . fst . head) $
182             groupBy (\(_,a) (_,b) -> a == b) $
183             sortBy (\(_,a) (_,b) -> compare a b) $
184             map doPpr $
185             imps
186         | otherwise
187           = Pretty.empty
188         
189         where doPpr lbl = (lbl, Pretty.render $ pprCLabel lbl astyle)
190               astyle = mkCodeStyle AsmStyle
191
192 #ifndef NCG_DEBUG
193     my_vcat sds = Pretty.vcat sds
194 #else
195     my_vcat sds = Pretty.vcat (
196                       intersperse (
197                          Pretty.char ' ' 
198                             Pretty.$$ Pretty.ptext SLIT("# ___ncg_debug_marker")
199                             Pretty.$$ Pretty.char ' '
200                       ) 
201                       sds
202                    )
203 #endif
204
205
206 -- Carries output of the code generator passes, for dumping.
207 --      Make sure to only fill the one's we're interested in to avoid
208 --      creating space leaks.
209
210 data CmmNativeGenDump
211         = CmmNativeGenDump
212         { cdCmmOpt              :: RawCmmTop
213         , cdNative              :: [NatCmmTop]
214         , cdLiveness            :: [LiveCmmTop]
215         , cdCoalesce            :: Maybe [LiveCmmTop]
216         , cdRegAllocStats       :: Maybe [RegAllocStats]
217         , cdColoredGraph        :: Maybe (Color.Graph Reg RegClass Reg)
218         , cdAlloced             :: [NatCmmTop] }
219
220 dchoose dflags opt a b
221         | dopt opt dflags       = a
222         | otherwise             = b
223
224 dchooses dflags opts a b
225         | or $ map ( (flip dopt) dflags) opts   = a
226         | otherwise             = b
227
228 -- | Complete native code generation phase for a single top-level chunk of Cmm.
229 --      Unless they're being dumped, intermediate data structures are squashed after
230 --      every stage to avoid creating space leaks.
231 --
232 cmmNativeGen :: DynFlags -> RawCmmTop -> UniqSM (CmmNativeGenDump, Pretty.Doc, [CLabel])
233 cmmNativeGen dflags cmm
234  = do   
235         --
236         fixed_cmm
237          <-     {-# SCC "fixAssigns"  #-}
238                 fixAssignsTop cmm
239
240         ---- cmm to cmm optimisations
241         (cmm, imports, ppr_cmm)
242          <- (\fixed_cmm
243          -> {-# SCC "genericOpt"  #-}
244            do   let (cmm, imports)      = cmmToCmm dflags fixed_cmm
245                 
246                 return  ( cmm
247                         , imports
248                         , dchoose dflags Opt_D_dump_cmm cmm (CmmData Text []))
249              ) fixed_cmm
250
251
252         ---- generate native code from cmm
253         (native, lastMinuteImports, ppr_native)
254          <- (\cmm 
255          -> {-# SCC "genMachCode" #-}
256            do   (machCode, lastMinuteImports)
257                         <- genMachCode dflags cmm
258
259                 return  ( machCode
260                         , lastMinuteImports
261                         , dchoose dflags Opt_D_dump_asm_native machCode [])
262             ) cmm
263
264
265         ---- tag instructions with register liveness information
266         (withLiveness, ppr_withLiveness)
267          <- (\native
268          -> {-# SCC "regLiveness" #-}
269            do 
270                 withLiveness    <- mapUs regLiveness native
271
272                 return  ( withLiveness
273                         , dchoose dflags Opt_D_dump_asm_liveness withLiveness []))
274                 native
275
276         ---- allocate registers
277         (alloced, ppr_alloced, ppr_coalesce, ppr_regAllocStats, ppr_coloredGraph)
278          <- (\withLiveness
279          -> {-# SCC "regAlloc" #-}
280            do
281                 if dopt Opt_RegsGraph dflags
282                  then do
283                         -- the regs usable for allocation
284                         let alloc_regs  
285                                 = foldr (\r -> plusUFM_C unionUniqSets
286                                                         $ unitUFM (regClass r) (unitUniqSet r))
287                                         emptyUFM
288                                 $ map RealReg allocatableRegs
289
290                         -- aggressively coalesce moves between virtual regs
291                         coalesced       <- regCoalesce withLiveness
292
293                         -- graph coloring register allocation
294                         (alloced, regAllocStats)
295                                 <- Color.regAlloc 
296                                         alloc_regs
297                                         (mkUniqSet [0..maxSpillSlots]) 
298                                         coalesced
299
300                         return  ( alloced
301                                 , dchoose  dflags Opt_D_dump_asm_regalloc       alloced []
302                                 , dchoose  dflags Opt_D_dump_asm_coalesce       (Just coalesced)     Nothing
303                                 , dchooses dflags
304                                         [ Opt_D_dump_asm_regalloc_stages
305                                         , Opt_D_drop_asm_stats]
306                                         (Just regAllocStats) Nothing
307                                 , dchoose  dflags Opt_D_dump_asm_conflicts      Nothing Nothing)
308
309                  else do
310                         -- do linear register allocation
311                         alloced <- mapUs regAlloc withLiveness
312                         return  ( alloced
313                                 , dchoose dflags Opt_D_dump_asm_regalloc        alloced []
314                                 , Nothing
315                                 , Nothing
316                                 , Nothing )) 
317                 withLiveness
318                         
319
320         ---- shortcut branches
321         let shorted     =
322                 {-# SCC "shortcutBranches" #-}
323                 shortcutBranches dflags alloced
324
325         ---- sequence blocks
326         let sequenced   =
327                 {-# SCC "sequenceBlocks" #-}
328                 map sequenceTop shorted
329
330         ---- x86fp_kludge
331         let final_mach_code =
332 #if i386_TARGET_ARCH
333                 {-# SCC "x86fp_kludge" #-}
334                 map x86fp_kludge sequenced
335 #else
336                 sequenced
337 #endif
338                 
339         ---- vcat
340         let final_sdoc  = 
341                 {-# SCC "vcat" #-}
342                 Pretty.vcat (map pprNatCmmTop final_mach_code)
343
344         let dump        =
345                 CmmNativeGenDump
346                 { cdCmmOpt              = ppr_cmm
347                 , cdNative              = ppr_native
348                 , cdLiveness            = ppr_withLiveness
349                 , cdCoalesce            = ppr_coalesce
350                 , cdRegAllocStats       = ppr_regAllocStats
351                 , cdColoredGraph        = ppr_coloredGraph
352                 , cdAlloced             = ppr_alloced }
353
354         returnUs (dump, final_sdoc Pretty.$$ Pretty.text "", lastMinuteImports ++ imports)
355
356 #if i386_TARGET_ARCH
357 x86fp_kludge :: NatCmmTop -> NatCmmTop
358 x86fp_kludge top@(CmmData _ _) = top
359 x86fp_kludge top@(CmmProc info lbl params code) = 
360         CmmProc info lbl params (map bb_i386_insert_ffrees code)
361         where
362                 bb_i386_insert_ffrees (BasicBlock id instrs) =
363                         BasicBlock id (i386_insert_ffrees instrs)
364 #endif
365
366
367 -- Dump output of native code generator passes
368 --      stripe across the outputs for each block so all the information for a
369 --      certain stage is concurrent in the dumps.
370 --
371 cmmNativeGenDump :: DynFlags -> Module -> ModLocation -> [CmmNativeGenDump] -> IO ()
372 cmmNativeGenDump dflags mod modLocation dump
373  = do
374         dumpIfSet_dyn dflags
375                 Opt_D_dump_opt_cmm "Optimised Cmm"
376                 (pprCmm $ Cmm $ map cdCmmOpt dump)
377
378         dumpIfSet_dyn dflags
379                 Opt_D_dump_asm_native   "Native code"
380                 (vcat $ map (docToSDoc . pprNatCmmTop)  $ concatMap cdNative dump)
381
382         dumpIfSet_dyn dflags
383                 Opt_D_dump_asm_liveness "Liveness annotations added"
384                 (vcat $ map (ppr . cdLiveness) dump)
385
386         dumpIfSet_dyn dflags
387                 Opt_D_dump_asm_coalesce "Reg-Reg moves coalesced"
388                 (vcat $ map (fromMaybe empty . liftM ppr . cdCoalesce) dump)
389
390         dumpIfSet_dyn dflags
391                 Opt_D_dump_asm_regalloc "Registers allocated"
392                 (vcat $ map (docToSDoc . pprNatCmmTop) $ concatMap cdAlloced dump)
393
394         -- with the graph coloring allocator, show the result of each build/spill stage
395         --        for each block in turn.
396         when (dopt Opt_D_dump_asm_regalloc_stages dflags)
397          $ do   mapM_ (\stats
398                          -> printDump
399                          $  vcat $ map (\(stage, stats) ->
400                                          text "-- Stage " <> int stage
401                                          $$ ppr stats)
402                                         (zip [0..] stats))
403                  $ map (fromMaybe [] . cdRegAllocStats) dump
404
405         -- Build a global register conflict graph.
406         --      If you want to see the graph for just one basic block then use asm-regalloc-stages instead.
407         dumpIfSet_dyn dflags
408                 Opt_D_dump_asm_conflicts "Register conflict graph"
409                 $ Color.dotGraph Color.regDotColor trivColorable
410                 $ foldl Color.union Color.initGraph
411                 $ catMaybes $ map cdColoredGraph dump
412
413         -- Drop native code generator statistics.
414         --      This is potentially a large amount of information, and we want to be able
415         --      to collect it while running nofib. Drop a new file instead of emitting
416         --      it to stdout/stderr.
417         --
418         when (dopt Opt_D_drop_asm_stats dflags)
419          $ do   -- make the drop file name based on the object file name
420                 let dropFile    = (init $ ml_obj_file modLocation) ++ "drop-asm-stats"
421
422                 -- slurp out all the regalloc stats
423                 let stats       = concat $ catMaybes $ map cdRegAllocStats dump
424
425                 -- build a global conflict graph
426                 let graph       = foldl Color.union Color.initGraph $ map raGraph stats
427
428                 -- pretty print the various sections and write out the file.
429                 let outSpills   = pprStatsSpills    stats
430                 let outLife     = pprStatsLifetimes stats
431                 let outConflict = pprStatsConflict  stats
432                 let outScatter  = pprStatsLifeConflict stats graph
433
434                 writeFile dropFile
435                         (showSDoc $ vcat [outSpills, outLife, outConflict, outScatter])
436
437         return ()
438
439 -- -----------------------------------------------------------------------------
440 -- Sequencing the basic blocks
441
442 -- Cmm BasicBlocks are self-contained entities: they always end in a
443 -- jump, either non-local or to another basic block in the same proc.
444 -- In this phase, we attempt to place the basic blocks in a sequence
445 -- such that as many of the local jumps as possible turn into
446 -- fallthroughs.
447
448 sequenceTop :: NatCmmTop -> NatCmmTop
449 sequenceTop top@(CmmData _ _) = top
450 sequenceTop (CmmProc info lbl params blocks) = 
451   CmmProc info lbl params (makeFarBranches $ sequenceBlocks blocks)
452
453 -- The algorithm is very simple (and stupid): we make a graph out of
454 -- the blocks where there is an edge from one block to another iff the
455 -- first block ends by jumping to the second.  Then we topologically
456 -- sort this graph.  Then traverse the list: for each block, we first
457 -- output the block, then if it has an out edge, we move the
458 -- destination of the out edge to the front of the list, and continue.
459
460 sequenceBlocks :: [NatBasicBlock] -> [NatBasicBlock]
461 sequenceBlocks [] = []
462 sequenceBlocks (entry:blocks) = 
463   seqBlocks (mkNode entry : reverse (flattenSCCs (sccBlocks blocks)))
464   -- the first block is the entry point ==> it must remain at the start.
465
466 sccBlocks :: [NatBasicBlock] -> [SCC (NatBasicBlock,Unique,[Unique])]
467 sccBlocks blocks = stronglyConnCompR (map mkNode blocks)
468
469 getOutEdges :: [Instr] -> [Unique]
470 getOutEdges instrs = case jumpDests (last instrs) [] of
471                         [one] -> [getUnique one]
472                         _many -> []
473                 -- we're only interested in the last instruction of
474                 -- the block, and only if it has a single destination.
475
476 mkNode block@(BasicBlock id instrs) = (block, getUnique id, getOutEdges instrs)
477
478 seqBlocks [] = []
479 seqBlocks ((block,_,[]) : rest)
480   = block : seqBlocks rest
481 seqBlocks ((block@(BasicBlock id instrs),_,[next]) : rest)
482   | can_fallthrough = BasicBlock id (init instrs) : seqBlocks rest'
483   | otherwise       = block : seqBlocks rest'
484   where
485         (can_fallthrough, rest') = reorder next [] rest
486           -- TODO: we should do a better job for cycles; try to maximise the
487           -- fallthroughs within a loop.
488 seqBlocks _ = panic "AsmCodegen:seqBlocks"
489
490 reorder id accum [] = (False, reverse accum)
491 reorder id accum (b@(block,id',out) : rest)
492   | id == id'  = (True, (block,id,out) : reverse accum ++ rest)
493   | otherwise  = reorder id (b:accum) rest
494
495
496 -- -----------------------------------------------------------------------------
497 -- Making far branches
498
499 -- Conditional branches on PowerPC are limited to +-32KB; if our Procs get too
500 -- big, we have to work around this limitation.
501
502 makeFarBranches :: [NatBasicBlock] -> [NatBasicBlock]
503
504 #if powerpc_TARGET_ARCH
505 makeFarBranches blocks
506     | last blockAddresses < nearLimit = blocks
507     | otherwise = zipWith handleBlock blockAddresses blocks
508     where
509         blockAddresses = scanl (+) 0 $ map blockLen blocks
510         blockLen (BasicBlock _ instrs) = length instrs
511         
512         handleBlock addr (BasicBlock id instrs)
513                 = BasicBlock id (zipWith makeFar [addr..] instrs)
514         
515         makeFar addr (BCC ALWAYS tgt) = BCC ALWAYS tgt
516         makeFar addr (BCC cond tgt)
517             | abs (addr - targetAddr) >= nearLimit
518             = BCCFAR cond tgt
519             | otherwise
520             = BCC cond tgt
521             where Just targetAddr = lookupUFM blockAddressMap tgt
522         makeFar addr other            = other
523         
524         nearLimit = 7000 -- 8192 instructions are allowed; let's keep some
525                          -- distance, as we have a few pseudo-insns that are
526                          -- pretty-printed as multiple instructions,
527                          -- and it's just not worth the effort to calculate
528                          -- things exactly
529         
530         blockAddressMap = listToUFM $ zip (map blockId blocks) blockAddresses
531 #else
532 makeFarBranches = id
533 #endif
534
535 -- -----------------------------------------------------------------------------
536 -- Shortcut branches
537
538 shortcutBranches :: DynFlags -> [NatCmmTop] -> [NatCmmTop]
539 shortcutBranches dflags tops
540   | optLevel dflags < 1 = tops    -- only with -O or higher
541   | otherwise           = map (apply_mapping mapping) tops'
542   where
543     (tops', mappings) = mapAndUnzip build_mapping tops
544     mapping = foldr plusUFM emptyUFM mappings
545
546 build_mapping top@(CmmData _ _) = (top, emptyUFM)
547 build_mapping (CmmProc info lbl params [])
548   = (CmmProc info lbl params [], emptyUFM)
549 build_mapping (CmmProc info lbl params (head:blocks))
550   = (CmmProc info lbl params (head:others), mapping)
551         -- drop the shorted blocks, but don't ever drop the first one,
552         -- because it is pointed to by a global label.
553   where
554     -- find all the blocks that just consist of a jump that can be
555     -- shorted.
556     (shortcut_blocks, others) = partitionWith split blocks
557     split (BasicBlock id [insn]) | Just dest <- canShortcut insn 
558                                  = Left (id,dest)
559     split other = Right other
560
561     -- build a mapping from BlockId to JumpDest for shorting branches
562     mapping = foldl add emptyUFM shortcut_blocks
563     add ufm (id,dest) = addToUFM ufm id dest
564     
565 apply_mapping ufm (CmmData sec statics) 
566   = CmmData sec (map (shortcutStatic (lookupUFM ufm)) statics)
567   -- we need to get the jump tables, so apply the mapping to the entries
568   -- of a CmmData too.
569 apply_mapping ufm (CmmProc info lbl params blocks)
570   = CmmProc info lbl params (map short_bb blocks)
571   where
572     short_bb (BasicBlock id insns) = BasicBlock id $! map short_insn insns
573     short_insn i = shortcutJump (lookupUFM ufm) i
574                  -- shortcutJump should apply the mapping repeatedly,
575                  -- just in case we can short multiple branches.
576
577 -- -----------------------------------------------------------------------------
578 -- Instruction selection
579
580 -- Native code instruction selection for a chunk of stix code.  For
581 -- this part of the computation, we switch from the UniqSM monad to
582 -- the NatM monad.  The latter carries not only a Unique, but also an
583 -- Int denoting the current C stack pointer offset in the generated
584 -- code; this is needed for creating correct spill offsets on
585 -- architectures which don't offer, or for which it would be
586 -- prohibitively expensive to employ, a frame pointer register.  Viz,
587 -- x86.
588
589 -- The offset is measured in bytes, and indicates the difference
590 -- between the current (simulated) C stack-ptr and the value it was at
591 -- the beginning of the block.  For stacks which grow down, this value
592 -- should be either zero or negative.
593
594 -- Switching between the two monads whilst carrying along the same
595 -- Unique supply breaks abstraction.  Is that bad?
596
597 genMachCode :: DynFlags -> RawCmmTop -> UniqSM ([NatCmmTop], [CLabel])
598
599 genMachCode dflags cmm_top
600   = do  { initial_us <- getUs
601         ; let initial_st           = mkNatM_State initial_us 0 dflags
602               (new_tops, final_st) = initNat initial_st (cmmTopCodeGen cmm_top)
603               final_delta          = natm_delta final_st
604               final_imports        = natm_imports final_st
605         ; if   final_delta == 0
606           then return (new_tops, final_imports)
607           else pprPanic "genMachCode: nonzero final delta" (int final_delta)
608     }
609
610 -- -----------------------------------------------------------------------------
611 -- Fixup assignments to global registers so that they assign to 
612 -- locations within the RegTable, if appropriate.
613
614 -- Note that we currently don't fixup reads here: they're done by
615 -- the generic optimiser below, to avoid having two separate passes
616 -- over the Cmm.
617
618 fixAssignsTop :: RawCmmTop -> UniqSM RawCmmTop
619 fixAssignsTop top@(CmmData _ _) = returnUs top
620 fixAssignsTop (CmmProc info lbl params blocks) =
621   mapUs fixAssignsBlock blocks `thenUs` \ blocks' ->
622   returnUs (CmmProc info lbl params blocks')
623
624 fixAssignsBlock :: CmmBasicBlock -> UniqSM CmmBasicBlock
625 fixAssignsBlock (BasicBlock id stmts) =
626   fixAssigns stmts `thenUs` \ stmts' ->
627   returnUs (BasicBlock id stmts')
628
629 fixAssigns :: [CmmStmt] -> UniqSM [CmmStmt]
630 fixAssigns stmts =
631   mapUs fixAssign stmts `thenUs` \ stmtss ->
632   returnUs (concat stmtss)
633
634 fixAssign :: CmmStmt -> UniqSM [CmmStmt]
635 fixAssign (CmmAssign (CmmGlobal reg) src)
636   | Left  realreg <- reg_or_addr
637   = returnUs [CmmAssign (CmmGlobal reg) src]
638   | Right baseRegAddr <- reg_or_addr
639   = returnUs [CmmStore baseRegAddr src]
640            -- Replace register leaves with appropriate StixTrees for
641            -- the given target. GlobalRegs which map to a reg on this
642            -- arch are left unchanged.  Assigning to BaseReg is always
643            -- illegal, so we check for that.
644   where
645         reg_or_addr = get_GlobalReg_reg_or_addr reg
646
647 fixAssign other_stmt = returnUs [other_stmt]
648
649 -- -----------------------------------------------------------------------------
650 -- Generic Cmm optimiser
651
652 {-
653 Here we do:
654
655   (a) Constant folding
656   (b) Simple inlining: a temporary which is assigned to and then
657       used, once, can be shorted.
658   (c) Replacement of references to GlobalRegs which do not have
659       machine registers by the appropriate memory load (eg.
660       Hp ==>  *(BaseReg + 34) ).
661   (d) Position independent code and dynamic linking
662         (i)  introduce the appropriate indirections
663              and position independent refs
664         (ii) compile a list of imported symbols
665
666 Ideas for other things we could do (ToDo):
667
668   - shortcut jumps-to-jumps
669   - eliminate dead code blocks
670   - simple CSE: if an expr is assigned to a temp, then replace later occs of
671     that expr with the temp, until the expr is no longer valid (can push through
672     temp assignments, and certain assigns to mem...)
673 -}
674
675 cmmToCmm :: DynFlags -> RawCmmTop -> (RawCmmTop, [CLabel])
676 cmmToCmm _ top@(CmmData _ _) = (top, [])
677 cmmToCmm dflags (CmmProc info lbl params blocks) = runCmmOpt dflags $ do
678   blocks' <- mapM cmmBlockConFold (cmmMiniInline blocks)
679   return $ CmmProc info lbl params blocks'
680
681 newtype CmmOptM a = CmmOptM (([CLabel], DynFlags) -> (# a, [CLabel] #))
682
683 instance Monad CmmOptM where
684   return x = CmmOptM $ \(imports, _) -> (# x,imports #)
685   (CmmOptM f) >>= g =
686     CmmOptM $ \(imports, dflags) ->
687                 case f (imports, dflags) of
688                   (# x, imports' #) ->
689                     case g x of
690                       CmmOptM g' -> g' (imports', dflags)
691
692 addImportCmmOpt :: CLabel -> CmmOptM ()
693 addImportCmmOpt lbl = CmmOptM $ \(imports, dflags) -> (# (), lbl:imports #)
694
695 getDynFlagsCmmOpt :: CmmOptM DynFlags
696 getDynFlagsCmmOpt = CmmOptM $ \(imports, dflags) -> (# dflags, imports #)
697
698 runCmmOpt :: DynFlags -> CmmOptM a -> (a, [CLabel])
699 runCmmOpt dflags (CmmOptM f) = case f ([], dflags) of
700                         (# result, imports #) -> (result, imports)
701
702 cmmBlockConFold :: CmmBasicBlock -> CmmOptM CmmBasicBlock
703 cmmBlockConFold (BasicBlock id stmts) = do
704   stmts' <- mapM cmmStmtConFold stmts
705   return $ BasicBlock id stmts'
706
707 cmmStmtConFold stmt
708    = case stmt of
709         CmmAssign reg src
710            -> do src' <- cmmExprConFold DataReference src
711                  return $ case src' of
712                    CmmReg reg' | reg == reg' -> CmmNop
713                    new_src -> CmmAssign reg new_src
714
715         CmmStore addr src
716            -> do addr' <- cmmExprConFold DataReference addr
717                  src'  <- cmmExprConFold DataReference src
718                  return $ CmmStore addr' src'
719
720         CmmJump addr regs
721            -> do addr' <- cmmExprConFold JumpReference addr
722                  return $ CmmJump addr' regs
723
724         CmmCall target regs args srt returns
725            -> do target' <- case target of
726                               CmmCallee e conv -> do
727                                 e' <- cmmExprConFold CallReference e
728                                 return $ CmmCallee e' conv
729                               other -> return other
730                  args' <- mapM (\(arg, hint) -> do
731                                   arg' <- cmmExprConFold DataReference arg
732                                   return (arg', hint)) args
733                  return $ CmmCall target' regs args' srt returns
734
735         CmmCondBranch test dest
736            -> do test' <- cmmExprConFold DataReference test
737                  return $ case test' of
738                    CmmLit (CmmInt 0 _) -> 
739                      CmmComment (mkFastString ("deleted: " ++ 
740                                         showSDoc (pprStmt stmt)))
741
742                    CmmLit (CmmInt n _) -> CmmBranch dest
743                    other -> CmmCondBranch test' dest
744
745         CmmSwitch expr ids
746            -> do expr' <- cmmExprConFold DataReference expr
747                  return $ CmmSwitch expr' ids
748
749         other
750            -> return other
751
752
753 cmmExprConFold referenceKind expr
754    = case expr of
755         CmmLoad addr rep
756            -> do addr' <- cmmExprConFold DataReference addr
757                  return $ CmmLoad addr' rep
758
759         CmmMachOp mop args
760            -- For MachOps, we first optimize the children, and then we try 
761            -- our hand at some constant-folding.
762            -> do args' <- mapM (cmmExprConFold DataReference) args
763                  return $ cmmMachOpFold mop args'
764
765         CmmLit (CmmLabel lbl)
766            -> do
767                 dflags <- getDynFlagsCmmOpt
768                 cmmMakeDynamicReference dflags addImportCmmOpt referenceKind lbl
769         CmmLit (CmmLabelOff lbl off)
770            -> do
771                  dflags <- getDynFlagsCmmOpt
772                  dynRef <- cmmMakeDynamicReference dflags addImportCmmOpt referenceKind lbl
773                  return $ cmmMachOpFold (MO_Add wordRep) [
774                      dynRef,
775                      (CmmLit $ CmmInt (fromIntegral off) wordRep)
776                    ]
777
778 #if powerpc_TARGET_ARCH
779            -- On powerpc (non-PIC), it's easier to jump directly to a label than
780            -- to use the register table, so we replace these registers
781            -- with the corresponding labels:
782         CmmReg (CmmGlobal GCEnter1)
783           | not opt_PIC
784           -> cmmExprConFold referenceKind $
785              CmmLit (CmmLabel (mkRtsCodeLabel SLIT( "__stg_gc_enter_1"))) 
786         CmmReg (CmmGlobal GCFun)
787           | not opt_PIC
788           -> cmmExprConFold referenceKind $
789              CmmLit (CmmLabel (mkRtsCodeLabel SLIT( "__stg_gc_fun")))
790 #endif
791
792         CmmReg (CmmGlobal mid)
793            -- Replace register leaves with appropriate StixTrees for
794            -- the given target.  MagicIds which map to a reg on this
795            -- arch are left unchanged.  For the rest, BaseReg is taken
796            -- to mean the address of the reg table in MainCapability,
797            -- and for all others we generate an indirection to its
798            -- location in the register table.
799            -> case get_GlobalReg_reg_or_addr mid of
800                  Left  realreg -> return expr
801                  Right baseRegAddr 
802                     -> case mid of 
803                           BaseReg -> cmmExprConFold DataReference baseRegAddr
804                           other   -> cmmExprConFold DataReference
805                                         (CmmLoad baseRegAddr (globalRegRep mid))
806            -- eliminate zero offsets
807         CmmRegOff reg 0
808            -> cmmExprConFold referenceKind (CmmReg reg)
809
810         CmmRegOff (CmmGlobal mid) offset
811            -- RegOf leaves are just a shorthand form. If the reg maps
812            -- to a real reg, we keep the shorthand, otherwise, we just
813            -- expand it and defer to the above code. 
814            -> case get_GlobalReg_reg_or_addr mid of
815                 Left  realreg -> return expr
816                 Right baseRegAddr
817                    -> cmmExprConFold DataReference (CmmMachOp (MO_Add wordRep) [
818                                         CmmReg (CmmGlobal mid),
819                                         CmmLit (CmmInt (fromIntegral offset)
820                                                        wordRep)])
821         other
822            -> return other
823
824 -- -----------------------------------------------------------------------------
825 -- Utils
826
827 bind f x = x $! f
828
829 \end{code}
830