summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenry Gressmann <mail@henrygressmann.de>2025-04-23 20:54:03 +0200
committerGitHub <noreply@github.com>2025-04-23 20:54:03 +0200
commitc1a8cfad737cc79772b44a99088bcccd0ab6ee02 (patch)
treea6e56a08d2063612c3eb2afb0189a688af137f29
parent1252a8936eb2a69496efc849f3eb59e72b964920 (diff)
parent3664c8b79918ffad109ccec32336d38c299f1351 (diff)
Merge pull request #39 from explodingcamera/feat/simd
initial simd support
-rw-r--r--Cargo.lock112
-rw-r--r--Cargo.toml6
-rw-r--r--crates/cli/src/args.rs1
-rw-r--r--crates/cli/src/bin.rs2
-rw-r--r--crates/cli/src/wat.rs2
-rw-r--r--crates/parser/src/conversion.rs1
-rw-r--r--crates/parser/src/lib.rs9
-rw-r--r--crates/parser/src/module.rs2
-rw-r--r--crates/parser/src/visit.rs16
-rw-r--r--crates/tinywasm/Cargo.toml10
-rw-r--r--crates/tinywasm/src/interpreter/executor.rs422
-rw-r--r--crates/tinywasm/src/interpreter/num_helpers.rs27
-rw-r--r--crates/tinywasm/src/interpreter/stack/call_stack.rs8
-rw-r--r--crates/tinywasm/src/interpreter/stack/value_stack.rs25
-rw-r--r--crates/tinywasm/src/interpreter/values.rs60
-rw-r--r--crates/tinywasm/src/lib.rs2
-rw-r--r--crates/tinywasm/src/store/memory.rs45
-rw-r--r--crates/tinywasm/src/store/mod.rs1
-rw-r--r--crates/tinywasm/tests/generated/wasm-1.csv2
-rw-r--r--crates/tinywasm/tests/generated/wasm-2.csv2
-rw-r--r--crates/tinywasm/tests/generated/wasm-memory64.csv2
-rw-r--r--crates/tinywasm/tests/generated/wasm-multi-memory.csv2
-rw-r--r--crates/tinywasm/tests/generated/wasm-relaxed-simd.csv1
-rw-r--r--crates/tinywasm/tests/generated/wasm-simd.csv2
-rw-r--r--crates/tinywasm/tests/host_func_signature_check.rs2
-rw-r--r--crates/tinywasm/tests/test-wasm-1.rs2
-rw-r--r--crates/tinywasm/tests/test-wasm-2.rs2
-rw-r--r--crates/tinywasm/tests/test-wasm-3.rs2
-rw-r--r--crates/tinywasm/tests/test-wasm-annotations.rs2
-rw-r--r--crates/tinywasm/tests/test-wasm-extended-const.rs2
-rw-r--r--crates/tinywasm/tests/test-wasm-multi-memory.rs2
-rw-r--r--crates/tinywasm/tests/test-wasm-relaxed-simd.rs2
-rw-r--r--crates/tinywasm/tests/test-wasm-simd.rs13
-rw-r--r--crates/tinywasm/tests/test-wast.rs2
-rw-r--r--crates/tinywasm/tests/testsuite/mod.rs2
-rw-r--r--crates/tinywasm/tests/testsuite/run.rs4
-rw-r--r--crates/tinywasm/tests/testsuite/util.rs30
-rw-r--r--crates/types/src/instructions.rs11
-rw-r--r--crates/types/src/lib.rs2
-rw-r--r--crates/types/src/value.rs8
-rw-r--r--examples/archive.rs2
-rw-r--r--examples/funcref_callbacks.rs2
-rw-r--r--examples/wasm-rust.rs2
43 files changed, 714 insertions, 142 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8bdb809..acdc41b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -63,9 +63,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "bitflags"
-version = "2.8.0"
+version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
+checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
[[package]]
name = "bumpalo"
@@ -114,18 +114,18 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.31"
+version = "4.5.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767"
+checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
-version = "4.5.31"
+version = "4.5.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863"
+checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5"
dependencies = [
"anstyle",
"clap_lex",
@@ -211,9 +211,9 @@ checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
[[package]]
name = "either"
-version = "1.14.0"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "embedded-io"
@@ -258,9 +258,9 @@ dependencies = [
[[package]]
name = "half"
-version = "2.4.1"
+version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
+checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9"
dependencies = [
"cfg-if",
"crunchy",
@@ -274,15 +274,15 @@ checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
[[package]]
name = "hermit-abi"
-version = "0.4.0"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
+checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e"
[[package]]
name = "humantime"
-version = "2.1.0"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f"
[[package]]
name = "include_dir"
@@ -311,9 +311,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
[[package]]
name = "indexmap"
-version = "2.7.1"
+version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
+checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
dependencies = [
"equivalent",
"hashbrown",
@@ -321,9 +321,9 @@ dependencies = [
[[package]]
name = "is-terminal"
-version = "0.4.15"
+version = "0.4.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37"
+checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
dependencies = [
"hermit-abi",
"libc",
@@ -341,9 +341,9 @@ dependencies = [
[[package]]
name = "itoa"
-version = "1.0.14"
+version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
+checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "leb128fmt"
@@ -353,9 +353,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "libc"
-version = "0.2.170"
+version = "0.2.171"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
+checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
[[package]]
name = "libm"
@@ -365,9 +365,9 @@ checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
[[package]]
name = "log"
-version = "0.4.26"
+version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
+checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "memchr"
@@ -386,15 +386,15 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.20.3"
+version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "oorandom"
-version = "11.1.4"
+version = "11.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
+checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
[[package]]
name = "owo-colors"
@@ -426,18 +426,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.93"
+version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
+checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.38"
+version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
@@ -499,9 +499,9 @@ checksum = "a157657054ffe556d8858504af8a672a054a6e0bd9e8ee531059100c0fa11bb2"
[[package]]
name = "ryu"
-version = "1.0.19"
+version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
+checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "same-file"
@@ -514,24 +514,24 @@ dependencies = [
[[package]]
name = "semver"
-version = "1.0.25"
+version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03"
+checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
[[package]]
name = "serde"
-version = "1.0.218"
+version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
+checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.218"
+version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
+checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
@@ -540,9 +540,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.139"
+version = "1.0.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6"
+checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
dependencies = [
"itoa",
"memchr",
@@ -552,9 +552,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.98"
+version = "2.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
+checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
dependencies = [
"proc-macro2",
"quote",
@@ -642,9 +642,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
-version = "1.0.17"
+version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "unicode-width"
@@ -664,9 +664,9 @@ dependencies = [
[[package]]
name = "wasm-encoder"
-version = "0.226.0"
+version = "0.229.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7d81b727619aec227dce83e7f7420d4e56c79acd044642a356ea045b98d4e13"
+checksum = "38ba1d491ecacb085a2552025c10a675a6fddcbd03b1fc9b36c536010ce265d2"
dependencies = [
"leb128fmt",
"wasmparser",
@@ -674,9 +674,9 @@ dependencies = [
[[package]]
name = "wasm-testsuite"
-version = "0.5.0"
+version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e01c897a970135c086793fa320de6632534ad7b4a519a3ca51c7ef40e6a567d7"
+checksum = "735333508bfc70a3cc7a7ed86b3cd53e4a775cbf78511eaec8ac4926ed3a0bf7"
dependencies = [
"include_dir",
"wast",
@@ -684,9 +684,9 @@ dependencies = [
[[package]]
name = "wasmparser"
-version = "0.226.0"
+version = "0.229.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc28600dcb2ba68d7e5f1c3ba4195c2bddc918c0243fd702d0b6dbd05689b681"
+checksum = "0cc3b1f053f5d41aa55640a1fa9b6d1b8a9e4418d118ce308d20e24ff3575a8c"
dependencies = [
"bitflags",
"indexmap",
@@ -695,9 +695,9 @@ dependencies = [
[[package]]
name = "wast"
-version = "226.0.0"
+version = "229.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bb903956d0151eabb6c30a2304dd61e5c8d7182805226120c2b6d611fb09a26"
+checksum = "63fcaff613c12225696bb163f79ca38ffb40e9300eff0ff4b8aa8b2f7eadf0d9"
dependencies = [
"bumpalo",
"leb128fmt",
@@ -708,9 +708,9 @@ dependencies = [
[[package]]
name = "wat"
-version = "1.226.0"
+version = "1.229.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f89a90ef2c401b8b5b2b704020bfa7a7f69b93c3034c7a4b4a88e21e9966581"
+checksum = "4189bad08b70455a9e9e67dc126d2dcf91fac143a80f1046747a5dde6d4c33e0"
dependencies = [
"wast",
]
diff --git a/Cargo.toml b/Cargo.toml
index e433260..1f645cf 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,9 +4,9 @@ default-members=[".", "crates/tinywasm", "crates/types", "crates/parser"]
resolver="2"
[workspace.dependencies]
-wast="226"
-wat="1.226"
-wasmparser={version="0.226", default-features=false}
+wast="229"
+wat="1.229"
+wasmparser={version="0.229", default-features=false}
eyre="0.6"
log="0.4"
pretty_env_logger="0.5"
diff --git a/crates/cli/src/args.rs b/crates/cli/src/args.rs
index 96c3605..1fec2d5 100644
--- a/crates/cli/src/args.rs
+++ b/crates/cli/src/args.rs
@@ -25,6 +25,7 @@ impl FromStr for WasmArg {
"i64" => val.parse::<i64>().map_err(|e| format!("invalid argument value for i64: {e:?}"))?.into(),
"f32" => val.parse::<f32>().map_err(|e| format!("invalid argument value for f32: {e:?}"))?.into(),
"f64" => val.parse::<f64>().map_err(|e| format!("invalid argument value for f64: {e:?}"))?.into(),
+ "v128" => val.parse::<i128>().map_err(|e| format!("invalid argument value for v128: {e:?}"))?.into(),
t => return Err(format!("Invalid arg type: {t}")),
};
diff --git a/crates/cli/src/bin.rs b/crates/cli/src/bin.rs
index 6efbba1..8c0fe93 100644
--- a/crates/cli/src/bin.rs
+++ b/crates/cli/src/bin.rs
@@ -4,7 +4,7 @@ use argh::FromArgs;
use args::WasmArg;
use eyre::Result;
use log::{debug, info};
-use tinywasm::{types::WasmValue, Module};
+use tinywasm::{Module, types::WasmValue};
use crate::args::to_wasm_args;
mod args;
diff --git a/crates/cli/src/wat.rs b/crates/cli/src/wat.rs
index fd00a8e..8d2998d 100644
--- a/crates/cli/src/wat.rs
+++ b/crates/cli/src/wat.rs
@@ -1,6 +1,6 @@
use wast::{
- parser::{self, ParseBuffer},
Wat,
+ parser::{self, ParseBuffer},
};
pub fn wat2wasm(wat: &str) -> Vec<u8> {
diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs
index 86548d6..a4e3b35 100644
--- a/crates/parser/src/conversion.rs
+++ b/crates/parser/src/conversion.rs
@@ -261,6 +261,7 @@ pub(crate) fn process_const_operators(ops: OperatorsReader<'_>) -> Result<ConstI
wasmparser::Operator::I64Const { value } => Ok(ConstInstruction::I64Const(*value)),
wasmparser::Operator::F32Const { value } => Ok(ConstInstruction::F32Const(f32::from_bits(value.bits()))),
wasmparser::Operator::F64Const { value } => Ok(ConstInstruction::F64Const(f64::from_bits(value.bits()))),
+ wasmparser::Operator::V128Const { value } => Ok(ConstInstruction::V128Const(value.i128())),
wasmparser::Operator::GlobalGet { global_index } => Ok(ConstInstruction::GlobalGet(*global_index)),
op => Err(crate::ParseError::UnsupportedOperator(format!("Unsupported const instruction: {op:?}"))),
}
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index e5022c5..aa33995 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -70,8 +70,6 @@ impl Parser {
gc_types: true,
stack_switching: false,
component_model: false,
- component_model_nested_names: false,
- component_model_values: false,
exceptions: false,
gc: false,
memory_control: false,
@@ -79,7 +77,12 @@ impl Parser {
threads: false,
shared_everything_threads: false,
legacy_exceptions: false,
- component_model_async: false,
+ cm_async: false,
+ cm_async_builtins: false,
+ cm_async_stackful: false,
+ cm_nested_names: false,
+ cm_values: false,
+ cm_error_context: false,
};
Validator::new_with_features(features.into())
}
diff --git a/crates/parser/src/module.rs b/crates/parser/src/module.rs
index ff6b22b..0e17ad9 100644
--- a/crates/parser/src/module.rs
+++ b/crates/parser/src/module.rs
@@ -130,7 +130,7 @@ impl ModuleReader {
return Err(ParseError::DuplicateSection("Code section".into()));
}
self.code.reserve(count as usize);
- validator.code_section_start(count, &range)?;
+ validator.code_section_start(&range)?;
}
CodeSectionEntry(function) => {
debug!("Found code section entry");
diff --git a/crates/parser/src/visit.rs b/crates/parser/src/visit.rs
index 8ed44be..10005c0 100644
--- a/crates/parser/src/visit.rs
+++ b/crates/parser/src/visit.rs
@@ -46,7 +46,7 @@ pub(crate) fn process_operators_and_validate<R: WasmModuleResources>(
reader.visit_operator(&mut ValidateThenVisit(reader.original_position(), &mut builder))??;
}
- builder.validator_finish(reader.original_position())?;
+ reader.finish()?;
if !builder.errors.is_empty() {
return Err(builder.errors.remove(0));
}
@@ -111,7 +111,7 @@ macro_rules! define_mem_operands_simd_lane {
pub(crate) struct FunctionBuilder<R: WasmModuleResources> {
validator: FuncValidator<R>,
instructions: Vec<Instruction>,
- v128_constants: Vec<u128>,
+ v128_constants: Vec<i128>,
label_ptrs: Vec<usize>,
local_addr_map: Vec<u32>,
errors: Vec<crate::ParseError>,
@@ -124,10 +124,6 @@ impl<R: WasmModuleResources> FunctionBuilder<R> {
) -> impl VisitOperator<'_, Output = Result<(), wasmparser::BinaryReaderError>> + VisitSimdOperator<'_> {
self.validator.simd_visitor(offset)
}
-
- pub(crate) fn validator_finish(&mut self, offset: usize) -> Result<(), wasmparser::BinaryReaderError> {
- self.validator.finish(offset)
- }
}
impl<R: WasmModuleResources> FunctionBuilder<R> {
@@ -534,12 +530,12 @@ impl<R: WasmModuleResources> wasmparser::VisitSimdOperator<'_> for FunctionBuild
}
fn visit_i8x16_shuffle(&mut self, lanes: [u8; 16]) -> Self::Output {
- self.v128_constants.push(u128::from_le_bytes(lanes));
- self.instructions.push(Instruction::I8x16Shuffle(self.v128_constants.len() as u32 - 1));
+ self.instructions.push(Instruction::I8x16Shuffle(self.v128_constants.len() as u32));
+ self.v128_constants.push(i128::from_le_bytes(lanes));
}
fn visit_v128_const(&mut self, value: wasmparser::V128) -> Self::Output {
- self.v128_constants.push(value.i128() as u128);
- self.instructions.push(Instruction::V128Const(self.v128_constants.len() as u32 - 1));
+ self.instructions.push(Instruction::V128Const(self.v128_constants.len() as u32));
+ self.v128_constants.push(value.i128());
}
}
diff --git a/crates/tinywasm/Cargo.toml b/crates/tinywasm/Cargo.toml
index 9be8233..3281476 100644
--- a/crates/tinywasm/Cargo.toml
+++ b/crates/tinywasm/Cargo.toml
@@ -20,7 +20,7 @@ tinywasm-types={version="0.9.0-alpha.0", path="../types", default-features=false
libm={version="0.2", default-features=false}
[dev-dependencies]
-wasm-testsuite={version="0.5.0"}
+wasm-testsuite={version="0.5.3"}
indexmap="2.7"
wast={workspace=true}
wat={workspace=true}
@@ -38,6 +38,9 @@ std=["tinywasm-parser?/std", "tinywasm-types/std"]
parser=["dep:tinywasm-parser"]
archive=["tinywasm-types/archive"]
+# enable simd support (unstable / unfinished)
+__simd=[]
+
[[test]]
name="test-wasm-1"
harness=false
@@ -82,6 +85,11 @@ harness=false
test=false
[[test]]
+name="test-wasm-simd"
+harness=false
+test=false
+
+[[test]]
name="test-wast"
harness=false
test=false
diff --git a/crates/tinywasm/src/interpreter/executor.rs b/crates/tinywasm/src/interpreter/executor.rs
index 4ba4556..4bf4f5d 100644
--- a/crates/tinywasm/src/interpreter/executor.rs
+++ b/crates/tinywasm/src/interpreter/executor.rs
@@ -4,9 +4,18 @@ use super::no_std_floats::NoStdFloatExt;
use alloc::{format, rc::Rc, string::ToString};
use core::ops::ControlFlow;
+
use interpreter::stack::CallFrame;
use tinywasm_types::*;
+#[cfg(all(feature = "std", feature = "__simd"))]
+use crate::std::simd::StdFloat;
+#[cfg(feature = "__simd")]
+use core::simd::{cmp::*, num::*, *};
+
+#[cfg(feature = "__simd")]
+use core::ops::{Index, IndexMut, Shl, Shr};
+
use super::num_helpers::*;
use super::stack::{BlockFrame, BlockType, Stack};
use super::values::*;
@@ -41,6 +50,8 @@ impl<'store, 'stack> Executor<'store, 'stack> {
#[inline(always)]
fn exec_next(&mut self) -> ControlFlow<Option<Error>> {
use tinywasm_types::Instruction::*;
+
+ #[rustfmt::skip]
match self.cf.fetch_instr() {
Nop | BrLabel(_) | I32ReinterpretF32 | I64ReinterpretF64 | F32ReinterpretI32 | F64ReinterpretI64 => {}
Unreachable => self.exec_unreachable()?,
@@ -305,6 +316,363 @@ impl<'store, 'stack> Executor<'store, 'stack> {
LocalCopy128(from, to) => self.exec_local_copy::<Value128>(*from, *to),
LocalCopyRef(from, to) => self.exec_local_copy::<ValueRef>(*from, *to),
+ #[cfg(feature = "__simd")] V128Not => self.stack.values.replace_top_same::<Value128>(|v| Ok(!v)).to_cf()?,
+ #[cfg(feature = "__simd")] V128And => self.stack.values.calculate_same::<Value128>(|a, b| Ok(a & b)).to_cf()?,
+ #[cfg(feature = "__simd")] V128AndNot => self.stack.values.calculate_same::<Value128>(|a, b| Ok(a & (!b))).to_cf()?,
+ #[cfg(feature = "__simd")] V128Or => self.stack.values.calculate_same::<Value128>(|a, b| Ok(a | b)).to_cf()?,
+ #[cfg(feature = "__simd")] V128Xor => self.stack.values.calculate_same::<Value128>(|a, b| Ok(a ^ b)).to_cf()?,
+ #[cfg(feature = "__simd")] V128Bitselect => self.stack.values.calculate_same_3::<Value128>(|v1, v2, c| Ok((v1 & c) | (v2 & !c))).to_cf()?,
+ #[cfg(feature = "__simd")] V128AnyTrue => self.stack.values.replace_top::<Value128, i32>(|v| Ok((v.reduce_or() != 0) as i32)).to_cf()?,
+ #[cfg(feature = "__simd")] I8x16Swizzle => self.stack.values.calculate_same::<Value128>(|a, s| Ok(a.swizzle_dyn(s))).to_cf()?,
+ #[cfg(feature = "__simd")] V128Load(arg) => self.exec_mem_load::<Value128, 16, _>(arg.mem_addr(), arg.offset(), |v| v)?,
+ #[cfg(feature = "__simd")] V128Store(arg) => self.exec_mem_store::<Value128, Value128, 16>(arg.mem_addr(), arg.offset(), |v| v)?,
+
+ #[cfg(feature = "__simd")] V128Store8Lane(arg, lane) => self.exec_mem_store_lane::<i8x16, i8, 1>(arg.mem_addr(), arg.offset(), *lane)?,
+ #[cfg(feature = "__simd")] V128Store16Lane(arg, lane) => self.exec_mem_store_lane::<i16x8, i16, 2>(arg.mem_addr(), arg.offset(), *lane)?,
+ #[cfg(feature = "__simd")] V128Store32Lane(arg, lane) => self.exec_mem_store_lane::<i32x4, i32, 4>(arg.mem_addr(), arg.offset(), *lane)?,
+ #[cfg(feature = "__simd")] V128Store64Lane(arg, lane) => self.exec_mem_store_lane::<i64x2, i64, 8>(arg.mem_addr(), arg.offset(), *lane)?,
+
+ // Load a single 32-bit or 64-bit element into the lowest bits of a v128 vector, and initialize all other bits of the v128 vector to zero.
+ #[cfg(feature = "__simd")] V128Load32Zero(arg) => self.exec_mem_load::<i32, 4, Value128>(arg.mem_addr(), arg.offset(), |v| {
+ let bytes = v.to_le_bytes();
+ u8x16::from_array([bytes[0], bytes[1], bytes[2], bytes[3], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
+ })?,
+ #[cfg(feature = "__simd")] V128Load64Zero(arg) => self.exec_mem_load::<i64, 8, Value128>(arg.mem_addr(), arg.offset(), |v| {
+ let bytes = v.to_le_bytes();
+ u8x16::from_array([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], 0, 0, 0, 0, 0, 0, 0, 0])
+ })?,
+
+ #[cfg(feature = "__simd")] V128Const(arg) => self.exec_const::<Value128>( self.cf.data().v128_constants[*arg as usize].to_le_bytes().into()),
+
+ #[cfg(feature = "__simd")] I8x16ExtractLaneS(lane) => self.stack.values.replace_top::<i8x16, i32>(|v| Ok(v[*lane as usize] as i32)).to_cf()?,
+ #[cfg(feature = "__simd")] I8x16ExtractLaneU(lane) => self.stack.values.replace_top::<u8x16, i32>(|v| Ok(v[*lane as usize] as i32)).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8ExtractLaneS(lane) => self.stack.values.replace_top::<i16x8, i32>(|v| Ok(v[*lane as usize] as i32)).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8ExtractLaneU(lane) => self.stack.values.replace_top::<u16x8, i32>(|v| Ok(v[*lane as usize] as i32)).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4ExtractLane(lane) => self.stack.values.replace_top::<i32x4, i32>(|v| Ok(v[*lane as usize])).to_cf()?,
+ #[cfg(feature = "__simd")] I64x2ExtractLane(lane) => self.stack.values.replace_top::<i64x2, i64>(|v| Ok(v[*lane as usize])).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4ExtractLane(lane) => self.stack.values.replace_top::<f32x4, f32>(|v| Ok(v[*lane as usize])).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2ExtractLane(lane) => self.stack.values.replace_top::<f64x2, f64>(|v| Ok(v[*lane as usize])).to_cf()?,
+
+ #[cfg(feature = "__simd")] V128Load8Lane(arg, lane) => self.exec_mem_load_lane::<i8, i8x16, 1>(arg.mem_addr(), arg.offset(), *lane)?,
+ #[cfg(feature = "__simd")] V128Load16Lane(arg, lane) => self.exec_mem_load_lane::<i16, i16x8, 2>(arg.mem_addr(), arg.offset(), *lane)?,
+ #[cfg(feature = "__simd")] V128Load32Lane(arg, lane) => self.exec_mem_load_lane::<i32, i32x4, 4>(arg.mem_addr(), arg.offset(), *lane)?,
+ #[cfg(feature = "__simd")] V128Load64Lane(arg, lane) => self.exec_mem_load_lane::<i64, i64x2, 8>(arg.mem_addr(), arg.offset(), *lane)?,
+
+ #[cfg(feature = "__simd")] I8x16Splat => self.stack.values.replace_top::<i32, i8x16>(|v| Ok(Simd::<i8, 16>::splat(v as i8))).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8Splat => self.stack.values.replace_top::<i32, i16x8>(|v| Ok(Simd::<i16, 8>::splat(v as i16))).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4Splat => self.stack.values.replace_top::<i32, i32x4>(|v| Ok(Simd::<i32, 4>::splat(v))).to_cf()?,
+ #[cfg(feature = "__simd")] I64x2Splat => self.stack.values.replace_top::<i64, i64x2>(|v| Ok(Simd::<i64, 2>::splat(v))).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Splat => self.stack.values.replace_top::<f32, f32x4>(|v| Ok(Simd::<f32, 4>::splat(v))).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Splat => self.stack.values.replace_top::<f64, f64x2>(|v| Ok(Simd::<f64, 2>::splat(v))).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16Eq => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_eq(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8Eq => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_eq(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4Eq => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_eq(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Eq => self.stack.values.calculate::<f32x4, _>(|a, b| Ok(a.simd_eq(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Eq => self.stack.values.calculate::<f64x2, _>(|a, b| Ok(a.simd_eq(b).to_int())).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16Ne => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_ne(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8Ne => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_ne(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4Ne => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_ne(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Ne => self.stack.values.calculate::<f32x4, _>(|a, b| Ok(a.simd_ne(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Ne => self.stack.values.calculate::<f64x2, _>(|a, b| Ok(a.simd_ne(b).to_int())).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16LtS => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_lt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8LtS => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_lt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4LtS => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_lt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I64x2LtS => self.stack.values.calculate_same::<i64x2>(|a, b| Ok(a.simd_lt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I8x16LtU => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_lt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8LtU => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_lt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4LtU => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_lt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Lt => self.stack.values.calculate::<f32x4, _>(|a, b| Ok(a.simd_lt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Lt => self.stack.values.calculate::<f64x2, _>(|a, b| Ok(a.simd_lt(b).to_int())).to_cf()?,
+
+ #[cfg(feature = "__simd")] I64x2GtS => self.stack.values.calculate_same::<i64x2>(|a, b| Ok(a.simd_gt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Gt => self.stack.values.calculate::<f32x4, _>(|a, b| Ok(a.simd_gt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Gt => self.stack.values.calculate::<f64x2, _>(|a, b| Ok(a.simd_gt(b).to_int())).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16GtS => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_gt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8GtS => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_gt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4GtS => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_gt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I64x2LeS => self.stack.values.calculate_same::<i64x2>(|a, b| Ok(a.simd_le(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Le => self.stack.values.calculate::<f32x4,_>(|a, b| Ok(a.simd_le(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Le => self.stack.values.calculate::<f64x2,_>(|a, b| Ok(a.simd_le(b).to_int())).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16GtU => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_gt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8GtU => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_gt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4GtU => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_gt(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I64x2GeS => self.stack.values.calculate_same::<i64x2>(|a, b| Ok(a.simd_ge(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Ge => self.stack.values.calculate::<f32x4,_>(|a, b| Ok(a.simd_ge(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Ge => self.stack.values.calculate::<f64x2,_>(|a, b| Ok(a.simd_ge(b).to_int())).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16LeS => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_le(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8LeS => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_le(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4LeS => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_le(b).to_int())).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16LeU => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_le(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8LeU => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_le(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4LeU => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_le(b).to_int())).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16GeS => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_ge(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8GeS => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_ge(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4GeS => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_ge(b).to_int())).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16GeU => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_ge(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8GeU => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_ge(b).to_int())).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4GeU => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_ge(b).to_int())).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16Abs => self.stack.values.replace_top_same::<i8x16>(|a| Ok(a.abs())).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8Abs => self.stack.values.replace_top_same::<i16x8>(|a| Ok(a.abs())).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4Abs => self.stack.values.replace_top_same::<i32x4>(|a| Ok(a.abs())).to_cf()?,
+ #[cfg(feature = "__simd")] I64x2Abs => self.stack.values.replace_top_same::<i64x2>(|a| Ok(a.abs())).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16Neg => self.stack.values.replace_top_same::<i8x16>(|a| Ok(-a)).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8Neg => self.stack.values.replace_top_same::<i16x8>(|a| Ok(-a)).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4Neg => self.stack.values.replace_top_same::<i32x4>(|a| Ok(-a)).to_cf()?,
+ #[cfg(feature = "__simd")] I64x2Neg => self.stack.values.replace_top_same::<i64x2>(|a| Ok(-a)).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16AllTrue => self.stack.values.replace_top::<i8x16, i32>(|v| Ok((v.simd_ne(Simd::splat(0)).all()) as i32)).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8AllTrue => self.stack.values.replace_top::<i16x8, i32>(|v| Ok((v.simd_ne(Simd::splat(0)).all()) as i32)).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4AllTrue => self.stack.values.replace_top::<i32x4, i32>(|v| Ok((v.simd_ne(Simd::splat(0)).all()) as i32)).to_cf()?,
+ #[cfg(feature = "__simd")] I64x2AllTrue => self.stack.values.replace_top::<i64x2, i32>(|v| Ok((v.simd_ne(Simd::splat(0)).all()) as i32)).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16Bitmask => self.stack.values.replace_top::<i8x16, i32>(|v| Ok(v.simd_lt(Simd::splat(0)).to_bitmask() as i32)).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8Bitmask => self.stack.values.replace_top::<i16x8, i32>(|v| Ok(v.simd_lt(Simd::splat(0)).to_bitmask() as i32)).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4Bitmask => self.stack.values.replace_top::<i32x4, i32>(|v| Ok(v.simd_lt(Simd::splat(0)).to_bitmask() as i32)).to_cf()?,
+ #[cfg(feature = "__simd")] I64x2Bitmask => self.stack.values.replace_top::<i64x2, i32>(|v| Ok(v.simd_lt(Simd::splat(0)).to_bitmask() as i32)).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16Shl => self.stack.values.calculate_diff::<i32, i8x16, i8x16>(|a, b| Ok(b.shl(a as i8))).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8Shl => self.stack.values.calculate_diff::<i32, i16x8, i16x8>(|a, b| Ok(b.shl(a as i16))).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4Shl => self.stack.values.calculate_diff::<i32, i32x4, i32x4>(|a, b| Ok(b.shl(a))).to_cf()?,
+ #[cfg(feature = "__simd")] I64x2Shl => self.stack.values.calculate_diff::<i32, i64x2, i64x2>(|a, b| Ok(b.shl(a as i64))).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16ShrS => self.stack.values.calculate_diff::<i32, i8x16, i8x16>(|a, b| Ok(b.shr(a as i8))).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8ShrS => self.stack.values.calculate_diff::<i32, i16x8, i16x8>(|a, b| Ok(b.shr(a as i16))).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4ShrS => self.stack.values.calculate_diff::<i32, i32x4, i32x4>(|a, b| Ok(b.shr(a))).to_cf()?,
+ #[cfg(feature = "__simd")] I64x2ShrS => self.stack.values.calculate_diff::<i32, i64x2, i64x2>(|a, b| Ok(b.shr(a as i64))).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16ShrU => self.stack.values.calculate_diff::<i32, u8x16, u8x16>(|a, b| Ok(b.shr(a as u8))).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8ShrU => self.stack.values.calculate_diff::<i32, u16x8, u16x8>(|a, b| Ok(b.shr(a as u16))).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4ShrU => self.stack.values.calculate_diff::<i32, u32x4, u32x4>(|a, b| Ok(b.shr(a as u32))).to_cf()?,
+ #[cfg(feature = "__simd")] I64x2ShrU => self.stack.values.calculate_diff::<i32, u64x2, u64x2>(|a, b| Ok(b.shr(a as u64))).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16Add => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a + b)).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8Add => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a + b)).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4Add => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a + b)).to_cf()?,
+ #[cfg(feature = "__simd")] I64x2Add => self.stack.values.calculate_same::<i64x2>(|a, b| Ok(a + b)).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16Sub => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a - b)).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8Sub => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a - b)).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4Sub => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a - b)).to_cf()?,
+ #[cfg(feature = "__simd")] I64x2Sub => self.stack.values.calculate_same::<i64x2>(|a, b| Ok(a - b)).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16MinS => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_min(b))).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8MinS => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_min(b))).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4MinS => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_min(b))).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16MinU => self.stack.values.calculate_same::<u8x16>(|a, b| Ok(a.simd_min(b))).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8MinU => self.stack.values.calculate_same::<u16x8>(|a, b| Ok(a.simd_min(b))).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4MinU => self.stack.values.calculate_same::<u32x4>(|a, b| Ok(a.simd_min(b))).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16MaxS => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_max(b))).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8MaxS => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_max(b))).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4MaxS => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_max(b))).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16MaxU => self.stack.values.calculate_same::<u8x16>(|a, b| Ok(a.simd_max(b))).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8MaxU => self.stack.values.calculate_same::<u16x8>(|a, b| Ok(a.simd_max(b))).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4MaxU => self.stack.values.calculate_same::<u32x4>(|a, b| Ok(a.simd_max(b))).to_cf()?,
+
+ #[cfg(feature = "__simd")] I64x2Mul => self.stack.values.calculate_same::<i64x2>(|a, b| Ok(a * b)).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8Mul => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a * b)).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4Mul => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a * b)).to_cf()?,
+
+ #[cfg(feature = "__simd")] I8x16NarrowI16x8S => unimplemented!(),
+ #[cfg(feature = "__simd")] I8x16NarrowI16x8U => unimplemented!(),
+ #[cfg(feature = "__simd")] I16x8NarrowI32x4S => unimplemented!(),
+ #[cfg(feature = "__simd")] I16x8NarrowI32x4U => unimplemented!(),
+
+ #[cfg(feature = "__simd")] I8x16AddSatS => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.saturating_add(b))).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8AddSatS => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.saturating_add(b))).to_cf()?,
+ #[cfg(feature = "__simd")] I8x16AddSatU => self.stack.values.calculate_same::<u8x16>(|a, b| Ok(a.saturating_add(b))).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8AddSatU => self.stack.values.calculate_same::<u16x8>(|a, b| Ok(a.saturating_add(b))).to_cf()?,
+ #[cfg(feature = "__simd")] I8x16SubSatS => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.saturating_sub(b))).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8SubSatS => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.saturating_sub(b))).to_cf()?,
+ #[cfg(feature = "__simd")] I8x16SubSatU => self.stack.values.calculate_same::<u8x16>(|a, b| Ok(a.saturating_sub(b))).to_cf()?,
+ #[cfg(feature = "__simd")] I16x8SubSatU => self.stack.values.calculate_same::<u16x8>(|a, b| Ok(a.saturating_sub(b))).to_cf()?,
+
+ #[cfg(feature = "__simd")] I16x8ExtAddPairwiseI8x16S => unimplemented!(),
+ #[cfg(feature = "__simd")] I16x8ExtAddPairwiseI8x16U => unimplemented!(),
+ #[cfg(feature = "__simd")] I32x4ExtAddPairwiseI16x8S => unimplemented!(),
+ #[cfg(feature = "__simd")] I32x4ExtAddPairwiseI16x8U => unimplemented!(),
+
+ #[cfg(feature = "__simd")] I16x8ExtMulLowI8x16S => unimplemented!(),
+ #[cfg(feature = "__simd")] I16x8ExtMulLowI8x16U => unimplemented!(),
+ #[cfg(feature = "__simd")] I16x8ExtMulHighI8x16S => unimplemented!(),
+ #[cfg(feature = "__simd")] I16x8ExtMulHighI8x16U => unimplemented!(),
+ #[cfg(feature = "__simd")] I32x4ExtMulLowI16x8S => unimplemented!(),
+ #[cfg(feature = "__simd")] I32x4ExtMulLowI16x8U => unimplemented!(),
+ #[cfg(feature = "__simd")] I32x4ExtMulHighI16x8S => unimplemented!(),
+ #[cfg(feature = "__simd")] I32x4ExtMulHighI16x8U => unimplemented!(),
+ #[cfg(feature = "__simd")] I64x2ExtMulLowI32x4S => unimplemented!(),
+ #[cfg(feature = "__simd")] I64x2ExtMulLowI32x4U => unimplemented!(),
+ #[cfg(feature = "__simd")] I64x2ExtMulHighI32x4S => unimplemented!(),
+ #[cfg(feature = "__simd")] I64x2ExtMulHighI32x4U => unimplemented!(),
+
+ #[cfg(feature = "__simd")] I16x8ExtendLowI8x16S => unimplemented!(),
+ #[cfg(feature = "__simd")] I16x8ExtendLowI8x16U => unimplemented!(),
+ #[cfg(feature = "__simd")] I16x8ExtendHighI8x16S => unimplemented!(),
+ #[cfg(feature = "__simd")] I16x8ExtendHighI8x16U => unimplemented!(),
+ #[cfg(feature = "__simd")] I32x4ExtendLowI16x8S => unimplemented!(),
+ #[cfg(feature = "__simd")] I32x4ExtendLowI16x8U => unimplemented!(),
+ #[cfg(feature = "__simd")] I32x4ExtendHighI16x8S => unimplemented!(),
+ #[cfg(feature = "__simd")] I32x4ExtendHighI16x8U => unimplemented!(),
+ #[cfg(feature = "__simd")] I64x2ExtendLowI32x4S => unimplemented!(),
+ #[cfg(feature = "__simd")] I64x2ExtendLowI32x4U => unimplemented!(),
+ #[cfg(feature = "__simd")] I64x2ExtendHighI32x4S => unimplemented!(),
+ #[cfg(feature = "__simd")] I64x2ExtendHighI32x4U => unimplemented!(),
+
+ #[cfg(feature = "__simd")] I8x16Popcnt => self.stack.values.replace_top::<i8x16, _>(|v| Ok(v.count_ones())).to_cf()?,
+
+ #[cfg(feature = "__simd")]
+ I16x8Q15MulrSatS => self.stack.values.calculate_same::<i16x8>(|a, b| {
+ let subq15mulr = |a,b| {
+ let a = a as i32;
+ let b = b as i32;
+ let r = (a * b + 0x4000) >> 15;
+ if r > i16::MAX as i32 {
+ i16::MAX
+ } else if r < i16::MIN as i32 {
+ i16::MIN
+ } else {
+ r as i16
+ }
+ };
+ Ok(Simd::<i16, 8>::from_array([
+ subq15mulr(a[0], b[0]),
+ subq15mulr(a[1], b[1]),
+ subq15mulr(a[2], b[2]),
+ subq15mulr(a[3], b[3]),
+ subq15mulr(a[4], b[4]),
+ subq15mulr(a[5], b[5]),
+ subq15mulr(a[6], b[6]),
+ subq15mulr(a[7], b[7]),
+ ]))
+ }).to_cf()?,
+
+ #[cfg(feature = "__simd")]
+ I32x4DotI16x8S => self.stack.values.calculate::<i16x8, i32x4>(|a, b| {
+ Ok(Simd::<i32, 4>::from_array([
+ i32::from(a[0] * b[0] + a[1] * b[1]),
+ i32::from(a[2] * b[2] + a[3] * b[3]),
+ i32::from(a[4] * b[4] + a[5] * b[5]),
+ i32::from(a[6] * b[6] + a[7] * b[7]),
+ ]))
+ }).to_cf()?,
+
+ #[cfg(feature = "__simd")] F32x4Ceil => self.stack.values.replace_top_same::<f32x4>(|v| Ok(v.ceil())).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Ceil => self.stack.values.replace_top_same::<f64x2>(|v| Ok(v.ceil())).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Floor => self.stack.values.replace_top_same::<f32x4>(|v| Ok(v.floor())).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Floor => self.stack.values.replace_top_same::<f64x2>(|v| Ok(v.floor())).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Trunc => self.stack.values.replace_top_same::<f32x4>(|v| Ok(v.trunc())).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Trunc => self.stack.values.replace_top_same::<f64x2>(|v| Ok(v.trunc())).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Abs => self.stack.values.replace_top_same::<f32x4>(|v| Ok(v.abs())).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Abs => self.stack.values.replace_top_same::<f64x2>(|v| Ok(v.abs())).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Neg => self.stack.values.replace_top_same::<f32x4>(|v| Ok(-v)).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Neg => self.stack.values.replace_top_same::<f64x2>(|v| Ok(-v)).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Sqrt => self.stack.values.replace_top_same::<f32x4>(|v| Ok(canonicalize_f32x4(v.sqrt()))).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Sqrt => self.stack.values.replace_top_same::<f64x2>(|v| Ok(canonicalize_f64x2(v.sqrt()))).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Add => self.stack.values.calculate_same::<f32x4>(|a, b| Ok(canonicalize_f32x4(a + b))).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Add => self.stack.values.calculate_same::<f64x2>(|a, b| Ok(canonicalize_f64x2(a + b))).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Sub => self.stack.values.calculate_same::<f32x4>(|a, b| Ok(canonicalize_f32x4(a - b))).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Sub => self.stack.values.calculate_same::<f64x2>(|a, b| Ok(canonicalize_f64x2(a - b))).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Mul => self.stack.values.calculate_same::<f32x4>(|a, b| Ok(canonicalize_f32x4(a * b))).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Mul => self.stack.values.calculate_same::<f64x2>(|a, b| Ok(canonicalize_f64x2(a * b))).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4Div => self.stack.values.calculate_same::<f32x4>(|a, b| Ok(canonicalize_f32x4(a / b))).to_cf()?,
+ #[cfg(feature = "__simd")] F64x2Div => self.stack.values.calculate_same::<f64x2>(|a, b| Ok(canonicalize_f64x2(a / b))).to_cf()?,
+ #[cfg(feature = "__simd")]
+ F32x4Min => self.stack.values.calculate_same::<f32x4>(|a, b| {
+ Ok(Simd::<f32, 4>::from_array([
+ b[0].tw_minimum(a[0]),
+ b[1].tw_minimum(a[1]),
+ b[2].tw_minimum(a[2]),
+ b[3].tw_minimum(a[3]),
+ ]))
+ }).to_cf()?,
+
+ #[cfg(feature = "__simd")]
+ F64x2Min => self.stack.values.calculate_same::<f64x2>(|a, b| {
+ Ok(Simd::<f64, 2>::from_array([
+ b[0].tw_minimum(a[0]),
+ b[1].tw_minimum(a[1]),
+ ]))
+ }).to_cf()?,
+
+ #[cfg(feature = "__simd")]
+ F32x4Max => self.stack.values.calculate_same::<f32x4>(|a, b| {
+ Ok(Simd::<f32, 4>::from_array([
+ b[0].tw_maximum(a[0]),
+ b[1].tw_maximum(a[1]),
+ b[2].tw_maximum(a[2]),
+ b[3].tw_maximum(a[3]),
+ ]))
+ }).to_cf()?,
+
+ #[cfg(feature = "__simd")]
+ F64x2Max => self.stack.values.calculate_same::<f64x2>(|a, b| {
+ Ok(Simd::<f64, 2>::from_array([
+ b[0].tw_maximum(a[0]),
+ b[1].tw_maximum(a[1]),
+ ]))
+ }).to_cf()?,
+
+ #[cfg(feature = "__simd")]
+ F32x4PMin => self.stack.values.calculate_same::<f32x4>(|a, b| {
+ Ok(Simd::<f32, 4>::from_array([
+ if b[0] < a[0] { b[0] } else { a[0]},
+ if b[1] < a[1] { b[1] } else { a[1]},
+ if b[2] < a[2] { b[2] } else { a[2]},
+ if b[3] < a[3] { b[3] } else { a[3]},
+ ]))
+ }).to_cf()?,
+
+ #[cfg(feature = "__simd")]
+ F32x4PMax => self.stack.values.calculate_same::<f32x4>(|a, b| {
+ Ok(Simd::<f32, 4>::from_array([
+ if b[0] > a[0] { b[0] } else { a[0]},
+ if b[1] > a[1] { b[1] } else { a[1]},
+ if b[2] > a[2] { b[2] } else { a[2]},
+ if b[3] > a[3] { b[3] } else { a[3]},
+ ]))
+ }).to_cf()?,
+
+ #[cfg(feature = "__simd")]
+ F64x2PMin => self.stack.values.calculate_same::<f64x2>(|a, b| {
+ Ok(Simd::<f64, 2>::from_array([
+ if b[0] < a[0] { b[0] } else { a[0]},
+ if b[1] < a[1] { b[1] } else { a[1]},
+ ]))
+ }).to_cf()?,
+
+ #[cfg(feature = "__simd")]
+ F64x2PMax => self.stack.values.calculate_same::<f64x2>(|a, b| {
+ Ok(Simd::<f64, 2>::from_array([
+ if b[0] > a[0] { b[0] } else { a[0]},
+ if b[1] > a[1] { b[1] } else { a[1]},
+ ]))
+ }).to_cf()?,
+
+ // not correct
+ #[cfg(feature = "__simd")] I32x4TruncSatF32x4S => self.stack.values.replace_top::<f32x4, f32x4>(|v| Ok(v.trunc())).to_cf()?,
+ #[cfg(feature = "__simd")] I32x4TruncSatF32x4U => self.stack.values.replace_top::<f32x4, f32x4>(|v| Ok(v.trunc())).to_cf()?,
+ #[cfg(feature = "__simd")] F32x4ConvertI32x4S => {},
+ #[cfg(feature = "__simd")] F32x4ConvertI32x4U => {},
+ #[cfg(feature = "__simd")] F64x2ConvertLowI32x4S => {},
+ #[cfg(feature = "__simd")] F64x2ConvertLowI32x4U => {},
+ #[cfg(feature = "__simd")] F32x4DemoteF64x2Zero => {},
+ #[cfg(feature = "__simd")] F64x2PromoteLowF32x4 => {},
+ #[cfg(feature = "__simd")] I32x4TruncSatF64x2SZero => unimplemented!(),
+ #[cfg(feature = "__simd")] I32x4TruncSatF64x2UZero => unimplemented!(),
+
i => return ControlFlow::Break(Some(Error::UnsupportedFeature(format!("unimplemented opcode: {i:?}")))),
};
@@ -629,6 +997,34 @@ impl<'store, 'stack> Executor<'store, 'stack> {
}
}
+ #[cfg(feature = "__simd")]
+ fn exec_mem_load_lane<
+ LOAD: MemLoadable<LOAD_SIZE>,
+ INTO: InternalValue + IndexMut<usize, Output = LOAD>,
+ const LOAD_SIZE: usize,
+ >(
+ &mut self,
+ mem_addr: tinywasm_types::MemAddr,
+ offset: u64,
+ lane: u8,
+ ) -> ControlFlow<Option<Error>> {
+ let mem = self.store.get_mem(self.module.resolve_mem_addr(mem_addr));
+ let mut imm = self.stack.values.pop::<INTO>();
+ let val = self.stack.values.pop::<i32>() as u64;
+ let Some(Ok(addr)) = offset.checked_add(val).map(TryInto::try_into) else {
+ cold();
+ return ControlFlow::Break(Some(Error::Trap(Trap::MemoryOutOfBounds {
+ offset: val as usize,
+ len: LOAD_SIZE,
+ max: 0,
+ })));
+ };
+ let val = mem.load_as::<LOAD_SIZE, LOAD>(addr).to_cf()?;
+ imm[lane as usize] = val;
+ self.stack.values.push(imm);
+ ControlFlow::Continue(())
+ }
+
fn exec_mem_load<LOAD: MemLoadable<LOAD_SIZE>, const LOAD_SIZE: usize, TARGET: InternalValue>(
&mut self,
mem_addr: tinywasm_types::MemAddr,
@@ -642,7 +1038,7 @@ impl<'store, 'stack> Executor<'store, 'stack> {
false => self.stack.values.pop::<i32>() as u32 as u64,
};
- let Some(Ok(addr)) = offset.checked_add(addr).map(TryInto::try_into) else {
+ let Some(Ok(addr)) = offset.checked_add(addr).map(|a| a.try_into()) else {
cold();
return ControlFlow::Break(Some(Error::Trap(Trap::MemoryOutOfBounds {
offset: addr as usize,
@@ -654,6 +1050,30 @@ impl<'store, 'stack> Executor<'store, 'stack> {
self.stack.values.push(cast(val));
ControlFlow::Continue(())
}
+
+ #[cfg(feature = "__simd")]
+ fn exec_mem_store_lane<T: InternalValue + Index<usize, Output = U>, U: MemStorable<N> + Copy, const N: usize>(
+ &mut self,
+ mem_addr: tinywasm_types::MemAddr,
+ offset: u64,
+ lane: u8,
+ ) -> ControlFlow<Option<Error>> {
+ let mem = self.store.get_mem_mut(self.module.resolve_mem_addr(mem_addr));
+ let val = self.stack.values.pop::<T>();
+ let val = val[lane as usize].to_mem_bytes();
+
+ let addr = match mem.is_64bit() {
+ true => self.stack.values.pop::<i64>() as u64,
+ false => self.stack.values.pop::<i32>() as u32 as u64,
+ };
+
+ if let Err(e) = mem.store((offset + addr) as usize, val.len(), &val) {
+ return ControlFlow::Break(Some(e));
+ }
+
+ ControlFlow::Continue(())
+ }
+
fn exec_mem_store<T: InternalValue, U: MemStorable<N>, const N: usize>(
&mut self,
mem_addr: tinywasm_types::MemAddr,
diff --git a/crates/tinywasm/src/interpreter/num_helpers.rs b/crates/tinywasm/src/interpreter/num_helpers.rs
index 02fbc24..678c32e 100644
--- a/crates/tinywasm/src/interpreter/num_helpers.rs
+++ b/crates/tinywasm/src/interpreter/num_helpers.rs
@@ -74,7 +74,8 @@ macro_rules! impl_wasm_float_ops {
// https://webassembly.github.io/spec/core/exec/numerics.html#op-fnearest
fn tw_nearest(self) -> Self {
match self {
- x if x.is_nan() => x, // preserve NaN
+ // x if x.is_nan() => x, // preserve NaN
+ x if x.is_nan() => Self::NAN, // Do not preserve NaN
x if x.is_infinite() || x == 0.0 => x, // preserve infinities and zeros
x if (0.0..=0.5).contains(&x) => 0.0,
x if (-0.5..0.0).contains(&x) => -0.0,
@@ -99,7 +100,8 @@ macro_rules! impl_wasm_float_ops {
Some(core::cmp::Ordering::Less) => self,
Some(core::cmp::Ordering::Greater) => other,
Some(core::cmp::Ordering::Equal) => if self.is_sign_negative() && other.is_sign_positive() { self } else { other },
- None => self + other, // At least one input is NaN. Use `+` to perform NaN propagation and quieting.
+ // None => self + other, // At least one input is NaN. Use `+` to perform NaN propagation and quieting.
+ None => Self::NAN, // Do not preserve NaN
}
}
@@ -111,7 +113,8 @@ macro_rules! impl_wasm_float_ops {
Some(core::cmp::Ordering::Greater) => self,
Some(core::cmp::Ordering::Less) => other,
Some(core::cmp::Ordering::Equal) => if self.is_sign_negative() && other.is_sign_positive() { other } else { self },
- None => self + other, // At least one input is NaN. Use `+` to perform NaN propagation and quieting.
+ // None => self + other, // At least one input is NaN. Use `+` to perform NaN propagation and quieting.
+ None => Self::NAN, // Do not preserve NaN
}
}
}
@@ -180,3 +183,21 @@ macro_rules! impl_checked_wrapping_rem {
}
impl_checked_wrapping_rem! { i32 i64 u32 u64 }
+
+#[cfg(feature = "__simd")]
+/// replace all NaNs in a f32x4 with f32::NAN
+pub(crate) fn canonicalize_f32x4(x: core::simd::f32x4) -> core::simd::f32x4 {
+ use core::simd::{Simd, num::SimdFloat};
+ let nan = Simd::splat(f32::NAN);
+ let mask = x.is_nan();
+ mask.select(nan, x)
+}
+
+#[cfg(feature = "__simd")]
+/// replace all NaNs in a f64x2 with f64::NAN
+pub(crate) fn canonicalize_f64x2(x: core::simd::f64x2) -> core::simd::f64x2 {
+ use core::simd::{Simd, num::SimdFloat};
+ let nan = Simd::splat(f64::NAN);
+ let mask = x.is_nan();
+ mask.select(nan, x)
+}
diff --git a/crates/tinywasm/src/interpreter/stack/call_stack.rs b/crates/tinywasm/src/interpreter/stack/call_stack.rs
index 11bbe29..c7f02b6 100644
--- a/crates/tinywasm/src/interpreter/stack/call_stack.rs
+++ b/crates/tinywasm/src/interpreter/stack/call_stack.rs
@@ -7,7 +7,7 @@ use crate::{Error, unlikely};
use alloc::boxed::Box;
use alloc::{rc::Rc, vec, vec::Vec};
-use tinywasm_types::{Instruction, LocalAddr, ModuleInstanceAddr, WasmFunction, WasmValue};
+use tinywasm_types::{Instruction, LocalAddr, ModuleInstanceAddr, WasmFunction, WasmFunctionData, WasmValue};
pub(crate) const MAX_CALL_STACK_SIZE: usize = 1024;
@@ -71,6 +71,12 @@ impl CallFrame {
}
#[inline]
+ #[allow(dead_code)]
+ pub(crate) fn data(&self) -> &WasmFunctionData {
+ &self.func_instance.data
+ }
+
+ #[inline]
pub(crate) fn incr_instr_ptr(&mut self) {
self.instr_ptr += 1;
}
diff --git a/crates/tinywasm/src/interpreter/stack/value_stack.rs b/crates/tinywasm/src/interpreter/stack/value_stack.rs
index 9830c01..481a88c 100644
--- a/crates/tinywasm/src/interpreter/stack/value_stack.rs
+++ b/crates/tinywasm/src/interpreter/stack/value_stack.rs
@@ -72,6 +72,12 @@ impl ValueStack {
}
#[inline]
+ #[allow(dead_code)]
+ pub(crate) fn calculate_same_3<T: InternalValue>(&mut self, func: impl FnOnce(T, T, T) -> Result<T>) -> Result<()> {
+ T::stack_calculate3(self, func)
+ }
+
+ #[inline]
pub(crate) fn calculate<T: InternalValue, U: InternalValue>(
&mut self,
func: impl FnOnce(T, T) -> Result<U>,
@@ -83,6 +89,18 @@ impl ValueStack {
}
#[inline]
+ #[allow(dead_code)]
+ pub(crate) fn calculate_diff<A: InternalValue, B: InternalValue, RES: InternalValue>(
+ &mut self,
+ func: impl FnOnce(A, B) -> Result<RES>,
+ ) -> Result<()> {
+ let v2 = B::stack_pop(self);
+ let v1 = A::stack_pop(self);
+ RES::stack_push(self, func(v1, v2)?);
+ Ok(())
+ }
+
+ #[inline]
pub(crate) fn replace_top<T: InternalValue, U: InternalValue>(
&mut self,
func: impl FnOnce(T) -> Result<U>,
@@ -170,11 +188,16 @@ impl ValueStack {
match val_type {
ValType::I32 => WasmValue::I32(self.pop()),
ValType::I64 => WasmValue::I64(self.pop()),
- ValType::V128 => WasmValue::V128(self.pop()),
ValType::F32 => WasmValue::F32(self.pop()),
ValType::F64 => WasmValue::F64(self.pop()),
ValType::RefExtern => WasmValue::RefExtern(ExternRef::new(self.pop())),
ValType::RefFunc => WasmValue::RefFunc(FuncRef::new(self.pop())),
+
+ #[cfg(not(feature = "__simd"))]
+ ValType::V128 => WasmValue::V128(self.pop()),
+
+ #[cfg(feature = "__simd")]
+ ValType::V128 => WasmValue::V128(i128::from_le_bytes(self.pop::<Value128>().to_array())),
}
}
diff --git a/crates/tinywasm/src/interpreter/values.rs b/crates/tinywasm/src/interpreter/values.rs
index 712baf7..779fc60 100644
--- a/crates/tinywasm/src/interpreter/values.rs
+++ b/crates/tinywasm/src/interpreter/values.rs
@@ -1,13 +1,17 @@
use crate::Result;
-use tinywasm_types::{ExternRef, FuncRef, LocalAddr, ValType, WasmValue};
use super::stack::{Locals, ValueStack};
+use tinywasm_types::{ExternRef, FuncRef, LocalAddr, ValType, WasmValue};
pub(crate) type Value32 = u32;
pub(crate) type Value64 = u64;
-pub(crate) type Value128 = u128;
pub(crate) type ValueRef = Option<u32>;
+#[cfg(feature = "__simd")]
+pub(crate) type Value128 = core::simd::u8x16;
+#[cfg(not(feature = "__simd"))]
+pub(crate) type Value128 = i128;
+
#[derive(Debug, Clone, Copy, PartialEq)]
/// A untyped WebAssembly value
pub enum TinyWasmValue {
@@ -106,9 +110,14 @@ impl TinyWasmValue {
ValType::I64 => WasmValue::I64(self.unwrap_64() as i64),
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 => WasmValue::RefExtern(ExternRef::new(self.unwrap_ref())),
ValType::RefFunc => WasmValue::RefFunc(FuncRef::new(self.unwrap_ref())),
+
+ #[cfg(feature = "__simd")]
+ ValType::V128 => WasmValue::V128(i128::from_le_bytes(self.unwrap_128().to_array())),
+
+ #[cfg(not(feature = "__simd"))]
+ ValType::V128 => WasmValue::V128(self.unwrap_128()),
}
}
}
@@ -118,11 +127,16 @@ impl From<&WasmValue> for TinyWasmValue {
match value {
WasmValue::I32(v) => TinyWasmValue::Value32(*v as u32),
WasmValue::I64(v) => TinyWasmValue::Value64(*v as u64),
- WasmValue::V128(v) => TinyWasmValue::Value128(*v),
WasmValue::F32(v) => TinyWasmValue::Value32(v.to_bits()),
WasmValue::F64(v) => TinyWasmValue::Value64(v.to_bits()),
WasmValue::RefExtern(v) => TinyWasmValue::ValueRef(v.addr()),
WasmValue::RefFunc(v) => TinyWasmValue::ValueRef(v.addr()),
+
+ #[cfg(not(feature = "__simd"))]
+ WasmValue::V128(v) => TinyWasmValue::Value128(*v),
+
+ #[cfg(feature = "__simd")]
+ WasmValue::V128(v) => TinyWasmValue::Value128(v.to_le_bytes().into()),
}
}
}
@@ -146,6 +160,10 @@ pub(crate) trait InternalValue: sealed::Sealed + Into<TinyWasmValue> {
fn stack_calculate(stack: &mut ValueStack, func: impl FnOnce(Self, Self) -> Result<Self>) -> Result<()>
where
Self: Sized;
+ #[allow(dead_code)]
+ fn stack_calculate3(stack: &mut ValueStack, func: impl FnOnce(Self, Self, Self) -> Result<Self>) -> Result<()>
+ where
+ Self: Sized;
fn stack_pop(stack: &mut ValueStack) -> Self
where
@@ -203,6 +221,19 @@ macro_rules! impl_internalvalue {
}
#[inline(always)]
+ fn stack_calculate3(stack: &mut ValueStack, func: impl FnOnce(Self, Self, Self) -> Result<Self>) -> Result<()> {
+ let v3 = stack.$stack.pop();
+ let v2 = stack.$stack.pop();
+ let v1 = stack.$stack.last_mut();
+ let (Some(v1), Some(v2), Some(v3)) = (v1, v2, v3) else {
+ unreachable!("ValueStack underflow, this is a bug");
+ };
+
+ *v1 = $to_internal(func($to_outer(*v1), $to_outer(v2), $to_outer(v3))?);
+ return Ok(())
+ }
+
+ #[inline(always)]
fn replace_top(stack: &mut ValueStack, func: impl FnOnce(Self) -> Result<Self>) -> Result<()> {
let Some(v) = stack.$stack.last_mut() else {
unreachable!("ValueStack underflow, this is a bug");
@@ -239,6 +270,25 @@ impl_internalvalue! {
Value64, stack_64, locals_64, u64, i64, |v| v as u64, |v| v as i64
Value32, stack_32, locals_32, u32, f32, f32::to_bits, f32::from_bits
Value64, stack_64, locals_64, u64, f64, f64::to_bits, f64::from_bits
- Value128, stack_128, locals_128, Value128, Value128, |v| v, |v| v
ValueRef, stack_ref, locals_ref, ValueRef, ValueRef, |v| v, |v| v
+ Value128, stack_128, locals_128, Value128, Value128, |v| v, |v| v
+}
+
+#[cfg(feature = "__simd")]
+use core::simd::{num::SimdUint, *};
+
+#[cfg(feature = "__simd")]
+impl_internalvalue! {
+ Value128, stack_128, locals_128, u8x16, i128, |v: i128| v.to_le_bytes().into(), |v: u8x16| i128::from_le_bytes(v.into())
+ Value128, stack_128, locals_128, u8x16, u128, |v: u128| v.to_le_bytes().into(), |v: u8x16| u128::from_le_bytes(v.into())
+ Value128, stack_128, locals_128, u8x16, i8x16, |v: i8x16| v.to_le_bytes(), |v: u8x16| v.cast()
+ Value128, stack_128, locals_128, u8x16, i16x8, |v: i16x8| v.to_le_bytes(), |v: u8x16| i16x8::from_le_bytes(v)
+ Value128, stack_128, locals_128, u8x16, i32x4, |v: i32x4| v.to_le_bytes(), |v: u8x16| i32x4::from_le_bytes(v)
+ Value128, stack_128, locals_128, u8x16, i64x2, |v: i64x2| v.to_le_bytes(), |v: u8x16| i64x2::from_le_bytes(v)
+ Value128, stack_128, locals_128, u8x16, f32x4, |v: f32x4| v.to_le_bytes(), |v: u8x16| f32x4::from_le_bytes(v)
+ Value128, stack_128, locals_128, u8x16, f64x2, |v: f64x2| v.to_le_bytes(), |v: u8x16| f64x2::from_le_bytes(v)
+
+ Value128, stack_128, locals_128, u8x16, u16x8, |v: u16x8| v.to_le_bytes(), |v: u8x16| u16x8::from_le_bytes(v)
+ Value128, stack_128, locals_128, u8x16, u32x4, |v: u32x4| v.to_le_bytes(), |v: u8x16| u32x4::from_le_bytes(v)
+ Value128, stack_128, locals_128, u8x16, u64x2, |v: u64x2| v.to_le_bytes(), |v: u8x16| u64x2::from_le_bytes(v)
}
diff --git a/crates/tinywasm/src/lib.rs b/crates/tinywasm/src/lib.rs
index d3431e2..9cb6c0a 100644
--- a/crates/tinywasm/src/lib.rs
+++ b/crates/tinywasm/src/lib.rs
@@ -5,7 +5,7 @@
))]
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)]
#![forbid(unsafe_code)]
-// #![cfg_attr(feature = "nightly", feature(portable_simd))]
+#![cfg_attr(feature = "__simd", feature(portable_simd))]
//! A tiny WebAssembly Runtime written in Rust
//!
diff --git a/crates/tinywasm/src/store/memory.rs b/crates/tinywasm/src/store/memory.rs
index 53c1133..7abd7b9 100644
--- a/crates/tinywasm/src/store/memory.rs
+++ b/crates/tinywasm/src/store/memory.rs
@@ -2,7 +2,10 @@ use alloc::vec;
use alloc::vec::Vec;
use tinywasm_types::{MemoryArch, MemoryType, ModuleInstanceAddr};
-use crate::{Error, Result, cold, log};
+use crate::{Error, Result, cold, interpreter::Value128, log};
+
+#[cfg(feature = "__simd")]
+use core::simd::ToBytes;
/// A WebAssembly Memory Instance
///
@@ -85,7 +88,7 @@ impl MemoryInstance {
return Err(self.trap_oob(addr, SIZE));
}
- Ok(T::from_le_bytes(match self.data[addr..end].try_into() {
+ Ok(T::from_mem_bytes(match self.data[addr..end].try_into() {
Ok(bytes) => bytes,
Err(_) => return Err(self.trap_oob(addr, SIZE)),
}))
@@ -161,30 +164,52 @@ pub(crate) trait MemStorable<const N: usize> {
/// A trait for types that can be loaded from memory
pub(crate) trait MemLoadable<const N: usize>: Sized + Copy {
/// Load a value from memory
- fn from_le_bytes(bytes: [u8; N]) -> Self;
+ fn from_mem_bytes(bytes: [u8; N]) -> Self;
}
macro_rules! impl_mem_traits {
- ($($type:ty, $size:expr),*) => {
+ ($($ty:ty, $size:expr),*) => {
$(
- impl MemLoadable<$size> for $type {
+ impl MemLoadable<$size> for $ty {
#[inline(always)]
- fn from_le_bytes(bytes: [u8; $size]) -> Self {
- <$type>::from_le_bytes(bytes)
+ fn from_mem_bytes(bytes: [u8; $size]) -> Self {
+ <$ty>::from_le_bytes(bytes.into())
}
}
- impl MemStorable<$size> for $type {
+ impl MemStorable<$size> for $ty {
#[inline(always)]
fn to_mem_bytes(self) -> [u8; $size] {
- self.to_ne_bytes()
+ self.to_le_bytes().into()
}
}
)*
}
}
-impl_mem_traits!(u8, 1, i8, 1, u16, 2, i16, 2, u32, 4, i32, 4, f32, 4, u64, 8, i64, 8, f64, 8, u128, 16, i128, 16);
+impl_mem_traits!(u8, 1, i8, 1, u16, 2, i16, 2, u32, 4, i32, 4, f32, 4, u64, 8, i64, 8, f64, 8, Value128, 16);
+
+#[cfg(feature = "__simd")]
+impl_mem_traits!(
+ core::simd::i8x16,
+ 16,
+ core::simd::i16x8,
+ 16,
+ core::simd::i32x4,
+ 16,
+ core::simd::i64x2,
+ 16,
+ core::simd::u16x8,
+ 16,
+ core::simd::u32x4,
+ 16,
+ core::simd::u64x2,
+ 16,
+ core::simd::f32x4,
+ 16,
+ core::simd::f64x2,
+ 16
+);
#[cfg(test)]
mod memory_instance_tests {
diff --git a/crates/tinywasm/src/store/mod.rs b/crates/tinywasm/src/store/mod.rs
index 358cbef..d53654e 100644
--- a/crates/tinywasm/src/store/mod.rs
+++ b/crates/tinywasm/src/store/mod.rs
@@ -442,6 +442,7 @@ impl Store {
F64Const(f) => (*f).into(),
I32Const(i) => (*i).into(),
I64Const(i) => (*i).into(),
+ V128Const(i) => (*i).into(),
GlobalGet(addr) => {
let addr = module_global_addrs.get(*addr as usize).ok_or_else(|| {
Error::Other(format!("global {addr} not found. This should have been caught by the validator"))
diff --git a/crates/tinywasm/tests/generated/wasm-1.csv b/crates/tinywasm/tests/generated/wasm-1.csv
index d403e3b..ebb511b 100644
--- a/crates/tinywasm/tests/generated/wasm-1.csv
+++ b/crates/tinywasm/tests/generated/wasm-1.csv
@@ -5,4 +5,4 @@
0.6.1,27572,335,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":162,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"bulk.wast","passed":75,"failed":42},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":98,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":179,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":186,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_copy.wast","passed":4450,"failed":0},{"name":"memory_fill.wast","passed":100,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_init.wast","passed":240,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"ref_func.wast","passed":9,"failed":8},{"name":"ref_is_null.wast","passed":4,"failed":12},{"name":"ref_null.wast","passed":1,"failed":2},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table-sub.wast","passed":2,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"table_copy.wast","passed":1613,"failed":115},{"name":"table_fill.wast","passed":23,"failed":22},{"name":"table_get.wast","passed":10,"failed":6},{"name":"table_grow.wast","passed":21,"failed":29},{"name":"table_init.wast","passed":719,"failed":61},{"name":"table_set.wast","passed":19,"failed":7},{"name":"table_size.wast","passed":8,"failed":31},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}]
0.7.0,27572,335,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":162,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"bulk.wast","passed":75,"failed":42},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":98,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":179,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":186,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_copy.wast","passed":4450,"failed":0},{"name":"memory_fill.wast","passed":100,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_init.wast","passed":240,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"ref_func.wast","passed":9,"failed":8},{"name":"ref_is_null.wast","passed":4,"failed":12},{"name":"ref_null.wast","passed":1,"failed":2},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table-sub.wast","passed":2,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"table_copy.wast","passed":1613,"failed":115},{"name":"table_fill.wast","passed":23,"failed":22},{"name":"table_get.wast","passed":10,"failed":6},{"name":"table_grow.wast","passed":21,"failed":29},{"name":"table_init.wast","passed":719,"failed":61},{"name":"table_set.wast","passed":19,"failed":7},{"name":"table_size.wast","passed":8,"failed":31},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}]
0.8.0,20360,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":162,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":128,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":98,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":927,"failed":0},{"name":"float_literals.wast","passed":179,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":471,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":178,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":88,"failed":0},{"name":"memory_grow.wast","passed":104,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}]
-0.9.0-alpha.0,19243,0,[{"name":"address.wast","passed":243,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":79,"failed":0},{"name":"binary.wast","passed":67,"failed":0},{"name":"block.wast","passed":171,"failed":0},{"name":"br.wast","passed":84,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":168,"failed":0},{"name":"break-drop.wast","passed":4,"failed":0},{"name":"call.wast","passed":82,"failed":0},{"name":"call_indirect.wast","passed":152,"failed":0},{"name":"comments.wast","passed":4,"failed":0},{"name":"const.wast","passed":668,"failed":0},{"name":"conversions.wast","passed":435,"failed":0},{"name":"custom.wast","passed":10,"failed":0},{"name":"data.wast","passed":45,"failed":0},{"name":"elem.wast","passed":55,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":82,"failed":0},{"name":"f32.wast","passed":2512,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2512,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":161,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":121,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"globals.wast","passed":78,"failed":0},{"name":"i32.wast","passed":443,"failed":0},{"name":"i64.wast","passed":389,"failed":0},{"name":"if.wast","passed":151,"failed":0},{"name":"imports.wast","passed":146,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":116,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":81,"failed":0},{"name":"memory.wast","passed":71,"failed":0},{"name":"memory_grow.wast","passed":94,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":173,"failed":0},{"name":"names.wast","passed":483,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":111,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":5,"failed":0},{"name":"start.wast","passed":19,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":2,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":62,"failed":0},{"name":"unreached-invalid.wast","passed":110,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}]
+0.9.0-alpha.0,19241,0,[{"name":"address.wast","passed":243,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":77,"failed":0},{"name":"binary.wast","passed":67,"failed":0},{"name":"block.wast","passed":171,"failed":0},{"name":"br.wast","passed":84,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":168,"failed":0},{"name":"break-drop.wast","passed":4,"failed":0},{"name":"call.wast","passed":82,"failed":0},{"name":"call_indirect.wast","passed":152,"failed":0},{"name":"comments.wast","passed":4,"failed":0},{"name":"const.wast","passed":668,"failed":0},{"name":"conversions.wast","passed":435,"failed":0},{"name":"custom.wast","passed":10,"failed":0},{"name":"data.wast","passed":45,"failed":0},{"name":"elem.wast","passed":55,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":82,"failed":0},{"name":"f32.wast","passed":2512,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2512,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":161,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":121,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"globals.wast","passed":78,"failed":0},{"name":"i32.wast","passed":443,"failed":0},{"name":"i64.wast","passed":389,"failed":0},{"name":"if.wast","passed":151,"failed":0},{"name":"imports.wast","passed":146,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":116,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":81,"failed":0},{"name":"memory.wast","passed":71,"failed":0},{"name":"memory_grow.wast","passed":94,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":173,"failed":0},{"name":"names.wast","passed":483,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":111,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":5,"failed":0},{"name":"start.wast","passed":19,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":2,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":62,"failed":0},{"name":"unreached-invalid.wast","passed":110,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}]
diff --git a/crates/tinywasm/tests/generated/wasm-2.csv b/crates/tinywasm/tests/generated/wasm-2.csv
index b0949ec..8e228b4 100644
--- a/crates/tinywasm/tests/generated/wasm-2.csv
+++ b/crates/tinywasm/tests/generated/wasm-2.csv
@@ -10,4 +10,4 @@
0.6.1,20278,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":162,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":98,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":179,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":186,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}]
0.7.0,20278,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":162,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":98,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":179,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":186,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}]
0.8.0,28008,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":162,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":128,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"bulk.wast","passed":117,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":98,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":927,"failed":0},{"name":"float_literals.wast","passed":179,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":471,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":178,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":88,"failed":0},{"name":"memory_copy.wast","passed":4450,"failed":0},{"name":"memory_fill.wast","passed":100,"failed":0},{"name":"memory_grow.wast","passed":104,"failed":0},{"name":"memory_init.wast","passed":240,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"obsolete-keywords.wast","passed":11,"failed":0},{"name":"ref_func.wast","passed":17,"failed":0},{"name":"ref_is_null.wast","passed":16,"failed":0},{"name":"ref_null.wast","passed":3,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table-sub.wast","passed":2,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"table_copy.wast","passed":1728,"failed":0},{"name":"table_fill.wast","passed":45,"failed":0},{"name":"table_get.wast","passed":16,"failed":0},{"name":"table_grow.wast","passed":58,"failed":0},{"name":"table_init.wast","passed":780,"failed":0},{"name":"table_set.wast","passed":26,"failed":0},{"name":"table_size.wast","passed":39,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}]
-0.9.0-alpha.0,27826,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":81,"failed":0},{"name":"binary.wast","passed":162,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"bulk.wast","passed":117,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":0},{"name":"comments.wast","passed":4,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":58,"failed":0},{"name":"elem.wast","passed":74,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":161,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":108,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":239,"failed":0},{"name":"imports.wast","passed":183,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_copy.wast","passed":4450,"failed":0},{"name":"memory_fill.wast","passed":100,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_init.wast","passed":240,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"ref_func.wast","passed":17,"failed":0},{"name":"ref_is_null.wast","passed":16,"failed":0},{"name":"ref_null.wast","passed":3,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":147,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table-sub.wast","passed":2,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"table_copy.wast","passed":1728,"failed":0},{"name":"table_fill.wast","passed":45,"failed":0},{"name":"table_get.wast","passed":16,"failed":0},{"name":"table_grow.wast","passed":50,"failed":0},{"name":"table_init.wast","passed":780,"failed":0},{"name":"table_set.wast","passed":26,"failed":0},{"name":"table_size.wast","passed":39,"failed":0},{"name":"token.wast","passed":2,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":6,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}]
+0.9.0-alpha.0,27822,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":79,"failed":0},{"name":"binary.wast","passed":160,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"bulk.wast","passed":117,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":0},{"name":"comments.wast","passed":4,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":58,"failed":0},{"name":"elem.wast","passed":74,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":161,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":108,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":239,"failed":0},{"name":"imports.wast","passed":183,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_copy.wast","passed":4450,"failed":0},{"name":"memory_fill.wast","passed":100,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_init.wast","passed":240,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"ref_func.wast","passed":17,"failed":0},{"name":"ref_is_null.wast","passed":16,"failed":0},{"name":"ref_null.wast","passed":3,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":147,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table-sub.wast","passed":2,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"table_copy.wast","passed":1728,"failed":0},{"name":"table_fill.wast","passed":45,"failed":0},{"name":"table_get.wast","passed":16,"failed":0},{"name":"table_grow.wast","passed":50,"failed":0},{"name":"table_init.wast","passed":780,"failed":0},{"name":"table_set.wast","passed":26,"failed":0},{"name":"table_size.wast","passed":39,"failed":0},{"name":"token.wast","passed":2,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":6,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}]
diff --git a/crates/tinywasm/tests/generated/wasm-memory64.csv b/crates/tinywasm/tests/generated/wasm-memory64.csv
index 039fe8c..20afc3b 100644
--- a/crates/tinywasm/tests/generated/wasm-memory64.csv
+++ b/crates/tinywasm/tests/generated/wasm-memory64.csv
@@ -1,2 +1,2 @@
0.8.0,15081,3214,[{"name":"address.wast","passed":260,"failed":0},{"name":"address0.wast","passed":92,"failed":0},{"name":"address1.wast","passed":127,"failed":0},{"name":"address64.wast","passed":0,"failed":242},{"name":"align.wast","passed":161,"failed":0},{"name":"align0.wast","passed":5,"failed":0},{"name":"align64.wast","passed":83,"failed":73},{"name":"annotations.wast","passed":74,"failed":0},{"name":"array_copy.wast","passed":4,"failed":31},{"name":"array_fill.wast","passed":3,"failed":14},{"name":"array_init_data.wast","passed":2,"failed":31},{"name":"array_init_elem.wast","passed":3,"failed":20},{"name":"binary-gc.wast","passed":1,"failed":0},{"name":"binary-leb128.wast","passed":92,"failed":1},{"name":"binary.wast","passed":124,"failed":0},{"name":"binary0.wast","passed":7,"failed":0},{"name":"br_if.wast","passed":119,"failed":0},{"name":"br_on_cast.wast","passed":6,"failed":31},{"name":"br_on_cast_fail.wast","passed":6,"failed":31},{"name":"br_on_non_null.wast","passed":1,"failed":9},{"name":"br_on_null.wast","passed":1,"failed":9},{"name":"br_table.wast","passed":24,"failed":162},{"name":"call_indirect.wast","passed":47,"failed":124},{"name":"call_ref.wast","passed":4,"failed":31},{"name":"data.wast","passed":59,"failed":6},{"name":"data0.wast","passed":7,"failed":0},{"name":"data1.wast","passed":14,"failed":0},{"name":"data_drop0.wast","passed":11,"failed":0},{"name":"elem.wast","passed":137,"failed":14},{"name":"endianness64.wast","passed":0,"failed":69},{"name":"exports.wast","passed":97,"failed":0},{"name":"exports0.wast","passed":8,"failed":0},{"name":"float_exprs0.wast","passed":14,"failed":0},{"name":"float_exprs1.wast","passed":3,"failed":0},{"name":"float_memory0.wast","passed":30,"failed":0},{"name":"float_memory64.wast","passed":0,"failed":90},{"name":"func.wast","passed":175,"failed":0},{"name":"id.wast","passed":7,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":99,"failed":82},{"name":"imports0.wast","passed":8,"failed":0},{"name":"imports1.wast","passed":5,"failed":0},{"name":"imports2.wast","passed":20,"failed":0},{"name":"imports3.wast","passed":10,"failed":0},{"name":"imports4.wast","passed":16,"failed":0},{"name":"linking.wast","passed":122,"failed":41},{"name":"linking0.wast","passed":6,"failed":0},{"name":"linking1.wast","passed":14,"failed":0},{"name":"linking2.wast","passed":11,"failed":0},{"name":"linking3.wast","passed":14,"failed":0},{"name":"load.wast","passed":118,"failed":0},{"name":"load0.wast","passed":3,"failed":0},{"name":"load1.wast","passed":18,"failed":0},{"name":"load2.wast","passed":38,"failed":0},{"name":"load64.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_init.wast","passed":10,"failed":0},{"name":"local_tee.wast","passed":98,"failed":0},{"name":"memory-multi.wast","passed":6,"failed":0},{"name":"memory.wast","passed":86,"failed":0},{"name":"memory64.wast","passed":10,"failed":53},{"name":"memory64/array.wast (skipped)","passed":0,"failed":0},{"name":"memory64/extern.wast (skipped)","passed":0,"failed":0},{"name":"memory64/global.wast (skipped)","passed":0,"failed":0},{"name":"memory64/i31.wast (skipped)","passed":0,"failed":0},{"name":"memory64/ref_null.wast (skipped)","passed":0,"failed":0},{"name":"memory64/select.wast (skipped)","passed":0,"failed":0},{"name":"memory64/simd_address.wast (skipped)","passed":0,"failed":0},{"name":"memory64/simd_lane.wast (skipped)","passed":0,"failed":0},{"name":"memory64/struct.wast (skipped)","passed":0,"failed":0},{"name":"memory64/table.wast (skipped)","passed":0,"failed":0},{"name":"memory_copy.wast","passed":8385,"failed":515},{"name":"memory_copy0.wast","passed":29,"failed":0},{"name":"memory_copy1.wast","passed":14,"failed":0},{"name":"memory_fill.wast","passed":164,"failed":36},{"name":"memory_fill0.wast","passed":16,"failed":0},{"name":"memory_grow.wast","passed":157,"failed":0},{"name":"memory_grow64.wast","passed":0,"failed":49},{"name":"memory_init.wast","passed":307,"failed":173},{"name":"memory_init0.wast","passed":13,"failed":0},{"name":"memory_redundancy64.wast","passed":0,"failed":8},{"name":"memory_size.wast","passed":49,"failed":0},{"name":"memory_size0.wast","passed":8,"failed":0},{"name":"memory_size1.wast","passed":15,"failed":0},{"name":"memory_size2.wast","passed":21,"failed":0},{"name":"memory_size3.wast","passed":2,"failed":0},{"name":"memory_trap0.wast","passed":14,"failed":0},{"name":"memory_trap1.wast","passed":168,"failed":0},{"name":"memory_trap64.wast","passed":0,"failed":172},{"name":"ref.wast","passed":12,"failed":1},{"name":"ref_as_non_null.wast","passed":1,"failed":6},{"name":"ref_cast.wast","passed":0,"failed":45},{"name":"ref_eq.wast","passed":6,"failed":83},{"name":"ref_is_null.wast","passed":2,"failed":20},{"name":"ref_test.wast","passed":0,"failed":71},{"name":"return_call.wast","passed":18,"failed":27},{"name":"return_call_indirect.wast","passed":31,"failed":45},{"name":"return_call_ref.wast","passed":11,"failed":40},{"name":"simd_memory-multi.wast","passed":0,"failed":1},{"name":"start0.wast","passed":9,"failed":0},{"name":"store.wast","passed":111,"failed":0},{"name":"store0.wast","passed":5,"failed":0},{"name":"store1.wast","passed":13,"failed":0},{"name":"table-sub.wast","passed":2,"failed":1},{"name":"table_copy.wast","passed":1742,"failed":30},{"name":"table_copy_mixed.wast","passed":3,"failed":1},{"name":"table_fill.wast","passed":9,"failed":71},{"name":"table_get.wast","passed":5,"failed":12},{"name":"table_grow.wast","passed":36,"failed":43},{"name":"table_init.wast","passed":588,"failed":288},{"name":"table_set.wast","passed":7,"failed":21},{"name":"table_size.wast","passed":2,"failed":38},{"name":"tag.wast","passed":1,"failed":8},{"name":"throw.wast","passed":3,"failed":10},{"name":"throw_ref.wast","passed":2,"failed":13},{"name":"token.wast","passed":61,"failed":0},{"name":"traps0.wast","passed":15,"failed":0},{"name":"try_table.wast","passed":11,"failed":51},{"name":"type-canon.wast","passed":0,"failed":2},{"name":"type-equivalence.wast","passed":12,"failed":20},{"name":"type-rec.wast","passed":6,"failed":14},{"name":"type-subtyping.wast","passed":16,"failed":86},{"name":"unreached-invalid.wast","passed":121,"failed":0},{"name":"unreached-valid.wast","passed":2,"failed":11}]
-0.9.0-alpha.0,1556,42,[{"name":"address.wast","passed":260,"failed":0},{"name":"address64.wast","passed":242,"failed":0},{"name":"align64.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":93,"failed":0},{"name":"binary.wast","passed":169,"failed":0},{"name":"endianness64.wast","passed":69,"failed":0},{"name":"float_memory64.wast","passed":90,"failed":0},{"name":"load64.wast","passed":97,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory64.wast","passed":65,"failed":0},{"name":"memory_grow64.wast","passed":49,"failed":0},{"name":"memory_redundancy64.wast","passed":8,"failed":0},{"name":"memory_trap64.wast","passed":172,"failed":0},{"name":"simd_address.wast","passed":7,"failed":42}]
+0.9.0-alpha.0,1598,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"address64.wast","passed":242,"failed":0},{"name":"align64.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":93,"failed":0},{"name":"binary.wast","passed":169,"failed":0},{"name":"endianness64.wast","passed":69,"failed":0},{"name":"float_memory64.wast","passed":90,"failed":0},{"name":"load64.wast","passed":97,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory64.wast","passed":65,"failed":0},{"name":"memory_grow64.wast","passed":49,"failed":0},{"name":"memory_redundancy64.wast","passed":8,"failed":0},{"name":"memory_trap64.wast","passed":172,"failed":0},{"name":"simd_address.wast","passed":49,"failed":0}]
diff --git a/crates/tinywasm/tests/generated/wasm-multi-memory.csv b/crates/tinywasm/tests/generated/wasm-multi-memory.csv
index ae9ba03..33debd6 100644
--- a/crates/tinywasm/tests/generated/wasm-multi-memory.csv
+++ b/crates/tinywasm/tests/generated/wasm-multi-memory.csv
@@ -1,2 +1,2 @@
0.8.0,1872,0,[{"name":"address0.wast","passed":92,"failed":0},{"name":"address1.wast","passed":127,"failed":0},{"name":"align.wast","passed":160,"failed":0},{"name":"align0.wast","passed":5,"failed":0},{"name":"binary.wast","passed":126,"failed":0},{"name":"binary0.wast","passed":7,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"data0.wast","passed":7,"failed":0},{"name":"data1.wast","passed":14,"failed":0},{"name":"data_drop0.wast","passed":11,"failed":0},{"name":"exports0.wast","passed":8,"failed":0},{"name":"float_exprs0.wast","passed":14,"failed":0},{"name":"float_exprs1.wast","passed":3,"failed":0},{"name":"float_memory0.wast","passed":30,"failed":0},{"name":"imports.wast","passed":175,"failed":0},{"name":"imports0.wast","passed":8,"failed":0},{"name":"imports1.wast","passed":5,"failed":0},{"name":"imports2.wast","passed":20,"failed":0},{"name":"imports3.wast","passed":10,"failed":0},{"name":"imports4.wast","passed":16,"failed":0},{"name":"linking0.wast","passed":6,"failed":0},{"name":"linking1.wast","passed":14,"failed":0},{"name":"linking2.wast","passed":11,"failed":0},{"name":"linking3.wast","passed":14,"failed":0},{"name":"load.wast","passed":118,"failed":0},{"name":"load0.wast","passed":3,"failed":0},{"name":"load1.wast","passed":18,"failed":0},{"name":"load2.wast","passed":38,"failed":0},{"name":"memory-multi.wast","passed":6,"failed":0},{"name":"memory.wast","passed":86,"failed":0},{"name":"memory_copy0.wast","passed":29,"failed":0},{"name":"memory_copy1.wast","passed":14,"failed":0},{"name":"memory_fill0.wast","passed":16,"failed":0},{"name":"memory_grow.wast","passed":157,"failed":0},{"name":"memory_init0.wast","passed":13,"failed":0},{"name":"memory_size.wast","passed":49,"failed":0},{"name":"memory_size0.wast","passed":8,"failed":0},{"name":"memory_size1.wast","passed":15,"failed":0},{"name":"memory_size2.wast","passed":21,"failed":0},{"name":"memory_size3.wast","passed":2,"failed":0},{"name":"memory_trap0.wast","passed":14,"failed":0},{"name":"memory_trap1.wast","passed":168,"failed":0},{"name":"multi-memory/simd_memory-multi.wast (skipped)","passed":0,"failed":0},{"name":"start0.wast","passed":9,"failed":0},{"name":"store.wast","passed":111,"failed":0},{"name":"store0.wast","passed":5,"failed":0},{"name":"store1.wast","passed":13,"failed":0},{"name":"traps0.wast","passed":15,"failed":0}]
-0.9.0-alpha.0,1872,0,[{"name":"address0.wast","passed":92,"failed":0},{"name":"address1.wast","passed":127,"failed":0},{"name":"align.wast","passed":160,"failed":0},{"name":"align0.wast","passed":5,"failed":0},{"name":"binary.wast","passed":126,"failed":0},{"name":"binary0.wast","passed":7,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"data0.wast","passed":7,"failed":0},{"name":"data1.wast","passed":14,"failed":0},{"name":"data_drop0.wast","passed":11,"failed":0},{"name":"exports0.wast","passed":8,"failed":0},{"name":"float_exprs0.wast","passed":14,"failed":0},{"name":"float_exprs1.wast","passed":3,"failed":0},{"name":"float_memory0.wast","passed":30,"failed":0},{"name":"imports.wast","passed":175,"failed":0},{"name":"imports0.wast","passed":8,"failed":0},{"name":"imports1.wast","passed":5,"failed":0},{"name":"imports2.wast","passed":20,"failed":0},{"name":"imports3.wast","passed":10,"failed":0},{"name":"imports4.wast","passed":16,"failed":0},{"name":"linking0.wast","passed":6,"failed":0},{"name":"linking1.wast","passed":14,"failed":0},{"name":"linking2.wast","passed":11,"failed":0},{"name":"linking3.wast","passed":14,"failed":0},{"name":"load.wast","passed":118,"failed":0},{"name":"load0.wast","passed":3,"failed":0},{"name":"load1.wast","passed":18,"failed":0},{"name":"load2.wast","passed":38,"failed":0},{"name":"memory-multi.wast","passed":6,"failed":0},{"name":"memory.wast","passed":86,"failed":0},{"name":"memory_copy0.wast","passed":29,"failed":0},{"name":"memory_copy1.wast","passed":14,"failed":0},{"name":"memory_fill0.wast","passed":16,"failed":0},{"name":"memory_grow.wast","passed":157,"failed":0},{"name":"memory_init0.wast","passed":13,"failed":0},{"name":"memory_size.wast","passed":49,"failed":0},{"name":"memory_size0.wast","passed":8,"failed":0},{"name":"memory_size1.wast","passed":15,"failed":0},{"name":"memory_size2.wast","passed":21,"failed":0},{"name":"memory_size3.wast","passed":2,"failed":0},{"name":"memory_trap0.wast","passed":14,"failed":0},{"name":"memory_trap1.wast","passed":168,"failed":0},{"name":"simd_memory-multi.wast (skipped)","passed":0,"failed":0},{"name":"start0.wast","passed":9,"failed":0},{"name":"store.wast","passed":111,"failed":0},{"name":"store0.wast","passed":5,"failed":0},{"name":"store1.wast","passed":13,"failed":0},{"name":"traps0.wast","passed":15,"failed":0}]
+0.9.0-alpha.0,1871,0,[{"name":"address0.wast","passed":92,"failed":0},{"name":"address1.wast","passed":127,"failed":0},{"name":"align.wast","passed":160,"failed":0},{"name":"align0.wast","passed":5,"failed":0},{"name":"binary.wast","passed":126,"failed":0},{"name":"binary0.wast","passed":6,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"data0.wast","passed":7,"failed":0},{"name":"data1.wast","passed":14,"failed":0},{"name":"data_drop0.wast","passed":11,"failed":0},{"name":"exports0.wast","passed":8,"failed":0},{"name":"float_exprs0.wast","passed":14,"failed":0},{"name":"float_exprs1.wast","passed":3,"failed":0},{"name":"float_memory0.wast","passed":30,"failed":0},{"name":"imports.wast","passed":175,"failed":0},{"name":"imports0.wast","passed":8,"failed":0},{"name":"imports1.wast","passed":5,"failed":0},{"name":"imports2.wast","passed":20,"failed":0},{"name":"imports3.wast","passed":10,"failed":0},{"name":"imports4.wast","passed":16,"failed":0},{"name":"linking0.wast","passed":6,"failed":0},{"name":"linking1.wast","passed":14,"failed":0},{"name":"linking2.wast","passed":11,"failed":0},{"name":"linking3.wast","passed":14,"failed":0},{"name":"load.wast","passed":118,"failed":0},{"name":"load0.wast","passed":3,"failed":0},{"name":"load1.wast","passed":18,"failed":0},{"name":"load2.wast","passed":38,"failed":0},{"name":"memory-multi.wast","passed":6,"failed":0},{"name":"memory.wast","passed":86,"failed":0},{"name":"memory_copy0.wast","passed":29,"failed":0},{"name":"memory_copy1.wast","passed":14,"failed":0},{"name":"memory_fill0.wast","passed":16,"failed":0},{"name":"memory_grow.wast","passed":157,"failed":0},{"name":"memory_init0.wast","passed":13,"failed":0},{"name":"memory_size.wast","passed":49,"failed":0},{"name":"memory_size0.wast","passed":8,"failed":0},{"name":"memory_size1.wast","passed":15,"failed":0},{"name":"memory_size2.wast","passed":21,"failed":0},{"name":"memory_size3.wast","passed":2,"failed":0},{"name":"memory_trap0.wast","passed":14,"failed":0},{"name":"memory_trap1.wast","passed":168,"failed":0},{"name":"simd_memory-multi.wast (skipped)","passed":0,"failed":0},{"name":"start0.wast","passed":9,"failed":0},{"name":"store.wast","passed":111,"failed":0},{"name":"store0.wast","passed":5,"failed":0},{"name":"store1.wast","passed":13,"failed":0},{"name":"traps0.wast","passed":15,"failed":0}]
diff --git a/crates/tinywasm/tests/generated/wasm-relaxed-simd.csv b/crates/tinywasm/tests/generated/wasm-relaxed-simd.csv
new file mode 100644
index 0000000..a6e6228
--- /dev/null
+++ b/crates/tinywasm/tests/generated/wasm-relaxed-simd.csv
@@ -0,0 +1 @@
+0.9.0-alpha.0,0,93,[{"name":"i16x8_relaxed_q15mulr_s.wast","passed":0,"failed":3},{"name":"i32x4_relaxed_trunc.wast","passed":0,"failed":17},{"name":"i8x16_relaxed_swizzle.wast","passed":0,"failed":6},{"name":"relaxed_dot_product.wast","passed":0,"failed":11},{"name":"relaxed_laneselect.wast","passed":0,"failed":12},{"name":"relaxed_madd_nmadd.wast","passed":0,"failed":19},{"name":"relaxed_min_max.wast","passed":0,"failed":25}]
diff --git a/crates/tinywasm/tests/generated/wasm-simd.csv b/crates/tinywasm/tests/generated/wasm-simd.csv
index d695dfa..86b7780 100644
--- a/crates/tinywasm/tests/generated/wasm-simd.csv
+++ b/crates/tinywasm/tests/generated/wasm-simd.csv
@@ -1,2 +1,2 @@
0.8.0,1300,24679,[{"name":"simd_address.wast","passed":4,"failed":45},{"name":"simd_align.wast","passed":46,"failed":54},{"name":"simd_bit_shift.wast","passed":39,"failed":213},{"name":"simd_bitwise.wast","passed":28,"failed":141},{"name":"simd_boolean.wast","passed":16,"failed":261},{"name":"simd_const.wast","passed":301,"failed":456},{"name":"simd_conversions.wast","passed":48,"failed":234},{"name":"simd_f32x4.wast","passed":16,"failed":774},{"name":"simd_f32x4_arith.wast","passed":16,"failed":1806},{"name":"simd_f32x4_cmp.wast","passed":24,"failed":2583},{"name":"simd_f32x4_pmin_pmax.wast","passed":14,"failed":3873},{"name":"simd_f32x4_rounding.wast","passed":24,"failed":177},{"name":"simd_f64x2.wast","passed":8,"failed":795},{"name":"simd_f64x2_arith.wast","passed":16,"failed":1809},{"name":"simd_f64x2_cmp.wast","passed":24,"failed":2661},{"name":"simd_f64x2_pmin_pmax.wast","passed":14,"failed":3873},{"name":"simd_f64x2_rounding.wast","passed":24,"failed":177},{"name":"simd_i16x8_arith.wast","passed":11,"failed":183},{"name":"simd_i16x8_arith2.wast","passed":19,"failed":153},{"name":"simd_i16x8_cmp.wast","passed":30,"failed":435},{"name":"simd_i16x8_extadd_pairwise_i8x16.wast","passed":4,"failed":17},{"name":"simd_i16x8_extmul_i8x16.wast","passed":12,"failed":105},{"name":"simd_i16x8_q15mulr_sat_s.wast","passed":3,"failed":27},{"name":"simd_i16x8_sat_arith.wast","passed":16,"failed":206},{"name":"simd_i32x4_arith.wast","passed":11,"failed":183},{"name":"simd_i32x4_arith2.wast","passed":26,"failed":123},{"name":"simd_i32x4_cmp.wast","passed":40,"failed":435},{"name":"simd_i32x4_dot_i16x8.wast","passed":3,"failed":27},{"name":"simd_i32x4_extadd_pairwise_i16x8.wast","passed":4,"failed":17},{"name":"simd_i32x4_extmul_i16x8.wast","passed":12,"failed":105},{"name":"simd_i32x4_trunc_sat_f32x4.wast","passed":4,"failed":103},{"name":"simd_i32x4_trunc_sat_f64x2.wast","passed":4,"failed":103},{"name":"simd_i64x2_arith.wast","passed":11,"failed":189},{"name":"simd_i64x2_arith2.wast","passed":2,"failed":23},{"name":"simd_i64x2_cmp.wast","passed":10,"failed":103},{"name":"simd_i64x2_extmul_i32x4.wast","passed":12,"failed":105},{"name":"simd_i8x16_arith.wast","passed":8,"failed":123},{"name":"simd_i8x16_arith2.wast","passed":25,"failed":186},{"name":"simd_i8x16_cmp.wast","passed":30,"failed":415},{"name":"simd_i8x16_sat_arith.wast","passed":24,"failed":190},{"name":"simd_int_to_int_extend.wast","passed":24,"failed":229},{"name":"simd_lane.wast","passed":189,"failed":286},{"name":"simd_linking.wast","passed":0,"failed":3},{"name":"simd_load.wast","passed":8,"failed":31},{"name":"simd_load16_lane.wast","passed":3,"failed":33},{"name":"simd_load32_lane.wast","passed":3,"failed":21},{"name":"simd_load64_lane.wast","passed":3,"failed":13},{"name":"simd_load8_lane.wast","passed":3,"failed":49},{"name":"simd_load_extend.wast","passed":18,"failed":86},{"name":"simd_load_splat.wast","passed":12,"failed":114},{"name":"simd_load_zero.wast","passed":10,"failed":29},{"name":"simd_splat.wast","passed":23,"failed":162},{"name":"simd_store.wast","passed":9,"failed":19},{"name":"simd_store16_lane.wast","passed":3,"failed":33},{"name":"simd_store32_lane.wast","passed":3,"failed":21},{"name":"simd_store64_lane.wast","passed":3,"failed":13},{"name":"simd_store8_lane.wast","passed":3,"failed":49}]
-0.9.0-alpha.0,1741,24238,[{"name":"simd_address.wast","passed":7,"failed":42},{"name":"simd_align.wast","passed":93,"failed":7},{"name":"simd_bit_shift.wast","passed":41,"failed":211},{"name":"simd_bitwise.wast","passed":30,"failed":139},{"name":"simd_boolean.wast","passed":18,"failed":259},{"name":"simd_const.wast","passed":551,"failed":206},{"name":"simd_conversions.wast","passed":50,"failed":232},{"name":"simd_f32x4.wast","passed":18,"failed":772},{"name":"simd_f32x4_arith.wast","passed":19,"failed":1803},{"name":"simd_f32x4_cmp.wast","passed":26,"failed":2581},{"name":"simd_f32x4_pmin_pmax.wast","passed":15,"failed":3872},{"name":"simd_f32x4_rounding.wast","passed":25,"failed":176},{"name":"simd_f64x2.wast","passed":10,"failed":793},{"name":"simd_f64x2_arith.wast","passed":19,"failed":1806},{"name":"simd_f64x2_cmp.wast","passed":26,"failed":2659},{"name":"simd_f64x2_pmin_pmax.wast","passed":15,"failed":3872},{"name":"simd_f64x2_rounding.wast","passed":25,"failed":176},{"name":"simd_i16x8_arith.wast","passed":13,"failed":181},{"name":"simd_i16x8_arith2.wast","passed":21,"failed":151},{"name":"simd_i16x8_cmp.wast","passed":32,"failed":433},{"name":"simd_i16x8_extadd_pairwise_i8x16.wast","passed":5,"failed":16},{"name":"simd_i16x8_extmul_i8x16.wast","passed":13,"failed":104},{"name":"simd_i16x8_q15mulr_sat_s.wast","passed":4,"failed":26},{"name":"simd_i16x8_sat_arith.wast","passed":18,"failed":204},{"name":"simd_i32x4_arith.wast","passed":13,"failed":181},{"name":"simd_i32x4_arith2.wast","passed":28,"failed":121},{"name":"simd_i32x4_cmp.wast","passed":42,"failed":433},{"name":"simd_i32x4_dot_i16x8.wast","passed":4,"failed":26},{"name":"simd_i32x4_extadd_pairwise_i16x8.wast","passed":5,"failed":16},{"name":"simd_i32x4_extmul_i16x8.wast","passed":13,"failed":104},{"name":"simd_i32x4_trunc_sat_f32x4.wast","passed":5,"failed":102},{"name":"simd_i32x4_trunc_sat_f64x2.wast","passed":5,"failed":102},{"name":"simd_i64x2_arith.wast","passed":13,"failed":187},{"name":"simd_i64x2_arith2.wast","passed":4,"failed":21},{"name":"simd_i64x2_cmp.wast","passed":11,"failed":102},{"name":"simd_i64x2_extmul_i32x4.wast","passed":13,"failed":104},{"name":"simd_i8x16_arith.wast","passed":10,"failed":121},{"name":"simd_i8x16_arith2.wast","passed":27,"failed":184},{"name":"simd_i8x16_cmp.wast","passed":32,"failed":413},{"name":"simd_i8x16_sat_arith.wast","passed":26,"failed":188},{"name":"simd_int_to_int_extend.wast","passed":25,"failed":228},{"name":"simd_lane.wast","passed":209,"failed":266},{"name":"simd_linking.wast","passed":0,"failed":3},{"name":"simd_load.wast","passed":24,"failed":15},{"name":"simd_load16_lane.wast","passed":4,"failed":32},{"name":"simd_load32_lane.wast","passed":4,"failed":20},{"name":"simd_load64_lane.wast","passed":4,"failed":12},{"name":"simd_load8_lane.wast","passed":4,"failed":48},{"name":"simd_load_extend.wast","passed":24,"failed":80},{"name":"simd_load_splat.wast","passed":17,"failed":109},{"name":"simd_load_zero.wast","passed":12,"failed":27},{"name":"simd_splat.wast","passed":37,"failed":148},{"name":"simd_store.wast","passed":20,"failed":8},{"name":"simd_store16_lane.wast","passed":3,"failed":33},{"name":"simd_store32_lane.wast","passed":3,"failed":21},{"name":"simd_store64_lane.wast","passed":3,"failed":13},{"name":"simd_store8_lane.wast","passed":3,"failed":49}]
+0.9.0-alpha.0,24355,1625,[{"name":"simd_address.wast","passed":49,"failed":0},{"name":"simd_align.wast","passed":100,"failed":0},{"name":"simd_bit_shift.wast","passed":252,"failed":0},{"name":"simd_bitwise.wast","passed":169,"failed":0},{"name":"simd_boolean.wast","passed":277,"failed":0},{"name":"simd_const.wast","passed":757,"failed":0},{"name":"simd_conversions.wast","passed":56,"failed":226},{"name":"simd_f32x4.wast","passed":790,"failed":0},{"name":"simd_f32x4_arith.wast","passed":1822,"failed":0},{"name":"simd_f32x4_cmp.wast","passed":2607,"failed":0},{"name":"simd_f32x4_pmin_pmax.wast","passed":3887,"failed":0},{"name":"simd_f32x4_rounding.wast","passed":148,"failed":53},{"name":"simd_f64x2.wast","passed":803,"failed":0},{"name":"simd_f64x2_arith.wast","passed":1824,"failed":1},{"name":"simd_f64x2_cmp.wast","passed":2685,"failed":0},{"name":"simd_f64x2_pmin_pmax.wast","passed":3887,"failed":0},{"name":"simd_f64x2_rounding.wast","passed":148,"failed":53},{"name":"simd_i16x8_arith.wast","passed":194,"failed":0},{"name":"simd_i16x8_arith2.wast","passed":142,"failed":30},{"name":"simd_i16x8_cmp.wast","passed":436,"failed":29},{"name":"simd_i16x8_extadd_pairwise_i8x16.wast","passed":5,"failed":16},{"name":"simd_i16x8_extmul_i8x16.wast","passed":13,"failed":104},{"name":"simd_i16x8_q15mulr_sat_s.wast","passed":30,"failed":0},{"name":"simd_i16x8_sat_arith.wast","passed":222,"failed":0},{"name":"simd_i32x4_arith.wast","passed":194,"failed":0},{"name":"simd_i32x4_arith2.wast","passed":149,"failed":0},{"name":"simd_i32x4_cmp.wast","passed":450,"failed":25},{"name":"simd_i32x4_dot_i16x8.wast","passed":14,"failed":16},{"name":"simd_i32x4_extadd_pairwise_i16x8.wast","passed":5,"failed":16},{"name":"simd_i32x4_extmul_i16x8.wast","passed":13,"failed":104},{"name":"simd_i32x4_trunc_sat_f32x4.wast","passed":17,"failed":90},{"name":"simd_i32x4_trunc_sat_f64x2.wast","passed":5,"failed":102},{"name":"simd_i64x2_arith.wast","passed":200,"failed":0},{"name":"simd_i64x2_arith2.wast","passed":25,"failed":0},{"name":"simd_i64x2_cmp.wast","passed":97,"failed":16},{"name":"simd_i64x2_extmul_i32x4.wast","passed":13,"failed":104},{"name":"simd_i8x16_arith.wast","passed":131,"failed":0},{"name":"simd_i8x16_arith2.wast","passed":179,"failed":32},{"name":"simd_i8x16_cmp.wast","passed":409,"failed":36},{"name":"simd_i8x16_sat_arith.wast","passed":214,"failed":0},{"name":"simd_int_to_int_extend.wast","passed":25,"failed":228},{"name":"simd_lane.wast","passed":331,"failed":144},{"name":"simd_linking.wast","passed":3,"failed":0},{"name":"simd_load.wast","passed":37,"failed":2},{"name":"simd_load16_lane.wast","passed":36,"failed":0},{"name":"simd_load32_lane.wast","passed":24,"failed":0},{"name":"simd_load64_lane.wast","passed":16,"failed":0},{"name":"simd_load8_lane.wast","passed":52,"failed":0},{"name":"simd_load_extend.wast","passed":20,"failed":84},{"name":"simd_load_splat.wast","passed":14,"failed":112},{"name":"simd_load_zero.wast","passed":39,"failed":0},{"name":"simd_memory-multi.wast","passed":1,"failed":0},{"name":"simd_splat.wast","passed":183,"failed":2},{"name":"simd_store.wast","passed":28,"failed":0},{"name":"simd_store16_lane.wast","passed":36,"failed":0},{"name":"simd_store32_lane.wast","passed":24,"failed":0},{"name":"simd_store64_lane.wast","passed":16,"failed":0},{"name":"simd_store8_lane.wast","passed":52,"failed":0}]
diff --git a/crates/tinywasm/tests/host_func_signature_check.rs b/crates/tinywasm/tests/host_func_signature_check.rs
index c60ade2..698ad61 100644
--- a/crates/tinywasm/tests/host_func_signature_check.rs
+++ b/crates/tinywasm/tests/host_func_signature_check.rs
@@ -1,8 +1,8 @@
use eyre::Result;
use std::fmt::Write;
use tinywasm::{
- types::{FuncType, ValType, WasmValue},
Extern, FuncContext, Imports, Module, Store,
+ types::{FuncType, ValType, WasmValue},
};
use tinywasm_types::ExternRef;
diff --git a/crates/tinywasm/tests/test-wasm-1.rs b/crates/tinywasm/tests/test-wasm-1.rs
index 94c83f9..be235ae 100644
--- a/crates/tinywasm/tests/test-wasm-1.rs
+++ b/crates/tinywasm/tests/test-wasm-1.rs
@@ -1,7 +1,7 @@
mod testsuite;
use eyre::Result;
use testsuite::TestSuite;
-use wasm_testsuite::data::{spec, SpecVersion};
+use wasm_testsuite::data::{SpecVersion, spec};
fn main() -> Result<()> {
TestSuite::set_log_level(log::LevelFilter::Off);
diff --git a/crates/tinywasm/tests/test-wasm-2.rs b/crates/tinywasm/tests/test-wasm-2.rs
index 9b30ac0..0379ca6 100644
--- a/crates/tinywasm/tests/test-wasm-2.rs
+++ b/crates/tinywasm/tests/test-wasm-2.rs
@@ -1,7 +1,7 @@
mod testsuite;
use eyre::Result;
use testsuite::TestSuite;
-use wasm_testsuite::data::{spec, SpecVersion};
+use wasm_testsuite::data::{SpecVersion, spec};
fn main() -> Result<()> {
TestSuite::set_log_level(log::LevelFilter::Off);
diff --git a/crates/tinywasm/tests/test-wasm-3.rs b/crates/tinywasm/tests/test-wasm-3.rs
index a0e2543..3e63dc5 100644
--- a/crates/tinywasm/tests/test-wasm-3.rs
+++ b/crates/tinywasm/tests/test-wasm-3.rs
@@ -1,7 +1,7 @@
mod testsuite;
use eyre::Result;
use testsuite::TestSuite;
-use wasm_testsuite::data::{spec, SpecVersion};
+use wasm_testsuite::data::{SpecVersion, spec};
fn main() -> Result<()> {
if !std::env::args().any(|x| &x == "--enable") {
diff --git a/crates/tinywasm/tests/test-wasm-annotations.rs b/crates/tinywasm/tests/test-wasm-annotations.rs
index 3170241..beac9eb 100644
--- a/crates/tinywasm/tests/test-wasm-annotations.rs
+++ b/crates/tinywasm/tests/test-wasm-annotations.rs
@@ -1,7 +1,7 @@
mod testsuite;
use eyre::Result;
use testsuite::TestSuite;
-use wasm_testsuite::data::{proposal, Proposal};
+use wasm_testsuite::data::{Proposal, proposal};
fn main() -> Result<()> {
TestSuite::set_log_level(log::LevelFilter::Off);
diff --git a/crates/tinywasm/tests/test-wasm-extended-const.rs b/crates/tinywasm/tests/test-wasm-extended-const.rs
index 7c9a304..888a49f 100644
--- a/crates/tinywasm/tests/test-wasm-extended-const.rs
+++ b/crates/tinywasm/tests/test-wasm-extended-const.rs
@@ -1,7 +1,7 @@
mod testsuite;
use eyre::Result;
use testsuite::TestSuite;
-use wasm_testsuite::data::{proposal, Proposal};
+use wasm_testsuite::data::{Proposal, proposal};
fn main() -> Result<()> {
TestSuite::set_log_level(log::LevelFilter::Off);
diff --git a/crates/tinywasm/tests/test-wasm-multi-memory.rs b/crates/tinywasm/tests/test-wasm-multi-memory.rs
index d491fb1..30052b0 100644
--- a/crates/tinywasm/tests/test-wasm-multi-memory.rs
+++ b/crates/tinywasm/tests/test-wasm-multi-memory.rs
@@ -1,7 +1,7 @@
mod testsuite;
use eyre::Result;
use testsuite::TestSuite;
-use wasm_testsuite::data::{proposal, Proposal};
+use wasm_testsuite::data::{Proposal, proposal};
fn main() -> Result<()> {
TestSuite::set_log_level(log::LevelFilter::Off);
diff --git a/crates/tinywasm/tests/test-wasm-relaxed-simd.rs b/crates/tinywasm/tests/test-wasm-relaxed-simd.rs
index 7af830a..0851d18 100644
--- a/crates/tinywasm/tests/test-wasm-relaxed-simd.rs
+++ b/crates/tinywasm/tests/test-wasm-relaxed-simd.rs
@@ -1,7 +1,7 @@
mod testsuite;
use eyre::Result;
use testsuite::TestSuite;
-use wasm_testsuite::data::{proposal, Proposal};
+use wasm_testsuite::data::{Proposal, proposal};
fn main() -> Result<()> {
TestSuite::set_log_level(log::LevelFilter::Off);
diff --git a/crates/tinywasm/tests/test-wasm-simd.rs b/crates/tinywasm/tests/test-wasm-simd.rs
new file mode 100644
index 0000000..d8f15ea
--- /dev/null
+++ b/crates/tinywasm/tests/test-wasm-simd.rs
@@ -0,0 +1,13 @@
+mod testsuite;
+use eyre::Result;
+use testsuite::TestSuite;
+use wasm_testsuite::data::{Proposal, proposal};
+
+fn main() -> Result<()> {
+ TestSuite::set_log_level(log::LevelFilter::Off);
+
+ let mut test_suite = TestSuite::new();
+ test_suite.run_files(proposal(&Proposal::Simd))?;
+ test_suite.save_csv("./tests/generated/wasm-simd.csv", env!("CARGO_PKG_VERSION"))?;
+ test_suite.report_status()
+}
diff --git a/crates/tinywasm/tests/test-wast.rs b/crates/tinywasm/tests/test-wast.rs
index 33c716c..40b0e04 100644
--- a/crates/tinywasm/tests/test-wast.rs
+++ b/crates/tinywasm/tests/test-wast.rs
@@ -1,6 +1,6 @@
use std::path::PathBuf;
-use eyre::{bail, eyre, Result};
+use eyre::{Result, bail, eyre};
use owo_colors::OwoColorize;
use testsuite::TestSuite;
diff --git a/crates/tinywasm/tests/testsuite/mod.rs b/crates/tinywasm/tests/testsuite/mod.rs
index ee0336e..c1ba46e 100644
--- a/crates/tinywasm/tests/testsuite/mod.rs
+++ b/crates/tinywasm/tests/testsuite/mod.rs
@@ -1,5 +1,5 @@
#![allow(unused)]
-use eyre::{eyre, Result};
+use eyre::{Result, eyre};
use indexmap::IndexMap;
use owo_colors::OwoColorize;
use std::io::{BufRead, Seek, SeekFrom};
diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs
index 0804266..d09efdb 100644
--- a/crates/tinywasm/tests/testsuite/run.rs
+++ b/crates/tinywasm/tests/testsuite/run.rs
@@ -2,14 +2,14 @@ use crate::testsuite::util::*;
use std::{borrow::Cow, collections::HashMap, fs::canonicalize, path::PathBuf};
use super::TestSuite;
-use eyre::{eyre, Result};
+use eyre::{Result, eyre};
use indexmap::IndexMap;
use log::{debug, error, info};
use tinywasm::{Extern, Imports, ModuleInstance};
use tinywasm_types::{ExternVal, MemoryType, ModuleInstanceAddr, TableType, ValType, WasmValue};
use wasm_testsuite::data::TestFile;
use wasm_testsuite::wast;
-use wasm_testsuite::wast::{lexer::Lexer, parser::ParseBuffer, Wast};
+use wasm_testsuite::wast::{Wast, lexer::Lexer, parser::ParseBuffer};
#[derive(Default)]
struct ModuleRegistry {
diff --git a/crates/tinywasm/tests/testsuite/util.rs b/crates/tinywasm/tests/testsuite/util.rs
index f8f862b..5e8558a 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 eyre::{Result, bail, eyre};
use tinywasm_types::{ExternRef, FuncRef, ModuleInstanceAddr, TinyWasmModule, ValType, WasmValue};
use wasm_testsuite::wast;
-use wasm_testsuite::wast::{core::AbstractHeapType, QuoteWat};
+use wasm_testsuite::wast::{QuoteWat, core::AbstractHeapType};
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();
@@ -96,13 +96,13 @@ fn wastarg2tinywasmvalue(arg: wast::WastArg) -> Result<tinywasm_types::WasmValue
bail!("unsupported arg type: Component");
};
- use wast::core::WastArgCore::{RefExtern, RefNull, F32, F64, I32, I64, V128};
+ use wast::core::WastArgCore::{F32, F64, I32, I64, RefExtern, RefNull, V128};
Ok(match arg {
F32(f) => WasmValue::F32(f32::from_bits(f.bits)),
F64(f) => WasmValue::F64(f64::from_bits(f.bits)),
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()),
+ V128(i) => WasmValue::V128(i128::from_le_bytes(i.to_le_bytes())),
RefExtern(v) => WasmValue::RefExtern(ExternRef::new(Some(v))),
RefNull(t) => match t {
wast::core::HeapType::Abstract { shared: false, ty: AbstractHeapType::Func } => {
@@ -117,19 +117,21 @@ fn wastarg2tinywasmvalue(arg: wast::WastArg) -> Result<tinywasm_types::WasmValue
})
}
-fn wast_i128_to_i128(i: wast::core::V128Pattern) -> u128 {
- match i {
+fn wast_i128_to_i128(i: wast::core::V128Pattern) -> i128 {
+ let res: Vec<u8> = match i {
wast::core::V128Pattern::F32x4(f) => {
- f.iter().fold(0, |acc, &f| (acc << 32) | nanpattern2tinywasmvalue(f).unwrap().as_f32().unwrap() as u128)
+ f.iter().flat_map(|v| nanpattern2tinywasmvalue(*v).unwrap().as_f32().unwrap().to_le_bytes()).collect()
}
wast::core::V128Pattern::F64x2(f) => {
- f.iter().fold(0, |acc, &f| (acc << 64) | nanpattern2tinywasmvalue(f).unwrap().as_f64().unwrap() as u128)
+ f.iter().flat_map(|v| nanpattern2tinywasmvalue(*v).unwrap().as_f64().unwrap().to_le_bytes()).collect()
}
- wast::core::V128Pattern::I16x8(f) => f.iter().fold(0, |acc, &f| (acc << 16) | f as u128),
- wast::core::V128Pattern::I32x4(f) => f.iter().fold(0, |acc, &f| (acc << 32) | f as u128),
- wast::core::V128Pattern::I64x2(f) => f.iter().fold(0, |acc, &f| (acc << 64) | f as u128),
- wast::core::V128Pattern::I8x16(f) => f.iter().fold(0, |acc, &f| (acc << 8) | f as u128),
- }
+ wast::core::V128Pattern::I16x8(f) => f.iter().flat_map(|v| v.to_le_bytes()).collect(),
+ wast::core::V128Pattern::I32x4(f) => f.iter().flat_map(|v| v.to_le_bytes()).collect(),
+ wast::core::V128Pattern::I64x2(f) => f.iter().flat_map(|v| v.to_le_bytes()).collect(),
+ wast::core::V128Pattern::I8x16(f) => f.iter().flat_map(|v| v.to_le_bytes()).collect(),
+ };
+
+ i128::from_le_bytes(res.try_into().unwrap())
}
fn wastret2tinywasmvalue(ret: wast::WastRet) -> Result<tinywasm_types::WasmValue> {
@@ -137,7 +139,7 @@ fn wastret2tinywasmvalue(ret: wast::WastRet) -> Result<tinywasm_types::WasmValue
bail!("unsupported arg type");
};
- use wast::core::WastRetCore::{RefExtern, RefFunc, RefNull, F32, F64, I32, I64, V128};
+ use wast::core::WastRetCore::{F32, F64, I32, I64, RefExtern, RefFunc, RefNull, V128};
Ok(match ret {
F32(f) => nanpattern2tinywasmvalue(f)?,
F64(f) => nanpattern2tinywasmvalue(f)?,
diff --git a/crates/types/src/instructions.rs b/crates/types/src/instructions.rs
index 899be65..9db5ed5 100644
--- a/crates/types/src/instructions.rs
+++ b/crates/types/src/instructions.rs
@@ -4,7 +4,6 @@ use crate::{ConstIdx, DataAddr, ElemAddr, ExternAddr, MemAddr};
/// Represents a memory immediate in a WebAssembly memory instruction.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
-
pub struct MemoryArg([u8; 12]);
impl MemoryArg {
@@ -36,6 +35,7 @@ pub enum ConstInstruction {
I64Const(i64),
F32Const(f32),
F64Const(f64),
+ V128Const(i128),
GlobalGet(GlobalAddr),
RefFunc(Option<FuncAddr>),
RefExtern(Option<ExternAddr>),
@@ -206,18 +206,17 @@ pub enum Instruction {
F32x4ExtractLane(u8), F32x4ReplaceLane(u8),
F64x2ExtractLane(u8), F64x2ReplaceLane(u8),
- V128Not, V128And, V128AndNot, V128Or, V128Xor, V128Bitselect, V128AnyTrue,
-
- I8x16Splat, I8x16Swizzle, I8x16Eq, I8x16Ne, I8x16LtS, I8x16LtU, I8x16GtS, I8x16GtU, I8x16LeS, I8x16LeU, I8x16GeS, I8x16GeU,
+ V128Not, V128And, V128AndNot, V128Or, V128Xor, V128Bitselect, V128AnyTrue, I8x16Swizzle,
+ I8x16Splat, I8x16Eq, I8x16Ne, I8x16LtS, I8x16LtU, I8x16GtS, I8x16GtU, I8x16LeS, I8x16LeU, I8x16GeS, I8x16GeU,
I16x8Splat, I16x8Eq, I16x8Ne, I16x8LtS, I16x8LtU, I16x8GtS, I16x8GtU, I16x8LeS, I16x8LeU, I16x8GeS, I16x8GeU,
I32x4Splat, I32x4Eq, I32x4Ne, I32x4LtS, I32x4LtU, I32x4GtS, I32x4GtU, I32x4LeS, I32x4LeU, I32x4GeS, I32x4GeU,
- I64x2Splat, I64x2Eq, I64x2Ne, I64x2LtS, I64x2GtS, I64x2LeS, I64x2GeS,
+ I64x2Splat, I64x2Eq, I64x2Ne, I64x2LtS, I64x2GtS, I64x2LeS, I64x2GeS,
F32x4Splat, F32x4Eq, F32x4Ne, F32x4Lt, F32x4Gt, F32x4Le, F32x4Ge,
F64x2Splat, F64x2Eq, F64x2Ne, F64x2Lt, F64x2Gt, F64x2Le, F64x2Ge,
I8x16Abs, I8x16Neg, I8x16AllTrue, I8x16Bitmask, I8x16Shl, I8x16ShrS, I8x16ShrU, I8x16Add, I8x16Sub, I8x16MinS, I8x16MinU, I8x16MaxS, I8x16MaxU,
I16x8Abs, I16x8Neg, I16x8AllTrue, I16x8Bitmask, I16x8Shl, I16x8ShrS, I16x8ShrU, I16x8Add, I16x8Sub, I16x8MinS, I16x8MinU, I16x8MaxS, I16x8MaxU,
- I32x4Abs, I32x4Neg, I32x4AllTrue, I32x4Bitmask, I32x4Shl, I32x4ShrS, I32x4ShrU, I32x4Add, I32x4Sub, I32x4MinS, I32x4MinU, I32x4MaxS, I32x4MaxU,
+ I32x4Abs, I32x4Neg, I32x4AllTrue, I32x4Bitmask, I32x4Shl, I32x4ShrS, I32x4ShrU, I32x4Add, I32x4Sub, I32x4MinS, I32x4MinU, I32x4MaxS, I32x4MaxU,
I64x2Abs, I64x2Neg, I64x2AllTrue, I64x2Bitmask, I64x2Shl, I64x2ShrS, I64x2ShrU, I64x2Add, I64x2Sub, I64x2Mul,
I8x16NarrowI16x8S, I8x16NarrowI16x8U, I8x16AddSatS, I8x16AddSatU, I8x16SubSatS, I8x16SubSatU, I8x16AvgrU,
diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs
index d9f2234..470c631 100644
--- a/crates/types/src/lib.rs
+++ b/crates/types/src/lib.rs
@@ -259,7 +259,7 @@ pub struct WasmFunction {
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
pub struct WasmFunctionData {
- pub v128_constants: Box<[u128]>,
+ pub v128_constants: Box<[i128]>,
}
/// A WebAssembly Module Export
diff --git a/crates/types/src/value.rs b/crates/types/src/value.rs
index 01a31d5..a9498cc 100644
--- a/crates/types/src/value.rs
+++ b/crates/types/src/value.rs
@@ -17,7 +17,7 @@ pub enum WasmValue {
/// A 64-bit float.
F64(f64),
// /// A 128-bit vector
- V128(u128),
+ V128(i128),
RefExtern(ExternRef),
RefFunc(FuncRef),
@@ -112,6 +112,7 @@ impl WasmValue {
Self::I64(i) => ConstInstruction::I64Const(*i),
Self::F32(i) => ConstInstruction::F32Const(*i),
Self::F64(i) => ConstInstruction::F64Const(*i),
+ Self::V128(i) => ConstInstruction::V128Const(*i),
Self::RefFunc(i) => ConstInstruction::RefFunc(i.addr()),
_ => unimplemented!("no const_instr for {:?}", self),
}
@@ -137,6 +138,7 @@ impl WasmValue {
match (self, other) {
(Self::I32(a), Self::I32(b)) => a == b,
(Self::I64(a), Self::I64(b)) => a == b,
+ (Self::V128(a), Self::V128(b)) => a == b,
(Self::RefExtern(addr), Self::RefExtern(addr2)) => addr == addr2,
(Self::RefFunc(addr), Self::RefFunc(addr2)) => addr == addr2,
(Self::F32(a), Self::F32(b)) => {
@@ -190,7 +192,7 @@ impl WasmValue {
}
#[doc(hidden)]
- pub fn as_v128(&self) -> Option<u128> {
+ pub fn as_v128(&self) -> Option<i128> {
match self {
Self::V128(i) => Some(*i),
_ => None,
@@ -309,4 +311,4 @@ macro_rules! impl_conversion_for_wasmvalue {
}
}
-impl_conversion_for_wasmvalue! { i32 => I32, i64 => I64, f32 => F32, f64 => F64, u128 => V128, ExternRef => RefExtern, FuncRef => RefFunc }
+impl_conversion_for_wasmvalue! { i32 => I32, i64 => I64, f32 => F32, f64 => F64, i128 => V128, ExternRef => RefExtern, FuncRef => RefFunc }
diff --git a/examples/archive.rs b/examples/archive.rs
index 6a3d54e..7a1021b 100644
--- a/examples/archive.rs
+++ b/examples/archive.rs
@@ -1,5 +1,5 @@
use eyre::Result;
-use tinywasm::{parser::Parser, types::TinyWasmModule, Module, Store};
+use tinywasm::{Module, Store, parser::Parser, types::TinyWasmModule};
const WASM: &str = r#"
(module
diff --git a/examples/funcref_callbacks.rs b/examples/funcref_callbacks.rs
index df50e75..01f833c 100644
--- a/examples/funcref_callbacks.rs
+++ b/examples/funcref_callbacks.rs
@@ -1,5 +1,5 @@
use eyre::Result;
-use tinywasm::{types::FuncRef, Extern, FuncContext, Imports, Module, Store};
+use tinywasm::{Extern, FuncContext, Imports, Module, Store, types::FuncRef};
fn main() -> Result<()> {
by_func_ref_passed()?;
diff --git a/examples/wasm-rust.rs b/examples/wasm-rust.rs
index 95769f4..d5a6b2a 100644
--- a/examples/wasm-rust.rs
+++ b/examples/wasm-rust.rs
@@ -1,6 +1,6 @@
use std::hint::black_box;
-use eyre::{eyre, Result};
+use eyre::{Result, eyre};
use tinywasm::{Extern, FuncContext, Imports, MemoryStringExt, Module, Store};
/// Examples of using WebAssembly compiled from Rust with tinywasm.