Parameterise the RegM monad on the FreeRegs type
[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 import RegAlloc.Liveness
24 import Reg
25
26 import Outputable
27 import Unique
28 import UniqFM
29 import UniqSupply
30
31
32 -- | Used to store the register assignment on entry to a basic block.
33 --      We use this to handle join points, where multiple branch instructions
34 --      target a particular label. We have to insert fixup code to make
35 --      the register assignments from the different sources match up.
36 --
37 type BlockAssignment
38         = BlockMap (FreeRegs, RegMap Loc)
39
40
41 -- | Where a vreg is currently stored
42 --      A temporary can be marked as living in both a register and memory
43 --      (InBoth), for example if it was recently loaded from a spill location.
44 --      This makes it cheap to spill (no save instruction required), but we
45 --      have to be careful to turn this into InReg if the value in the
46 --      register is changed.
47
48 --      This is also useful when a temporary is about to be clobbered.  We
49 --      save it in a spill location, but mark it as InBoth because the current
50 --      instruction might still want to read it.
51 --
52 data Loc
53         -- | vreg is in a register
54         = InReg   !RealReg
55
56         -- | vreg is held in a stack slot
57         | InMem   {-# UNPACK #-}  !StackSlot
58
59
60         -- | vreg is held in both a register and a stack slot
61         | InBoth   !RealReg
62                    {-# UNPACK #-} !StackSlot
63         deriving (Eq, Show, Ord)
64
65 instance Outputable Loc where
66         ppr l = text (show l)
67
68
69 -- | Get the reg numbers stored in this Loc.
70 regsOfLoc :: Loc -> [RealReg]
71 regsOfLoc (InReg r)    = [r]
72 regsOfLoc (InBoth r _) = [r]
73 regsOfLoc (InMem _)    = []
74
75
76 -- | Reasons why instructions might be inserted by the spiller.
77 --      Used when generating stats for -ddrop-asm-stats.
78 --
79 data SpillReason
80         -- | vreg was spilled to a slot so we could use its
81         --      current hreg for another vreg
82         = SpillAlloc    !Unique
83
84         -- | vreg was moved because its hreg was clobbered
85         | SpillClobber  !Unique
86
87         -- | vreg was loaded from a spill slot
88         | SpillLoad     !Unique
89
90         -- | reg-reg move inserted during join to targets
91         | SpillJoinRR   !Unique
92
93         -- | reg-mem move inserted during join to targets
94         | SpillJoinRM   !Unique
95
96
97 -- | Used to carry interesting stats out of the register allocator.
98 data RegAllocStats
99         = RegAllocStats
100         { ra_spillInstrs        :: UniqFM [Int] }
101
102
103 -- | The register alloctor state
104 data RA_State freeRegs
105         = RA_State
106
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   :: !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 freeRegs a
135         = RegM { unReg :: RA_State freeRegs -> (# RA_State freeRegs, a #) }
136
137