NCG: Split linear allocator into separate modules.
[ghc-hetmet.git] / compiler / nativeGen / RegAlloc / Linear / Base.hs
1
2 -- | Put common type definitions here to break recursive module dependencies.
3
4 module RegAlloc.Linear.Base (
5         BlockAssignment,
6         Loc(..),
7
8         -- for stats
9         SpillReason(..),
10         RegAllocStats(..),
11         
12         -- the allocator monad
13         RA_State(..),
14         RegM(..)
15 )
16
17 where
18
19 import RegAlloc.Linear.FreeRegs
20 import RegAlloc.Linear.StackMap
21
22 import RegLiveness
23 import MachRegs
24
25 import Outputable
26 import Unique
27 import UniqFM
28 import UniqSupply
29
30
31 -- | Used to store the register assignment on entry to a basic block.
32 --      We use this to handle join points, where multiple branch instructions
33 --      target a particular label. We have to insert fixup code to make
34 --      the register assignments from the different sources match up.
35 --
36 type BlockAssignment 
37         = BlockMap (FreeRegs, RegMap Loc)
38
39
40 -- | Where a vreg is currently stored
41 --      A temporary can be marked as living in both a register and memory
42 --      (InBoth), for example if it was recently loaded from a spill location.
43 --      This makes it cheap to spill (no save instruction required), but we
44 --      have to be careful to turn this into InReg if the value in the
45 --      register is changed.
46
47 --      This is also useful when a temporary is about to be clobbered.  We
48 --      save it in a spill location, but mark it as InBoth because the current
49 --      instruction might still want to read it.
50 --
51 data Loc 
52         -- | vreg is in a register
53         = InReg   {-# UNPACK #-} !RegNo
54
55         -- | vreg is held in a stack slot
56         | InMem   {-# UNPACK #-} !StackSlot
57
58
59         -- | vreg is held in both a register and a stack slot
60         | InBoth  {-# UNPACK #-}  !RegNo
61                    {-# UNPACK #-} !StackSlot
62         deriving (Eq, Show, Ord)
63
64 instance Outputable Loc where
65         ppr l = text (show l)
66
67
68 -- | Reasons why instructions might be inserted by the spiller.
69 --      Used when generating stats for -ddrop-asm-stats.
70 --
71 data SpillReason
72         -- | vreg was spilled to a slot so we could use its
73         --      current hreg for another vreg
74         = SpillAlloc    !Unique 
75
76         -- | vreg was moved because its hreg was clobbered
77         | SpillClobber  !Unique 
78
79         -- | vreg was loaded from a spill slot
80         | SpillLoad     !Unique 
81
82         -- | reg-reg move inserted during join to targets
83         | SpillJoinRR   !Unique 
84
85         -- | reg-mem move inserted during join to targets
86         | SpillJoinRM   !Unique 
87
88
89 -- | Used to carry interesting stats out of the register allocator.
90 data RegAllocStats
91         = RegAllocStats
92         { ra_spillInstrs        :: UniqFM [Int] }
93
94
95 -- | The register alloctor state
96 data RA_State 
97         = RA_State 
98
99         -- | the current mapping from basic blocks to 
100         --      the register assignments at the beginning of that block.
101         { ra_blockassig :: BlockAssignment
102         
103         -- | free machine registers
104         , ra_freeregs   :: {-#UNPACK#-}!FreeRegs
105
106         -- | assignment of temps to locations
107         , ra_assig      :: RegMap Loc
108
109         -- | current stack delta
110         , ra_delta      :: Int
111
112         -- | free stack slots for spilling
113         , ra_stack      :: StackMap
114
115         -- | unique supply for generating names for join point fixup blocks.
116         , ra_us         :: UniqSupply
117
118         -- | Record why things were spilled, for -ddrop-asm-stats.
119         --      Just keep a list here instead of a map of regs -> reasons.
120         --      We don't want to slow down the allocator if we're not going to emit the stats.
121         , ra_spills     :: [SpillReason] }
122
123
124 -- | The register allocator monad type.
125 newtype RegM a 
126         = RegM { unReg :: RA_State -> (# RA_State, a #) }
127
128