diff options
| author | Henry Gressmann <mail@henrygressmann.de> | 2023-12-18 15:01:30 +0100 |
|---|---|---|
| committer | Henry Gressmann <mail@henrygressmann.de> | 2023-12-18 15:01:30 +0100 |
| commit | 8f33b67404160ce8cf35a22c0d0993112b5abe9c (patch) | |
| tree | a94aa18a777d4d47c1b5dbc25abe0851883938c2 /crates/parser/src | |
| parent | 45c740b7d7553d3016cf5c73b891f512a9975afe (diff) | |
feat: global parsing, improve testsuite
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
Diffstat (limited to 'crates/parser/src')
| -rw-r--r-- | crates/parser/src/conversion.rs | 49 | ||||
| -rw-r--r-- | crates/parser/src/lib.rs | 3 | ||||
| -rw-r--r-- | crates/parser/src/module.rs | 18 |
3 files changed, 60 insertions, 10 deletions
diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index 269bb66..9f4930a 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -1,10 +1,43 @@ use alloc::{boxed::Box, format, string::ToString, vec::Vec}; use log::info; -use tinywasm_types::{BlockArgs, Export, ExternalKind, FuncType, Instruction, MemArg, ValType}; +use tinywasm_types::{ + BlockArgs, ConstInstruction, Export, ExternalKind, FuncType, Global, Instruction, MemArg, ValType, +}; use wasmparser::{FuncValidator, ValidatorResources}; use crate::{module::CodeSection, Result}; +pub(crate) fn convert_module_globals<'a, T: IntoIterator<Item = wasmparser::Result<wasmparser::Global<'a>>>>( + globals: T, +) -> Result<Vec<Global>> { + let globals = globals + .into_iter() + .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)); + + Ok(Global { + ty, + init: process_const_operator(ops[ops.len() - 2].clone())?, + mutable: global.ty.mutable, + }) + }) + .collect::<Result<Vec<_>>>()?; + Ok(globals) +} + pub(crate) fn convert_module_export(export: wasmparser::Export) -> Result<Export> { let kind = match export.kind { wasmparser::ExternalKind::Func => ExternalKind::Func, @@ -105,6 +138,20 @@ pub(crate) fn convert_memarg(memarg: wasmparser::MemArg) -> MemArg { } } +pub fn process_const_operator(op: wasmparser::Operator) -> Result<ConstInstruction> { + match op { + wasmparser::Operator::I32Const { value } => Ok(ConstInstruction::I32Const(value)), + wasmparser::Operator::I64Const { value } => Ok(ConstInstruction::I64Const(value)), + wasmparser::Operator::F32Const { value } => Ok(ConstInstruction::F32Const(f32::from_bits(value.bits()))), // TODO: check if this is correct + wasmparser::Operator::F64Const { value } => Ok(ConstInstruction::F64Const(f64::from_bits(value.bits()))), // TODO: check if this is correct + wasmparser::Operator::GlobalGet { global_index } => Ok(ConstInstruction::GlobalGet(global_index)), + op => Err(crate::ParseError::UnsupportedOperator(format!( + "Unsupported instruction: {:?}", + op + ))), + } +} + pub fn process_operators<'a>( mut offset: usize, ops: impl Iterator<Item = Result<wasmparser::Operator<'a>, wasmparser::BinaryReaderError>>, diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 0719c96..bcaef76 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -114,12 +114,15 @@ impl TryFrom<ModuleReader> for TinyWasmModule { }) .collect::<Vec<_>>(); + let globals = reader.global_section; + Ok(TinyWasmModule { version: reader.version, start_func: reader.start_func, types: reader.type_section.into_boxed_slice(), funcs: funcs.into_boxed_slice(), exports: reader.export_section.into_boxed_slice(), + globals: globals.into_boxed_slice(), }) } } diff --git a/crates/parser/src/module.rs b/crates/parser/src/module.rs index 69bb894..6f823de 100644 --- a/crates/parser/src/module.rs +++ b/crates/parser/src/module.rs @@ -1,7 +1,7 @@ use crate::log::debug; use alloc::{boxed::Box, format, vec::Vec}; use core::fmt::Debug; -use tinywasm_types::{Export, FuncType, Instruction, ValType}; +use tinywasm_types::{Export, FuncType, Global, Instruction, ValType}; use wasmparser::{Payload, Validator}; use crate::{conversion, ParseError, Result}; @@ -21,10 +21,10 @@ pub struct ModuleReader { pub function_section: Vec<u32>, pub export_section: Vec<Export>, pub code_section: Vec<CodeSection>, + pub global_section: Vec<Global>, // pub table_section: Option<TableSectionReader<'a>>, // pub memory_section: Option<MemorySectionReader<'a>>, - // pub global_section: Option<GlobalSectionReader<'a>>, // pub element_section: Option<ElementSectionReader<'a>>, // pub data_section: Option<DataSectionReader<'a>>, // pub import_section: Option<ImportSectionReader<'a>>, @@ -39,9 +39,9 @@ impl Debug for ModuleReader { .field("function_section", &self.function_section) .field("code_section", &self.code_section) .field("export_section", &self.export_section) + .field("global_section", &self.global_section) // .field("table_section", &self.table_section) // .field("memory_section", &self.memory_section) - // .field("global_section", &self.global_section) // .field("element_section", &self.element_section) // .field("data_section", &self.data_section) // .field("import_section", &self.import_section) @@ -84,6 +84,11 @@ impl ModuleReader { validator.function_section(&reader)?; self.function_section = reader.into_iter().map(|f| Ok(f?)).collect::<Result<Vec<_>>>()?; } + GlobalSection(reader) => { + debug!("Found global section"); + validator.global_section(&reader)?; + self.global_section = conversion::convert_module_globals(reader)?; + } TableSection(_reader) => { return Err(ParseError::UnsupportedSection("Table section".into())); // debug!("Found table section"); @@ -96,12 +101,7 @@ impl ModuleReader { // validator.memory_section(&reader)?; // self.memory_section = Some(reader); } - GlobalSection(_reader) => { - return Err(ParseError::UnsupportedSection("Global section".into())); - // debug!("Found global section"); - // validator.global_section(&reader)?; - // self.global_section = Some(reader); - } + ElementSection(_reader) => { return Err(ParseError::UnsupportedSection("Element section".into())); // debug!("Found element section"); |
