use crate::{
Result,
codegen::CodeGenError,
format_err,
isa::reg::{Reg, RegClass},
regset::{RegBitSet, RegSet},
};
pub(crate) struct RegAlloc {
regset: RegSet,
}
impl RegAlloc {
pub fn from(gpr: RegBitSet, fpr: RegBitSet) -> Self {
let rs = RegSet::new(gpr, fpr);
Self { regset: rs }
}
pub fn reg_for_class<F>(&mut self, class: RegClass, spill: &mut F) -> Result<Reg>
where
F: FnMut(&mut RegAlloc) -> Result<()>,
{
match self.regset.reg_for_class(class) {
Some(reg) => Ok(reg),
None => {
spill(self)?;
self.regset
.reg_for_class(class)
.ok_or_else(|| format_err!(CodeGenError::expected_register_to_be_available()))
}
}
}
pub fn reg_available(&self, reg: Reg) -> bool {
self.regset.named_reg_available(reg)
}
pub fn reg<F>(&mut self, named: Reg, mut spill: F) -> Result<Reg>
where
F: FnMut(&mut RegAlloc) -> Result<()>,
{
match self.regset.reg(named) {
Some(reg) => Ok(reg),
None => {
spill(self)?;
self.regset
.reg(named)
.ok_or_else(|| format_err!(CodeGenError::expected_register_to_be_available()))
}
}
}
pub fn free(&mut self, reg: Reg) {
self.regset.free(reg);
}
}