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