#[cfg(feature = "simd")]
use crate::core::simd::{ImmLaneIdx16, ImmLaneIdx2, ImmLaneIdx4, ImmLaneIdx8};
use crate::{core::TrapCode, index::*, *};
impl Instruction {
pub fn visit_regs<V: VisitRegs>(&mut self, visitor: &mut V) {
HostVisitor::host_visitor(self, visitor)
}
}
pub trait VisitRegs {
fn visit_result_reg(&mut self, reg: &mut Reg);
fn visit_result_regs(&mut self, reg: &mut RegSpan, len: Option<u16>);
fn visit_input_reg(&mut self, reg: &mut Reg);
fn visit_input_regs(&mut self, regs: &mut RegSpan, len: Option<u16>);
}
trait HostVisitor {
fn host_visitor<V: VisitRegs>(self, visitor: &mut V);
}
impl HostVisitor for &'_ mut Reg {
fn host_visitor<V: VisitRegs>(self, visitor: &mut V) {
visitor.visit_input_reg(self);
}
}
impl<const N: usize> HostVisitor for &'_ mut [Reg; N] {
fn host_visitor<V: VisitRegs>(self, visitor: &mut V) {
for reg in self {
visitor.visit_input_reg(reg);
}
}
}
impl HostVisitor for &'_ mut RegSpan {
fn host_visitor<V: VisitRegs>(self, visitor: &mut V) {
visitor.visit_input_regs(self, None);
}
}
impl HostVisitor for &'_ mut BoundedRegSpan {
fn host_visitor<V: VisitRegs>(self, visitor: &mut V) {
let len = self.len();
visitor.visit_input_regs(self.span_mut(), Some(len));
}
}
impl<const N: u16> HostVisitor for &'_ mut FixedRegSpan<N> {
fn host_visitor<V: VisitRegs>(self, visitor: &mut V) {
visitor.visit_input_regs(self.span_mut(), Some(N));
}
}
macro_rules! impl_host_visitor_for {
( $( $ty:ident $(<$t:ident>)? ),* $(,)? ) => {
$(
impl $(<$t>)? HostVisitor for &'_ mut $ty $(<$t>)? {
#[inline]
fn host_visitor<V: VisitRegs>(self, _visitor: &mut V) {}
}
)*
};
}
impl_host_visitor_for!(
u8,
i8,
i16,
u16,
i32,
u32,
TrapCode,
BlockFuel,
AnyConst16,
AnyConst32,
BranchOffset,
BranchOffset16,
InternalFunc,
Func,
FuncType,
Global,
Memory,
Table,
Elem,
Data,
Const16<T>,
Const32<T>,
Sign<T>,
ShiftAmount<T>,
Offset8,
Offset16,
Offset64,
Offset64Lo,
Offset64Hi,
Address32,
);
#[cfg(feature = "simd")]
impl_host_visitor_for!(ImmLaneIdx16, ImmLaneIdx2, ImmLaneIdx4, ImmLaneIdx8,);
pub struct Res<T>(T);
impl HostVisitor for Res<&'_ mut Reg> {
fn host_visitor<V: VisitRegs>(self, visitor: &mut V) {
visitor.visit_result_reg(self.0);
}
}
impl HostVisitor for Res<&'_ mut [Reg; 2]> {
fn host_visitor<V: VisitRegs>(self, visitor: &mut V) {
visitor.visit_result_reg(&mut self.0[0]);
visitor.visit_result_reg(&mut self.0[1]);
}
}
impl HostVisitor for Res<&'_ mut RegSpan> {
fn host_visitor<V: VisitRegs>(self, visitor: &mut V) {
visitor.visit_result_regs(self.0, None);
}
}
impl HostVisitor for Res<&'_ mut BoundedRegSpan> {
fn host_visitor<V: VisitRegs>(self, visitor: &mut V) {
let len = self.0.len();
visitor.visit_result_regs(self.0.span_mut(), Some(len));
}
}
impl<const N: u16> HostVisitor for Res<&'_ mut FixedRegSpan<N>> {
fn host_visitor<V: VisitRegs>(self, visitor: &mut V) {
visitor.visit_result_regs(self.0.span_mut(), Some(N));
}
}
macro_rules! impl_host_visitor {
(
$(
$( #[doc = $doc:literal] )*
#[snake_name($snake_name:ident)]
$name:ident
$(
{
$( @ $result_name:ident: $result_ty:ty, )?
$(
$( #[$field_docs:meta] )*
$field_name:ident: $field_ty:ty
),*
$(,)?
}
)?
),* $(,)?
) => {
impl<'a> HostVisitor for &'a mut Instruction {
fn host_visitor<V: VisitRegs>(self, visitor: &mut V) {
match self {
$(
Instruction::$name { $( $( $result_name, )? $( $field_name, )* )? } => {
$(
$( Res($result_name).host_visitor(visitor); )?
$( $field_name.host_visitor(visitor); )*
)?
}
)*
}
}
}
};
}
for_each_op!(impl_host_visitor);