winch_codegen/
regalloc.rs
1use crate::{
2 codegen::CodeGenError,
3 isa::reg::{Reg, RegClass},
4 regset::{RegBitSet, RegSet},
5};
6
7use anyhow::{anyhow, Result};
8
9pub(crate) struct RegAlloc {
21 regset: RegSet,
23}
24
25impl RegAlloc {
26 pub fn from(gpr: RegBitSet, fpr: RegBitSet) -> Self {
28 let rs = RegSet::new(gpr, fpr);
29 Self { regset: rs }
30 }
31
32 pub fn reg_for_class<F>(&mut self, class: RegClass, spill: &mut F) -> Result<Reg>
35 where
36 F: FnMut(&mut RegAlloc) -> Result<()>,
37 {
38 match self.regset.reg_for_class(class) {
39 Some(reg) => Ok(reg),
40 None => {
41 spill(self)?;
42 self.regset
43 .reg_for_class(class)
44 .ok_or_else(|| anyhow!(CodeGenError::expected_register_to_be_available()))
45 }
46 }
47 }
48
49 pub fn reg_available(&self, reg: Reg) -> bool {
51 self.regset.named_reg_available(reg)
52 }
53
54 pub fn reg<F>(&mut self, named: Reg, mut spill: F) -> Result<Reg>
56 where
57 F: FnMut(&mut RegAlloc) -> Result<()>,
58 {
59 match self.regset.reg(named) {
60 Some(reg) => Ok(reg),
61 None => {
62 spill(self)?;
63 self.regset
64 .reg(named)
65 .ok_or_else(|| anyhow!(CodeGenError::expected_register_to_be_available()))
66 }
67 }
68 }
69
70 pub fn free(&mut self, reg: Reg) {
72 self.regset.free(reg);
73 }
74}