use regalloc2::{PReg, VReg};
use super::{RealReg, Reg, VirtualReg, Writable};
use core::fmt::Debug;
const VALUE_REGS_PARTS: usize = 2;
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct ValueRegs<R: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel> {
parts: [R; VALUE_REGS_PARTS],
}
impl<R: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel> Debug for ValueRegs<R> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut f = f.debug_tuple("ValueRegs");
let mut last_valid = true;
for part in self.parts {
if part.is_invalid_sentinel() {
last_valid = false;
} else {
debug_assert!(last_valid);
f.field(&part);
}
}
f.finish()
}
}
pub trait InvalidSentinel: Copy + Eq {
fn invalid_sentinel() -> Self;
fn is_invalid_sentinel(self) -> bool {
self == Self::invalid_sentinel()
}
}
impl InvalidSentinel for Reg {
fn invalid_sentinel() -> Self {
Reg::from(VReg::invalid())
}
}
impl InvalidSentinel for VirtualReg {
fn invalid_sentinel() -> Self {
VirtualReg::from(VReg::invalid())
}
}
impl InvalidSentinel for RealReg {
fn invalid_sentinel() -> Self {
RealReg::from(PReg::invalid())
}
}
impl InvalidSentinel for Writable<Reg> {
fn invalid_sentinel() -> Self {
Writable::from_reg(Reg::invalid_sentinel())
}
}
impl<R: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel> ValueRegs<R> {
pub fn invalid() -> Self {
ValueRegs {
parts: [R::invalid_sentinel(); VALUE_REGS_PARTS],
}
}
pub fn is_valid(self) -> bool {
!self.parts[0].is_invalid_sentinel()
}
pub fn is_invalid(self) -> bool {
self.parts[0].is_invalid_sentinel()
}
pub fn only_reg(self) -> Option<R> {
if self.len() == 1 {
Some(self.parts[0])
} else {
None
}
}
pub fn regs(&self) -> &[R] {
&self.parts[0..self.len()]
}
pub fn regs_mut(&mut self) -> &mut [R] {
let len = self.len();
&mut self.parts[0..len]
}
}
impl<R: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel> ValueRegs<R> {
pub fn one(reg: R) -> Self {
ValueRegs {
parts: [reg, R::invalid_sentinel()],
}
}
pub fn two(r1: R, r2: R) -> Self {
ValueRegs { parts: [r1, r2] }
}
pub fn len(self) -> usize {
(self.parts[0] != R::invalid_sentinel()) as usize
+ (self.parts[1] != R::invalid_sentinel()) as usize
}
pub fn map<NewR, F>(self, f: F) -> ValueRegs<NewR>
where
NewR: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel,
F: Fn(R) -> NewR,
{
ValueRegs {
parts: [f(self.parts[0]), f(self.parts[1])],
}
}
}
pub(crate) fn writable_value_regs(regs: ValueRegs<Reg>) -> ValueRegs<Writable<Reg>> {
regs.map(|r| Writable::from_reg(r))
}
pub(crate) fn non_writable_value_regs(regs: ValueRegs<Writable<Reg>>) -> ValueRegs<Reg> {
regs.map(|r| r.to_reg())
}