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