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