use ir::{AbiParam, ArgumentLoc};
use isa::{ConstraintKind, OperandConstraint, RegClassIndex, RegInfo, TargetIsa};
use std::fmt;
#[derive(Clone, Copy, Debug)]
pub enum Affinity {
Unassigned,
Stack,
Reg(RegClassIndex),
}
impl Default for Affinity {
fn default() -> Self {
Affinity::Unassigned
}
}
impl Affinity {
pub fn new(constraint: &OperandConstraint) -> Self {
if constraint.kind == ConstraintKind::Stack {
Affinity::Stack
} else {
Affinity::Reg(constraint.regclass.into())
}
}
pub fn abi(arg: &AbiParam, isa: &TargetIsa) -> Self {
match arg.location {
ArgumentLoc::Unassigned => Affinity::Unassigned,
ArgumentLoc::Reg(_) => Affinity::Reg(isa.regclass_for_abi_type(arg.value_type).into()),
ArgumentLoc::Stack(_) => Affinity::Stack,
}
}
pub fn is_unassigned(self) -> bool {
match self {
Affinity::Unassigned => true,
_ => false,
}
}
pub fn is_reg(self) -> bool {
match self {
Affinity::Reg(_) => true,
_ => false,
}
}
pub fn is_stack(self) -> bool {
match self {
Affinity::Stack => true,
_ => false,
}
}
pub fn merge(&mut self, constraint: &OperandConstraint, reginfo: &RegInfo) {
match *self {
Affinity::Unassigned => *self = Self::new(constraint),
Affinity::Reg(rc) => {
if constraint.kind != ConstraintKind::Stack && !constraint.regclass.has_subclass(rc)
{
if let Some(subclass) = constraint.regclass.intersect_index(reginfo.rc(rc)) {
*self = Affinity::Reg(subclass);
}
}
}
Affinity::Stack => {}
}
}
pub fn display<'a, R: Into<Option<&'a RegInfo>>>(self, regs: R) -> DisplayAffinity<'a> {
DisplayAffinity(self, regs.into())
}
}
pub struct DisplayAffinity<'a>(Affinity, Option<&'a RegInfo>);
impl<'a> fmt::Display for DisplayAffinity<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
Affinity::Unassigned => write!(f, "unassigned"),
Affinity::Stack => write!(f, "stack"),
Affinity::Reg(rci) => match self.1 {
Some(regs) => write!(f, "{}", regs.rc(rci)),
None => write!(f, "{}", rci),
},
}
}
}