///|
/// A packed allocation result location within one allocation session.
///
/// Spill indices are session-local and must be translated at ownership
/// boundaries before they are exposed as product-facing stack-slot handles.
#valtype
pub(all) struct AllocationLocation {
encoded : Int64
} derive(Eq)
///|
fn reg_class_code(class : RegClass) -> Int {
match class {
Int => 0
Float => 1
Vector => 2
FpVector => 3
}
}
///|
fn reg_class_from_code(code : Int) -> RegClass {
match code {
0 => Int
1 => Float
2 => Vector
_ => FpVector
}
}
///|
pub fn AllocationLocation::reg(reg : PhysicalReg) -> AllocationLocation {
{ encoded: (reg.id.to_int64() << 3) | reg_class_code(reg.class).to_int64(), }
}
///|
pub fn AllocationLocation::spill(index : Int) -> AllocationLocation {
{ encoded: (index.to_int64() << 3) | 4L, }
}
///|
pub fn AllocationLocation::register(self : AllocationLocation) -> PhysicalReg? {
if self.is_spill() {
None
} else {
Some(self.register_unchecked())
}
}
///|
/// Decode a register location after `is_register` has been established.
pub fn AllocationLocation::register_unchecked(
self : AllocationLocation,
) -> PhysicalReg {
PhysicalReg::new(
(self.encoded >> 3).to_int(),
reg_class_from_code((self.encoded & 7L).to_int()),
)
}
///|
pub fn AllocationLocation::spill_index(self : AllocationLocation) -> Int? {
if self.is_spill() {
Some(self.spill_index_unchecked())
} else {
None
}
}
///|
/// Decode a spill location after `is_spill` has been established.
pub fn AllocationLocation::spill_index_unchecked(
self : AllocationLocation,
) -> Int {
(self.encoded >> 3).to_int()
}
///|
pub fn AllocationLocation::is_register(self : AllocationLocation) -> Bool {
(self.encoded & 7L) != 4L
}
///|
pub fn AllocationLocation::is_spill(self : AllocationLocation) -> Bool {
(self.encoded & 7L) == 4L
}
///|
pub impl Debug for AllocationLocation with fn to_repr(self) {
match self.register() {
Some(reg) => Repr::ctor("Reg", [(None, Repr(reg))])
None => Repr::ctor("Spill", [(None, Repr(self.spill_index().unwrap()))])
}
}
///|
pub extend AllocationLocation with Debug::{to_repr}
///|
pub extend AllocationLocation with Eq::{not_equal, equal}