From c0b356b025ef93eb3c1378c203858c3a7486f398 Mon Sep 17 00:00:00 2001 From: Henry Date: Mon, 4 May 2026 19:25:22 +0200 Subject: chore: simplify parser & reduce allocations Signed-off-by: Henry --- crates/parser/build.rs | 4 +- crates/parser/src/conversion.rs | 51 +++------- crates/parser/src/macros.rs | 87 ++---------------- crates/parser/src/module.rs | 199 ++++++++++++++++++---------------------- crates/parser/src/parallel.rs | 6 +- crates/parser/src/visit.rs | 18 ++-- 6 files changed, 127 insertions(+), 238 deletions(-) (limited to 'crates') diff --git a/crates/parser/build.rs b/crates/parser/build.rs index d5c6dec..6b3f385 100644 --- a/crates/parser/build.rs +++ b/crates/parser/build.rs @@ -3,7 +3,7 @@ use std::env; fn main() { println!("cargo::rustc-check-cfg=cfg(parallel_parser)"); - if env::var("CARGO_FEATURE_PARALLEL").is_err() { + if env::var_os("CARGO_FEATURE_PARALLEL").is_none() { return; } @@ -11,6 +11,6 @@ fn main() { let os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default(); if !arch.starts_with("wasm") && os != "unknown" && os != "none" { - println!("cargo:rustc-cfg=parallel_parser"); + println!("cargo::rustc-cfg=parallel_parser"); } } diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index fea43ba..4561974 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -3,13 +3,10 @@ use alloc::sync::Arc; use crate::{Result, module::FunctionCode, visit::process_operators_and_validate}; use alloc::{boxed::Box, format, string::ToString, vec::Vec}; use tinywasm_types::*; -use wasmparser::{CompositeInnerType, FuncValidator, FuncValidatorAllocations, OperatorsReader, ValidatorResources}; - -pub(crate) fn convert_module_elements<'a, T: IntoIterator>>>( - elements: T, -) -> Result> { - elements.into_iter().map(|element| convert_module_element(element?)).collect::>>() -} +use wasmparser::{ + CompositeInnerType, FuncValidator, FuncValidatorAllocations, OperatorsReader, OperatorsReaderAllocations, + ValidatorResources, +}; pub(crate) fn convert_module_element(element: wasmparser::Element<'_>) -> Result { let kind = match element.kind { @@ -44,12 +41,6 @@ pub(crate) fn convert_module_element(element: wasmparser::Element<'_>) -> Result } } -pub(crate) fn convert_module_data_sections<'a, T: IntoIterator>>>( - data_sections: T, -) -> Result> { - data_sections.into_iter().map(|data| convert_module_data(data?)).collect::>>() -} - pub(crate) fn convert_module_data(data: wasmparser::Data<'_>) -> Result { Ok(tinywasm_types::Data { data: data.data.to_vec().into_boxed_slice(), @@ -64,12 +55,6 @@ pub(crate) fn convert_module_data(data: wasmparser::Data<'_>) -> Result>>>( - imports: T, -) -> Result> { - imports.into_iter().map(|import| convert_module_import(import?)).collect::>>() -} - pub(crate) fn convert_module_import(import: wasmparser::Import<'_>) -> Result { let kind = match import.ty { wasmparser::TypeRef::Func(ty) => ImportKind::Function(ty), @@ -100,12 +85,6 @@ pub(crate) fn convert_module_import(import: wasmparser::Import<'_>) -> Result>>( - memory_types: T, -) -> Result> { - memory_types.into_iter().map(|memory| Ok(convert_module_memory(memory?))).collect::>>() -} - pub(crate) fn convert_module_memory(memory: wasmparser::MemoryType) -> MemoryType { MemoryType::new( if memory.memory64 { MemoryArch::I64 } else { MemoryArch::I32 }, @@ -115,12 +94,6 @@ pub(crate) fn convert_module_memory(memory: wasmparser::MemoryType) -> MemoryTyp ) } -pub(crate) fn convert_module_tables<'a, T: IntoIterator>>>( - table_types: T, -) -> Result> { - table_types.into_iter().map(|table| convert_module_table(table?)).collect::>>() -} - pub(crate) fn convert_module_table(table: wasmparser::Table<'_>) -> Result { let size_initial = table.ty.initial.try_into().map_err(|_| { crate::ParseError::UnsupportedOperator(format!("Table size initial is too large: {}", table.ty.initial)) @@ -134,7 +107,7 @@ pub(crate) fn convert_module_table(table: wasmparser::Table<'_>) -> Result>, -) -> Result> { +) -> Result> { globals .into_iter() .map(|global| { @@ -143,7 +116,7 @@ pub(crate) fn convert_module_globals( let ops = global.init_expr.get_operators_reader(); Ok(Global { init: process_const_operators(ops)?, ty: GlobalType::new(ty, global.ty.mutable) }) }) - .collect::>>() + .collect::>>() } pub(crate) fn convert_module_export(export: wasmparser::Export<'_>) -> Result { @@ -163,7 +136,8 @@ pub(crate) fn convert_module_export(export: wasmparser::Export<'_>) -> Result, mut validator: FuncValidator, -) -> Result<(FunctionCode, FuncValidatorAllocations)> { + reader_allocs: OperatorsReaderAllocations, +) -> Result<(FunctionCode, FuncValidatorAllocations, OperatorsReaderAllocations)> { let locals_reader = func.get_locals_reader()?; let count = locals_reader.get_count(); let pos = locals_reader.original_position(); @@ -199,8 +173,13 @@ pub(crate) fn convert_module_code( } } - let (body, data, allocations) = process_operators_and_validate(validator, func, local_addr_map)?; - Ok((FunctionCode { instructions: body, data, locals: local_counts, uses_local_memory: false }, allocations)) + let (body, data, validator_allocs, reader_allocs) = + process_operators_and_validate(validator, func, local_addr_map, reader_allocs)?; + Ok(( + FunctionCode { instructions: body, data, locals: local_counts, uses_local_memory: false }, + validator_allocs, + reader_allocs, + )) } pub(crate) fn convert_module_type(ty: wasmparser::RecGroup) -> Result> { diff --git a/crates/parser/src/macros.rs b/crates/parser/src/macros.rs index dded6d8..b21c1e8 100644 --- a/crates/parser/src/macros.rs +++ b/crates/parser/src/macros.rs @@ -1,94 +1,19 @@ pub(crate) mod visit { macro_rules! validate_then_visit { - ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => { - $(validate_then_visit!(@@$proposal $op $({ $($arg: $argty),* })? => $visit ($($ann)*));)* - }; - - // These special-case arms exist so we only clone wasmparser's non-Copy payloads - (@@mvp BrTable { $arg:ident: $argty:ty } => $visit:ident ($($ann:tt)*)) => { - fn $visit(&mut self, $arg: $argty) -> Self::Output { - self.0.$visit($arg.clone()); - let validation = self.0.validator.visitor(self.0.position).$visit($arg); - if let Err(e) = validation { - cold_path(); - self.0.record_error(crate::ParseError::ParseError { message: e.to_string(), offset: self.0.position }); - } - } - }; - - (@@reference_types TypedSelectMulti { $arg:ident: $argty:ty } => $visit:ident ($($ann:tt)*)) => { - fn $visit(&mut self, $arg: $argty) -> Self::Output { - self.0.$visit($arg.clone()); - let validation = self.0.validator.visitor(self.0.position).$visit($arg); - if let Err(e) = validation { - cold_path(); - self.0.record_error(crate::ParseError::ParseError { message: e.to_string(), offset: self.0.position }); - } - } - }; - - (@@exceptions TryTable { $arg:ident: $argty:ty } => $visit:ident ($($ann:tt)*)) => { - fn $visit(&mut self, $arg: $argty) -> Self::Output { - self.0.$visit($arg.clone()); - let validation = self.0.validator.visitor(self.0.position).$visit($arg); - if let Err(e) = validation { - cold_path(); - self.0.record_error(crate::ParseError::ParseError { message: e.to_string(), offset: self.0.position }); - } - } - }; - - (@@stack_switching Resume { cont_type_index: $cont:ty, resume_table: $table:ty } => $visit:ident ($($ann:tt)*)) => { - fn $visit(&mut self, cont_type_index: $cont, resume_table: $table) -> Self::Output { - self.0.$visit(cont_type_index, resume_table.clone()); - let validation = self.0.validator.visitor(self.0.position).$visit(cont_type_index, resume_table); - if let Err(e) = validation { - cold_path(); - self.0.record_error(crate::ParseError::ParseError { message: e.to_string(), offset: self.0.position }); - } - } - }; - - (@@stack_switching ResumeThrow { cont_type_index: $cont:ty, tag_index: $tag:ty, resume_table: $table:ty } => $visit:ident ($($ann:tt)*)) => { - fn $visit(&mut self, cont_type_index: $cont, tag_index: $tag, resume_table: $table) -> Self::Output { - self.0.$visit(cont_type_index, tag_index, resume_table.clone()); - let validation = self.0.validator.visitor(self.0.position).$visit(cont_type_index, tag_index, resume_table); - if let Err(e) = validation { - cold_path(); - self.0.record_error(crate::ParseError::ParseError { message: e.to_string(), offset: self.0.position }); - } - } - }; - - (@@stack_switching ResumeThrowRef { cont_type_index: $cont:ty, resume_table: $table:ty } => $visit:ident ($($ann:tt)*)) => { - fn $visit(&mut self, cont_type_index: $cont, resume_table: $table) -> Self::Output { - self.0.$visit(cont_type_index, resume_table.clone()); - let validation = self.0.validator.visitor(self.0.position).$visit(cont_type_index, resume_table); - if let Err(e) = validation { - cold_path(); - self.0.record_error(crate::ParseError::ParseError { message: e.to_string(), offset: self.0.position }); - } - } - }; - - (@@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*)) => { + ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {$( fn $visit(&mut self $($(,$arg: $argty)*)?) -> Self::Output { - self.0.$visit($($($arg),*)?); + self.0.$visit($($($arg.clone()),*)?); let validation = self.0.validator.visitor(self.0.position).$visit($($($arg),*)?); if let Err(e) = validation { cold_path(); self.0.record_error(crate::ParseError::ParseError { message: e.to_string(), offset: self.0.position }); } } - }; + )*}; } macro_rules! validate_then_visit_simd { - ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => { - $(validate_then_visit_simd!(@@$proposal $op $({ $($arg: $argty),* })? => $visit ($($ann)*));)* - }; - - (@@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*)) => { + ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {$( fn $visit(&mut self $($(,$arg: $argty)*)?) -> Self::Output { self.0.$visit($($($arg),*)?); let validation = self.0.validator.simd_visitor(self.0.position).$visit($($($arg),*)?); @@ -97,7 +22,7 @@ pub(crate) mod visit { self.0.record_error(crate::ParseError::ParseError { message: e.to_string(), offset: self.0.position }); } } - }; + )*}; } macro_rules! define_operand { @@ -166,7 +91,7 @@ pub(crate) mod visit { (@@tail_call $($rest:tt)* ) => {}; (@@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*)) => { - fn $visit(&mut self $($(,_: $argty)*)?) { + fn $visit(&mut self $($(,_: $argty)*)?) -> Self::Output { self.unsupported(stringify!($visit)) } }; diff --git a/crates/parser/src/module.rs b/crates/parser/src/module.rs index 5f5e5e2..fab6258 100644 --- a/crates/parser/src/module.rs +++ b/crates/parser/src/module.rs @@ -1,11 +1,11 @@ use crate::log::debug; -use crate::{ParseError, ParserOptions, Result, conversion, optimize}; +use crate::{ParseError, ParserOptions, Result, conversion::*, optimize}; use alloc::sync::Arc; -use alloc::{format, string::ToString, vec::Vec}; +use alloc::{boxed::Box, format, string::ToString, vec::Vec}; use core::marker::PhantomData; use core::ops::Range; use tinywasm_types::*; -use wasmparser::{FuncValidatorAllocations, Payload, Validator}; +use wasmparser::{FuncValidatorAllocations, OperatorsReaderAllocations, Payload, Validator}; pub(crate) struct FunctionCode { pub instructions: Vec, @@ -46,21 +46,23 @@ pub(crate) fn optimize_function_code( #[derive(Default)] pub(crate) struct ModuleReader<'a> { func_validator_allocations: Option, + operators_reader_allocations: Option, + has_code_section: bool, marker: PhantomData<&'a [u8]>, pub(crate) version: Option, pub(crate) start_func: Option, - pub(crate) func_types: Vec>, - pub(crate) code_type_addrs: Vec, - pub(crate) exports: Vec, + pub(crate) func_types: Arc<[Arc]>, + pub(crate) code_type_addrs: Box<[u32]>, + pub(crate) exports: Arc<[Export]>, pub(crate) code: Vec, - pub(crate) globals: Vec, - pub(crate) table_types: Vec, - pub(crate) memory_types: Vec, - pub(crate) imports: Vec, - pub(crate) data: Vec, - pub(crate) elements: Vec, + pub(crate) globals: Box<[Global]>, + pub(crate) table_types: Box<[TableType]>, + pub(crate) memory_types: Box<[MemoryType]>, + pub(crate) imports: Box<[Import]>, + pub(crate) data: Box<[Data]>, + pub(crate) elements: Box<[Element]>, pub(crate) end_reached: bool, #[cfg(parallel_parser)] @@ -75,6 +77,14 @@ impl<'a> ModuleReader<'a> { } pub(crate) fn process_payload(&mut self, payload: Payload<'_>, validator: &mut Validator) -> Result<()> { + fn check_section(section: &str, duplicate: bool) -> Result<()> { + debug!("found {section} section"); + if duplicate { + return Err(ParseError::DuplicateSection(format!("{section} section"))); + } + Ok(()) + } + match payload { Payload::Version { num, encoding, range } => { validator.version(num, encoding, &range)?; @@ -84,99 +94,65 @@ impl<'a> ModuleReader<'a> { } } Payload::StartSection { func, range } => { - if self.start_func.is_some() { - return Err(ParseError::DuplicateSection("Start section".into())); - } - - debug!("Found start section"); + check_section("start", self.start_func.is_some())?; validator.start_section(func, &range)?; self.start_func = Some(func); } Payload::TypeSection(reader) => { - if !self.func_types.is_empty() { - return Err(ParseError::DuplicateSection("Type section".into())); - } - - debug!("Found type section"); + check_section("type", !self.func_types.is_empty())?; validator.type_section(&reader)?; - self.func_types = - reader.into_iter().map(|t| conversion::convert_module_type(t?)).collect::>>()?; + self.func_types = reader.into_iter().map(|t| convert_module_type(t?)).collect::>()?; } Payload::GlobalSection(reader) => { - if !self.globals.is_empty() { - return Err(ParseError::DuplicateSection("Global section".into())); - } - - debug!("Found global section"); + check_section("global", !self.globals.is_empty())?; validator.global_section(&reader)?; - self.globals = conversion::convert_module_globals(reader)?; + self.globals = convert_module_globals(reader)?; } Payload::TableSection(reader) => { - if !self.table_types.is_empty() { - return Err(ParseError::DuplicateSection("Table section".into())); - } - - debug!("Found table section"); + check_section("table", !self.table_types.is_empty())?; validator.table_section(&reader)?; - self.table_types = conversion::convert_module_tables(reader)?; + self.table_types = + reader.into_iter().map(|table| convert_module_table(table?)).collect::>()?; } Payload::MemorySection(reader) => { - if !self.memory_types.is_empty() { - return Err(ParseError::DuplicateSection("Memory section".into())); - } - - debug!("Found memory section"); + check_section("memory", !self.memory_types.is_empty())?; validator.memory_section(&reader)?; - self.memory_types = conversion::convert_module_memories(reader)?; + self.memory_types = + reader.into_iter().map(|memory| Ok(convert_module_memory(memory?))).collect::>()?; } Payload::ElementSection(reader) => { debug!("Found element section"); validator.element_section(&reader)?; - self.elements = conversion::convert_module_elements(reader)?; + self.elements = + reader.into_iter().map(|element| convert_module_element(element?)).collect::>()?; } Payload::DataSection(reader) => { - if !self.data.is_empty() { - return Err(ParseError::DuplicateSection("Data section".into())); - } - - debug!("Found data section"); + check_section("data", !self.data.is_empty())?; validator.data_section(&reader)?; - self.data = conversion::convert_module_data_sections(reader)?; + self.data = reader.into_iter().map(|data| convert_module_data(data?)).collect::>()?; } Payload::DataCountSection { count, range } => { debug!("Found data count section"); if !self.data.is_empty() { - return Err(ParseError::DuplicateSection("Data count section".into())); + return Err(ParseError::UnsupportedSection("Data count section after data section".into())); } validator.data_count_section(count, &range)?; } Payload::FunctionSection(reader) => { - if !self.code_type_addrs.is_empty() { - return Err(ParseError::DuplicateSection("Function section".into())); - } - - debug!("Found function section"); + check_section("function", !self.code_type_addrs.is_empty())?; validator.function_section(&reader)?; - self.code_type_addrs = reader.into_iter().map(|f| Ok(f?)).collect::>>()?; + self.code_type_addrs = reader.into_iter().map(|f| Ok(f?)).collect::>()?; } Payload::ImportSection(reader) => { - if !self.imports.is_empty() { - return Err(ParseError::DuplicateSection("Import section".into())); - } - - debug!("Found import section"); + check_section("import", !self.imports.is_empty())?; validator.import_section(&reader)?; - self.imports = conversion::convert_module_imports(reader.into_imports())?; + self.imports = + reader.into_imports().map(|import| convert_module_import(import?)).collect::>()?; } Payload::ExportSection(reader) => { - if !self.exports.is_empty() { - return Err(ParseError::DuplicateSection("Export section".into())); - } - - debug!("Found export section"); + check_section("export", !self.exports.is_empty())?; validator.export_section(&reader)?; - self.exports = - reader.into_iter().map(|e| conversion::convert_module_export(e?)).collect::>>()?; + self.exports = reader.into_iter().map(|e| convert_module_export(e?)).collect::>()?; } Payload::End(offset) => { debug!("Reached end of module"); @@ -192,7 +168,7 @@ impl<'a> ModuleReader<'a> { debug!("Skipping custom section: {:?}", _reader.name()); } Payload::CodeSectionStart { .. } | Payload::CodeSectionEntry(_) => { - return Err(ParseError::Other("code section payload handled separately".into())); + unreachable!("code section payload handled separately") } Payload::UnknownSection { .. } => return Err(ParseError::UnsupportedSection("Unknown section".into())), section => return Err(ParseError::UnsupportedSection(format!("Unsupported section: {section:?}"))), @@ -242,20 +218,26 @@ impl<'a> ModuleReader<'a> { options: &ParserOptions, ) -> Result<()> { debug!("Found code section entry"); - let ordinal = self.code.len(); + + let func_validator_allocs = self.func_validator_allocations.take().unwrap_or_default(); + let operators_reader_allocs = self.operators_reader_allocations.take().unwrap_or_default(); + let func_to_validate = validator.code_section_entry(&function)?; - let func_validator = - func_to_validate.into_validator(self.func_validator_allocations.take().unwrap_or_default()); - let (code, allocations) = conversion::convert_module_code(function, func_validator)?; - let code = optimize_function_code( + let func_validator = func_to_validate.into_validator(func_validator_allocs); + + let (code, func_validator_allocs, operators_reader_allocs) = + convert_module_code(function, func_validator, operators_reader_allocs)?; + + self.code.push(optimize_function_code( code, options, - self.function_results(ordinal), - (imported_func_count(&self.imports) + ordinal) as u32, + self.function_results(self.code.len()), + (imported_func_count(&self.imports) + self.code.len()) as u32, imported_memory_count(&self.imports), - ); - self.code.push(code); - self.func_validator_allocations = Some(allocations); + )); + + self.func_validator_allocations = Some(func_validator_allocs); + self.operators_reader_allocations = Some(operators_reader_allocs); Ok(()) } @@ -376,50 +358,51 @@ impl<'a> ModuleReader<'a> { LocalMemoryAllocation::Skip }; - let mut funcs = Vec::with_capacity(self.code.len()); - let mut func_type_idxs = self + let func_type_idxs = self .imports .iter() .filter_map(|import| match import.kind { ImportKind::Function(type_idx) => Some(type_idx), _ => None, }) - .collect::>(); - func_type_idxs.extend(self.code_type_addrs.iter().copied()); - - for (code, ty_idx) in self.code.into_iter().zip(self.code_type_addrs) { - let ty = self.func_types.get(ty_idx as usize).expect("No func type for func, this is a bug").clone(); - let params = ValueCounts::from_iter(ty.params()); - let results = ValueCounts::from_iter(ty.results()); - if code.uses_local_memory { - local_memory_allocation = LocalMemoryAllocation::Eager; - } + .chain(self.code_type_addrs.iter().copied()) + .collect(); + + let funcs = self + .code + .into_iter() + .zip(self.code_type_addrs) + .map(|(code, ty_idx)| { + let ty = self.func_types.get(ty_idx as usize).expect("No func type for func, this is a bug").clone(); + let params = ValueCounts::from_iter(ty.params()); + let results = ValueCounts::from_iter(ty.results()); + if code.uses_local_memory { + local_memory_allocation = LocalMemoryAllocation::Eager; + } - funcs.push( - WasmFunction { + Arc::new(WasmFunction { instructions: code.instructions.into(), data: code.data, locals: code.locals, params, results, ty, - } - .into(), - ); - } + }) + }) + .collect(); Ok(ModuleInner { - funcs: funcs.into(), - func_types: self.func_types.into(), - func_type_idxs: func_type_idxs.into(), - globals: self.globals.into(), - table_types: self.table_types.into(), - imports: self.imports.into(), + funcs, + func_types: self.func_types, + func_type_idxs, + globals: self.globals, + table_types: self.table_types, + imports: self.imports, start_func: self.start_func, - data: self.data.into(), - exports: self.exports.into(), - elements: self.elements.into(), - memory_types: self.memory_types.into(), + data: self.data, + exports: self.exports, + elements: self.elements, + memory_types: self.memory_types, local_memory_allocation, } .into()) diff --git a/crates/parser/src/parallel.rs b/crates/parser/src/parallel.rs index 778e4ad..4400053 100644 --- a/crates/parser/src/parallel.rs +++ b/crates/parser/src/parallel.rs @@ -66,12 +66,12 @@ fn process_function_job( imported_memory_count: u32, ) -> Result<(usize, FunctionCode)> { let validator = job.func_to_validate.into_validator(FuncValidatorAllocations::default()); - let (code, _allocations) = match job.body { - FunctionBodyInput::Borrowed(func) => conversion::convert_module_code(func, validator)?, + let (code, _, _) = match job.body { + FunctionBodyInput::Borrowed(func) => conversion::convert_module_code(func, validator, Default::default())?, FunctionBodyInput::Owned(body) => { let reader = wasmparser::BinaryReader::new(&body.section_bytes[body.body_range], body.body_offset); let func = wasmparser::FunctionBody::new(reader); - conversion::convert_module_code(func, validator)? + conversion::convert_module_code(func, validator, Default::default())? } }; diff --git a/crates/parser/src/visit.rs b/crates/parser/src/visit.rs index d1612ed..5fddad9 100644 --- a/crates/parser/src/visit.rs +++ b/crates/parser/src/visit.rs @@ -5,8 +5,8 @@ use alloc::string::ToString; use alloc::vec::Vec; use tinywasm_types::{Instruction, MemoryArg, WasmFunctionData}; use wasmparser::{ - FrameKind, FuncValidator, FuncValidatorAllocations, FunctionBody, VisitOperator, VisitSimdOperator, - WasmModuleResources, + FrameKind, FuncValidator, FuncValidatorAllocations, FunctionBody, OperatorsReader, OperatorsReaderAllocations, + VisitOperator, VisitSimdOperator, WasmModuleResources, }; #[derive(Debug, Clone, Copy)] @@ -51,7 +51,6 @@ impl FunctionDataBuilder { } } } - struct ValidateThenVisit<'a, R: WasmModuleResources>(&'a mut FunctionBuilder); fn operand_size(ty: wasmparser::ValType) -> OperandSize { @@ -75,12 +74,14 @@ impl VisitSimdOperator<'_> for ValidateThenVisit<'_, R> wasmparser::for_each_visit_simd_operator!(validate_then_visit_simd); } -pub(crate) fn process_operators_and_validate( - validator: FuncValidator, +pub(crate) fn process_operators_and_validate( + validator: FuncValidator, body: FunctionBody<'_>, local_addr_map: Vec, -) -> Result<(Vec, WasmFunctionData, FuncValidatorAllocations)> { - let mut reader = body.get_operators_reader()?; + allocs: OperatorsReaderAllocations, +) -> Result<(Vec, WasmFunctionData, FuncValidatorAllocations, OperatorsReaderAllocations)> { + let reader = body.get_binary_reader_for_operators()?; + let mut reader = OperatorsReader::new_with_allocs(reader, allocs); let mut builder = FunctionBuilder::new(validator, local_addr_map); while !reader.eof() { @@ -92,11 +93,12 @@ pub(crate) fn process_operators_and_validate( } reader.finish()?; + if let Some(error) = builder.error { return Err(error); } - Ok((builder.instructions, builder.data.finish(), builder.validator.into_allocations())) + Ok((builder.instructions, builder.data.finish(), builder.validator.into_allocations(), reader.into_allocations())) } pub(crate) struct FunctionBuilder { -- cgit v1.3.1