Path: blob/main/cranelift/codegen/src/isa/pulley_shared/inst/args.rs
1693 views
//! Pulley instruction arguments.12use super::*;3use crate::ir::ExternalName;4use crate::machinst::abi::StackAMode;5use pulley_interpreter::encode;6use pulley_interpreter::regs::Reg as _;7use std::fmt;89/// A macro for defining a newtype of `Reg` that enforces some invariant about10/// the wrapped `Reg` (such as that it is of a particular register class).11macro_rules! newtype_of_reg {12(13$newtype_reg:ident,14$newtype_writable_reg:ident,15$class:expr16) => {17/// A newtype wrapper around `Reg`.18#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]19pub struct $newtype_reg(Reg);2021impl PartialEq<Reg> for $newtype_reg {22fn eq(&self, other: &Reg) -> bool {23self.0 == *other24}25}2627impl From<$newtype_reg> for Reg {28fn from(r: $newtype_reg) -> Self {29r.030}31}3233impl TryFrom<Reg> for $newtype_reg {34type Error = ();35fn try_from(r: Reg) -> Result<Self, Self::Error> {36Self::new(r).ok_or(())37}38}3940impl $newtype_reg {41/// Create this newtype from the given register, or return `None` if the register42/// is not a valid instance of this newtype.43pub fn new(reg: Reg) -> Option<Self> {44if reg.class() == $class {45Some(Self(reg))46} else {47None48}49}5051/// Get this newtype's underlying `Reg`.52pub fn to_reg(self) -> Reg {53self.054}55}5657// Convenience impl so that people working with this newtype can use it58// "just like" a plain `Reg`.59//60// NB: We cannot implement `DerefMut` because that would let people do61// nasty stuff like `*my_xreg.deref_mut() = some_freg`, breaking the62// invariants that `XReg` provides.63impl std::ops::Deref for $newtype_reg {64type Target = Reg;6566fn deref(&self) -> &Reg {67&self.068}69}7071/// If you know what you're doing, you can explicitly mutably borrow the72/// underlying `Reg`. Don't make it point to the wrong type of register73/// please.74impl AsMut<Reg> for $newtype_reg {75fn as_mut(&mut self) -> &mut Reg {76&mut self.077}78}7980/// Writable Reg.81pub type $newtype_writable_reg = Writable<$newtype_reg>;8283impl From<pulley_interpreter::regs::$newtype_reg> for $newtype_reg {84fn from(r: pulley_interpreter::regs::$newtype_reg) -> Self {85Self::new(regalloc2::PReg::new(usize::from(r as u8), $class).into()).unwrap()86}87}88impl From<$newtype_reg> for pulley_interpreter::regs::$newtype_reg {89fn from(r: $newtype_reg) -> Self {90Self::new(r.to_real_reg().unwrap().hw_enc()).unwrap()91}92}93impl<'a> From<&'a $newtype_reg> for pulley_interpreter::regs::$newtype_reg {94fn from(r: &'a $newtype_reg) -> Self {95Self::new(r.to_real_reg().unwrap().hw_enc()).unwrap()96}97}98impl From<$newtype_writable_reg> for pulley_interpreter::regs::$newtype_reg {99fn from(r: $newtype_writable_reg) -> Self {100Self::new(r.to_reg().to_real_reg().unwrap().hw_enc()).unwrap()101}102}103impl<'a> From<&'a $newtype_writable_reg> for pulley_interpreter::regs::$newtype_reg {104fn from(r: &'a $newtype_writable_reg) -> Self {105Self::new(r.to_reg().to_real_reg().unwrap().hw_enc()).unwrap()106}107}108109impl TryFrom<Writable<Reg>> for $newtype_writable_reg {110type Error = ();111fn try_from(r: Writable<Reg>) -> Result<Self, Self::Error> {112let r = r.to_reg();113match $newtype_reg::new(r) {114Some(r) => Ok(Writable::from_reg(r)),115None => Err(()),116}117}118}119};120}121122// Newtypes for registers classes.123newtype_of_reg!(XReg, WritableXReg, RegClass::Int);124newtype_of_reg!(FReg, WritableFReg, RegClass::Float);125newtype_of_reg!(VReg, WritableVReg, RegClass::Vector);126127impl XReg {128/// Index of the first "special" register, or the end of which registers129/// regalloc is allowed to use.130pub const SPECIAL_START: u8 = pulley_interpreter::regs::XReg::SPECIAL_START;131132/// Returns whether this is a "special" physical register for pulley.133pub fn is_special(&self) -> bool {134match self.as_pulley() {135Some(reg) => reg.is_special(),136None => false,137}138}139140/// Returns the pulley-typed register, if this is a physical register.141pub fn as_pulley(&self) -> Option<pulley_interpreter::XReg> {142let enc = self.to_real_reg()?.hw_enc();143Some(pulley_interpreter::XReg::new(enc).unwrap())144}145}146147pub use super::super::lower::isle::generated_code::Amode;148149impl Amode {150/// Add the registers referenced by this Amode to `collector`.151pub(crate) fn get_operands(&mut self, collector: &mut impl OperandVisitor) {152match self {153Amode::RegOffset { base, offset: _ } => collector.reg_use(base),154// Registers used in these modes aren't allocatable.155Amode::SpOffset { .. } | Amode::Stack { .. } => {}156}157}158159pub(crate) fn get_base_register(&self) -> Option<XReg> {160match self {161Amode::RegOffset { base, offset: _ } => Some(*base),162Amode::SpOffset { .. } | Amode::Stack { .. } => Some(XReg::new(stack_reg()).unwrap()),163}164}165166pub(crate) fn get_offset_with_state<P>(&self, state: &EmitState<P>) -> i32167where168P: PulleyTargetKind,169{170match self {171Amode::RegOffset { base: _, offset } | Amode::SpOffset { offset } => *offset,172Amode::Stack { amode } => {173let offset64 = match amode {174StackAMode::IncomingArg(offset, stack_args_size) => {175let offset = i64::from(*stack_args_size) - *offset;176let frame_layout = state.frame_layout();177let sp_offset = frame_layout.tail_args_size178+ frame_layout.setup_area_size179+ frame_layout.clobber_size180+ frame_layout.fixed_frame_storage_size181+ frame_layout.outgoing_args_size;182i64::from(sp_offset) - offset183}184StackAMode::Slot(offset) => {185offset + i64::from(state.frame_layout().outgoing_args_size)186}187StackAMode::OutgoingArg(offset) => *offset,188};189i32::try_from(offset64).unwrap()190}191}192}193}194195impl core::fmt::Display for Amode {196fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {197match self {198Amode::SpOffset { offset } => {199if *offset >= 0 {200write!(f, "sp+{offset}")201} else {202write!(f, "sp{offset}")203}204}205Amode::RegOffset { base, offset } => {206let name = reg_name(**base);207if *offset >= 0 {208write!(f, "{name}+{offset}")209} else {210write!(f, "{name}{offset}")211}212}213Amode::Stack { amode } => core::fmt::Debug::fmt(amode, f),214}215}216}217218impl From<StackAMode> for Amode {219fn from(amode: StackAMode) -> Self {220Amode::Stack { amode }221}222}223224/// The size of an operand or operation.225#[derive(Clone, Copy, Debug, PartialEq, Eq)]226pub enum OperandSize {227/// 32 bits.228Size32,229/// 64 bits.230Size64,231}232233pub use crate::isa::pulley_shared::lower::isle::generated_code::Cond;234235impl Cond {236/// Collect register operands within `collector` for register allocation.237pub fn get_operands(&mut self, collector: &mut impl OperandVisitor) {238match self {239Cond::If32 { reg } | Cond::IfNot32 { reg } => collector.reg_use(reg),240241Cond::IfXeq32 { src1, src2 }242| Cond::IfXneq32 { src1, src2 }243| Cond::IfXslt32 { src1, src2 }244| Cond::IfXslteq32 { src1, src2 }245| Cond::IfXult32 { src1, src2 }246| Cond::IfXulteq32 { src1, src2 }247| Cond::IfXeq64 { src1, src2 }248| Cond::IfXneq64 { src1, src2 }249| Cond::IfXslt64 { src1, src2 }250| Cond::IfXslteq64 { src1, src2 }251| Cond::IfXult64 { src1, src2 }252| Cond::IfXulteq64 { src1, src2 } => {253collector.reg_use(src1);254collector.reg_use(src2);255}256257Cond::IfXeq32I32 { src1, src2 }258| Cond::IfXneq32I32 { src1, src2 }259| Cond::IfXslt32I32 { src1, src2 }260| Cond::IfXslteq32I32 { src1, src2 }261| Cond::IfXsgt32I32 { src1, src2 }262| Cond::IfXsgteq32I32 { src1, src2 }263| Cond::IfXeq64I32 { src1, src2 }264| Cond::IfXneq64I32 { src1, src2 }265| Cond::IfXslt64I32 { src1, src2 }266| Cond::IfXslteq64I32 { src1, src2 }267| Cond::IfXsgt64I32 { src1, src2 }268| Cond::IfXsgteq64I32 { src1, src2 } => {269collector.reg_use(src1);270let _: &mut i32 = src2;271}272273Cond::IfXult32I32 { src1, src2 }274| Cond::IfXulteq32I32 { src1, src2 }275| Cond::IfXugt32I32 { src1, src2 }276| Cond::IfXugteq32I32 { src1, src2 }277| Cond::IfXult64I32 { src1, src2 }278| Cond::IfXulteq64I32 { src1, src2 }279| Cond::IfXugt64I32 { src1, src2 }280| Cond::IfXugteq64I32 { src1, src2 } => {281collector.reg_use(src1);282let _: &mut u32 = src2;283}284}285}286287/// Encode this condition as a branch into `sink`.288///289/// Note that the offset encoded to jump by is filled in as 0 and it's290/// assumed `MachBuffer` will come back and clean it up.291pub fn encode(&self, sink: &mut impl Extend<u8>, rel: i32) {292match *self {293Cond::If32 { reg } => encode::br_if32(sink, reg, rel),294Cond::IfNot32 { reg } => encode::br_if_not32(sink, reg, rel),295Cond::IfXeq32 { src1, src2 } => encode::br_if_xeq32(sink, src1, src2, rel),296Cond::IfXneq32 { src1, src2 } => encode::br_if_xneq32(sink, src1, src2, rel),297Cond::IfXslt32 { src1, src2 } => encode::br_if_xslt32(sink, src1, src2, rel),298Cond::IfXslteq32 { src1, src2 } => encode::br_if_xslteq32(sink, src1, src2, rel),299Cond::IfXult32 { src1, src2 } => encode::br_if_xult32(sink, src1, src2, rel),300Cond::IfXulteq32 { src1, src2 } => encode::br_if_xulteq32(sink, src1, src2, rel),301Cond::IfXeq64 { src1, src2 } => encode::br_if_xeq64(sink, src1, src2, rel),302Cond::IfXneq64 { src1, src2 } => encode::br_if_xneq64(sink, src1, src2, rel),303Cond::IfXslt64 { src1, src2 } => encode::br_if_xslt64(sink, src1, src2, rel),304Cond::IfXslteq64 { src1, src2 } => encode::br_if_xslteq64(sink, src1, src2, rel),305Cond::IfXult64 { src1, src2 } => encode::br_if_xult64(sink, src1, src2, rel),306Cond::IfXulteq64 { src1, src2 } => encode::br_if_xulteq64(sink, src1, src2, rel),307308Cond::IfXeq32I32 { src1, src2 } => match i8::try_from(src2) {309Ok(src2) => encode::br_if_xeq32_i8(sink, src1, src2, rel),310Err(_) => encode::br_if_xeq32_i32(sink, src1, src2, rel),311},312Cond::IfXneq32I32 { src1, src2 } => match i8::try_from(src2) {313Ok(src2) => encode::br_if_xneq32_i8(sink, src1, src2, rel),314Err(_) => encode::br_if_xneq32_i32(sink, src1, src2, rel),315},316Cond::IfXslt32I32 { src1, src2 } => match i8::try_from(src2) {317Ok(src2) => encode::br_if_xslt32_i8(sink, src1, src2, rel),318Err(_) => encode::br_if_xslt32_i32(sink, src1, src2, rel),319},320Cond::IfXslteq32I32 { src1, src2 } => match i8::try_from(src2) {321Ok(src2) => encode::br_if_xslteq32_i8(sink, src1, src2, rel),322Err(_) => encode::br_if_xslteq32_i32(sink, src1, src2, rel),323},324Cond::IfXsgt32I32 { src1, src2 } => match i8::try_from(src2) {325Ok(src2) => encode::br_if_xsgt32_i8(sink, src1, src2, rel),326Err(_) => encode::br_if_xsgt32_i32(sink, src1, src2, rel),327},328Cond::IfXsgteq32I32 { src1, src2 } => match i8::try_from(src2) {329Ok(src2) => encode::br_if_xsgteq32_i8(sink, src1, src2, rel),330Err(_) => encode::br_if_xsgteq32_i32(sink, src1, src2, rel),331},332Cond::IfXult32I32 { src1, src2 } => match u8::try_from(src2) {333Ok(src2) => encode::br_if_xult32_u8(sink, src1, src2, rel),334Err(_) => encode::br_if_xult32_u32(sink, src1, src2, rel),335},336Cond::IfXulteq32I32 { src1, src2 } => match u8::try_from(src2) {337Ok(src2) => encode::br_if_xulteq32_u8(sink, src1, src2, rel),338Err(_) => encode::br_if_xulteq32_u32(sink, src1, src2, rel),339},340Cond::IfXugt32I32 { src1, src2 } => match u8::try_from(src2) {341Ok(src2) => encode::br_if_xugt32_u8(sink, src1, src2, rel),342Err(_) => encode::br_if_xugt32_u32(sink, src1, src2, rel),343},344Cond::IfXugteq32I32 { src1, src2 } => match u8::try_from(src2) {345Ok(src2) => encode::br_if_xugteq32_u8(sink, src1, src2, rel),346Err(_) => encode::br_if_xugteq32_u32(sink, src1, src2, rel),347},348349Cond::IfXeq64I32 { src1, src2 } => match i8::try_from(src2) {350Ok(src2) => encode::br_if_xeq64_i8(sink, src1, src2, rel),351Err(_) => encode::br_if_xeq64_i32(sink, src1, src2, rel),352},353Cond::IfXneq64I32 { src1, src2 } => match i8::try_from(src2) {354Ok(src2) => encode::br_if_xneq64_i8(sink, src1, src2, rel),355Err(_) => encode::br_if_xneq64_i32(sink, src1, src2, rel),356},357Cond::IfXslt64I32 { src1, src2 } => match i8::try_from(src2) {358Ok(src2) => encode::br_if_xslt64_i8(sink, src1, src2, rel),359Err(_) => encode::br_if_xslt64_i32(sink, src1, src2, rel),360},361Cond::IfXslteq64I32 { src1, src2 } => match i8::try_from(src2) {362Ok(src2) => encode::br_if_xslteq64_i8(sink, src1, src2, rel),363Err(_) => encode::br_if_xslteq64_i32(sink, src1, src2, rel),364},365Cond::IfXsgt64I32 { src1, src2 } => match i8::try_from(src2) {366Ok(src2) => encode::br_if_xsgt64_i8(sink, src1, src2, rel),367Err(_) => encode::br_if_xsgt64_i32(sink, src1, src2, rel),368},369Cond::IfXsgteq64I32 { src1, src2 } => match i8::try_from(src2) {370Ok(src2) => encode::br_if_xsgteq64_i8(sink, src1, src2, rel),371Err(_) => encode::br_if_xsgteq64_i32(sink, src1, src2, rel),372},373Cond::IfXult64I32 { src1, src2 } => match u8::try_from(src2) {374Ok(src2) => encode::br_if_xult64_u8(sink, src1, src2, rel),375Err(_) => encode::br_if_xult64_u32(sink, src1, src2, rel),376},377Cond::IfXulteq64I32 { src1, src2 } => match u8::try_from(src2) {378Ok(src2) => encode::br_if_xulteq64_u8(sink, src1, src2, rel),379Err(_) => encode::br_if_xulteq64_u32(sink, src1, src2, rel),380},381Cond::IfXugt64I32 { src1, src2 } => match u8::try_from(src2) {382Ok(src2) => encode::br_if_xugt64_u8(sink, src1, src2, rel),383Err(_) => encode::br_if_xugt64_u32(sink, src1, src2, rel),384},385Cond::IfXugteq64I32 { src1, src2 } => match u8::try_from(src2) {386Ok(src2) => encode::br_if_xugteq64_u8(sink, src1, src2, rel),387Err(_) => encode::br_if_xugteq64_u32(sink, src1, src2, rel),388},389}390}391392/// Inverts this conditional.393pub fn invert(&self) -> Cond {394match *self {395Cond::If32 { reg } => Cond::IfNot32 { reg },396Cond::IfNot32 { reg } => Cond::If32 { reg },397Cond::IfXeq32 { src1, src2 } => Cond::IfXneq32 { src1, src2 },398Cond::IfXneq32 { src1, src2 } => Cond::IfXeq32 { src1, src2 },399Cond::IfXeq64 { src1, src2 } => Cond::IfXneq64 { src1, src2 },400Cond::IfXneq64 { src1, src2 } => Cond::IfXeq64 { src1, src2 },401402// Note that for below the condition changes but the operands are403// also swapped.404Cond::IfXslt32 { src1, src2 } => Cond::IfXslteq32 {405src1: src2,406src2: src1,407},408Cond::IfXslteq32 { src1, src2 } => Cond::IfXslt32 {409src1: src2,410src2: src1,411},412Cond::IfXult32 { src1, src2 } => Cond::IfXulteq32 {413src1: src2,414src2: src1,415},416Cond::IfXulteq32 { src1, src2 } => Cond::IfXult32 {417src1: src2,418src2: src1,419},420Cond::IfXslt64 { src1, src2 } => Cond::IfXslteq64 {421src1: src2,422src2: src1,423},424Cond::IfXslteq64 { src1, src2 } => Cond::IfXslt64 {425src1: src2,426src2: src1,427},428Cond::IfXult64 { src1, src2 } => Cond::IfXulteq64 {429src1: src2,430src2: src1,431},432Cond::IfXulteq64 { src1, src2 } => Cond::IfXult64 {433src1: src2,434src2: src1,435},436437Cond::IfXeq32I32 { src1, src2 } => Cond::IfXneq32I32 { src1, src2 },438Cond::IfXneq32I32 { src1, src2 } => Cond::IfXeq32I32 { src1, src2 },439Cond::IfXslt32I32 { src1, src2 } => Cond::IfXsgteq32I32 { src1, src2 },440Cond::IfXslteq32I32 { src1, src2 } => Cond::IfXsgt32I32 { src1, src2 },441Cond::IfXult32I32 { src1, src2 } => Cond::IfXugteq32I32 { src1, src2 },442Cond::IfXulteq32I32 { src1, src2 } => Cond::IfXugt32I32 { src1, src2 },443Cond::IfXsgt32I32 { src1, src2 } => Cond::IfXslteq32I32 { src1, src2 },444Cond::IfXsgteq32I32 { src1, src2 } => Cond::IfXslt32I32 { src1, src2 },445Cond::IfXugt32I32 { src1, src2 } => Cond::IfXulteq32I32 { src1, src2 },446Cond::IfXugteq32I32 { src1, src2 } => Cond::IfXult32I32 { src1, src2 },447448Cond::IfXeq64I32 { src1, src2 } => Cond::IfXneq64I32 { src1, src2 },449Cond::IfXneq64I32 { src1, src2 } => Cond::IfXeq64I32 { src1, src2 },450Cond::IfXslt64I32 { src1, src2 } => Cond::IfXsgteq64I32 { src1, src2 },451Cond::IfXslteq64I32 { src1, src2 } => Cond::IfXsgt64I32 { src1, src2 },452Cond::IfXult64I32 { src1, src2 } => Cond::IfXugteq64I32 { src1, src2 },453Cond::IfXulteq64I32 { src1, src2 } => Cond::IfXugt64I32 { src1, src2 },454Cond::IfXsgt64I32 { src1, src2 } => Cond::IfXslteq64I32 { src1, src2 },455Cond::IfXsgteq64I32 { src1, src2 } => Cond::IfXslt64I32 { src1, src2 },456Cond::IfXugt64I32 { src1, src2 } => Cond::IfXulteq64I32 { src1, src2 },457Cond::IfXugteq64I32 { src1, src2 } => Cond::IfXult64I32 { src1, src2 },458}459}460}461462impl fmt::Display for Cond {463fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {464match self {465Cond::If32 { reg } => write!(f, "if32 {}", reg_name(**reg)),466Cond::IfNot32 { reg } => write!(f, "if_not32 {}", reg_name(**reg)),467Cond::IfXeq32 { src1, src2 } => {468write!(f, "if_xeq32 {}, {}", reg_name(**src1), reg_name(**src2))469}470Cond::IfXneq32 { src1, src2 } => {471write!(f, "if_xneq32 {}, {}", reg_name(**src1), reg_name(**src2))472}473Cond::IfXslt32 { src1, src2 } => {474write!(f, "if_xslt32 {}, {}", reg_name(**src1), reg_name(**src2))475}476Cond::IfXslteq32 { src1, src2 } => {477write!(f, "if_xslteq32 {}, {}", reg_name(**src1), reg_name(**src2))478}479Cond::IfXult32 { src1, src2 } => {480write!(f, "if_xult32 {}, {}", reg_name(**src1), reg_name(**src2))481}482Cond::IfXulteq32 { src1, src2 } => {483write!(f, "if_xulteq32 {}, {}", reg_name(**src1), reg_name(**src2))484}485Cond::IfXeq64 { src1, src2 } => {486write!(f, "if_xeq64 {}, {}", reg_name(**src1), reg_name(**src2))487}488Cond::IfXneq64 { src1, src2 } => {489write!(f, "if_xneq64 {}, {}", reg_name(**src1), reg_name(**src2))490}491Cond::IfXslt64 { src1, src2 } => {492write!(f, "if_xslt64 {}, {}", reg_name(**src1), reg_name(**src2))493}494Cond::IfXslteq64 { src1, src2 } => {495write!(f, "if_xslteq64 {}, {}", reg_name(**src1), reg_name(**src2))496}497Cond::IfXult64 { src1, src2 } => {498write!(f, "if_xult64 {}, {}", reg_name(**src1), reg_name(**src2))499}500Cond::IfXulteq64 { src1, src2 } => {501write!(f, "if_xulteq64 {}, {}", reg_name(**src1), reg_name(**src2))502}503Cond::IfXeq32I32 { src1, src2 } => {504write!(f, "if_xeq32_i32 {}, {src2}", reg_name(**src1))505}506Cond::IfXneq32I32 { src1, src2 } => {507write!(f, "if_xneq32_i32 {}, {src2}", reg_name(**src1))508}509Cond::IfXslt32I32 { src1, src2 } => {510write!(f, "if_xslt32_i32 {}, {src2}", reg_name(**src1))511}512Cond::IfXslteq32I32 { src1, src2 } => {513write!(f, "if_xslteq32_i32 {}, {src2}", reg_name(**src1))514}515Cond::IfXsgt32I32 { src1, src2 } => {516write!(f, "if_xsgt32_i32 {}, {src2}", reg_name(**src1))517}518Cond::IfXsgteq32I32 { src1, src2 } => {519write!(f, "if_xsgteq32_i32 {}, {src2}", reg_name(**src1))520}521Cond::IfXult32I32 { src1, src2 } => {522write!(f, "if_xult32_i32 {}, {src2}", reg_name(**src1))523}524Cond::IfXulteq32I32 { src1, src2 } => {525write!(f, "if_xulteq32_i32 {}, {src2}", reg_name(**src1))526}527Cond::IfXugt32I32 { src1, src2 } => {528write!(f, "if_xugt32_i32 {}, {src2}", reg_name(**src1))529}530Cond::IfXugteq32I32 { src1, src2 } => {531write!(f, "if_xugteq32_i32 {}, {src2}", reg_name(**src1))532}533Cond::IfXeq64I32 { src1, src2 } => {534write!(f, "if_xeq64_i32 {}, {src2}", reg_name(**src1))535}536Cond::IfXneq64I32 { src1, src2 } => {537write!(f, "if_xneq64_i32 {}, {src2}", reg_name(**src1))538}539Cond::IfXslt64I32 { src1, src2 } => {540write!(f, "if_xslt64_i32 {}, {src2}", reg_name(**src1))541}542Cond::IfXslteq64I32 { src1, src2 } => {543write!(f, "if_xslteq64_i32 {}, {src2}", reg_name(**src1))544}545Cond::IfXsgt64I32 { src1, src2 } => {546write!(f, "if_xsgt64_i32 {}, {src2}", reg_name(**src1))547}548Cond::IfXsgteq64I32 { src1, src2 } => {549write!(f, "if_xsgteq64_i32 {}, {src2}", reg_name(**src1))550}551Cond::IfXult64I32 { src1, src2 } => {552write!(f, "if_xult64_i32 {}, {src2}", reg_name(**src1))553}554Cond::IfXulteq64I32 { src1, src2 } => {555write!(f, "if_xulteq64_i32 {}, {src2}", reg_name(**src1))556}557Cond::IfXugt64I32 { src1, src2 } => {558write!(f, "if_xugt64_i32 {}, {src2}", reg_name(**src1))559}560Cond::IfXugteq64I32 { src1, src2 } => {561write!(f, "if_xugteq64_i32 {}, {src2}", reg_name(**src1))562}563}564}565}566567/// Payload of `CallInfo` for call instructions568#[derive(Clone, Debug)]569pub struct PulleyCall {570/// The external name that's being called, or the Cranelift-generated571/// function that's being invoked.572pub name: ExternalName,573/// Arguments tracked in this call invocation which aren't assigned fixed574/// registers. This tracks up to 4 registers and all remaining registers575/// will be present and tracked in `CallInfo<T>` fields.576pub args: SmallVec<[XReg; 4]>,577}578579pub use super::super::lower::isle::generated_code::AddrO32;580581impl Copy for AddrO32 {}582583impl AddrO32 {584/// Implementation of regalloc for this addressing mode.585pub fn collect_operands(&mut self, collector: &mut impl OperandVisitor) {586match self {587AddrO32::Base { addr, offset: _ } => {588collector.reg_use(addr);589}590}591}592}593594impl From<AddrO32> for pulley_interpreter::AddrO32 {595fn from(addr: AddrO32) -> Self {596match addr {597AddrO32::Base { addr, offset } => Self {598addr: addr.into(),599offset,600},601}602}603}604605impl fmt::Display for AddrO32 {606fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {607match self {608AddrO32::Base { addr, offset } => {609let addr = reg_name(**addr);610write!(f, "{addr}, {offset}")611}612}613}614}615616pub use super::super::lower::isle::generated_code::AddrZ;617618impl Copy for AddrZ {}619620impl AddrZ {621/// Implementation of regalloc for this addressing mode.622pub fn collect_operands(&mut self, collector: &mut impl OperandVisitor) {623match self {624AddrZ::Base { addr, offset: _ } => {625collector.reg_use(addr);626}627}628}629}630631impl From<AddrZ> for pulley_interpreter::AddrZ {632fn from(addr: AddrZ) -> Self {633match addr {634AddrZ::Base { addr, offset } => Self {635addr: addr.into(),636offset,637},638}639}640}641642impl fmt::Display for AddrZ {643fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {644match self {645AddrZ::Base { addr, offset } => {646let addr = reg_name(**addr);647write!(f, "{addr}, {offset}")648}649}650}651}652653pub use super::super::lower::isle::generated_code::AddrG32;654655impl Copy for AddrG32 {}656657impl AddrG32 {658/// Implementation of regalloc for this addressing mode.659pub fn collect_operands(&mut self, collector: &mut impl OperandVisitor) {660match self {661AddrG32::RegisterBound {662host_heap_base,663host_heap_bound,664wasm_addr,665offset: _,666} => {667collector.reg_use(host_heap_base);668collector.reg_use(host_heap_bound);669collector.reg_use(wasm_addr);670}671}672}673}674675impl From<AddrG32> for pulley_interpreter::AddrG32 {676fn from(addr: AddrG32) -> Self {677match addr {678AddrG32::RegisterBound {679host_heap_base,680host_heap_bound,681wasm_addr,682offset,683} => Self {684host_heap_base: host_heap_base.into(),685host_heap_bound: host_heap_bound.into(),686wasm_addr: wasm_addr.into(),687offset,688},689}690}691}692693impl fmt::Display for AddrG32 {694fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {695match self {696AddrG32::RegisterBound {697host_heap_base,698host_heap_bound,699wasm_addr,700offset,701} => {702let host_heap_base = reg_name(**host_heap_base);703let host_heap_bound = reg_name(**host_heap_bound);704let wasm_addr = reg_name(**wasm_addr);705write!(706f,707"{host_heap_base}, {host_heap_bound}, {wasm_addr}, {offset}",708)709}710}711}712}713714pub use super::super::lower::isle::generated_code::AddrG32Bne;715716impl Copy for AddrG32Bne {}717718impl AddrG32Bne {719/// Implementation of regalloc for this addressing mode.720pub fn collect_operands(&mut self, collector: &mut impl OperandVisitor) {721match self {722AddrG32Bne::BoundNe {723host_heap_base,724host_heap_bound_addr,725host_heap_bound_offset: _,726wasm_addr,727offset: _,728} => {729collector.reg_use(host_heap_base);730collector.reg_use(host_heap_bound_addr);731collector.reg_use(wasm_addr);732}733}734}735}736737impl From<AddrG32Bne> for pulley_interpreter::AddrG32Bne {738fn from(addr: AddrG32Bne) -> Self {739match addr {740AddrG32Bne::BoundNe {741host_heap_base,742host_heap_bound_addr,743host_heap_bound_offset,744wasm_addr,745offset,746} => Self {747host_heap_base: host_heap_base.into(),748host_heap_bound_addr: host_heap_bound_addr.into(),749host_heap_bound_offset,750wasm_addr: wasm_addr.into(),751offset,752},753}754}755}756757impl fmt::Display for AddrG32Bne {758fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {759match self {760AddrG32Bne::BoundNe {761host_heap_base,762host_heap_bound_addr,763host_heap_bound_offset,764wasm_addr,765offset,766} => {767let host_heap_base = reg_name(**host_heap_base);768let host_heap_bound_addr = reg_name(**host_heap_bound_addr);769let wasm_addr = reg_name(**wasm_addr);770write!(771f,772"{host_heap_base}, \773*[{host_heap_bound_addr} + {host_heap_bound_offset}], \774{wasm_addr}, \775{offset}",776)777}778}779}780}781782783