summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--Cargo.lock59
-rw-r--r--crates/parser/src/conversion.rs8
-rw-r--r--crates/parser/src/lib.rs2
-rw-r--r--crates/tinywasm/src/func.rs18
-rw-r--r--crates/tinywasm/src/interpreter/stack/value_stack.rs12
-rw-r--r--crates/tinywasm/src/interpreter/values.rs16
-rw-r--r--crates/tinywasm/src/module.rs1
-rw-r--r--crates/tinywasm/src/store/mod.rs17
-rw-r--r--crates/tinywasm/src/store/table.rs6
-rw-r--r--crates/tinywasm/tests/host_func_signature_check.rs5
-rw-r--r--crates/tinywasm/tests/testsuite/util.rs27
-rw-r--r--crates/types/src/instructions.rs6
-rw-r--r--crates/types/src/value.rs122
14 files changed, 192 insertions, 108 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e52cdc6..ab30d8d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- **Breaking:**: New backwards-incompatible version of the twasm format (upgraded `rkyv` to 0.8.0)
+- **Breaking:**: `RefNull` has been removed and replaced with new `FuncRef` and `ExternRef` structs
- Increased MSRV to 1.83.0
### Fixed
diff --git a/Cargo.lock b/Cargo.lock
index 5333d98..c31c41f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -25,19 +25,20 @@ checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "argh"
-version = "0.1.12"
+version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7af5ba06967ff7214ce4c7419c7d185be7ecd6cc4965a8f6e1d8ce0398aad219"
+checksum = "34ff18325c8a36b82f992e533ece1ec9f9a9db446bd1c14d4f936bac88fcd240"
dependencies = [
"argh_derive",
"argh_shared",
+ "rust-fuzzy-search",
]
[[package]]
name = "argh_derive"
-version = "0.1.12"
+version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56df0aeedf6b7a2fc67d06db35b09684c3e8da0c95f8f27685cb17e08413d87a"
+checksum = "adb7b2b83a50d329d5d8ccc620f5c7064028828538bdf5646acd60dc1f767803"
dependencies = [
"argh_shared",
"proc-macro2",
@@ -47,9 +48,9 @@ dependencies = [
[[package]]
name = "argh_shared"
-version = "0.1.12"
+version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5693f39141bda5760ecc4111ab08da40565d1771038c4a0250f03457ec707531"
+checksum = "a464143cc82dedcdc3928737445362466b7674b5db4e2eb8e869846d6d84f4f6"
dependencies = [
"serde",
]
@@ -202,9 +203,9 @@ dependencies = [
[[package]]
name = "crossbeam-deque"
-version = "0.8.5"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
+checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
@@ -221,9 +222,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
-version = "0.8.20"
+version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
+checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crunchy"
@@ -363,9 +364,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
[[package]]
name = "libc"
-version = "0.2.167"
+version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
+checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "libm"
@@ -473,9 +474,9 @@ dependencies = [
[[package]]
name = "quote"
-version = "1.0.37"
+version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
@@ -578,6 +579,12 @@ dependencies = [
]
[[package]]
+name = "rust-fuzzy-search"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a157657054ffe556d8858504af8a672a054a6e0bd9e8ee531059100c0fa11bb2"
+
+[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -594,24 +601,24 @@ dependencies = [
[[package]]
name = "semver"
-version = "1.0.23"
+version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
+checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
[[package]]
name = "serde"
-version = "1.0.215"
+version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
+checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.215"
+version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
+checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
@@ -620,9 +627,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.133"
+version = "1.0.134"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
+checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d"
dependencies = [
"itoa",
"memchr",
@@ -638,9 +645,9 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]]
name = "syn"
-version = "2.0.90"
+version = "2.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
+checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a"
dependencies = [
"proc-macro2",
"quote",
@@ -668,9 +675,9 @@ dependencies = [
[[package]]
name = "tinyvec"
-version = "1.8.0"
+version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
+checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8"
dependencies = [
"tinyvec_macros",
]
diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs
index 1ebe392..273dd44 100644
--- a/crates/parser/src/conversion.rs
+++ b/crates/parser/src/conversion.rs
@@ -251,8 +251,12 @@ pub(crate) fn process_const_operators(ops: OperatorsReader<'_>) -> Result<ConstI
assert!(matches!(ops[ops.len() - 1], wasmparser::Operator::End));
match &ops[ops.len() - 2] {
- wasmparser::Operator::RefNull { hty } => Ok(ConstInstruction::RefNull(convert_heaptype(*hty))),
- wasmparser::Operator::RefFunc { function_index } => Ok(ConstInstruction::RefFunc(*function_index)),
+ wasmparser::Operator::RefNull { hty } => match convert_heaptype(*hty) {
+ ValType::RefFunc => Ok(ConstInstruction::RefFunc(None)),
+ ValType::RefExtern => Ok(ConstInstruction::RefExtern(None)),
+ _ => unimplemented!("Unsupported heap type: {:?}", hty),
+ },
+ wasmparser::Operator::RefFunc { function_index } => Ok(ConstInstruction::RefFunc(Some(*function_index))),
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()))),
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index dcb05f0..04da9da 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -65,6 +65,7 @@ impl Parser {
memory64: true,
custom_page_sizes: true,
+ extended_const: false,
wide_arithmetic: false,
gc_types: true,
stack_switching: false,
@@ -73,7 +74,6 @@ impl Parser {
component_model_values: false,
component_model_more_flags: false,
exceptions: false,
- extended_const: false,
gc: false,
memory_control: false,
relaxed_simd: false,
diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs
index 47a2cdf..f5a9873 100644
--- a/crates/tinywasm/src/func.rs
+++ b/crates/tinywasm/src/func.rs
@@ -2,7 +2,7 @@ use crate::interpreter::stack::{CallFrame, Stack};
use crate::{log, unlikely, Function};
use crate::{Error, FuncContext, Result, Store};
use alloc::{boxed::Box, format, string::String, string::ToString, vec, vec::Vec};
-use tinywasm_types::{FuncType, ModuleInstanceAddr, ValType, WasmValue};
+use tinywasm_types::{ExternRef, FuncRef, FuncType, ModuleInstanceAddr, ValType, WasmValue};
#[derive(Debug)]
/// A function handle
@@ -219,6 +219,18 @@ impl ToValType for f64 {
}
}
+impl ToValType for FuncRef {
+ fn to_val_type() -> ValType {
+ ValType::RefFunc
+ }
+}
+
+impl ToValType for ExternRef {
+ fn to_val_type() -> ValType {
+ ValType::RefExtern
+ }
+}
+
macro_rules! impl_val_types_from_tuple {
($($t:ident),+) => {
impl<$($t),+> ValTypesFromTuple for ($($t,)+)
@@ -251,11 +263,15 @@ impl_from_wasm_value_tuple_single!(i32);
impl_from_wasm_value_tuple_single!(i64);
impl_from_wasm_value_tuple_single!(f32);
impl_from_wasm_value_tuple_single!(f64);
+impl_from_wasm_value_tuple_single!(FuncRef);
+impl_from_wasm_value_tuple_single!(ExternRef);
impl_into_wasm_value_tuple_single!(i32);
impl_into_wasm_value_tuple_single!(i64);
impl_into_wasm_value_tuple_single!(f32);
impl_into_wasm_value_tuple_single!(f64);
+impl_into_wasm_value_tuple_single!(FuncRef);
+impl_into_wasm_value_tuple_single!(ExternRef);
impl_val_types_from_tuple!(T1);
impl_val_types_from_tuple!(T1, T2);
diff --git a/crates/tinywasm/src/interpreter/stack/value_stack.rs b/crates/tinywasm/src/interpreter/stack/value_stack.rs
index ab739a3..ea6a082 100644
--- a/crates/tinywasm/src/interpreter/stack/value_stack.rs
+++ b/crates/tinywasm/src/interpreter/stack/value_stack.rs
@@ -1,5 +1,5 @@
use alloc::vec::Vec;
-use tinywasm_types::{ValType, ValueCounts, ValueCountsSmall, WasmValue};
+use tinywasm_types::{ExternRef, FuncRef, ValType, ValueCounts, ValueCountsSmall, WasmValue};
use crate::{interpreter::*, Result};
@@ -173,14 +173,8 @@ impl ValueStack {
ValType::V128 => WasmValue::V128(self.pop()),
ValType::F32 => WasmValue::F32(self.pop()),
ValType::F64 => WasmValue::F64(self.pop()),
- ValType::RefExtern => match self.pop() {
- Some(v) => WasmValue::RefExtern(v),
- None => WasmValue::RefNull(ValType::RefExtern),
- },
- ValType::RefFunc => match self.pop() {
- Some(v) => WasmValue::RefFunc(v),
- None => WasmValue::RefNull(ValType::RefFunc),
- },
+ ValType::RefExtern => WasmValue::RefExtern(ExternRef::new(self.pop())),
+ ValType::RefFunc => WasmValue::RefFunc(FuncRef::new(self.pop())),
}
}
diff --git a/crates/tinywasm/src/interpreter/values.rs b/crates/tinywasm/src/interpreter/values.rs
index efee9b8..712baf7 100644
--- a/crates/tinywasm/src/interpreter/values.rs
+++ b/crates/tinywasm/src/interpreter/values.rs
@@ -1,5 +1,5 @@
use crate::Result;
-use tinywasm_types::{LocalAddr, ValType, WasmValue};
+use tinywasm_types::{ExternRef, FuncRef, LocalAddr, ValType, WasmValue};
use super::stack::{Locals, ValueStack};
@@ -107,14 +107,8 @@ impl TinyWasmValue {
ValType::F32 => WasmValue::F32(f32::from_bits(self.unwrap_32())),
ValType::F64 => WasmValue::F64(f64::from_bits(self.unwrap_64())),
ValType::V128 => WasmValue::V128(self.unwrap_128()),
- ValType::RefExtern => match self.unwrap_ref() {
- Some(v) => WasmValue::RefExtern(v),
- None => WasmValue::RefNull(ValType::RefExtern),
- },
- ValType::RefFunc => match self.unwrap_ref() {
- Some(v) => WasmValue::RefFunc(v),
- None => WasmValue::RefNull(ValType::RefFunc),
- },
+ ValType::RefExtern => WasmValue::RefExtern(ExternRef::new(self.unwrap_ref())),
+ ValType::RefFunc => WasmValue::RefFunc(FuncRef::new(self.unwrap_ref())),
}
}
}
@@ -127,8 +121,8 @@ impl From<&WasmValue> for TinyWasmValue {
WasmValue::V128(v) => TinyWasmValue::Value128(*v),
WasmValue::F32(v) => TinyWasmValue::Value32(v.to_bits()),
WasmValue::F64(v) => TinyWasmValue::Value64(v.to_bits()),
- WasmValue::RefFunc(v) | WasmValue::RefExtern(v) => TinyWasmValue::ValueRef(Some(*v)),
- WasmValue::RefNull(_) => TinyWasmValue::ValueRef(None),
+ WasmValue::RefExtern(v) => TinyWasmValue::ValueRef(v.addr()),
+ WasmValue::RefFunc(v) => TinyWasmValue::ValueRef(v.addr()),
}
}
}
diff --git a/crates/tinywasm/src/module.rs b/crates/tinywasm/src/module.rs
index f6e8e04..26cea9c 100644
--- a/crates/tinywasm/src/module.rs
+++ b/crates/tinywasm/src/module.rs
@@ -47,6 +47,7 @@ impl Module {
/// Instantiate the module in the given store
///
/// Runs the start function if it exists
+ ///
/// If you want to run the start function yourself, use `ModuleInstance::instantiate`
///
/// See <https://webassembly.github.io/spec/core/exec/modules.html#exec-instantiation>
diff --git a/crates/tinywasm/src/store/mod.rs b/crates/tinywasm/src/store/mod.rs
index d4bbf33..86cbb5d 100644
--- a/crates/tinywasm/src/store/mod.rs
+++ b/crates/tinywasm/src/store/mod.rs
@@ -278,12 +278,13 @@ impl Store {
fn elem_addr(&self, item: &ElementItem, globals: &[Addr], funcs: &[FuncAddr]) -> Result<Option<u32>> {
let res = match item {
- ElementItem::Func(addr) | ElementItem::Expr(ConstInstruction::RefFunc(addr)) => {
+ ElementItem::Func(addr) | ElementItem::Expr(ConstInstruction::RefFunc(Some(addr))) => {
Some(funcs.get(*addr as usize).copied().ok_or_else(|| {
Error::Other(format!("function {addr} not found. This should have been caught by the validator"))
})?)
}
- ElementItem::Expr(ConstInstruction::RefNull(_ty)) => None,
+ ElementItem::Expr(ConstInstruction::RefFunc(None)) => None,
+ ElementItem::Expr(ConstInstruction::RefExtern(None)) => None,
ElementItem::Expr(ConstInstruction::GlobalGet(addr)) => {
let addr = globals.get(*addr as usize).copied().ok_or_else(|| {
Error::Other(format!("global {addr} not found. This should have been caught by the validator"))
@@ -450,10 +451,14 @@ impl Store {
self.data.globals.get(*addr as usize).expect("global not found. This should be unreachable");
global.value.get()
}
- RefNull(t) => t.default_value().into(),
- RefFunc(idx) => TinyWasmValue::ValueRef(Some(*module_func_addrs.get(*idx as usize).ok_or_else(|| {
- Error::Other(format!("function {idx} not found. This should have been caught by the validator"))
- })?)),
+ RefFunc(None) => TinyWasmValue::ValueRef(None),
+ RefExtern(None) => TinyWasmValue::ValueRef(None),
+ RefFunc(Some(idx)) => {
+ TinyWasmValue::ValueRef(Some(*module_func_addrs.get(*idx as usize).ok_or_else(|| {
+ Error::Other(format!("function {idx} not found. This should have been caught by the validator"))
+ })?))
+ }
+ _ => return Err(Error::Other("unsupported const instruction".to_string())),
};
Ok(val)
}
diff --git a/crates/tinywasm/src/store/table.rs b/crates/tinywasm/src/store/table.rs
index 5520faf..0cbd054 100644
--- a/crates/tinywasm/src/store/table.rs
+++ b/crates/tinywasm/src/store/table.rs
@@ -30,8 +30,8 @@ impl TableInstance {
let val = self.get(addr)?.addr();
Ok(match self.kind.element_type {
- ValType::RefFunc => val.map_or(WasmValue::RefNull(ValType::RefFunc), WasmValue::RefFunc),
- ValType::RefExtern => val.map_or(WasmValue::RefNull(ValType::RefExtern), WasmValue::RefExtern),
+ ValType::RefFunc => WasmValue::RefFunc(FuncRef::new(val)),
+ ValType::RefExtern => WasmValue::RefExtern(ExternRef::new(val)),
_ => Err(Error::UnsupportedFeature("non-ref table".into()))?,
})
}
@@ -211,7 +211,7 @@ mod tests {
}
match table_instance.get_wasm_val(1) {
- Ok(WasmValue::RefNull(ValType::RefFunc)) => {}
+ Ok(WasmValue::RefFunc(f)) if f.is_null() => {}
_ => panic!("get_wasm_val failed to return the correct WasmValue"),
}
diff --git a/crates/tinywasm/tests/host_func_signature_check.rs b/crates/tinywasm/tests/host_func_signature_check.rs
index 787b24a..c60ade2 100644
--- a/crates/tinywasm/tests/host_func_signature_check.rs
+++ b/crates/tinywasm/tests/host_func_signature_check.rs
@@ -4,6 +4,7 @@ use tinywasm::{
types::{FuncType, ValType, WasmValue},
Extern, FuncContext, Imports, Module, Store,
};
+use tinywasm_types::ExternRef;
const VAL_LISTS: &[&[WasmValue]] = &[
&[],
@@ -11,7 +12,7 @@ const VAL_LISTS: &[&[WasmValue]] = &[
&[WasmValue::I32(0), WasmValue::I32(0)], // 2 of the same
&[WasmValue::I32(0), WasmValue::I32(0), WasmValue::F64(0.0)], // add another type
&[WasmValue::I32(0), WasmValue::F64(0.0), WasmValue::I32(0)], // reorder
- &[WasmValue::RefExtern(0), WasmValue::F64(0.0), WasmValue::I32(0)], // all different types
+ &[WasmValue::RefExtern(ExternRef::null()), WasmValue::F64(0.0), WasmValue::I32(0)], // all different types
];
// (f64, i32, i32) and (f64) can be used to "match_none"
@@ -37,7 +38,6 @@ fn test_return_invalid_type() -> Result<()> {
for (module, func_ty, test_args) in mod_list {
for result_to_try in VAL_LISTS {
- println!("trying");
let mut store = Store::default();
let mut imports = Imports::new();
imports
@@ -146,7 +146,6 @@ fn proxy_module(func_ty: &FuncType) -> Module {
let results_text = join_surround(results, "result");
let params_text = join_surround(params, "param");
- // let params_gets: String = params.iter().enumerate().map(|(num, _)| format!("(local.get {num})\n")).collect();
let params_gets: String = params.iter().enumerate().fold(String::new(), |mut acc, (num, _)| {
let _ = writeln!(acc, "(local.get {num})", num = num);
acc
diff --git a/crates/tinywasm/tests/testsuite/util.rs b/crates/tinywasm/tests/testsuite/util.rs
index e3aafcb..b555153 100644
--- a/crates/tinywasm/tests/testsuite/util.rs
+++ b/crates/tinywasm/tests/testsuite/util.rs
@@ -1,9 +1,9 @@
use std::panic::{self, AssertUnwindSafe};
use eyre::{bail, eyre, Result};
-use tinywasm_types::{ModuleInstanceAddr, TinyWasmModule, ValType, WasmValue};
-use wasm_testsuite::wast::{core::AbstractHeapType, QuoteWat};
+use tinywasm_types::{ExternRef, FuncRef, ModuleInstanceAddr, TinyWasmModule, ValType, WasmValue};
use wasm_testsuite::wast;
+use wasm_testsuite::wast::{core::AbstractHeapType, QuoteWat};
pub fn try_downcast_panic(panic: Box<dyn std::any::Any + Send>) -> String {
let info = panic.downcast_ref::<panic::PanicHookInfo>().or(None).map(ToString::to_string).clone();
@@ -103,13 +103,13 @@ fn wastarg2tinywasmvalue(arg: wast::WastArg) -> Result<tinywasm_types::WasmValue
I32(i) => WasmValue::I32(i),
I64(i) => WasmValue::I64(i),
V128(i) => WasmValue::V128(i128::from_le_bytes(i.to_le_bytes()).try_into().unwrap()),
- RefExtern(v) => WasmValue::RefExtern(v),
+ RefExtern(v) => WasmValue::RefExtern(ExternRef::new(Some(v))),
RefNull(t) => match t {
wast::core::HeapType::Abstract { shared: false, ty: AbstractHeapType::Func } => {
- WasmValue::RefNull(ValType::RefFunc)
+ WasmValue::RefFunc(FuncRef::null())
}
wast::core::HeapType::Abstract { shared: false, ty: AbstractHeapType::Extern } => {
- WasmValue::RefNull(ValType::RefExtern)
+ WasmValue::RefExtern(ExternRef::null())
}
_ => bail!("unsupported arg type: refnull: {:?}", t),
},
@@ -146,23 +146,18 @@ fn wastret2tinywasmvalue(ret: wast::WastRet) -> Result<tinywasm_types::WasmValue
V128(i) => WasmValue::V128(wast_i128_to_i128(i)),
RefNull(t) => match t {
Some(wast::core::HeapType::Abstract { shared: false, ty: AbstractHeapType::Func }) => {
- WasmValue::RefNull(ValType::RefFunc)
+ WasmValue::RefFunc(FuncRef::null())
}
Some(wast::core::HeapType::Abstract { shared: false, ty: AbstractHeapType::Extern }) => {
- WasmValue::RefNull(ValType::RefExtern)
+ WasmValue::RefExtern(ExternRef::null())
}
_ => bail!("unsupported arg type: refnull: {:?}", t),
},
- RefExtern(v) => match v {
- Some(v) => WasmValue::RefExtern(v),
- None => WasmValue::RefNull(ValType::RefExtern),
- _ => bail!("unsupported arg type: refextern: {:?}", v),
- },
- RefFunc(v) => match v {
- Some(wast::token::Index::Num(n, _)) => WasmValue::RefFunc(n),
- None => WasmValue::RefNull(ValType::RefFunc),
+ RefExtern(v) => WasmValue::RefExtern(ExternRef::new(v)),
+ RefFunc(v) => WasmValue::RefFunc(FuncRef::new(match v {
+ Some(wast::token::Index::Num(n, _)) => Some(n),
_ => bail!("unsupported arg type: reffunc: {:?}", v),
- },
+ })),
a => bail!("unsupported arg type {:?}", a),
})
}
diff --git a/crates/types/src/instructions.rs b/crates/types/src/instructions.rs
index fb3c1cc..8f77b31 100644
--- a/crates/types/src/instructions.rs
+++ b/crates/types/src/instructions.rs
@@ -1,5 +1,5 @@
use super::{FuncAddr, GlobalAddr, LabelAddr, LocalAddr, TableAddr, TypeAddr, ValType};
-use crate::{ConstIdx, DataAddr, ElemAddr, MemAddr};
+use crate::{ConstIdx, DataAddr, ElemAddr, ExternAddr, MemAddr};
/// Represents a memory immediate in a WebAssembly memory instruction.
#[derive(Debug, Copy, Clone, PartialEq)]
@@ -37,8 +37,8 @@ pub enum ConstInstruction {
F32Const(f32),
F64Const(f64),
GlobalGet(GlobalAddr),
- RefNull(ValType),
- RefFunc(FuncAddr),
+ RefFunc(Option<FuncAddr>),
+ RefExtern(Option<ExternAddr>),
}
/// A WebAssembly Instruction
diff --git a/crates/types/src/value.rs b/crates/types/src/value.rs
index 8bbcaf2..6651c0e 100644
--- a/crates/types/src/value.rs
+++ b/crates/types/src/value.rs
@@ -19,12 +19,92 @@ pub enum WasmValue {
// /// A 128-bit vector
V128(u128),
- RefExtern(ExternAddr),
- RefFunc(FuncAddr),
- RefNull(ValType),
+ RefExtern(ExternRef),
+ RefFunc(FuncRef),
+}
+
+#[derive(Clone, Copy, PartialEq)]
+pub struct ExternRef(Option<ExternAddr>);
+
+#[derive(Clone, Copy, PartialEq)]
+pub struct FuncRef(Option<FuncAddr>);
+
+impl Debug for ExternRef {
+ fn fmt(&self, f: &mut alloc::fmt::Formatter<'_>) -> alloc::fmt::Result {
+ match self.0 {
+ Some(addr) => write!(f, "extern({:?})", addr),
+ None => write!(f, "extern(null)"),
+ }
+ }
+}
+
+impl Debug for FuncRef {
+ fn fmt(&self, f: &mut alloc::fmt::Formatter<'_>) -> alloc::fmt::Result {
+ match self.0 {
+ Some(addr) => write!(f, "func({:?})", addr),
+ None => write!(f, "func(null)"),
+ }
+ }
+}
+
+impl FuncRef {
+ /// Create a new `FuncRef` from a `FuncAddr`.
+ /// Should only be used by the runtime.
+ #[doc(hidden)]
+ #[inline]
+ pub const fn new(addr: Option<FuncAddr>) -> Self {
+ Self(addr)
+ }
+
+ /// Create a null `FuncRef`.
+ #[inline]
+ pub const fn null() -> Self {
+ Self(None)
+ }
+
+ /// Check if the `FuncRef` is null.
+ #[inline]
+ pub const fn is_null(&self) -> bool {
+ self.0.is_none()
+ }
+
+ /// Get the `FuncAddr` from the `FuncRef`.
+ #[inline]
+ pub const fn addr(&self) -> Option<FuncAddr> {
+ self.0
+ }
+}
+
+impl ExternRef {
+ /// Create a new `ExternRef` from an `ExternAddr`.
+ /// Should only be used by the runtime.
+ #[doc(hidden)]
+ #[inline]
+ pub const fn new(addr: Option<ExternAddr>) -> Self {
+ Self(addr)
+ }
+
+ /// Create a null `ExternRef`.
+ #[inline]
+ pub const fn null() -> Self {
+ Self(None)
+ }
+
+ /// Check if the `ExternRef` is null.
+ #[inline]
+ pub const fn is_null(&self) -> bool {
+ self.0.is_none()
+ }
+
+ /// Get the `ExternAddr` from the `ExternRef`.
+ #[inline]
+ pub const fn addr(&self) -> Option<ExternAddr> {
+ self.0
+ }
}
impl WasmValue {
+ #[doc(hidden)]
#[inline]
pub fn const_instr(&self) -> ConstInstruction {
match self {
@@ -32,10 +112,7 @@ impl WasmValue {
Self::I64(i) => ConstInstruction::I64Const(*i),
Self::F32(i) => ConstInstruction::F32Const(*i),
Self::F64(i) => ConstInstruction::F64Const(*i),
- Self::RefFunc(i) => ConstInstruction::RefFunc(*i),
- Self::RefNull(ty) => ConstInstruction::RefNull(*ty),
-
- // Self::RefExtern(addr) => ConstInstruction::RefExtern(*addr),
+ Self::RefFunc(i) => ConstInstruction::RefFunc(i.addr()),
_ => unimplemented!("no const_instr for {:?}", self),
}
}
@@ -49,17 +126,17 @@ impl WasmValue {
ValType::F32 => Self::F32(0.0),
ValType::F64 => Self::F64(0.0),
ValType::V128 => Self::V128(0),
- ValType::RefFunc => Self::RefNull(ValType::RefFunc),
- ValType::RefExtern => Self::RefNull(ValType::RefExtern),
+ ValType::RefFunc => Self::RefFunc(FuncRef::null()),
+ ValType::RefExtern => Self::RefExtern(ExternRef::null()),
}
}
+ /// Check if two values are equal, ignoring differences in NaN values.
#[inline]
pub fn eq_loose(&self, other: &Self) -> bool {
match (self, other) {
(Self::I32(a), Self::I32(b)) => a == b,
(Self::I64(a), Self::I64(b)) => a == b,
- (Self::RefNull(v), Self::RefNull(v2)) => v == v2,
(Self::RefExtern(addr), Self::RefExtern(addr2)) => addr == addr2,
(Self::RefFunc(addr), Self::RefFunc(addr2)) => addr == addr2,
(Self::F32(a), Self::F32(b)) => {
@@ -121,25 +198,17 @@ impl WasmValue {
}
#[doc(hidden)]
- pub fn as_ref_extern(&self) -> Option<ExternAddr> {
- match self {
- Self::RefExtern(addr) => Some(*addr),
- _ => None,
- }
- }
-
- #[doc(hidden)]
- pub fn as_ref_func(&self) -> Option<FuncAddr> {
+ pub fn as_ref_extern(&self) -> Option<ExternRef> {
match self {
- Self::RefFunc(addr) => Some(*addr),
+ Self::RefExtern(ref_extern) => Some(*ref_extern),
_ => None,
}
}
#[doc(hidden)]
- pub fn as_ref_null(&self) -> Option<ValType> {
+ pub fn as_ref_func(&self) -> Option<FuncRef> {
match self {
- Self::RefNull(ty) => Some(*ty),
+ Self::RefFunc(ref_func) => Some(*ref_func),
_ => None,
}
}
@@ -156,9 +225,8 @@ impl Debug for WasmValue {
WasmValue::F32(i) => write!(f, "f32({i})"),
WasmValue::F64(i) => write!(f, "f64({i})"),
WasmValue::V128(i) => write!(f, "v128({i:?})"),
- WasmValue::RefExtern(addr) => write!(f, "ref.extern({addr:?})"),
- WasmValue::RefFunc(addr) => write!(f, "ref.func({addr:?})"),
- WasmValue::RefNull(ty) => write!(f, "ref.null({ty:?})"),
+ WasmValue::RefExtern(i) => write!(f, "ref({i:?})"),
+ WasmValue::RefFunc(i) => write!(f, "func({i:?})"),
}
}
}
@@ -175,7 +243,6 @@ impl WasmValue {
Self::V128(_) => ValType::V128,
Self::RefExtern(_) => ValType::RefExtern,
Self::RefFunc(_) => ValType::RefFunc,
- Self::RefNull(ty) => *ty,
}
}
}
@@ -206,6 +273,7 @@ impl ValType {
WasmValue::default_for(*self)
}
+ #[doc(hidden)]
#[inline]
pub fn is_simd(&self) -> bool {
matches!(self, ValType::V128)
@@ -241,4 +309,4 @@ macro_rules! impl_conversion_for_wasmvalue {
}
}
-impl_conversion_for_wasmvalue! { i32 => I32, i64 => I64, f32 => F32, f64 => F64, u128 => V128 }
+impl_conversion_for_wasmvalue! { i32 => I32, i64 => I64, f32 => F32, f64 => F64, u128 => V128, ExternRef => RefExtern, FuncRef => RefFunc }