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