diff options
| -rw-r--r-- | Cargo.lock | 145 | ||||
| -rw-r--r-- | Cargo.toml | 10 | ||||
| -rw-r--r-- | crates/parser/src/conversion.rs | 8 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/executor.rs | 124 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/value128.rs | 141 | ||||
| -rw-r--r-- | crates/tinywasm/src/store/memory.rs | 13 | ||||
| -rw-r--r-- | crates/tinywasm/tests/generated/wasm-custom-page-sizes.csv | 2 | ||||
| -rw-r--r-- | crates/tinywasm/tests/generated/wasm-simd.csv | 2 | ||||
| -rw-r--r-- | examples/simple2.rs | 21 |
9 files changed, 329 insertions, 137 deletions
@@ -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", @@ -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(()) +} |
