summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenry Gressmann <mail@henrygressmann.de>2025-12-08 21:58:16 +0100
committerHenry Gressmann <mail@henrygressmann.de>2025-12-08 21:58:16 +0100
commit2911204b3b2508c729c2584016cccd3ef57ffc91 (patch)
treea261be9b88891a6509b4f9f2498713e724fecc93
parentf7f77cd3026e39a2c29faf539575ef57165c81db (diff)
chore: update everything, more simd stuff
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
-rw-r--r--Cargo.lock145
-rw-r--r--Cargo.toml10
-rw-r--r--crates/parser/src/conversion.rs8
-rw-r--r--crates/tinywasm/src/interpreter/executor.rs124
-rw-r--r--crates/tinywasm/src/interpreter/value128.rs141
-rw-r--r--crates/tinywasm/src/store/memory.rs13
-rw-r--r--crates/tinywasm/tests/generated/wasm-custom-page-sizes.csv2
-rw-r--r--crates/tinywasm/tests/generated/wasm-simd.csv2
-rw-r--r--examples/simple2.rs21
9 files changed, 329 insertions, 137 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 2547a99..bc5a5fd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -12,6 +12,15 @@ dependencies = [
]
[[package]]
+name = "alloca"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4"
+dependencies = [
+ "cc",
+]
+
+[[package]]
name = "anes"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -80,6 +89,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
+name = "cc"
+version = "1.2.49"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215"
+dependencies = [
+ "find-msvc-tools",
+ "shlex",
+]
+
+[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -148,10 +167,11 @@ dependencies = [
[[package]]
name = "criterion"
-version = "0.7.0"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928"
+checksum = "4d883447757bb0ee46f233e9dc22eb84d93a9508c9b868687b274fc431d886bf"
dependencies = [
+ "alloca",
"anes",
"cast",
"ciborium",
@@ -160,6 +180,7 @@ dependencies = [
"itertools",
"num-traits",
"oorandom",
+ "page_size",
"rayon",
"regex",
"serde",
@@ -170,9 +191,9 @@ dependencies = [
[[package]]
name = "criterion-plot"
-version = "0.6.0"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338"
+checksum = "ed943f81ea2faa8dcecbbfa50164acf95d555afec96a27871663b300e387b2e4"
dependencies = [
"cast",
"itertools",
@@ -257,6 +278,12 @@ dependencies = [
]
[[package]]
+name = "find-msvc-tools"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844"
+
+[[package]]
name = "half"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -354,9 +381,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "libc"
-version = "0.2.177"
+version = "0.2.178"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
+checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
[[package]]
name = "libm"
@@ -404,6 +431,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52"
[[package]]
+name = "page_size"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
name = "postcard"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -563,6 +600,12 @@ dependencies = [
]
[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
name = "syn"
version = "2.0.111"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -628,7 +671,7 @@ dependencies = [
"tinywasm-parser",
"tinywasm-types",
"wasm-testsuite",
- "wast 242.0.0",
+ "wast",
"wat",
]
@@ -641,7 +684,7 @@ dependencies = [
"log",
"pretty_env_logger",
"tinywasm",
- "wast 242.0.0",
+ "wast",
]
[[package]]
@@ -650,7 +693,7 @@ version = "0.9.0-alpha.0"
dependencies = [
"log",
"tinywasm-types",
- "wasmparser 0.242.0",
+ "wasmparser",
]
[[package]]
@@ -696,50 +739,29 @@ dependencies = [
[[package]]
name = "wasm-encoder"
-version = "0.239.0"
+version = "0.243.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5be00faa2b4950c76fe618c409d2c3ea5a3c9422013e079482d78544bb2d184c"
+checksum = "c55db9c896d70bd9fa535ce83cd4e1f2ec3726b0edd2142079f594fc3be1cb35"
dependencies = [
"leb128fmt",
- "wasmparser 0.239.0",
-]
-
-[[package]]
-name = "wasm-encoder"
-version = "0.242.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67f90e55bc9c6ee6954a757cc6eb3424d96b442e5252ed10fea627e518878d36"
-dependencies = [
- "leb128fmt",
- "wasmparser 0.242.0",
+ "wasmparser",
]
[[package]]
name = "wasm-testsuite"
-version = "0.5.12"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bc4691cd6c251229ed1580c7547800f4ffb4ec9586d7ed5f2a6e1f130d65aa5"
+checksum = "cad9eeaabcdbbe221f3fd9a90eabab05362d8f444dc09bc0930a341ea9779e9e"
dependencies = [
"include_dir",
- "wast 239.0.0",
-]
-
-[[package]]
-name = "wasmparser"
-version = "0.239.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c9d90bb93e764f6beabf1d02028c70a2156a6583e63ac4218dd07ef733368b0"
-dependencies = [
- "bitflags",
- "indexmap",
- "semver",
+ "wast",
]
[[package]]
name = "wasmparser"
-version = "0.242.0"
+version = "0.243.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed3c6e611f4cd748d85c767815823b777dc56afca793fcda27beae4e85028849"
+checksum = "f6d8db401b0528ec316dfbe579e6ab4152d61739cfe076706d2009127970159d"
dependencies = [
"bitflags",
"indexmap",
@@ -748,40 +770,43 @@ dependencies = [
[[package]]
name = "wast"
-version = "239.0.0"
+version = "243.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9139176fe8a2590e0fb174cdcaf373b224cb93c3dde08e4297c1361d2ba1ea5d"
+checksum = "df21d01c2d91e46cb7a221d79e58a2d210ea02020d57c092e79255cc2999ca7f"
dependencies = [
"bumpalo",
"leb128fmt",
"memchr",
"unicode-width",
- "wasm-encoder 0.239.0",
+ "wasm-encoder",
]
[[package]]
-name = "wast"
-version = "242.0.0"
+name = "wat"
+version = "1.243.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50a61ae2997784a4ae2a47b3a99f7cf0ad2a54db09624a28a0c2e9d7a24408ce"
+checksum = "226a9a91cd80a50449312fef0c75c23478fcecfcc4092bdebe1dc8e760ef521b"
dependencies = [
- "bumpalo",
- "leb128fmt",
- "memchr",
- "unicode-width",
- "wasm-encoder 0.242.0",
+ "wast",
]
[[package]]
-name = "wat"
-version = "1.242.0"
+name = "winapi"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ae8cf6adfb79b5d89cb3fe68bd56aaab9409d9cf23b588097eae7d75585dae2"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
- "wast 242.0.0",
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
]
[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
name = "winapi-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -791,6 +816,12 @@ dependencies = [
]
[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -807,18 +838,18 @@ dependencies = [
[[package]]
name = "zerocopy"
-version = "0.8.30"
+version = "0.8.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea879c944afe8a2b25fef16bb4ba234f47c694565e97383b36f3a878219065c"
+checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
-version = "0.8.30"
+version = "0.8.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf955aa904d6040f70dc8e9384444cb1030aed272ba3cb09bbc4ab9e7c1f34f5"
+checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
dependencies = [
"proc-macro2",
"quote",
diff --git a/Cargo.toml b/Cargo.toml
index 443c8d0..e6d1cb4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,14 +4,14 @@ default-members=[".", "crates/tinywasm", "crates/types", "crates/parser"]
resolver="2"
[workspace.dependencies]
-wast="242"
-wat="1.242"
-wasmparser={version="0.242", default-features=false}
+wast="243"
+wat="1.243"
+wasmparser={version="0.243", default-features=false}
eyre="0.6"
log="0.4"
pretty_env_logger="0.5"
-criterion={version="0.7", default-features=false, features=["cargo_bench_support", "rayon"]}
-wasm-testsuite={version="0.5"}
+criterion={version="0.8", default-features=false, features=["cargo_bench_support", "rayon"]}
+wasm-testsuite={version="0.6"}
indexmap="2.12"
owo-colors={version="4.2"}
serde_json={version="1.0"}
diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs
index a4e3b35..b62e670 100644
--- a/crates/parser/src/conversion.rs
+++ b/crates/parser/src/conversion.rs
@@ -94,6 +94,12 @@ pub(crate) fn convert_module_import(import: wasmparser::Import<'_>) -> Result<Im
wasmparser::TypeRef::Tag(ty) => {
return Err(crate::ParseError::UnsupportedOperator(format!("Unsupported import kind: {ty:?}")));
}
+ _ => {
+ return Err(crate::ParseError::UnsupportedOperator(format!(
+ "Unsupported import kind: {:?}",
+ import.ty
+ )));
+ }
},
})
}
@@ -156,7 +162,7 @@ pub(crate) fn convert_module_export(export: wasmparser::Export<'_>) -> Result<Ex
wasmparser::ExternalKind::Table => ExternalKind::Table,
wasmparser::ExternalKind::Memory => ExternalKind::Memory,
wasmparser::ExternalKind::Global => ExternalKind::Global,
- wasmparser::ExternalKind::Tag => {
+ wasmparser::ExternalKind::Tag | wasmparser::ExternalKind::FuncExact => {
return Err(crate::ParseError::UnsupportedOperator(format!("Unsupported export kind: {:?}", export.kind)));
}
};
diff --git a/crates/tinywasm/src/interpreter/executor.rs b/crates/tinywasm/src/interpreter/executor.rs
index 8033a4e..f026244 100644
--- a/crates/tinywasm/src/interpreter/executor.rs
+++ b/crates/tinywasm/src/interpreter/executor.rs
@@ -318,45 +318,45 @@ impl<'store, 'stack> Executor<'store, 'stack> {
V128AnyTrue => self.stack.values.replace_top::<Value128, i32>(|v| Ok((v.reduce_or() != 0) as i32)).to_cf()?,
I8x16Swizzle => self.stack.values.calculate_same::<Value128>(|a, s| Ok(a.swizzle(s))).to_cf()?,
- // V128Load(arg) => self.exec_mem_load::<Value128, 16, _>(arg.mem_addr(), arg.offset(), |v| v)?,
- // V128Load8x8S(_arg) => unimplemented!(),
- // V128Load8x8U(_arg) => unimplemented!(),
- // V128Load16x4S(_arg) => unimplemented!(),
- // V128Load16x4U(_arg) => unimplemented!(),
- // V128Load32x2S(_arg) => unimplemented!(),
- // V128Load32x2U(_arg) => unimplemented!(),
- // V128Load8Splat(_arg) => unimplemented!(),
- // V128Load16Splat(_arg) => unimplemented!(),
- // V128Load32Splat(_arg) => unimplemented!(),
- // V128Load64Splat(_arg) => unimplemented!(),
+ V128Load(arg) => self.exec_mem_load::<Value128, 16, _>(arg.mem_addr(), arg.offset(), |v| v)?,
+ V128Load8x8S(arg) => self.exec_mem_load::<i8, 1, Value128>(arg.mem_addr(), arg.offset(), Value128::extend_8_i8)?,
+ V128Load8x8U(_arg) => self.exec_mem_load::<u8, 1, Value128>(_arg.mem_addr(), _arg.offset(), Value128::extend_8_u8)?,
+ V128Load16x4S(_arg) => self.exec_mem_load::<i16, 2, Value128>(_arg.mem_addr(), _arg.offset(), Value128::extend_4_i16)?,
+ V128Load16x4U(_arg) => self.exec_mem_load::<u16, 2, Value128>(_arg.mem_addr(), _arg.offset(), Value128::extend_4_u16)?,
+ V128Load32x2S(_arg) => self.exec_mem_load::<i32, 4, Value128>(_arg.mem_addr(), _arg.offset(), Value128::extend_2_i32)?,
+ V128Load32x2U(_arg) => self.exec_mem_load::<u32, 4, Value128>(_arg.mem_addr(), _arg.offset(), Value128::extend_2_u32)?,
+ V128Load8Splat(_arg) => self.exec_mem_load::<i8, 1, Value128>(_arg.mem_addr(), _arg.offset(), Value128::splat_i8)?,
+ V128Load16Splat(_arg) => self.exec_mem_load::<i16, 2, Value128>(_arg.mem_addr(), _arg.offset(), Value128::splat_i16)?,
+ V128Load32Splat(_arg) => self.exec_mem_load::<i32, 4, Value128>(_arg.mem_addr(), _arg.offset(), Value128::splat_i32)?,
+ V128Load64Splat(_arg) => self.exec_mem_load::<i64, 8, Value128>(_arg.mem_addr(), _arg.offset(), Value128::splat_i64)?,
- // V128Store(arg) => self.exec_mem_store::<Value128, Value128, 16>(arg.mem_addr(), arg.offset(), |v| v)?,
+ V128Store(arg) => self.exec_mem_store::<Value128, Value128, 16>(arg.mem_addr(), arg.offset(), |v| v)?,
- // V128Store8Lane(arg, lane) => self.exec_mem_store_lane::<i8x16, i8, 1>(arg.mem_addr(), arg.offset(), *lane)?,
- // V128Store16Lane(arg, lane) => self.exec_mem_store_lane::<i16x8, i16, 2>(arg.mem_addr(), arg.offset(), *lane)?,
- // V128Store32Lane(arg, lane) => self.exec_mem_store_lane::<i32x4, i32, 4>(arg.mem_addr(), arg.offset(), *lane)?,
- // V128Store64Lane(arg, lane) => self.exec_mem_store_lane::<i64x2, i64, 8>(arg.mem_addr(), arg.offset(), *lane)?,
+ V128Store8Lane(arg, lane) => self.exec_mem_store_lane::<i8, 1>(arg.mem_addr(), arg.offset(), *lane)?,
+ V128Store16Lane(arg, lane) => self.exec_mem_store_lane::<i16, 2>(arg.mem_addr(), arg.offset(), *lane)?,
+ V128Store32Lane(arg, lane) => self.exec_mem_store_lane::<i32, 4>(arg.mem_addr(), arg.offset(), *lane)?,
+ V128Store64Lane(arg, lane) => self.exec_mem_store_lane::<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.
- // 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])
- // })?,
- // 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])
- // })?,
+ // 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.
+ V128Load32Zero(arg) => self.exec_mem_load::<i32, 4, Value128>(arg.mem_addr(), arg.offset(), |v| {
+ let bytes = v.to_le_bytes();
+ Value128::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
+ })?,
+ V128Load64Zero(arg) => self.exec_mem_load::<i64, 8, Value128>(arg.mem_addr(), arg.offset(), |v| {
+ let bytes = v.to_le_bytes();
+ Value128::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], 0, 0, 0, 0, 0, 0, 0, 0])
+ })?,
- // V128Const(arg) => self.exec_const::<Value128>( self.cf.data().v128_constants[*arg as usize].to_le_bytes().into()),
+ V128Const(arg) => self.exec_const::<Value128>( self.cf.data().v128_constants[*arg as usize].into()),
- // I8x16ExtractLaneS(lane) => self.stack.values.replace_top::<i8x16, i32>(|v| Ok(v[*lane as usize] as i32)).to_cf()?,
- // I8x16ExtractLaneU(lane) => self.stack.values.replace_top::<u8x16, i32>(|v| Ok(v[*lane as usize] as i32)).to_cf()?,
- // I16x8ExtractLaneS(lane) => self.stack.values.replace_top::<i16x8, i32>(|v| Ok(v[*lane as usize] as i32)).to_cf()?,
- // I16x8ExtractLaneU(lane) => self.stack.values.replace_top::<u16x8, i32>(|v| Ok(v[*lane as usize] as i32)).to_cf()?,
- // I32x4ExtractLane(lane) => self.stack.values.replace_top::<i32x4, i32>(|v| Ok(v[*lane as usize])).to_cf()?,
- // I64x2ExtractLane(lane) => self.stack.values.replace_top::<i64x2, i64>(|v| Ok(v[*lane as usize])).to_cf()?,
- // F32x4ExtractLane(lane) => self.stack.values.replace_top::<f32x4, f32>(|v| Ok(v[*lane as usize])).to_cf()?,
- // F64x2ExtractLane(lane) => self.stack.values.replace_top::<f64x2, f64>(|v| Ok(v[*lane as usize])).to_cf()?,
+ // I8x16ExtractLaneS(lane) => self.stack.values.replace_top::<Value128, i32>(|v| Ok(v[*lane as usize] as i32)).to_cf()?,
+ // I8x16ExtractLaneU(lane) => self.stack.values.replace_top::<Value128, i32>(|v| Ok(v[*lane as usize] as i32)).to_cf()?,
+ // I16x8ExtractLaneS(lane) => self.stack.values.replace_top::<Value128, i32>(|v| Ok(v[*lane as usize] as i32)).to_cf()?,
+ // I16x8ExtractLaneU(lane) => self.stack.values.replace_top::<Value128, i32>(|v| Ok(v[*lane as usize] as i32)).to_cf()?,
+ // I32x4ExtractLane(lane) => self.stack.values.replace_top::<Value128, i32>(|v| Ok(v[*lane as usize])).to_cf()?,
+ // I64x2ExtractLane(lane) => self.stack.values.replace_top::<Value128, i64>(|v| Ok(v[*lane as usize])).to_cf()?,
+ // F32x4ExtractLane(lane) => self.stack.values.replace_top::<Value128, f32>(|v| Ok(v[*lane as usize])).to_cf()?,
+ // F64x2ExtractLane(lane) => self.stack.values.replace_top::<Value128, f64>(|v| Ok(v[*lane as usize])).to_cf()?,
// V128Load8Lane(arg, lane) => self.exec_mem_load_lane::<i8, i8x16, 1>(arg.mem_addr(), arg.offset(), *lane)?,
// V128Load16Lane(arg, lane) => self.exec_mem_load_lane::<i16, i16x8, 2>(arg.mem_addr(), arg.offset(), *lane)?,
@@ -1038,18 +1038,14 @@ impl<'store, 'stack> Executor<'store, 'stack> {
}
}
- // fn exec_mem_load_lane<
- // LOAD: MemLoadable<LOAD_SIZE>,
- // INTO: InternalValue + IndexMut<usize, Output = LOAD>,
- // const LOAD_SIZE: usize,
- // >(
+ // fn exec_mem_load_lane<LOAD: MemValue<LOAD_SIZE>, 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 mut imm = self.stack.values.pop::<Value128>().to_mem_bytes();
// let val = self.stack.values.pop::<i32>() as u64;
// let Some(Ok(addr)) = offset.checked_add(val).map(TryInto::try_into) else {
// cold();
@@ -1059,13 +1055,15 @@ impl<'store, 'stack> Executor<'store, 'stack> {
// max: 0,
// })));
// };
- // let val = mem.load_as::<LOAD_SIZE, LOAD>(addr).to_cf()?;
- // imm[lane as usize] = val;
- // self.stack.values.push(imm);
+ // let val = mem.load_as::<LOAD_SIZE, LOAD>(addr).to_cf()?.to_mem_bytes();
+
+ // // imm[lane as usize] = val;
+
+ // self.stack.values.push(Value128::from_mem_bytes(imm));
// ControlFlow::Continue(())
// }
- fn exec_mem_load<LOAD: MemLoadable<LOAD_SIZE>, const LOAD_SIZE: usize, TARGET: InternalValue>(
+ fn exec_mem_load<LOAD: MemValue<LOAD_SIZE>, const LOAD_SIZE: usize, TARGET: InternalValue>(
&mut self,
mem_addr: tinywasm_types::MemAddr,
offset: u64,
@@ -1091,29 +1089,29 @@ impl<'store, 'stack> Executor<'store, 'stack> {
ControlFlow::Continue(())
}
- // 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();
+ fn exec_mem_store_lane<U: MemValue<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::<Value128>().to_mem_bytes();
+ 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,
- // };
+ 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));
- // }
+ if let Err(e) = mem.store((offset + addr) as usize, val.len(), &val) {
+ return ControlFlow::Break(Some(e));
+ }
- // ControlFlow::Continue(())
- // }
+ ControlFlow::Continue(())
+ }
- fn exec_mem_store<T: InternalValue, U: MemStorable<N>, const N: usize>(
+ fn exec_mem_store<T: InternalValue, U: MemValue<N>, const N: usize>(
&mut self,
mem_addr: tinywasm_types::MemAddr,
offset: u64,
diff --git a/crates/tinywasm/src/interpreter/value128.rs b/crates/tinywasm/src/interpreter/value128.rs
index 12d70e5..b9c96a9 100644
--- a/crates/tinywasm/src/interpreter/value128.rs
+++ b/crates/tinywasm/src/interpreter/value128.rs
@@ -33,6 +33,147 @@ impl Value128 {
}
Self::from_le_bytes(result_bytes)
}
+
+ pub const fn extend_8_i8(src: i8) -> Self {
+ let mut result_bytes = [0u8; 16];
+ let mut i = 0;
+ while i < 8 {
+ result_bytes[i * 2] = src as u8;
+ result_bytes[i * 2 + 1] = if src < 0 { 0xFF } else { 0x00 };
+ i += 1;
+ }
+ Self::from_le_bytes(result_bytes)
+ }
+
+ pub const fn extend_8_u8(src: u8) -> Self {
+ let mut result_bytes = [0u8; 16];
+ let mut i = 0;
+ while i < 8 {
+ result_bytes[i * 2] = src;
+ result_bytes[i * 2 + 1] = 0x00;
+ i += 1;
+ }
+ Self::from_le_bytes(result_bytes)
+ }
+
+ pub const fn extend_4_i16(src: i16) -> Self {
+ let mut result_bytes = [0u8; 16];
+ let mut i = 0;
+ while i < 4 {
+ let bytes = src.to_le_bytes();
+ result_bytes[i * 4] = bytes[0];
+ result_bytes[i * 4 + 1] = bytes[1];
+ result_bytes[i * 4 + 2] = if src < 0 { 0xFF } else { 0x00 };
+ result_bytes[i * 4 + 3] = if src < 0 { 0xFF } else { 0x00 };
+ i += 1;
+ }
+ Self::from_le_bytes(result_bytes)
+ }
+
+ pub const fn extend_4_u16(src: u16) -> Self {
+ let mut result_bytes = [0u8; 16];
+ let mut i = 0;
+ while i < 4 {
+ let bytes = src.to_le_bytes();
+ result_bytes[i * 4] = bytes[0];
+ result_bytes[i * 4 + 1] = bytes[1];
+ result_bytes[i * 4 + 2] = 0x00;
+ result_bytes[i * 4 + 3] = 0x00;
+ i += 1;
+ }
+ Self::from_le_bytes(result_bytes)
+ }
+
+ pub const fn extend_2_i32(src: i32) -> Self {
+ let mut result_bytes = [0u8; 16];
+ let mut i = 0;
+ while i < 2 {
+ let bytes = src.to_le_bytes();
+ result_bytes[i * 8] = bytes[0];
+ result_bytes[i * 8 + 1] = bytes[1];
+ result_bytes[i * 8 + 2] = bytes[2];
+ result_bytes[i * 8 + 3] = bytes[3];
+ result_bytes[i * 8 + 4] = if src < 0 { 0xFF } else { 0x00 };
+ result_bytes[i * 8 + 5] = if src < 0 { 0xFF } else { 0x00 };
+ result_bytes[i * 8 + 6] = if src < 0 { 0xFF } else { 0x00 };
+ result_bytes[i * 8 + 7] = if src < 0 { 0xFF } else { 0x00 };
+ i += 1;
+ }
+ Self::from_le_bytes(result_bytes)
+ }
+
+ pub const fn extend_2_u32(src: u32) -> Self {
+ let mut result_bytes = [0u8; 16];
+ let mut i = 0;
+ while i < 2 {
+ let bytes = src.to_le_bytes();
+ result_bytes[i * 8] = bytes[0];
+ result_bytes[i * 8 + 1] = bytes[1];
+ result_bytes[i * 8 + 2] = bytes[2];
+ result_bytes[i * 8 + 3] = bytes[3];
+ result_bytes[i * 8 + 4] = 0x00;
+ result_bytes[i * 8 + 5] = 0x00;
+ result_bytes[i * 8 + 6] = 0x00;
+ result_bytes[i * 8 + 7] = 0x00;
+ i += 1;
+ }
+ Self::from_le_bytes(result_bytes)
+ }
+
+ pub const fn splat_i8(src: i8) -> Self {
+ let mut result_bytes = [0u8; 16];
+ let byte = src as u8;
+ let mut i = 0;
+ while i < 16 {
+ result_bytes[i] = byte;
+ i += 1;
+ }
+ Self::from_le_bytes(result_bytes)
+ }
+
+ pub const fn splat_i16(src: i16) -> Self {
+ let mut result_bytes = [0u8; 16];
+ let bytes = src.to_le_bytes();
+ let mut i = 0;
+ while i < 8 {
+ result_bytes[i * 2] = bytes[0];
+ result_bytes[i * 2 + 1] = bytes[1];
+ i += 1;
+ }
+ Self::from_le_bytes(result_bytes)
+ }
+
+ pub const fn splat_i32(src: i32) -> Self {
+ let mut result_bytes = [0u8; 16];
+ let bytes = src.to_le_bytes();
+ let mut i = 0;
+ while i < 4 {
+ result_bytes[i * 4] = bytes[0];
+ result_bytes[i * 4 + 1] = bytes[1];
+ result_bytes[i * 4 + 2] = bytes[2];
+ result_bytes[i * 4 + 3] = bytes[3];
+ i += 1;
+ }
+ Self::from_le_bytes(result_bytes)
+ }
+
+ pub const fn splat_i64(src: i64) -> Self {
+ let mut result_bytes = [0u8; 16];
+ let bytes = src.to_le_bytes();
+ let mut i = 0;
+ while i < 2 {
+ result_bytes[i * 8] = bytes[0];
+ result_bytes[i * 8 + 1] = bytes[1];
+ result_bytes[i * 8 + 2] = bytes[2];
+ result_bytes[i * 8 + 3] = bytes[3];
+ result_bytes[i * 8 + 4] = bytes[4];
+ result_bytes[i * 8 + 5] = bytes[5];
+ result_bytes[i * 8 + 6] = bytes[6];
+ result_bytes[i * 8 + 7] = bytes[7];
+ i += 1;
+ }
+ Self::from_le_bytes(result_bytes)
+ }
}
impl From<Value128> for i128 {
diff --git a/crates/tinywasm/src/store/memory.rs b/crates/tinywasm/src/store/memory.rs
index 267ca9a..8898212 100644
--- a/crates/tinywasm/src/store/memory.rs
+++ b/crates/tinywasm/src/store/memory.rs
@@ -76,7 +76,7 @@ impl MemoryInstance {
Ok(&self.data[addr..end])
}
- pub(crate) fn load_as<const SIZE: usize, T: MemLoadable<SIZE>>(&self, addr: usize) -> Result<T> {
+ pub(crate) fn load_as<const SIZE: usize, T: MemValue<SIZE>>(&self, addr: usize) -> Result<T> {
let Some(end) = addr.checked_add(SIZE) else {
return Err(self.trap_oob(addr, SIZE));
};
@@ -152,14 +152,11 @@ impl MemoryInstance {
}
}
-/// A trait for types that can be stored in memory
-pub(crate) trait MemStorable<const N: usize> {
+/// A trait for types that can be converted to and from static byte arrays
+pub(crate) trait MemValue<const N: usize>: Copy + Sized {
/// Store a value in memory
fn to_mem_bytes(self) -> [u8; N];
-}
-/// 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_mem_bytes(bytes: [u8; N]) -> Self;
}
@@ -167,14 +164,12 @@ pub(crate) trait MemLoadable<const N: usize>: Sized + Copy {
macro_rules! impl_mem_traits {
($($ty:ty, $size:expr),*) => {
$(
- impl MemLoadable<$size> for $ty {
+ impl MemValue<$size> for $ty {
#[inline(always)]
fn from_mem_bytes(bytes: [u8; $size]) -> Self {
<$ty>::from_le_bytes(bytes.into())
}
- }
- impl MemStorable<$size> for $ty {
#[inline(always)]
fn to_mem_bytes(self) -> [u8; $size] {
self.to_le_bytes().into()
diff --git a/crates/tinywasm/tests/generated/wasm-custom-page-sizes.csv b/crates/tinywasm/tests/generated/wasm-custom-page-sizes.csv
index 5ba121e..1761a0a 100644
--- a/crates/tinywasm/tests/generated/wasm-custom-page-sizes.csv
+++ b/crates/tinywasm/tests/generated/wasm-custom-page-sizes.csv
@@ -1,2 +1,2 @@
0.8.0,57,0,[{"name":"custom-page-sizes-invalid.wast","passed":22,"failed":0},{"name":"custom-page-sizes.wast","passed":35,"failed":0}]
-0.9.0-alpha.0,76,0,[{"name":"custom-page-sizes-invalid.wast","passed":23,"failed":0},{"name":"custom-page-sizes.wast","passed":45,"failed":0},{"name":"memory_max.wast","passed":4,"failed":0},{"name":"memory_max_i64.wast","passed":4,"failed":0}]
+0.9.0-alpha.0,80,0,[{"name":"custom-page-sizes-invalid.wast","passed":23,"failed":0},{"name":"custom-page-sizes.wast","passed":45,"failed":0},{"name":"memory_max.wast","passed":6,"failed":0},{"name":"memory_max_i64.wast","passed":6,"failed":0}]
diff --git a/crates/tinywasm/tests/generated/wasm-simd.csv b/crates/tinywasm/tests/generated/wasm-simd.csv
index 73e3b92..f87cc69 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,24450,1539,[{"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":50,"failed":232},{"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":187,"failed":14},{"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":187,"failed":14},{"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":18},{"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":113,"failed":0},{"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_select.wast","passed":7,"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}]
+0.9.0-alpha.0,2460,23529,[{"name":"simd_address.wast","passed":49,"failed":0},{"name":"simd_align.wast","passed":100,"failed":0},{"name":"simd_bit_shift.wast","passed":41,"failed":211},{"name":"simd_bitwise.wast","passed":169,"failed":0},{"name":"simd_boolean.wast","passed":139,"failed":138},{"name":"simd_const.wast","passed":755,"failed":2},{"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":28},{"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":213,"failed":262},{"name":"simd_linking.wast","passed":3,"failed":0},{"name":"simd_load.wast","passed":29,"failed":10},{"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":30,"failed":74},{"name":"simd_load_splat.wast","passed":122,"failed":4},{"name":"simd_load_zero.wast","passed":37,"failed":2},{"name":"simd_memory-multi.wast","passed":1,"failed":0},{"name":"simd_select.wast","passed":7,"failed":0},{"name":"simd_splat.wast","passed":27,"failed":158},{"name":"simd_store.wast","passed":28,"failed":0},{"name":"simd_store16_lane.wast","passed":4,"failed":32},{"name":"simd_store32_lane.wast","passed":4,"failed":20},{"name":"simd_store64_lane.wast","passed":4,"failed":12},{"name":"simd_store8_lane.wast","passed":52,"failed":0}]
diff --git a/examples/simple2.rs b/examples/simple2.rs
new file mode 100644
index 0000000..a3124f8
--- /dev/null
+++ b/examples/simple2.rs
@@ -0,0 +1,21 @@
+use eyre::Result;
+use tinywasm::{Module, Store};
+
+const WASM: &str = r#"
+(module
+ (func $return (param $lhs i32) (param $rhs i64) (result i32 i64)
+ local.get $lhs
+ local.get $rhs)
+ (export "return" (func $return)))
+"#;
+
+fn main() -> Result<()> {
+ let wasm = wat::parse_str(WASM).expect("failed to parse wat");
+ let module = Module::parse_bytes(&wasm)?;
+ let mut store = Store::default();
+ let instance = module.instantiate(&mut store, None)?;
+ let add = instance.exported_func::<(i32, i64), (i32, i64)>(&store, "return")?;
+
+ assert_eq!(add.call(&mut store, (1, 2))?, (1, 2));
+ Ok(())
+}