1 use crate::{
2     isa::reg::{Reg, RegClass},
3     regset::{RegBitSet, RegSet},
4 };
5 
6 /// The register allocator.
7 ///
8 /// The register allocator uses a single-pass algorithm;
9 /// its implementation uses a bitset as a freelist
10 /// to track per-class register availability.
11 ///
12 /// If a particular register is not available upon request
13 /// the register allocation will perform a "spill", essentially
14 /// moving Local and Register values in the stack to memory.
15 /// This processs ensures that whenever a register is requested,
16 /// it is going to be available.
17 pub(crate) struct RegAlloc {
18     /// The register set.
19     regset: RegSet,
20 }
21 
22 impl RegAlloc {
23     /// Create a register allocator from a bit set for each register class.
24     pub fn from(gpr: RegBitSet, fpr: RegBitSet) -> Self {
25         let rs = RegSet::new(gpr, fpr);
26         Self { regset: rs }
27     }
28 
29     /// Allocate the next available register for the given class,
30     /// spilling if not available.
31     pub fn reg_for_class<F>(&mut self, class: RegClass, spill: &mut F) -> Reg
32     where
33         F: FnMut(&mut RegAlloc),
34     {
35         self.regset.reg_for_class(class).unwrap_or_else(|| {
36             spill(self);
37             self.regset.reg_for_class(class).unwrap_or_else(|| {
38                 panic!("expected register for class {:?}, to be avilable", class)
39             })
40         })
41     }
42 
43     /// Returns true if the specified register is allocatable.
44     pub fn reg_available(&self, reg: Reg) -> bool {
45         self.regset.named_reg_available(reg)
46     }
47 
48     /// Request a specific register, spilling if not available.
49     pub fn reg<F>(&mut self, named: Reg, mut spill: F) -> Reg
50     where
51         F: FnMut(&mut RegAlloc),
52     {
53         self.regset.reg(named).unwrap_or_else(|| {
54             spill(self);
55             self.regset
56                 .reg(named)
57                 .expect(&format!("register {:?} to be available", named))
58         })
59     }
60 
61     /// Free the given register.
62     pub fn free(&mut self, reg: Reg) {
63         self.regset.free(reg);
64     }
65 }
66