12da108dfSSaúl Cabrera use crate::{
2*b112bb85SNick Fitzgerald     Result,
3b93e1bc0SSaúl Cabrera     codegen::CodeGenError,
4*b112bb85SNick Fitzgerald     format_err,
52da108dfSSaúl Cabrera     isa::reg::{Reg, RegClass},
64b288ba8SSaúl Cabrera     regset::{RegBitSet, RegSet},
72da108dfSSaúl Cabrera };
8835abbcdSSaúl Cabrera 
9835abbcdSSaúl Cabrera /// The register allocator.
10835abbcdSSaúl Cabrera ///
11835abbcdSSaúl Cabrera /// The register allocator uses a single-pass algorithm;
12835abbcdSSaúl Cabrera /// its implementation uses a bitset as a freelist
13835abbcdSSaúl Cabrera /// to track per-class register availability.
14835abbcdSSaúl Cabrera ///
15835abbcdSSaúl Cabrera /// If a particular register is not available upon request
16835abbcdSSaúl Cabrera /// the register allocation will perform a "spill", essentially
17835abbcdSSaúl Cabrera /// moving Local and Register values in the stack to memory.
180e9121daSFrankReh /// This process ensures that whenever a register is requested,
19835abbcdSSaúl Cabrera /// it is going to be available.
20835abbcdSSaúl Cabrera pub(crate) struct RegAlloc {
214b288ba8SSaúl Cabrera     /// The register set.
22835abbcdSSaúl Cabrera     regset: RegSet,
23835abbcdSSaúl Cabrera }
24835abbcdSSaúl Cabrera 
25835abbcdSSaúl Cabrera impl RegAlloc {
264b288ba8SSaúl Cabrera     /// Create a register allocator from a bit set for each register class.
from(gpr: RegBitSet, fpr: RegBitSet) -> Self274b288ba8SSaúl Cabrera     pub fn from(gpr: RegBitSet, fpr: RegBitSet) -> Self {
284b288ba8SSaúl Cabrera         let rs = RegSet::new(gpr, fpr);
294b288ba8SSaúl Cabrera         Self { regset: rs }
30835abbcdSSaúl Cabrera     }
31835abbcdSSaúl Cabrera 
3214b39bc2SSaúl Cabrera     /// Allocate the next available register for the given class,
3314b39bc2SSaúl Cabrera     /// spilling if not available.
reg_for_class<F>(&mut self, class: RegClass, spill: &mut F) -> Result<Reg> where F: FnMut(&mut RegAlloc) -> Result<()>,34b93e1bc0SSaúl Cabrera     pub fn reg_for_class<F>(&mut self, class: RegClass, spill: &mut F) -> Result<Reg>
357ec92512SSaúl Cabrera     where
36b93e1bc0SSaúl Cabrera         F: FnMut(&mut RegAlloc) -> Result<()>,
377ec92512SSaúl Cabrera     {
38b93e1bc0SSaúl Cabrera         match self.regset.reg_for_class(class) {
39b93e1bc0SSaúl Cabrera             Some(reg) => Ok(reg),
40b93e1bc0SSaúl Cabrera             None => {
41b93e1bc0SSaúl Cabrera                 spill(self)?;
42a0442ea0SHamir Mahal                 self.regset
43a0442ea0SHamir Mahal                     .reg_for_class(class)
44*b112bb85SNick Fitzgerald                     .ok_or_else(|| format_err!(CodeGenError::expected_register_to_be_available()))
45b93e1bc0SSaúl Cabrera             }
46b93e1bc0SSaúl Cabrera         }
47835abbcdSSaúl Cabrera     }
48835abbcdSSaúl Cabrera 
4914b39bc2SSaúl Cabrera     /// Returns true if the specified register is allocatable.
reg_available(&self, reg: Reg) -> bool5014b39bc2SSaúl Cabrera     pub fn reg_available(&self, reg: Reg) -> bool {
5114b39bc2SSaúl Cabrera         self.regset.named_reg_available(reg)
52af4d94c8SSaúl Cabrera     }
53af4d94c8SSaúl Cabrera 
5414b39bc2SSaúl Cabrera     /// Request a specific register, spilling if not available.
reg<F>(&mut self, named: Reg, mut spill: F) -> Result<Reg> where F: FnMut(&mut RegAlloc) -> Result<()>,55b93e1bc0SSaúl Cabrera     pub fn reg<F>(&mut self, named: Reg, mut spill: F) -> Result<Reg>
567ec92512SSaúl Cabrera     where
57b93e1bc0SSaúl Cabrera         F: FnMut(&mut RegAlloc) -> Result<()>,
587ec92512SSaúl Cabrera     {
59b93e1bc0SSaúl Cabrera         match self.regset.reg(named) {
60b93e1bc0SSaúl Cabrera             Some(reg) => Ok(reg),
61b93e1bc0SSaúl Cabrera             None => {
62b93e1bc0SSaúl Cabrera                 spill(self)?;
63835abbcdSSaúl Cabrera                 self.regset
6414b39bc2SSaúl Cabrera                     .reg(named)
65*b112bb85SNick Fitzgerald                     .ok_or_else(|| format_err!(CodeGenError::expected_register_to_be_available()))
66b93e1bc0SSaúl Cabrera             }
67b93e1bc0SSaúl Cabrera         }
68835abbcdSSaúl Cabrera     }
69835abbcdSSaúl Cabrera 
7014b39bc2SSaúl Cabrera     /// Free the given register.
free(&mut self, reg: Reg)7114b39bc2SSaúl Cabrera     pub fn free(&mut self, reg: Reg) {
7214b39bc2SSaúl Cabrera         self.regset.free(reg);
73835abbcdSSaúl Cabrera     }
74835abbcdSSaúl Cabrera }
75