diff options
| author | Henry <mail@henrygressmann.de> | 2023-12-22 00:03:03 +0100 |
|---|---|---|
| committer | Henry <mail@henrygressmann.de> | 2023-12-22 00:03:03 +0100 |
| commit | 295a48c57672b3e7109c1d650313a00e15a6c01d (patch) | |
| tree | 419a73091059fa16d8c914432d08315beeefb02a /crates/parser/src | |
| parent | fcb92cab9a440931ebc90dfdb94974084d5e066b (diff) | |
feat: improve parser
Signed-off-by: Henry <mail@henrygressmann.de>
Diffstat (limited to 'crates/parser/src')
| -rw-r--r-- | crates/parser/src/conversion.rs | 62 | ||||
| -rw-r--r-- | crates/parser/src/lib.rs | 2 | ||||
| -rw-r--r-- | crates/parser/src/module.rs | 52 |
3 files changed, 91 insertions, 25 deletions
diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index e3dffbc..7d3215d 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -4,10 +4,40 @@ use tinywasm_types::{ BlockArgs, ConstInstruction, Export, ExternalKind, FuncType, Global, GlobalType, Import, ImportKind, Instruction, MemArg, MemoryArch, MemoryType, TableType, ValType, }; -use wasmparser::{FuncValidator, ValidatorResources}; +use wasmparser::{FuncValidator, OperatorsReader, ValidatorResources}; use crate::{module::CodeSection, Result}; +pub(crate) fn convert_module_data_sections<'a, T: IntoIterator<Item = wasmparser::Result<wasmparser::Data<'a>>>>( + data_sections: T, +) -> Result<Vec<tinywasm_types::Data>> { + let data_sections = data_sections + .into_iter() + .map(|data| convert_module_data(data?)) + .collect::<Result<Vec<_>>>()?; + Ok(data_sections) +} + +pub(crate) fn convert_module_data(data: wasmparser::Data<'_>) -> Result<tinywasm_types::Data> { + Ok(tinywasm_types::Data { + data: data.data.to_vec().into_boxed_slice(), + range: data.range, + kind: match data.kind { + wasmparser::DataKind::Active { + memory_index, + offset_expr, + } => { + let offset = process_const_operators(offset_expr.get_operators_reader())?; + tinywasm_types::DataKind::Active { + mem: memory_index, + offset, + } + } + wasmparser::DataKind::Passive => tinywasm_types::DataKind::Passive, + }, + }) +} + pub(crate) fn convert_module_imports<'a, T: IntoIterator<Item = wasmparser::Result<wasmparser::Import<'a>>>>( imports: T, ) -> Result<Vec<Import>> { @@ -20,8 +50,8 @@ pub(crate) fn convert_module_imports<'a, T: IntoIterator<Item = wasmparser::Resu pub(crate) fn convert_module_import(import: wasmparser::Import<'_>) -> Result<Import> { Ok(Import { - module: import.module.to_string(), - name: import.name.to_string(), + module: import.module.to_string().into_boxed_str(), + name: import.name.to_string().into_boxed_str(), kind: match import.ty { wasmparser::TypeRef::Func(ty) => ImportKind::Func(ty), wasmparser::TypeRef::Table(ty) => ImportKind::Table(convert_module_table(ty)?), @@ -90,21 +120,10 @@ pub(crate) fn convert_module_globals<'a, T: IntoIterator<Item = wasmparser::Resu .map(|global| { let global = global?; let ty = convert_valtype(&global.ty.content_type); - - let ops = global - .init_expr - .get_operators_reader() - .into_iter() - .collect::<wasmparser::Result<Vec<_>>>()?; - - // In practice, the len can never be something other than 2, - // but we'll keep this here since it's part of the spec - // Invalid modules will be rejected by the validator anyway (there are also tests for this in the testsuite) - assert!(ops.len() >= 2); - assert!(matches!(ops[ops.len() - 1], wasmparser::Operator::End)); + let ops = global.init_expr.get_operators_reader(); Ok(Global { - init: process_const_operator(ops[ops.len() - 2].clone())?, + init: process_const_operators(ops)?, ty: GlobalType { mutable: global.ty.mutable, ty, @@ -215,6 +234,17 @@ pub(crate) fn convert_memarg(memarg: wasmparser::MemArg) -> MemArg { } } +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, + // but we'll keep this here since it's part of the spec + // Invalid modules will be rejected by the validator anyway (there are also tests for this in the testsuite) + assert!(ops.len() >= 2); + assert!(matches!(ops[ops.len() - 1], wasmparser::Operator::End)); + + Ok(process_const_operator(ops[ops.len() - 2].clone())?) +} + pub fn process_const_operator(op: wasmparser::Operator) -> Result<ConstInstruction> { match op { wasmparser::Operator::I32Const { value } => Ok(ConstInstruction::I32Const(value)), diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 36deb7f..f1477f9 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -126,6 +126,8 @@ impl TryFrom<ModuleReader> for TinyWasmModule { globals: globals.into_boxed_slice(), table_types: table_types.into_boxed_slice(), memory_types: reader.memory_types.into_boxed_slice(), + imports: reader.imports.into_boxed_slice(), + data: reader.data.into_boxed_slice(), }) } } diff --git a/crates/parser/src/module.rs b/crates/parser/src/module.rs index 0dbd36b..fdad900 100644 --- a/crates/parser/src/module.rs +++ b/crates/parser/src/module.rs @@ -1,11 +1,10 @@ use crate::log::debug; +use crate::{conversion, ParseError, Result}; use alloc::{boxed::Box, format, vec::Vec}; use core::fmt::Debug; -use tinywasm_types::{Export, FuncType, Global, Import, Instruction, MemoryType, TableType, ValType}; +use tinywasm_types::{Data, Export, FuncType, Global, Import, Instruction, MemoryType, TableType, ValType}; use wasmparser::{Payload, Validator}; -use crate::{conversion, ParseError, Result}; - #[derive(Debug, Clone, PartialEq)] pub struct CodeSection { pub locals: Box<[ValType]>, @@ -25,9 +24,9 @@ pub struct ModuleReader { pub table_types: Vec<TableType>, pub memory_types: Vec<MemoryType>, pub imports: Vec<Import>, + pub data: Vec<Data>, // pub element_section: Option<ElementSectionReader<'a>>, - // pub data_section: Option<DataSectionReader<'a>>, pub end_reached: bool, } @@ -67,11 +66,19 @@ impl ModuleReader { } } StartSection { func, range } => { + if self.start_func.is_some() { + return Err(ParseError::DuplicateSection("Start section".into())); + } + debug!("Found start section"); validator.start_section(func, &range)?; self.start_func = Some(func); } TypeSection(reader) => { + if !self.func_types.is_empty() { + return Err(ParseError::DuplicateSection("Type section".into())); + } + debug!("Found type section"); validator.type_section(&reader)?; self.func_types = reader @@ -80,21 +87,37 @@ impl ModuleReader { .collect::<Result<Vec<FuncType>>>()?; } FunctionSection(reader) => { + if !self.func_addrs.is_empty() { + return Err(ParseError::DuplicateSection("Function section".into())); + } + debug!("Found function section"); validator.function_section(&reader)?; self.func_addrs = reader.into_iter().map(|f| Ok(f?)).collect::<Result<Vec<_>>>()?; } GlobalSection(reader) => { + if !self.globals.is_empty() { + return Err(ParseError::DuplicateSection("Global section".into())); + } + debug!("Found global section"); validator.global_section(&reader)?; self.globals = conversion::convert_module_globals(reader)?; } TableSection(reader) => { + if !self.table_types.is_empty() { + return Err(ParseError::DuplicateSection("Table section".into())); + } + debug!("Found table section"); validator.table_section(&reader)?; self.table_types = conversion::convert_module_tables(reader)?; } MemorySection(reader) => { + if !self.memory_types.is_empty() { + return Err(ParseError::DuplicateSection("Memory section".into())); + } + debug!("Found memory section"); validator.memory_section(&reader)?; self.memory_types = conversion::convert_module_memories(reader)?; @@ -105,11 +128,14 @@ impl ModuleReader { // validator.element_section(&reader)?; // self.element_section = Some(reader); } - DataSection(_reader) => { - return Err(ParseError::UnsupportedSection("Data section".into())); - // debug!("Found data section"); - // validator.data_section(&reader)?; - // self.data_section = Some(reader); + DataSection(reader) => { + if !self.data.is_empty() { + return Err(ParseError::DuplicateSection("Data section".into())); + } + + debug!("Found data section"); + validator.data_section(&reader)?; + self.data = conversion::convert_module_data_sections(reader)?; } CodeSectionStart { count, range, .. } => { debug!("Found code section ({} functions)", count); @@ -127,11 +153,19 @@ impl ModuleReader { .push(conversion::convert_module_code(function, func_validator)?); } ImportSection(reader) => { + if !self.imports.is_empty() { + return Err(ParseError::DuplicateSection("Import section".into())); + } + debug!("Found import section"); validator.import_section(&reader)?; self.imports = conversion::convert_module_imports(reader)?; } ExportSection(reader) => { + if !self.exports.is_empty() { + return Err(ParseError::DuplicateSection("Export section".into())); + } + debug!("Found export section"); validator.export_section(&reader)?; self.exports = reader |
