summaryrefslogtreecommitdiff
path: root/crates/parser/src
diff options
context:
space:
mode:
authorHenry Gressmann <mail@henrygressmann.de>2024-05-29 01:22:31 +0200
committerHenry Gressmann <mail@henrygressmann.de>2024-05-29 01:22:31 +0200
commit9d7c1924f1d0e9f79e31da4b84d9da12c3d37945 (patch)
treef3a98df3fdb4a87a1ecd321cb96aa8255b95d615 /crates/parser/src
parentdce86f8f9ad919fa2dc1db043209fe1b1c9f08de (diff)
chore: improve parser, clean up interpreter loop
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
Diffstat (limited to 'crates/parser/src')
-rw-r--r--crates/parser/src/conversion.rs28
-rw-r--r--crates/parser/src/lib.rs45
-rw-r--r--crates/parser/src/module.rs46
-rw-r--r--crates/parser/src/visit.rs264
4 files changed, 166 insertions, 217 deletions
diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs
index bc082f0..e8dd9a8 100644
--- a/crates/parser/src/conversion.rs
+++ b/crates/parser/src/conversion.rs
@@ -1,5 +1,5 @@
use crate::Result;
-use crate::{module::Code, visit::process_operators};
+use crate::{module::Code, visit::process_operators_and_validate};
use alloc::{boxed::Box, format, string::ToString, vec::Vec};
use tinywasm_types::*;
use wasmparser::{FuncValidator, OperatorsReader, ValidatorResources};
@@ -174,17 +174,20 @@ pub(crate) fn convert_module_code(
let count = locals_reader.get_count();
let pos = locals_reader.original_position();
- let mut locals = Vec::with_capacity(count as usize);
- for (i, local) in locals_reader.into_iter().enumerate() {
- let local = local?;
- validator.define_locals(pos + i, local.0, local.1)?;
- for _ in 0..local.0 {
- locals.push(convert_valtype(&local.1));
+ let locals = {
+ let mut locals = Vec::new();
+ locals.reserve_exact(count as usize);
+ for (i, local) in locals_reader.into_iter().enumerate() {
+ let local = local?;
+ validator.define_locals(pos + i, local.0, local.1)?;
+ for _ in 0..local.0 {
+ locals.push(convert_valtype(&local.1));
+ }
}
- }
+ locals.into_boxed_slice()
+ };
- let body = process_operators(Some(validator), func)?;
- let locals = locals.into_boxed_slice();
+ let body = process_operators_and_validate(validator, func)?;
Ok((body, locals))
}
@@ -196,6 +199,7 @@ pub(crate) fn convert_module_type(ty: wasmparser::RecGroup) -> Result<FuncType>
"Expected exactly one type in the type section".to_string(),
));
}
+
let ty = types.next().unwrap().unwrap_func();
let params = ty.params().iter().map(convert_valtype).collect::<Vec<ValType>>().into_boxed_slice();
let results = ty.results().iter().map(convert_valtype).collect::<Vec<ValType>>().into_boxed_slice();
@@ -230,10 +234,6 @@ pub(crate) fn convert_valtype(valtype: &wasmparser::ValType) -> ValType {
}
}
-pub(crate) fn convert_memarg(memarg: wasmparser::MemArg) -> MemoryArg {
- MemoryArg { offset: memarg.offset, mem_addr: memarg.memory }
-}
-
pub(crate) fn process_const_operators(ops: OperatorsReader<'_>) -> Result<ConstInstruction> {
let ops = ops.into_iter().collect::<wasmparser::Result<Vec<_>>>()?;
// In practice, the len can never be something other than 2,
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index dd10f4d..4ee9bb5 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -31,10 +31,9 @@ mod conversion;
mod error;
mod module;
mod visit;
-use alloc::{string::ToString, vec::Vec};
+use alloc::vec::Vec;
pub use error::*;
use module::ModuleReader;
-use tinywasm_types::WasmFunction;
use wasmparser::{Validator, WasmFeaturesInflated};
pub use tinywasm_types::TinyWasmModule;
@@ -93,7 +92,7 @@ impl Parser {
return Err(ParseError::EndNotReached);
}
- reader.try_into()
+ reader.to_module()
}
#[cfg(feature = "std")]
@@ -133,7 +132,7 @@ impl Parser {
reader.process_payload(payload, &mut validator)?;
buffer.drain(..consumed);
if eof || reader.end_reached {
- return reader.try_into();
+ return reader.to_module();
}
}
};
@@ -145,42 +144,6 @@ impl TryFrom<ModuleReader> for TinyWasmModule {
type Error = ParseError;
fn try_from(reader: ModuleReader) -> Result<Self> {
- if !reader.end_reached {
- return Err(ParseError::EndNotReached);
- }
-
- let code_type_addrs = reader.code_type_addrs;
- let local_function_count = reader.code.len();
-
- if code_type_addrs.len() != local_function_count {
- return Err(ParseError::Other("Code and code type address count mismatch".to_string()));
- }
-
- let funcs = reader
- .code
- .into_iter()
- .zip(code_type_addrs)
- .map(|((instructions, locals), ty_idx)| WasmFunction {
- instructions,
- locals,
- ty: reader.func_types.get(ty_idx as usize).expect("No func type for func, this is a bug").clone(),
- })
- .collect::<Vec<_>>();
-
- let globals = reader.globals;
- let table_types = reader.table_types;
-
- Ok(TinyWasmModule {
- funcs: funcs.into_boxed_slice(),
- func_types: reader.func_types.into_boxed_slice(),
- globals: globals.into_boxed_slice(),
- table_types: table_types.into_boxed_slice(),
- imports: reader.imports.into_boxed_slice(),
- start_func: reader.start_func,
- data: reader.data.into_boxed_slice(),
- exports: reader.exports.into_boxed_slice(),
- elements: reader.elements.into_boxed_slice(),
- memory_types: reader.memory_types.into_boxed_slice(),
- })
+ reader.to_module()
}
}
diff --git a/crates/parser/src/module.rs b/crates/parser/src/module.rs
index 1cd5ed5..a4bdba4 100644
--- a/crates/parser/src/module.rs
+++ b/crates/parser/src/module.rs
@@ -1,7 +1,11 @@
use crate::log::debug;
use crate::{conversion, ParseError, Result};
+use alloc::string::ToString;
use alloc::{boxed::Box, format, vec::Vec};
-use tinywasm_types::{Data, Element, Export, FuncType, Global, Import, Instruction, MemoryType, TableType, ValType};
+use tinywasm_types::{
+ Data, Element, Export, FuncType, Global, Import, Instruction, MemoryType, TableType, TinyWasmModule, ValType,
+ WasmFunction,
+};
use wasmparser::{FuncValidatorAllocations, Payload, Validator};
pub(crate) type Code = (Box<[Instruction]>, Box<[ValType]>);
@@ -173,4 +177,44 @@ impl ModuleReader {
Ok(())
}
+
+ #[inline]
+ pub(crate) fn to_module(self) -> Result<TinyWasmModule> {
+ if !self.end_reached {
+ return Err(ParseError::EndNotReached);
+ }
+
+ let local_function_count = self.code.len();
+
+ if self.code_type_addrs.len() != local_function_count {
+ return Err(ParseError::Other("Code and code type address count mismatch".to_string()));
+ }
+
+ let funcs = self
+ .code
+ .into_iter()
+ .zip(self.code_type_addrs)
+ .map(|((instructions, locals), ty_idx)| WasmFunction {
+ instructions,
+ locals,
+ ty: self.func_types.get(ty_idx as usize).expect("No func type for func, this is a bug").clone(),
+ })
+ .collect::<Vec<_>>();
+
+ let globals = self.globals;
+ let table_types = self.table_types;
+
+ Ok(TinyWasmModule {
+ funcs: funcs.into_boxed_slice(),
+ func_types: self.func_types.into_boxed_slice(),
+ globals: globals.into_boxed_slice(),
+ table_types: table_types.into_boxed_slice(),
+ imports: self.imports.into_boxed_slice(),
+ start_func: self.start_func,
+ data: self.data.into_boxed_slice(),
+ exports: self.exports.into_boxed_slice(),
+ elements: self.elements.into_boxed_slice(),
+ memory_types: self.memory_types.into_boxed_slice(),
+ })
+ }
}
diff --git a/crates/parser/src/visit.rs b/crates/parser/src/visit.rs
index 6002996..bddd01d 100644
--- a/crates/parser/src/visit.rs
+++ b/crates/parser/src/visit.rs
@@ -1,122 +1,99 @@
use crate::{conversion::convert_blocktype, Result};
-use crate::conversion::{convert_heaptype, convert_memarg, convert_valtype};
+use crate::conversion::{convert_heaptype, convert_valtype};
use alloc::string::ToString;
-use alloc::{boxed::Box, format, vec::Vec};
-use tinywasm_types::Instruction;
+use alloc::{boxed::Box, vec::Vec};
+use tinywasm_types::{Instruction, MemoryArg};
use wasmparser::{FuncValidator, FunctionBody, VisitOperator, WasmModuleResources};
struct ValidateThenVisit<'a, T, U>(T, &'a mut U);
macro_rules! validate_then_visit {
- ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident)*) => {
- $(
- fn $visit(&mut self $($(,$arg: $argty)*)?) -> Self::Output {
- self.0.$visit($($($arg.clone()),*)?)?;
- Ok(self.1.$visit($($($arg),*)?))
- }
- )*
- };
+ ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident)*) => {$(
+ fn $visit(&mut self $($(,$arg: $argty)*)?) -> Self::Output {
+ self.0.$visit($($($arg.clone()),*)?)?;
+ self.1.$visit($($($arg),*)?);
+ Ok(())
+ }
+ )*};
}
impl<'a, T, U> VisitOperator<'a> for ValidateThenVisit<'_, T, U>
where
T: VisitOperator<'a, Output = wasmparser::Result<()>>,
- U: VisitOperator<'a>,
+ U: VisitOperator<'a, Output = ()>,
{
- type Output = Result<U::Output>;
+ type Output = Result<()>;
wasmparser::for_each_operator!(validate_then_visit);
}
-pub(crate) fn process_operators<R: WasmModuleResources>(
- validator: Option<&mut FuncValidator<R>>,
+pub(crate) fn process_operators_and_validate<R: WasmModuleResources>(
+ validator: &mut FuncValidator<R>,
body: FunctionBody<'_>,
) -> Result<Box<[Instruction]>> {
let mut reader = body.get_operators_reader()?;
let remaining = reader.get_binary_reader().bytes_remaining();
let mut builder = FunctionBuilder::new(remaining);
- if let Some(validator) = validator {
- while !reader.eof() {
- let validate = validator.visitor(reader.original_position());
- reader.visit_operator(&mut ValidateThenVisit(validate, &mut builder))???;
- }
- validator.finish(reader.original_position())?;
- } else {
- while !reader.eof() {
- reader.visit_operator(&mut builder)??;
- }
+ while !reader.eof() {
+ let validate = validator.visitor(reader.original_position());
+ reader.visit_operator(&mut ValidateThenVisit(validate, &mut builder))??;
+ }
+ validator.finish(reader.original_position())?;
+ if !builder.errors.is_empty() {
+ return Err(builder.errors.remove(0));
}
Ok(builder.instructions.into_boxed_slice())
}
macro_rules! define_operands {
- ($($name:ident, $instr:expr),*) => {
- $(
- #[inline(always)]
- fn $name(&mut self) -> Self::Output {
- self.instructions.push($instr);
- Ok(())
- }
- )*
- };
+ ($($name:ident, $instr:expr),*) => {$(
+ fn $name(&mut self) -> Self::Output {
+ self.instructions.push($instr);
+ }
+ )*};
}
macro_rules! define_primitive_operands {
- ($($name:ident, $instr:expr, $ty:ty),*) => {
- $(
- #[inline(always)]
- fn $name(&mut self, arg: $ty) -> Self::Output {
- self.instructions.push($instr(arg));
- Ok(())
- }
- )*
- };
- ($($name:ident, $instr:expr, $ty:ty, $ty2:ty),*) => {
- $(
- #[inline(always)]
- fn $name(&mut self, arg: $ty, arg2: $ty) -> Self::Output {
- self.instructions.push($instr(arg, arg2));
- Ok(())
- }
- )*
- };
+ ($($name:ident, $instr:expr, $ty:ty),*) => {$(
+ fn $name(&mut self, arg: $ty) -> Self::Output {
+ self.instructions.push($instr(arg));
+ }
+ )*};
+ ($($name:ident, $instr:expr, $ty:ty, $ty2:ty),*) => {$(
+ fn $name(&mut self, arg: $ty, arg2: $ty2) -> Self::Output {
+ self.instructions.push($instr(arg, arg2));
+ }
+ )*};
}
macro_rules! define_mem_operands {
- ($($name:ident, $instr:ident),*) => {
- $(
- #[inline(always)]
- fn $name(&mut self, memarg: wasmparser::MemArg) -> Self::Output {
- let arg = convert_memarg(memarg);
- self.instructions.push(Instruction::$instr {
- offset: arg.offset,
- mem_addr: arg.mem_addr,
- });
- Ok(())
- }
- )*
- };
+ ($($name:ident, $instr:ident),*) => {$(
+ fn $name(&mut self, memarg: wasmparser::MemArg) -> Self::Output {
+ self.instructions.push(Instruction::$instr {
+ offset: memarg.offset,
+ mem_addr: memarg.memory,
+ });
+ }
+ )*};
}
pub(crate) struct FunctionBuilder {
instructions: Vec<Instruction>,
label_ptrs: Vec<usize>,
+ errors: Vec<crate::ParseError>,
}
impl FunctionBuilder {
pub(crate) fn new(instr_capacity: usize) -> Self {
- Self { instructions: Vec::with_capacity(instr_capacity / 4), label_ptrs: Vec::with_capacity(256) }
- }
-
- #[cold]
- fn unsupported(&self, name: &str) -> Result<()> {
- Err(crate::ParseError::UnsupportedOperator(format!("Unsupported instruction: {:?}", name)))
+ Self {
+ instructions: Vec::with_capacity(instr_capacity),
+ label_ptrs: Vec::with_capacity(256),
+ errors: Vec::new(),
+ }
}
- #[inline(always)]
- fn visit(&mut self, op: Instruction) -> Result<()> {
- self.instructions.push(op);
- Ok(())
+ fn unsupported(&mut self, name: &str) {
+ self.errors.push(crate::ParseError::UnsupportedOperator(name.to_string()));
}
}
@@ -132,14 +109,14 @@ macro_rules! impl_visit_operator {
(@@bulk_memory $($rest:tt)* ) => {};
(@@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident) => {
#[cold]
- fn $visit(&mut self $($(,$arg: $argty)*)?) -> Result<()>{
+ fn $visit(&mut self $($(,$arg: $argty)*)?) {
self.unsupported(stringify!($visit))
}
};
}
impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
- type Output = Result<()>;
+ type Output = ();
wasmparser::for_each_operator!(impl_visit_operator);
define_primitive_operands! {
@@ -148,7 +125,15 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
visit_global_get, Instruction::GlobalGet, u32,
visit_global_set, Instruction::GlobalSet, u32,
visit_i32_const, Instruction::I32Const, i32,
- visit_i64_const, Instruction::I64Const, i64
+ visit_i64_const, Instruction::I64Const, i64,
+ visit_call, Instruction::Call, u32,
+ visit_local_set, Instruction::LocalSet, u32,
+ visit_local_tee, Instruction::LocalTee, u32
+ }
+
+ define_primitive_operands! {
+ visit_memory_size, Instruction::MemorySize, u32, u8,
+ visit_memory_grow, Instruction::MemoryGrow, u32, u8
}
define_mem_operands! {
@@ -325,116 +310,95 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
visit_i64_trunc_sat_f64_u, Instruction::I64TruncSatF64U
}
- #[inline(always)]
fn visit_i32_store(&mut self, memarg: wasmparser::MemArg) -> Self::Output {
- let arg = convert_memarg(memarg);
+ let arg = MemoryArg { offset: memarg.offset, mem_addr: memarg.memory };
let i32store = Instruction::I32Store { offset: arg.offset, mem_addr: arg.mem_addr };
if self.instructions.len() < 3 || arg.mem_addr > 0xFF || arg.offset > 0xFFFF_FFFF {
- return self.visit(i32store);
+ return self.instructions.push(i32store);
}
match self.instructions[self.instructions.len() - 2..] {
[Instruction::LocalGet(a), Instruction::I32Const(b)] => {
self.instructions.pop();
self.instructions.pop();
- self.visit(Instruction::I32StoreLocal {
+ self.instructions.push(Instruction::I32StoreLocal {
local: a,
const_i32: b,
offset: arg.offset as u32,
mem_addr: arg.mem_addr as u8,
})
}
- _ => self.visit(i32store),
+ _ => self.instructions.push(i32store),
}
}
- #[inline(always)]
fn visit_local_get(&mut self, idx: u32) -> Self::Output {
- let Some(instruction) = self.instructions.last_mut() else {
- return self.visit(Instruction::LocalGet(idx));
- };
-
+ if self.instructions.is_empty() {
+ return self.instructions.push(Instruction::LocalGet(idx));
+ }
+ let instruction = self.instructions.last_mut().unwrap();
match instruction {
Instruction::LocalGet(a) => *instruction = Instruction::LocalGet2(*a, idx),
Instruction::LocalGet2(a, b) => *instruction = Instruction::LocalGet3(*a, *b, idx),
Instruction::LocalTee(a) => *instruction = Instruction::LocalTeeGet(*a, idx),
- _ => return self.visit(Instruction::LocalGet(idx)),
+ _ => self.instructions.push(Instruction::LocalGet(idx)),
};
-
- Ok(())
}
- #[inline(always)]
- fn visit_local_set(&mut self, idx: u32) -> Self::Output {
- self.visit(Instruction::LocalSet(idx))
- }
-
- #[inline(always)]
- fn visit_local_tee(&mut self, idx: u32) -> Self::Output {
- self.visit(Instruction::LocalTee(idx))
- }
-
- #[inline(always)]
fn visit_i64_rotl(&mut self) -> Self::Output {
if self.instructions.len() < 2 {
- return self.visit(Instruction::I64Rotl);
+ return self.instructions.push(Instruction::I64Rotl);
}
match self.instructions[self.instructions.len() - 2..] {
[Instruction::I64Xor, Instruction::I64Const(a)] => {
self.instructions.pop();
self.instructions.pop();
- self.visit(Instruction::I64XorConstRotl(a))
+ self.instructions.push(Instruction::I64XorConstRotl(a))
}
- _ => self.visit(Instruction::I64Rotl),
+ _ => self.instructions.push(Instruction::I64Rotl),
}
}
- #[inline(always)]
fn visit_i32_add(&mut self) -> Self::Output {
if self.instructions.len() < 2 {
- return self.visit(Instruction::I32Add);
+ return self.instructions.push(Instruction::I32Add);
}
match self.instructions[self.instructions.len() - 2..] {
[Instruction::LocalGet(a), Instruction::I32Const(b)] => {
self.instructions.pop();
self.instructions.pop();
- self.visit(Instruction::I32LocalGetConstAdd(a, b))
+ self.instructions.push(Instruction::I32LocalGetConstAdd(a, b))
}
- _ => self.visit(Instruction::I32Add),
+ _ => self.instructions.push(Instruction::I32Add),
}
}
- #[inline(always)]
fn visit_block(&mut self, blockty: wasmparser::BlockType) -> Self::Output {
self.label_ptrs.push(self.instructions.len());
- self.visit(Instruction::Block(convert_blocktype(blockty), 0))
+ self.instructions.push(Instruction::Block(convert_blocktype(blockty), 0))
}
- #[inline(always)]
fn visit_loop(&mut self, ty: wasmparser::BlockType) -> Self::Output {
self.label_ptrs.push(self.instructions.len());
- self.visit(Instruction::Loop(convert_blocktype(ty), 0))
+ self.instructions.push(Instruction::Loop(convert_blocktype(ty), 0))
}
- #[inline(always)]
fn visit_if(&mut self, ty: wasmparser::BlockType) -> Self::Output {
self.label_ptrs.push(self.instructions.len());
- self.visit(Instruction::If(convert_blocktype(ty).into(), 0, 0))
+ self.instructions.push(Instruction::If(convert_blocktype(ty).into(), 0, 0))
}
- #[inline(always)]
fn visit_else(&mut self) -> Self::Output {
self.label_ptrs.push(self.instructions.len());
- self.visit(Instruction::Else(0))
+ self.instructions.push(Instruction::Else(0))
}
- #[inline(always)]
fn visit_end(&mut self) -> Self::Output {
let Some(label_pointer) = self.label_ptrs.pop() else {
- return self.visit(Instruction::Return);
+ return self.instructions.push(Instruction::Return);
};
let current_instr_ptr = self.instructions.len();
@@ -444,19 +408,22 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
.try_into()
.expect("else_instr_end_offset is too large, tinywasm does not support if blocks that large");
- #[cold]
- fn error() -> crate::ParseError {
- crate::ParseError::UnsupportedOperator(
- "Expected to end an if block, but the last label was not an if".to_string(),
- )
- }
-
// since we're ending an else block, we need to end the if block as well
- let if_label_pointer = self.label_ptrs.pop().ok_or_else(error)?;
+ let Some(if_label_pointer) = self.label_ptrs.pop() else {
+ self.errors.push(crate::ParseError::UnsupportedOperator(
+ "Expected to end an if block, but there was no if block to end".to_string(),
+ ));
+
+ return;
+ };
let if_instruction = &mut self.instructions[if_label_pointer];
let Instruction::If(_, else_offset, end_offset) = if_instruction else {
- return Err(error());
+ self.errors.push(crate::ParseError::UnsupportedOperator(
+ "Expected to end an if block, but the last label was not an if".to_string(),
+ ));
+
+ return;
};
*else_offset = (label_pointer - if_label_pointer)
@@ -479,10 +446,9 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
}
};
- self.visit(Instruction::EndBlockFrame)
+ self.instructions.push(Instruction::EndBlockFrame)
}
- #[inline(always)]
fn visit_br_table(&mut self, targets: wasmparser::BrTable<'_>) -> Self::Output {
let def = targets.default();
let instrs = targets
@@ -492,37 +458,18 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
.expect("BrTable targets are invalid, this should have been caught by the validator");
self.instructions.extend(([Instruction::BrTable(def, instrs.len() as u32)].into_iter()).chain(instrs));
- Ok(())
- }
-
- #[inline(always)]
- fn visit_call(&mut self, idx: u32) -> Self::Output {
- self.visit(Instruction::Call(idx))
}
- #[inline(always)]
fn visit_call_indirect(&mut self, ty: u32, table: u32, _table_byte: u8) -> Self::Output {
- self.visit(Instruction::CallIndirect(ty, table))
+ self.instructions.push(Instruction::CallIndirect(ty, table))
}
- #[inline(always)]
- fn visit_memory_size(&mut self, mem: u32, mem_byte: u8) -> Self::Output {
- self.visit(Instruction::MemorySize(mem, mem_byte))
- }
-
- #[inline(always)]
- fn visit_memory_grow(&mut self, mem: u32, mem_byte: u8) -> Self::Output {
- self.visit(Instruction::MemoryGrow(mem, mem_byte))
- }
-
- #[inline(always)]
fn visit_f32_const(&mut self, val: wasmparser::Ieee32) -> Self::Output {
- self.visit(Instruction::F32Const(f32::from_bits(val.bits())))
+ self.instructions.push(Instruction::F32Const(f32::from_bits(val.bits())))
}
- #[inline(always)]
fn visit_f64_const(&mut self, val: wasmparser::Ieee64) -> Self::Output {
- self.visit(Instruction::F64Const(f64::from_bits(val.bits())))
+ self.instructions.push(Instruction::F64Const(f64::from_bits(val.bits())))
}
// Bulk Memory Operations
@@ -538,26 +485,21 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
visit_elem_drop, Instruction::ElemDrop, u32
}
- #[inline(always)]
fn visit_table_copy(&mut self, dst_table: u32, src_table: u32) -> Self::Output {
- self.visit(Instruction::TableCopy { from: src_table, to: dst_table })
+ self.instructions.push(Instruction::TableCopy { from: src_table, to: dst_table })
}
// Reference Types
-
- #[inline(always)]
fn visit_ref_null(&mut self, ty: wasmparser::HeapType) -> Self::Output {
- self.visit(Instruction::RefNull(convert_heaptype(ty)))
+ self.instructions.push(Instruction::RefNull(convert_heaptype(ty)))
}
- #[inline(always)]
fn visit_ref_is_null(&mut self) -> Self::Output {
- self.visit(Instruction::RefIsNull)
+ self.instructions.push(Instruction::RefIsNull)
}
- #[inline(always)]
fn visit_typed_select(&mut self, ty: wasmparser::ValType) -> Self::Output {
- self.visit(Instruction::Select(Some(convert_valtype(&ty))))
+ self.instructions.push(Instruction::Select(Some(convert_valtype(&ty))))
}
define_primitive_operands! {