cranelift_codegen/isa/pulley_shared/inst/
args.rsuse super::*;
use crate::machinst::abi::StackAMode;
use pulley_interpreter::regs::Reg as _;
macro_rules! newtype_of_reg {
(
$newtype_reg:ident,
$newtype_writable_reg:ident,
$class:expr
) => {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct $newtype_reg(Reg);
impl PartialEq<Reg> for $newtype_reg {
fn eq(&self, other: &Reg) -> bool {
self.0 == *other
}
}
impl From<$newtype_reg> for Reg {
fn from(r: $newtype_reg) -> Self {
r.0
}
}
impl TryFrom<Reg> for $newtype_reg {
type Error = ();
fn try_from(r: Reg) -> Result<Self, Self::Error> {
Self::new(r).ok_or(())
}
}
impl $newtype_reg {
pub fn new(reg: Reg) -> Option<Self> {
if reg.class() == $class {
Some(Self(reg))
} else {
None
}
}
pub fn to_reg(self) -> Reg {
self.0
}
}
impl std::ops::Deref for $newtype_reg {
type Target = Reg;
fn deref(&self) -> &Reg {
&self.0
}
}
impl AsMut<Reg> for $newtype_reg {
fn as_mut(&mut self) -> &mut Reg {
&mut self.0
}
}
pub type $newtype_writable_reg = Writable<$newtype_reg>;
impl From<pulley_interpreter::regs::$newtype_reg> for $newtype_reg {
fn from(r: pulley_interpreter::regs::$newtype_reg) -> Self {
Self::new(regalloc2::PReg::new(usize::from(r as u8), $class).into()).unwrap()
}
}
impl From<$newtype_reg> for pulley_interpreter::regs::$newtype_reg {
fn from(r: $newtype_reg) -> Self {
Self::new(r.to_real_reg().unwrap().hw_enc()).unwrap()
}
}
impl<'a> From<&'a $newtype_reg> for pulley_interpreter::regs::$newtype_reg {
fn from(r: &'a $newtype_reg) -> Self {
Self::new(r.to_real_reg().unwrap().hw_enc()).unwrap()
}
}
impl From<$newtype_writable_reg> for pulley_interpreter::regs::$newtype_reg {
fn from(r: $newtype_writable_reg) -> Self {
Self::new(r.to_reg().to_real_reg().unwrap().hw_enc()).unwrap()
}
}
impl<'a> From<&'a $newtype_writable_reg> for pulley_interpreter::regs::$newtype_reg {
fn from(r: &'a $newtype_writable_reg) -> Self {
Self::new(r.to_reg().to_real_reg().unwrap().hw_enc()).unwrap()
}
}
impl TryFrom<Writable<Reg>> for $newtype_writable_reg {
type Error = ();
fn try_from(r: Writable<Reg>) -> Result<Self, Self::Error> {
let r = r.to_reg();
match $newtype_reg::new(r) {
Some(r) => Ok(Writable::from_reg(r)),
None => Err(()),
}
}
}
};
}
newtype_of_reg!(XReg, WritableXReg, RegClass::Int);
newtype_of_reg!(FReg, WritableFReg, RegClass::Float);
newtype_of_reg!(VReg, WritableVReg, RegClass::Vector);
impl XReg {
pub const SPECIAL_START: u8 = pulley_interpreter::regs::XReg::SPECIAL_START;
pub fn is_special(&self) -> bool {
match self.as_pulley() {
Some(reg) => reg.is_special(),
None => false,
}
}
pub fn as_pulley(&self) -> Option<pulley_interpreter::XReg> {
let enc = self.to_real_reg()?.hw_enc();
Some(pulley_interpreter::XReg::new(enc).unwrap())
}
}
pub use super::super::lower::isle::generated_code::ExtKind;
pub use super::super::lower::isle::generated_code::Amode;
impl Amode {
pub(crate) fn get_operands(&mut self, collector: &mut impl OperandVisitor) {
match self {
Amode::RegOffset { base, offset: _ } => collector.reg_use(base),
Amode::SpOffset { .. } | Amode::Stack { .. } => {}
}
}
pub(crate) fn get_base_register(&self) -> Option<Reg> {
match self {
Amode::RegOffset { base, offset: _ } => Some((*base).into()),
Amode::SpOffset { .. } | Amode::Stack { .. } => Some(stack_reg()),
}
}
pub(crate) fn get_offset_with_state<P>(&self, state: &EmitState<P>) -> i64
where
P: PulleyTargetKind,
{
match self {
Amode::RegOffset { base: _, offset } | Amode::SpOffset { offset } => *offset,
Amode::Stack { amode } => match amode {
StackAMode::IncomingArg(offset, stack_args_size) => {
let offset = i64::from(*stack_args_size) - *offset;
let frame_layout = state.frame_layout();
let sp_offset = frame_layout.tail_args_size
+ frame_layout.setup_area_size
+ frame_layout.clobber_size
+ frame_layout.fixed_frame_storage_size
+ frame_layout.outgoing_args_size;
i64::from(sp_offset) - offset
}
StackAMode::Slot(offset) => *offset,
StackAMode::OutgoingArg(offset) => *offset,
},
}
}
}
impl core::fmt::Display for Amode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Amode::SpOffset { offset } => {
if *offset >= 0 {
write!(f, "sp+{offset}")
} else {
write!(f, "sp{offset}")
}
}
Amode::RegOffset { base, offset } => {
let name = reg_name(**base);
if *offset >= 0 {
write!(f, "{name}+{offset}")
} else {
write!(f, "{name}{offset}")
}
}
Amode::Stack { amode } => core::fmt::Debug::fmt(amode, f),
}
}
}
impl From<StackAMode> for Amode {
fn from(amode: StackAMode) -> Self {
Amode::Stack { amode }
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum OperandSize {
Size32,
Size64,
}