2 -- | Put common type definitions here to break recursive module dependencies.
4 module RegAlloc.Linear.Base (
14 -- the allocator monad
21 import RegAlloc.Linear.FreeRegs
22 import RegAlloc.Linear.StackMap
23 import RegAlloc.Liveness
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.
38 = BlockMap (FreeRegs, RegMap Loc)
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.
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.
53 -- | vreg is in a register
56 -- | vreg is held in a stack slot
57 | InMem {-# UNPACK #-} !StackSlot
60 -- | vreg is held in both a register and a stack slot
62 {-# UNPACK #-} !StackSlot
63 deriving (Eq, Show, Ord)
65 instance Outputable Loc where
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 _) = []
76 -- | Reasons why instructions might be inserted by the spiller.
77 -- Used when generating stats for -ddrop-asm-stats.
80 -- | vreg was spilled to a slot so we could use its
81 -- current hreg for another vreg
84 -- | vreg was moved because its hreg was clobbered
85 | SpillClobber !Unique
87 -- | vreg was loaded from a spill slot
90 -- | reg-reg move inserted during join to targets
93 -- | reg-mem move inserted during join to targets
97 -- | Used to carry interesting stats out of the register allocator.
100 { ra_spillInstrs :: UniqFM [Int] }
103 -- | The register alloctor state
108 -- | the current mapping from basic blocks to
109 -- the register assignments at the beginning of that block.
110 ra_blockassig :: BlockAssignment
112 -- | free machine registers
113 , ra_freeregs :: {-#UNPACK#-}!FreeRegs
115 -- | assignment of temps to locations
116 , ra_assig :: RegMap Loc
118 -- | current stack delta
121 -- | free stack slots for spilling
122 , ra_stack :: StackMap
124 -- | unique supply for generating names for join point fixup blocks.
125 , ra_us :: UniqSupply
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] }
133 -- | The register allocator monad type.
135 = RegM { unReg :: RA_State -> (# RA_State, a #) }