From a0368bc39ac620b867a105ca0c9bc12824abcd9d Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Sat, 24 Feb 2024 22:16:10 +0100 Subject: feat: switch to own fork of wasmparser Signed-off-by: Henry Gressmann --- crates/parser/src/conversion.rs | 76 +++++++++++++++++++++++++++++------------ crates/parser/src/lib.rs | 34 ++++++++++++++++-- 2 files changed, 86 insertions(+), 24 deletions(-) (limited to 'crates/parser/src') diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index 68567f3..f81b9e7 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -15,26 +15,34 @@ pub(crate) fn convert_module_elements<'a, T: IntoIterator) -> Result { let kind = match element.kind { wasmparser::ElementKind::Active { table_index, offset_expr } => tinywasm_types::ElementKind::Active { - table: table_index, + table: table_index.unwrap_or(0), offset: process_const_operators(offset_expr.get_operators_reader())?, }, wasmparser::ElementKind::Passive => tinywasm_types::ElementKind::Passive, wasmparser::ElementKind::Declared => tinywasm_types::ElementKind::Declared, }; - let items = match element.items { + match element.items { wasmparser::ElementItems::Functions(funcs) => { - funcs.into_iter().map(|func| Ok(ElementItem::Func(func?))).collect::>>()?.into_boxed_slice() + let items = funcs + .into_iter() + .map(|func| Ok(ElementItem::Func(func?))) + .collect::>>()? + .into_boxed_slice(); + + Ok(tinywasm_types::Element { kind, items, ty: ValType::RefFunc, range: element.range }) } - wasmparser::ElementItems::Expressions(exprs) => exprs - .into_iter() - .map(|expr| Ok(ElementItem::Expr(process_const_operators(expr?.get_operators_reader())?))) - .collect::>>()? - .into_boxed_slice(), - }; + wasmparser::ElementItems::Expressions(ty, exprs) => { + let items = exprs + .into_iter() + .map(|expr| Ok(ElementItem::Expr(process_const_operators(expr?.get_operators_reader())?))) + .collect::>>()? + .into_boxed_slice(); - Ok(tinywasm_types::Element { kind, items, ty: convert_valtype(&element.ty), range: element.range }) + Ok(tinywasm_types::Element { kind, items, ty: convert_reftype(&ty), range: element.range }) + } + } } pub(crate) fn convert_module_data_sections<'a, T: IntoIterator>>>( @@ -71,7 +79,11 @@ pub(crate) fn convert_module_import(import: wasmparser::Import<'_>) -> Result ImportKind::Function(ty), - wasmparser::TypeRef::Table(ty) => ImportKind::Table(convert_module_table(ty)?), + wasmparser::TypeRef::Table(ty) => ImportKind::Table(TableType { + element_type: convert_reftype(&ty.element_type), + size_initial: ty.initial, + size_max: ty.maximum, + }), wasmparser::TypeRef::Memory(ty) => ImportKind::Memory(convert_module_memory(ty)?), wasmparser::TypeRef::Global(ty) => { ImportKind::Global(GlobalType { mutable: ty.mutable, ty: convert_valtype(&ty.content_type) }) @@ -103,16 +115,16 @@ pub(crate) fn convert_module_memory(memory: wasmparser::MemoryType) -> Result>>( +pub(crate) fn convert_module_tables<'a, T: IntoIterator>>>( table_types: T, ) -> Result> { let table_type = table_types.into_iter().map(|table| convert_module_table(table?)).collect::>>()?; Ok(table_type) } -pub(crate) fn convert_module_table(table: wasmparser::TableType) -> Result { - let ty = convert_valtype(&table.element_type); - Ok(TableType { element_type: ty, size_initial: table.initial, size_max: table.maximum }) +pub(crate) fn convert_module_table(table: wasmparser::Table<'_>) -> Result { + let ty = convert_reftype(&table.ty.element_type); + Ok(TableType { element_type: ty, size_initial: table.ty.initial, size_max: table.ty.maximum }) } pub(crate) fn convert_module_globals<'a, T: IntoIterator>>>( @@ -168,8 +180,15 @@ pub(crate) fn convert_module_code( Ok(CodeSection { locals: locals.into_boxed_slice(), body }) } -pub(crate) fn convert_module_type(ty: wasmparser::Type) -> Result { - let wasmparser::Type::Func(ty) = ty; +pub(crate) fn convert_module_type(ty: wasmparser::RecGroup) -> Result { + let mut types = ty.types(); + + if types.len() != 1 { + return Err(crate::ParseError::UnsupportedOperator( + "Expected exactly one type in the type section".to_string(), + )); + } + let ty = types.next().unwrap().unwrap_func(); let params = ty.params().iter().map(|p| Ok(convert_valtype(p))).collect::>>()?.into_boxed_slice(); @@ -188,6 +207,14 @@ pub(crate) fn convert_blocktype(blocktype: wasmparser::BlockType) -> BlockArgs { } } +pub(crate) fn convert_reftype(reftype: &wasmparser::RefType) -> ValType { + match reftype { + _ if reftype.is_func_ref() => ValType::RefFunc, + _ if reftype.is_extern_ref() => ValType::RefExtern, + _ => unimplemented!("Unsupported reference type: {:?}", reftype), + } +} + pub(crate) fn convert_valtype(valtype: &wasmparser::ValType) -> ValType { use wasmparser::ValType::*; match valtype { @@ -195,9 +222,8 @@ pub(crate) fn convert_valtype(valtype: &wasmparser::ValType) -> ValType { I64 => ValType::I64, F32 => ValType::F32, F64 => ValType::F64, + Ref(r) => convert_reftype(r), V128 => unimplemented!("128-bit values are not supported yet"), - FuncRef => ValType::RefFunc, - ExternRef => ValType::RefExtern, } } @@ -217,7 +243,7 @@ pub(crate) fn process_const_operators(ops: OperatorsReader<'_>) -> Result) -> Result { match op { - wasmparser::Operator::RefNull { ty } => Ok(ConstInstruction::RefNull(convert_valtype(&ty))), + wasmparser::Operator::RefNull { hty } => Ok(ConstInstruction::RefNull(convert_heaptype(hty))), wasmparser::Operator::RefFunc { function_index } => Ok(ConstInstruction::RefFunc(function_index)), wasmparser::Operator::I32Const { value } => Ok(ConstInstruction::I32Const(value)), wasmparser::Operator::I64Const { value } => Ok(ConstInstruction::I64Const(value)), @@ -228,6 +254,14 @@ pub(crate) fn process_const_operator(op: wasmparser::Operator<'_>) -> Result ValType { + match heap { + wasmparser::HeapType::Func => ValType::RefFunc, + wasmparser::HeapType::Extern => ValType::RefExtern, + _ => unimplemented!("Unsupported heap type: {:?}", heap), + } +} + pub(crate) fn process_operators( ops: OperatorsReader<'_>, mut validator: FuncValidator, @@ -357,7 +391,7 @@ pub(crate) fn process_operators( I64Const { value } => Instruction::I64Const(value), F32Const { value } => Instruction::F32Const(f32::from_bits(value.bits())), F64Const { value } => Instruction::F64Const(f64::from_bits(value.bits())), - RefNull { ty } => Instruction::RefNull(convert_valtype(&ty)), + RefNull { hty } => Instruction::RefNull(convert_heaptype(hty)), RefIsNull => Instruction::RefIsNull, RefFunc { function_index } => Instruction::RefFunc(function_index), I32Load { memarg } => Instruction::I32Load(convert_memarg(memarg)), diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 8cc34db..72b3f81 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -32,7 +32,7 @@ use alloc::{string::ToString, vec::Vec}; pub use error::*; use module::ModuleReader; use tinywasm_types::{TypedWasmFunction, WasmFunction}; -use wasmparser::Validator; +use wasmparser::{Validator, WasmFeatures}; pub use tinywasm_types::TinyWasmModule; @@ -46,10 +46,38 @@ impl Parser { Self {} } + fn create_validator(&self) -> Validator { + let features = WasmFeatures { + bulk_memory: true, + floats: true, + function_references: true, + multi_value: true, + mutable_global: true, + reference_types: true, + sign_extension: true, + saturating_float_to_int: true, + + component_model: false, + component_model_nested_names: false, + component_model_values: false, + exceptions: false, + extended_const: false, + gc: false, + memory64: false, + memory_control: false, + relaxed_simd: false, + simd: false, + tail_call: false, + threads: false, + multi_memory: false, // should be working mostly + }; + Validator::new_with_features(features) + } + /// Parse a [`TinyWasmModule`] from bytes pub fn parse_module_bytes(&self, wasm: impl AsRef<[u8]>) -> Result { let wasm = wasm.as_ref(); - let mut validator = Validator::new(); + let mut validator = self.create_validator(); let mut reader = ModuleReader::new(); for payload in wasmparser::Parser::new(0).parse_all(wasm) { @@ -79,7 +107,7 @@ impl Parser { pub fn parse_module_stream(&self, mut stream: impl std::io::Read) -> Result { use alloc::format; - let mut validator = Validator::new(); + let mut validator = self.create_validator(); let mut reader = ModuleReader::new(); let mut buffer = Vec::new(); let mut parser = wasmparser::Parser::new(0); -- cgit v1.3.1