summaryrefslogtreecommitdiff
path: root/crates/parser/src
diff options
context:
space:
mode:
authorHenry <mail@henrygressmann.de>2023-12-22 00:03:03 +0100
committerHenry <mail@henrygressmann.de>2023-12-22 00:03:03 +0100
commit295a48c57672b3e7109c1d650313a00e15a6c01d (patch)
tree419a73091059fa16d8c914432d08315beeefb02a /crates/parser/src
parentfcb92cab9a440931ebc90dfdb94974084d5e066b (diff)
feat: improve parser
Signed-off-by: Henry <mail@henrygressmann.de>
Diffstat (limited to 'crates/parser/src')
-rw-r--r--crates/parser/src/conversion.rs62
-rw-r--r--crates/parser/src/lib.rs2
-rw-r--r--crates/parser/src/module.rs52
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