use crate::{
Error,
engine::{CompiledFuncEntry, WasmOperator, WasmTranslator, translator::FuncTranslator},
};
use wasmparser::{VisitOperator, WasmFeatures};
macro_rules! impl_visit_operator_for_fuel_metering {
( @mvp $($rest:tt)* ) => {
impl_visit_operator_for_fuel_metering!(@@supported $($rest)*);
};
( @sign_extension $($rest:tt)* ) => {
impl_visit_operator_for_fuel_metering!(@@supported $($rest)*);
};
( @saturating_float_to_int $($rest:tt)* ) => {
impl_visit_operator_for_fuel_metering!(@@supported $($rest)*);
};
( @bulk_memory $($rest:tt)* ) => {
impl_visit_operator_for_fuel_metering!(@@supported $($rest)*);
};
( @reference_types $($rest:tt)* ) => {
impl_visit_operator_for_fuel_metering!(@@supported $($rest)*);
};
( @tail_call $($rest:tt)* ) => {
impl_visit_operator_for_fuel_metering!(@@supported $($rest)*);
};
( @wide_arithmetic $($rest:tt)* ) => {
impl_visit_operator_for_fuel_metering!(@@supported $($rest)*);
};
( @simd $($rest:tt)* ) => {
impl_visit_operator_for_fuel_metering!(@@supported $($rest)*);
};
( @relaxed_simd $($rest:tt)* ) => {
impl_visit_operator_for_fuel_metering!(@@supported $($rest)*);
};
( @@supported $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident $_ann:tt $($rest:tt)* ) => {
#[inline]
fn $visit(&mut self $($(, $arg: $argty)*)?) -> Self::Output {
self.0.bump_fuel_for_operator(WasmOperator::$op)?;
self.0.$visit( $( $($arg),* )? )
}
impl_visit_operator_for_fuel_metering!($($rest)*);
};
( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident $_ann:tt $($rest:tt)* ) => {
#[inline]
fn $visit(&mut self $($(, $arg: $argty)*)?) -> Self::Output {
self.0.$visit( $( $($arg),* )? )
}
impl_visit_operator_for_fuel_metering!($($rest)*);
};
() => {};
}
#[derive(Debug)]
pub struct FuelMeteringFuncTranslator(FuncTranslator);
impl From<FuncTranslator> for FuelMeteringFuncTranslator {
fn from(translator: FuncTranslator) -> Self {
Self(translator)
}
}
impl<'a> VisitOperator<'a> for FuelMeteringFuncTranslator {
type Output = Result<(), Error>;
#[cfg(feature = "simd")]
fn simd_visitor(
&mut self,
) -> Option<&mut dyn wasmparser::VisitSimdOperator<'a, Output = Self::Output>> {
Some(self)
}
wasmparser::for_each_visit_operator!(impl_visit_operator_for_fuel_metering);
}
#[cfg(feature = "simd")]
impl<'a> wasmparser::VisitSimdOperator<'a> for FuelMeteringFuncTranslator {
wasmparser::for_each_visit_simd_operator!(impl_visit_operator_for_fuel_metering);
}
impl<'a> WasmTranslator<'a> for FuelMeteringFuncTranslator {
type Allocations = <FuncTranslator as WasmTranslator<'a>>::Allocations;
#[inline]
fn setup(&mut self, bytes: &[u8]) -> Result<bool, Error> {
self.0.setup(bytes)
}
#[inline]
fn features(&self) -> WasmFeatures {
self.0.features()
}
#[inline]
fn translate_locals(
&mut self,
amount: u32,
value_type: wasmparser::ValType,
) -> Result<(), Error> {
self.0.translate_locals(amount, value_type)
}
#[inline]
fn finish_translate_locals(&mut self) -> Result<(), Error> {
self.0.finish_translate_locals()
}
#[inline]
fn update_pos(&mut self, pos: usize) {
self.0.update_pos(pos)
}
#[inline]
fn finish(self, finalize: impl FnOnce(CompiledFuncEntry)) -> Result<Self::Allocations, Error> {
self.0.finish(finalize)
}
}