summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock116
-rw-r--r--crates/parser/Cargo.toml2
-rw-r--r--crates/parser/README.md4
-rw-r--r--crates/parser/src/conversion.rs76
-rw-r--r--crates/parser/src/lib.rs34
-rw-r--r--crates/tinywasm/src/runtime/interpreter/mod.rs6
6 files changed, 197 insertions, 41 deletions
diff --git a/Cargo.lock b/Cargo.lock
index bf9afe3..4fddf4d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -29,6 +29,19 @@ dependencies = [
]
[[package]]
+name = "ahash"
+version = "0.8.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f"
+dependencies = [
+ "cfg-if",
+ "const-random",
+ "once_cell",
+ "version_check",
+ "zerocopy",
+]
+
+[[package]]
name = "aho-corasick"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -196,9 +209,9 @@ dependencies = [
[[package]]
name = "bstr"
-version = "1.9.0"
+version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc"
+checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
dependencies = [
"memchr",
"serde",
@@ -396,6 +409,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed3d0b5ff30645a68f35ece8cea4556ca14ef8a1651455f789a099a0513532a6"
[[package]]
+name = "const-random"
+version = "0.1.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aaf16c9c2c612020bcfd042e170f6e32de9b9d75adb5277cdbbd2e2c8c8299a"
+dependencies = [
+ "const-random-macro",
+]
+
+[[package]]
+name = "const-random-macro"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
+dependencies = [
+ "getrandom",
+ "once_cell",
+ "tiny-keccak",
+]
+
+[[package]]
name = "core-foundation"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -523,7 +556,7 @@ dependencies = [
"cranelift-entity",
"fxhash",
"hashbrown 0.12.3",
- "indexmap",
+ "indexmap 1.9.3",
"log",
"smallvec",
]
@@ -851,6 +884,12 @@ dependencies = [
]
[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
name = "eyre"
version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1020,7 +1059,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
dependencies = [
"fallible-iterator",
- "indexmap",
+ "indexmap 1.9.3",
"stable_deref_trait",
]
@@ -1059,7 +1098,7 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
- "ahash",
+ "ahash 0.7.8",
]
[[package]]
@@ -1067,6 +1106,9 @@ name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
+dependencies = [
+ "ahash 0.8.9",
+]
[[package]]
name = "hermit-abi"
@@ -1150,6 +1192,16 @@ dependencies = [
]
[[package]]
+name = "indexmap"
+version = "2.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
+dependencies = [
+ "equivalent",
+ "hashbrown 0.14.3",
+]
+
+[[package]]
name = "indexmap-nostd"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1678,7 +1730,7 @@ dependencies = [
"bytecheck 0.6.12",
"bytes",
"hashbrown 0.12.3",
- "indexmap",
+ "indexmap 1.9.3",
"ptr_meta",
"rend",
"rkyv_derive",
@@ -1975,6 +2027,15 @@ dependencies = [
]
[[package]]
+name = "tiny-keccak"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
+dependencies = [
+ "crunchy",
+]
+
+[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2035,7 +2096,7 @@ version = "0.4.1"
dependencies = [
"log",
"tinywasm-types",
- "wasmparser-nostd",
+ "tinywasm-wasmparser",
]
[[package]]
@@ -2058,6 +2119,19 @@ dependencies = [
]
[[package]]
+name = "tinywasm-wasmparser"
+version = "0.200.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9fce1b3563499af272f7e88c8b0357e740e62c2bcf59f134992698d35af96da"
+dependencies = [
+ "ahash 0.8.9",
+ "bitflags 2.4.2",
+ "hashbrown 0.14.3",
+ "indexmap 2.2.3",
+ "semver",
+]
+
+[[package]]
name = "tracing"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2282,7 +2356,7 @@ dependencies = [
"bytes",
"cfg-if",
"derivative",
- "indexmap",
+ "indexmap 1.9.3",
"js-sys",
"more-asserts",
"rustc-demangle",
@@ -2388,7 +2462,7 @@ dependencies = [
"bytecheck 0.6.12",
"enum-iterator",
"enumset",
- "indexmap",
+ "indexmap 1.9.3",
"more-asserts",
"rkyv",
"target-lexicon",
@@ -2410,7 +2484,7 @@ dependencies = [
"derivative",
"enum-iterator",
"fnv",
- "indexmap",
+ "indexmap 1.9.3",
"lazy_static",
"libc",
"mach",
@@ -2460,7 +2534,7 @@ version = "0.95.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2ea896273ea99b15132414be1da01ab0d8836415083298ecaffbe308eaac87a"
dependencies = [
- "indexmap",
+ "indexmap 1.9.3",
"url",
]
@@ -2767,3 +2841,23 @@ dependencies = [
"once_cell",
"pkg-config",
]
+
+[[package]]
+name = "zerocopy"
+version = "0.7.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.50",
+]
diff --git a/crates/parser/Cargo.toml b/crates/parser/Cargo.toml
index 0fee8e1..73eec99 100644
--- a/crates/parser/Cargo.toml
+++ b/crates/parser/Cargo.toml
@@ -9,7 +9,7 @@ repository.workspace=true
[dependencies]
# fork of wasmparser with no_std support, see https://github.com/bytecodealliance/wasmtime/issues/3495
-wasmparser={version="0.100", package="wasmparser-nostd", default-features=false}
+wasmparser={version="0.200.2", package="tinywasm-wasmparser", default-features=false}
log={version="0.4", optional=true}
tinywasm-types={version="0.4.0", path="../types", default-features=false}
diff --git a/crates/parser/README.md b/crates/parser/README.md
index 8ac7a30..563cd6b 100644
--- a/crates/parser/README.md
+++ b/crates/parser/README.md
@@ -1,7 +1,7 @@
# `tinywasm-parser`
-This crate provides a parser that can parse WebAssembly modules into a TinyWasm module. It is based on
-[`wasmparser_nostd`](https://crates.io/crates/wasmparser_nostd) and used by [`tinywasm`](https://crates.io/crates/tinywasm).
+This crate provides a parser that can parse WebAssembly modules into a TinyWasm module.
+It uses [my fork](https://crates.io/crates/tinywasm-wasmparser) of the [`wasmparser`](https://crates.io/crates/wasmparser) crate that has been modified to be compatible with `no_std` environments.
## Features
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<Item = wasmparser::Res
pub(crate) fn convert_module_element(element: wasmparser::Element<'_>) -> Result<tinywasm_types::Element> {
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::<Result<Vec<_>>>()?.into_boxed_slice()
+ let items = funcs
+ .into_iter()
+ .map(|func| Ok(ElementItem::Func(func?)))
+ .collect::<Result<Vec<_>>>()?
+ .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::<Result<Vec<_>>>()?
- .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::<Result<Vec<_>>>()?
+ .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<Item = wasmparser::Result<wasmparser::Data<'a>>>>(
@@ -71,7 +79,11 @@ pub(crate) fn convert_module_import(import: wasmparser::Import<'_>) -> Result<Im
name: import.name.to_string().into_boxed_str(),
kind: match import.ty {
wasmparser::TypeRef::Func(ty) => 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<Me
})
}
-pub(crate) fn convert_module_tables<T: IntoIterator<Item = wasmparser::Result<wasmparser::TableType>>>(
+pub(crate) fn convert_module_tables<'a, T: IntoIterator<Item = wasmparser::Result<wasmparser::Table<'a>>>>(
table_types: T,
) -> Result<Vec<TableType>> {
let table_type = table_types.into_iter().map(|table| convert_module_table(table?)).collect::<Result<Vec<_>>>()?;
Ok(table_type)
}
-pub(crate) fn convert_module_table(table: wasmparser::TableType) -> Result<TableType> {
- 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<TableType> {
+ 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<Item = wasmparser::Result<wasmparser::Global<'a>>>>(
@@ -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<FuncType> {
- let wasmparser::Type::Func(ty) = ty;
+pub(crate) fn convert_module_type(ty: wasmparser::RecGroup) -> Result<FuncType> {
+ 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::<Result<Vec<ValType>>>()?.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<ConstI
pub(crate) fn process_const_operator(op: wasmparser::Operator<'_>) -> Result<ConstInstruction> {
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<Con
}
}
+fn convert_heaptype(heap: wasmparser::HeapType) -> 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<ValidatorResources>,
@@ -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<TinyWasmModule> {
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<TinyWasmModule> {
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);
diff --git a/crates/tinywasm/src/runtime/interpreter/mod.rs b/crates/tinywasm/src/runtime/interpreter/mod.rs
index 78f6ed2..b06152d 100644
--- a/crates/tinywasm/src/runtime/interpreter/mod.rs
+++ b/crates/tinywasm/src/runtime/interpreter/mod.rs
@@ -203,7 +203,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
BlockFrame::new(
cf.instr_ptr,
cf.instr_ptr + *end_offset,
- stack.values.len(), // - params,
+ stack.values.len(),
BlockType::If,
args,
module,
@@ -219,7 +219,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
let label = BlockFrame::new(
cf.instr_ptr + *else_offset,
cf.instr_ptr + *end_offset,
- stack.values.len(), // - params,
+ stack.values.len(),
BlockType::Else,
args,
module,
@@ -236,7 +236,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
BlockFrame::new(
cf.instr_ptr,
cf.instr_ptr + *end_offset,
- stack.values.len(), // - params,
+ stack.values.len(),
BlockType::Loop,
args,
module,