diff --git a/Cargo.lock b/Cargo.lock index acf2468ef..f8617a683 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + [[package]] name = "aho-corasick" version = "1.1.4" @@ -67,6 +73,18 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "auditable-serde" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7bf8143dfc3c0258df908843e169b5cc5fcf76c7718bd66135ef4a9cd558c5" +dependencies = [ + "semver", + "serde", + "serde_json", + "topological-sort", +] + [[package]] name = "beef" version = "0.5.2" @@ -161,6 +179,15 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -186,6 +213,17 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "either" version = "1.15.0" @@ -237,6 +275,16 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "flate2" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -249,6 +297,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + [[package]] name = "futures" version = "0.3.31" @@ -360,12 +417,114 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + [[package]] name = "id-arena" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "im-rc" version = "15.1.0" @@ -434,12 +593,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "leb128" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" - [[package]] name = "leb128fmt" version = "0.1.0" @@ -458,6 +611,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + [[package]] name = "log" version = "0.4.28" @@ -526,12 +685,28 @@ dependencies = [ "syn", ] +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + [[package]] name = "once_cell_polyfill" version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + [[package]] name = "petgraph" version = "0.6.5" @@ -569,6 +744,15 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + [[package]] name = "prettyplease" version = "0.2.37" @@ -778,6 +962,12 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + [[package]] name = "sized-chunks" version = "0.6.5" @@ -809,6 +999,12 @@ dependencies = [ "smallvec", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "strsim" version = "0.11.1" @@ -826,6 +1022,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "terminal_size" version = "0.4.3" @@ -867,6 +1074,16 @@ dependencies = [ "syn", ] +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "toml" version = "0.8.23" @@ -908,6 +1125,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" +[[package]] +name = "topological-sort" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d" + [[package]] name = "typenum" version = "1.19.0" @@ -950,6 +1173,24 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -964,9 +1205,9 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wac-graph" -version = "0.6.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d94268a683b67ae20210565b5f91e106fe05034c36b931e739fe90377ed80b98" +checksum = "d511e0c9462a5f6369e7e17e9f0f3b566eab2a235076a23f2db19ca7bf36d32c" dependencies = [ "anyhow", "id-arena", @@ -976,16 +1217,16 @@ dependencies = [ "semver", "thiserror", "wac-types", - "wasm-encoder 0.202.0", - "wasm-metadata 0.202.0", - "wasmparser 0.202.0", + "wasm-encoder 0.239.0", + "wasm-metadata 0.239.0", + "wasmparser 0.239.0", ] [[package]] name = "wac-parser" -version = "0.6.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616ec0c4f63641fa095b4a551263fe35a15c72c9680b650b8f08f70db0fdbd19" +checksum = "b47c29a894f9f82c4da2d036d410babb3bd5aed0acfb4c3d779b536a4316cba0" dependencies = [ "anyhow", "id-arena", @@ -997,23 +1238,23 @@ dependencies = [ "serde", "thiserror", "wac-graph", - "wasm-encoder 0.202.0", - "wasm-metadata 0.202.0", - "wasmparser 0.202.0", + "wasm-encoder 0.239.0", + "wasm-metadata 0.239.0", + "wasmparser 0.239.0", ] [[package]] name = "wac-types" -version = "0.6.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5028a15e266f4c8fed48beb95aebb76af5232dcd554fd849a305a4e5cce1563" +checksum = "64fdef742a5198856c7c754944b329ed684f703dca477d0a77b474b37d990121" dependencies = [ "anyhow", "id-arena", "indexmap", "semver", - "wasm-encoder 0.202.0", - "wasmparser 0.202.0", + "wasm-encoder 0.239.0", + "wasmparser 0.239.0", ] [[package]] @@ -1045,11 +1286,12 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.202.0" +version = "0.239.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd106365a7f5f7aa3c1916a98cbb3ad477f5ff96ddb130285a91c6e7429e67a" +checksum = "5be00faa2b4950c76fe618c409d2c3ea5a3c9422013e079482d78544bb2d184c" dependencies = [ - "leb128", + "leb128fmt", + "wasmparser 0.239.0", ] [[package]] @@ -1064,18 +1306,21 @@ dependencies = [ [[package]] name = "wasm-metadata" -version = "0.202.0" +version = "0.239.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "094aea3cb90e09f16ee25a4c0e324b3e8c934e7fd838bfa039aef5352f44a917" +checksum = "20b3ec880a9ac69ccd92fbdbcf46ee833071cf09f82bb005b2327c7ae6025ae2" dependencies = [ "anyhow", + "auditable-serde", + "flate2", "indexmap", "serde", "serde_derive", "serde_json", "spdx", - "wasm-encoder 0.202.0", - "wasmparser 0.202.0", + "url", + "wasm-encoder 0.239.0", + "wasmparser 0.239.0", ] [[package]] @@ -1092,13 +1337,15 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.202.0" +version = "0.239.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6998515d3cf3f8b980ef7c11b29a9b1017d4cf86b99ae93b546992df9931413" +checksum = "8c9d90bb93e764f6beabf1d02028c70a2156a6583e63ac4218dd07ef733368b0" dependencies = [ "bitflags", + "hashbrown 0.15.5", "indexmap", "semver", + "serde", ] [[package]] @@ -1450,3 +1697,86 @@ dependencies = [ "unicode-xid", "wasmparser 0.243.0", ] + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/crates/c/src/lib.rs b/crates/c/src/lib.rs index d1d11ddc8..8999112d5 100644 --- a/crates/c/src/lib.rs +++ b/crates/c/src/lib.rs @@ -1706,6 +1706,16 @@ impl<'a> wit_bindgen_core::AnonymousTypeGenerator<'a> for InterfaceGenerator<'a> fn anonymous_type_type(&mut self, _id: TypeId, _ty: &Type, _docs: &Docs) { todo!("print_anonymous_type for type"); } + + fn anonymous_type_fixed_size_list( + &mut self, + _id: TypeId, + _ty: &Type, + _size: u32, + _docs: &Docs, + ) { + todo!("print_anonymous_type for fixed size list"); + } } pub enum CTypeNameInfo<'a> { diff --git a/crates/core/src/abi.rs b/crates/core/src/abi.rs index 98e2bf998..245644ceb 100644 --- a/crates/core/src/abi.rs +++ b/crates/core/src/abi.rs @@ -309,6 +309,39 @@ def_instruction! { ty: TypeId, } : [2] => [1], + /// Pops all fields for a fixed list off the stack and then composes them + /// into an array. + FixedSizeListLift { + element: &'a Type, + size: u32, + id: TypeId, + } : [*size as usize] => [1], + + /// Pops an array off the stack, decomposes the elements and then pushes them onto the stack. + FixedSizeListLower { + element: &'a Type, + size: u32, + id: TypeId, + } : [1] => [*size as usize], + + /// Pops an array and an address off the stack, passes each element to a block storing it + FixedSizeListLowerToMemory { + element: &'a Type, + size: u32, + id: TypeId, + } : [2] => [0], + + /// Pops base address, pushes an array + /// + /// This will also pop a block from the block stack which is how to + /// read each individual element from the list. + FixedSizeListLiftFromMemory { + element: &'a Type, + size: u32, + id: TypeId, + } : [1] => [1], + + /// Pushes an operand onto the stack representing the list item from /// each iteration of the list. /// @@ -840,7 +873,7 @@ fn needs_deallocate(resolve: &Resolve, ty: &Type, what: Deallocate) -> bool { TypeDefKind::Flags(_) | TypeDefKind::Enum(_) => false, TypeDefKind::Future(_) | TypeDefKind::Stream(_) => what.handles(), TypeDefKind::Unknown => unreachable!(), - TypeDefKind::FixedSizeList(..) => todo!(), + TypeDefKind::FixedSizeList(t, _) => needs_deallocate(resolve, t, what), }, Type::Bool @@ -1552,7 +1585,21 @@ impl<'a, B: Bindgen> Generator<'a, B> { }); } TypeDefKind::Unknown => unreachable!(), - TypeDefKind::FixedSizeList(..) => todo!(), + TypeDefKind::FixedSizeList(ty, size) => { + self.emit(&FixedSizeListLower { + element: ty, + size: *size, + id, + }); + let mut values = self + .stack + .drain(self.stack.len() - (*size as usize)..) + .collect::>(); + for value in values.drain(..) { + self.stack.push(value); + self.lower(ty); + } + } }, } } @@ -1735,7 +1782,24 @@ impl<'a, B: Bindgen> Generator<'a, B> { }); } TypeDefKind::Unknown => unreachable!(), - TypeDefKind::FixedSizeList(..) => todo!(), + TypeDefKind::FixedSizeList(ty, size) => { + let temp = flat_types(self.resolve, ty, None).unwrap(); + let flat_per_elem = temp.to_vec().len(); + let flatsize = flat_per_elem * (*size as usize); + let mut lowered_args = self + .stack + .drain(self.stack.len() - flatsize..) + .collect::>(); + for _ in 0..*size { + self.stack.extend(lowered_args.drain(..flat_per_elem)); + self.lift(ty); + } + self.emit(&FixedSizeListLift { + element: ty, + size: *size, + id, + }); + } }, } } @@ -1917,7 +1981,21 @@ impl<'a, B: Bindgen> Generator<'a, B> { } TypeDefKind::Unknown => unreachable!(), - TypeDefKind::FixedSizeList(..) => todo!(), + TypeDefKind::FixedSizeList(element, size) => { + // resembles write_list_to_memory + self.push_block(); + self.emit(&IterElem { element }); + self.emit(&IterBasePointer); + let elem_addr = self.stack.pop().unwrap(); + self.write_to_memory(element, elem_addr, offset); + self.finish_block(0); + self.stack.push(addr); + self.emit(&FixedSizeListLowerToMemory { + element, + size: *size, + id, + }); + } }, } } @@ -2104,7 +2182,19 @@ impl<'a, B: Bindgen> Generator<'a, B> { } TypeDefKind::Unknown => unreachable!(), - TypeDefKind::FixedSizeList(..) => todo!(), + TypeDefKind::FixedSizeList(ty, size) => { + self.push_block(); + self.emit(&IterBasePointer); + let elemaddr = self.stack.pop().unwrap(); + self.read_from_memory(ty, elemaddr, Default::default()); + self.finish_block(1); + self.stack.push(addr.clone()); + self.emit(&FixedSizeListLiftFromMemory { + element: ty, + size: *size, + id, + }); + } }, } } @@ -2413,7 +2503,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { TypeDefKind::Future(_) => unreachable!(), TypeDefKind::Stream(_) => unreachable!(), TypeDefKind::Unknown => unreachable!(), - TypeDefKind::FixedSizeList(..) => todo!(), + TypeDefKind::FixedSizeList(_, _) => {} }, } } diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index 993583b06..ff54d2815 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -195,6 +195,7 @@ pub trait AnonymousTypeGenerator<'a> { fn anonymous_type_option(&mut self, id: TypeId, ty: &Type, docs: &Docs); fn anonymous_type_result(&mut self, id: TypeId, ty: &Result_, docs: &Docs); fn anonymous_type_list(&mut self, id: TypeId, ty: &Type, docs: &Docs); + fn anonymous_type_fixed_size_list(&mut self, id: TypeId, ty: &Type, size: u32, docs: &Docs); fn anonymous_type_future(&mut self, id: TypeId, ty: &Option, docs: &Docs); fn anonymous_type_stream(&mut self, id: TypeId, ty: &Option, docs: &Docs); fn anonymous_type_type(&mut self, id: TypeId, ty: &Type, docs: &Docs); @@ -217,7 +218,9 @@ pub trait AnonymousTypeGenerator<'a> { TypeDefKind::Future(f) => self.anonymous_type_future(id, f, &ty.docs), TypeDefKind::Stream(s) => self.anonymous_type_stream(id, s, &ty.docs), TypeDefKind::Handle(handle) => self.anonymous_type_handle(id, handle, &ty.docs), - TypeDefKind::FixedSizeList(..) => todo!(), + TypeDefKind::FixedSizeList(t, size) => { + self.anonymous_type_fixed_size_list(id, t, *size, &ty.docs) + } TypeDefKind::Unknown => unreachable!(), } } diff --git a/crates/core/src/types.rs b/crates/core/src/types.rs index 35d6f5f6c..c3e4e107c 100644 --- a/crates/core/src/types.rs +++ b/crates/core/src/types.rs @@ -203,7 +203,9 @@ impl Types { // should use the same ownership semantics as `own` info.has_own_handle = true; } - TypeDefKind::FixedSizeList(..) => todo!(), + TypeDefKind::FixedSizeList(ty, _) => { + info = self.type_info(resolve, ty); + } TypeDefKind::Unknown => unreachable!(), } let prev = self.type_info.insert(ty, info); diff --git a/crates/cpp/src/lib.rs b/crates/cpp/src/lib.rs index cc2f8e98b..415200170 100644 --- a/crates/cpp/src/lib.rs +++ b/crates/cpp/src/lib.rs @@ -74,6 +74,7 @@ struct Includes { // needs wit types needs_wit: bool, needs_memory: bool, + needs_array: bool, } #[derive(Default)] @@ -415,6 +416,9 @@ impl Cpp { if self.dependencies.needs_memory { self.include(""); } + if self.dependencies.needs_array { + self.include(""); + } if self.dependencies.needs_bit { self.include(""); } @@ -1667,7 +1671,13 @@ impl CppInterfaceGenerator<'_> { TypeDefKind::Future(_) => todo!(), TypeDefKind::Stream(_) => todo!(), TypeDefKind::Type(ty) => self.type_name(ty, from_namespace, flavor), - TypeDefKind::FixedSizeList(_, _) => todo!(), + TypeDefKind::FixedSizeList(ty, size) => { + self.r#gen.dependencies.needs_array = true; + format!( + "std::array<{}, {size}>", + self.type_name(ty, from_namespace, flavor) + ) + } TypeDefKind::Unknown => todo!(), }, Type::ErrorContext => todo!(), @@ -2616,7 +2626,86 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> { results.push(move_if_necessary(&result)); } } - abi::Instruction::IterElem { .. } => results.push("IterElem".to_string()), + abi::Instruction::FixedSizeListLift { + element, + size, + id: _, + } => { + let tmp = self.tmp(); + let result = format!("result{tmp}"); + let typename = self + .r#gen + .type_name(element, &self.namespace, Flavor::InStruct); + self.push_str(&format!("std::array<{typename}, {size}> {result} = {{",)); + for a in operands.drain(0..(*size as usize)) { + self.push_str(&a); + self.push_str(", "); + } + self.push_str("};\n"); + results.push(result); + } + abi::Instruction::FixedSizeListLiftFromMemory { + element, + size: elemsize, + id: _, + } => { + let body = self.blocks.pop().unwrap(); + let tmp = self.tmp(); + let vec = format!("array{tmp}"); + let source = operands[0].clone(); + let size = self.r#gen.sizes.size(element); + let size_str = size.format(POINTER_SIZE_EXPRESSION); + let typename = self + .r#gen + .type_name(element, &self.namespace, Flavor::InStruct); + let ptr_type = self.r#gen.r#gen.opts.ptr_type(); + self.push_str(&format!("std::array<{typename}, {elemsize}> {vec};\n")); + self.push_str(&format!( + "{{ + {ptr_type} outer_base = {source};\n" + )); + let source: String = "outer_base".into(); + // let vec: String = "outer_vec".into(); + self.push_str(&format!("for (unsigned i = 0; i<{elemsize}; ++i) {{\n",)); + self.push_str(&format!("{ptr_type} base = {source} + i * {size_str};\n")); + self.push_str(&body.0); + self.push_str(&format!("{vec}[i] = {};", body.1[0])); + self.push_str("\n}\n}\n"); + results.push(vec); + } + abi::Instruction::FixedSizeListLower { .. } => todo!(), + abi::Instruction::FixedSizeListLowerToMemory { + element, + size: elemsize, + id: _, + } => { + let body = self.blocks.pop().unwrap(); + let vec = operands[0].clone(); + let target = operands[1].clone(); + let size = self.r#gen.sizes.size(element); + let size_str = size.format(POINTER_SIZE_EXPRESSION); + let typename = self + .r#gen + .type_name(element, &self.namespace, Flavor::InStruct); + let ptr_type = self.r#gen.r#gen.opts.ptr_type(); + self.push_str(&format!( + "{{ + {ptr_type} outer_base = {target};\n" + )); + let target: String = "outer_base".into(); + self.push_str(&format!( + "std::array<{typename}, {elemsize}>& outer_vec = {vec};\n" + )); + let vec: String = "outer_vec".into(); + self.push_str(&format!("for (unsigned i = 0; i<{vec}.size(); ++i) {{\n",)); + self.push_str(&format!( + "{ptr_type} base = {target} + i * {size_str}; + {typename}& iter_elem = {vec}[i];\n" + )); + self.push_str(&body.0); + self.push_str("\n}\n}\n"); + } + abi::Instruction::IterElem { .. } => results.push("iter_elem".to_string()), abi::Instruction::IterBasePointer => results.push("base".to_string()), abi::Instruction::RecordLower { record, .. } => { let op = &operands[0]; @@ -3222,7 +3311,7 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> { self.src.push_str(">("); } if *amt == 1 { - if operands[0].starts_with("std::move(") { + if operands[0].starts_with("std::move(") && !operands[0].contains('.') { // remove the std::move due to return value optimization (and complex rules about when std::move harms) self.src.push_str(&operands[0][9..]); } else { diff --git a/crates/csharp/src/function.rs b/crates/csharp/src/function.rs index c22389c2a..3c4f58eae 100644 --- a/crates/csharp/src/function.rs +++ b/crates/csharp/src/function.rs @@ -1391,6 +1391,10 @@ impl Bindgen for FunctionBindgen<'_, '_> { | Instruction::ErrorContextLower { .. } | Instruction::ErrorContextLift { .. } | Instruction::DropHandle { .. } + | Instruction::FixedSizeListLift { .. } + | Instruction::FixedSizeListLower { .. } + | Instruction::FixedSizeListLowerToMemory { .. } + | Instruction::FixedSizeListLiftFromMemory { .. } => { dbg!(inst); todo!() diff --git a/crates/moonbit/src/lib.rs b/crates/moonbit/src/lib.rs index 36368150c..28b741a63 100644 --- a/crates/moonbit/src/lib.rs +++ b/crates/moonbit/src/lib.rs @@ -2696,6 +2696,10 @@ impl Bindgen for FunctionBindgen<'_, '_> { Instruction::ErrorContextLower { .. } | Instruction::ErrorContextLift { .. } | Instruction::DropHandle { .. } => todo!(), + Instruction::FixedSizeListLift { .. } => todo!(), + Instruction::FixedSizeListLower { .. } => todo!(), + Instruction::FixedSizeListLowerToMemory { .. } => todo!(), + Instruction::FixedSizeListLiftFromMemory { .. } => todo!(), } } diff --git a/crates/rust/src/bindgen.rs b/crates/rust/src/bindgen.rs index df3623476..7513176e1 100644 --- a/crates/rust/src/bindgen.rs +++ b/crates/rust/src/bindgen.rs @@ -784,6 +784,24 @@ impl Bindgen for FunctionBindgen<'_, '_> { results.push(len); } + Instruction::FixedSizeListLowerToMemory { + element, + size: _, + id: _, + } => { + let body = self.blocks.pop().unwrap(); + let vec = operands[0].clone(); + let target = operands[1].clone(); + let size = self.r#gen.sizes.size(element); + self.push_str(&format!("for (i, e) in {vec}.into_iter().enumerate() {{\n",)); + self.push_str(&format!( + "let base = {target}.add(i * {});\n", + size.format(POINTER_SIZE_EXPRESSION) + )); + self.push_str(&body); + self.push_str("\n}\n"); + } + Instruction::ListLift { element, .. } => { let body = self.blocks.pop().unwrap(); let tmp = self.tmp(); @@ -1211,6 +1229,53 @@ impl Bindgen for FunctionBindgen<'_, '_> { Instruction::DropHandle { .. } => { uwriteln!(self.src, "let _ = {};", operands[0]); } + Instruction::FixedSizeListLift { + element: _, + size, + id: _, + } => { + let tmp = self.tmp(); + let result = format!("result{tmp}"); + self.push_str(&format!("let {result} = [",)); + for a in operands.drain(0..(*size as usize)) { + self.push_str(&a); + self.push_str(", "); + } + self.push_str("];\n"); + results.push(result); + } + Instruction::FixedSizeListLower { + element: _, + size, + id: _, + } => { + for i in 0..(*size as usize) { + results.push(format!("{}[{i}]", operands[0])); + } + } + Instruction::FixedSizeListLiftFromMemory { + element, + size, + id: _, + } => { + let body = self.blocks.pop().unwrap(); + let elemsize = self + .r#gen + .sizes + .size(element) + .format(POINTER_SIZE_EXPRESSION); + let base = operands[0].clone(); + let tmp = self.tmp(); + let index_var = format!("idx{tmp}"); + self.push_str(&format!( + " let array{tmp}: [_; {size}] = core::array::from_fn(|{index_var}| {{ + let base = {base}.add({index_var} * {elemsize}); + {body} + }});" + )); + let result = format!("array{tmp}"); + results.push(result); + } } } } diff --git a/crates/rust/src/interface.rs b/crates/rust/src/interface.rs index c9a55eb14..d54e72be0 100644 --- a/crates/rust/src/interface.rs +++ b/crates/rust/src/interface.rs @@ -3017,4 +3017,17 @@ impl<'a, 'b> wit_bindgen_core::AnonymousTypeGenerator<'a> for AnonTypeGenerator< self.interface.print_optional_ty(ty.as_ref(), mode); self.interface.push_str(">"); } + + fn anonymous_type_fixed_size_list(&mut self, _id: TypeId, ty: &Type, size: u32, _docs: &Docs) { + self.interface.push_str("["); + self.interface.print_ty( + ty, + TypeMode { + lifetime: None, + lists_borrowed: false, + style: TypeOwnershipStyle::Owned, + }, + ); + self.interface.push_str(&format!("; {size}]")); + } } diff --git a/crates/test/Cargo.toml b/crates/test/Cargo.toml index fb8f45aca..f17d7b46f 100644 --- a/crates/test/Cargo.toml +++ b/crates/test/Cargo.toml @@ -25,9 +25,9 @@ regex = "1.11.1" serde = { workspace = true } toml = "0.8.20" wasi-preview1-component-adapter-provider = "37.0.2" -wac-parser = "0.6.1" -wac-types = "0.6.1" -wac-graph = "0.6.1" +wac-parser = "0.8.1" +wac-types = "0.8.1" +wac-graph = "0.8.1" wasm-compose = { workspace = true } indexmap = { workspace = true } wasm-encoder = { workspace = true } diff --git a/tests/runtime/fixed-size-list/runner.rs b/tests/runtime/fixed-size-list/runner.rs new file mode 100644 index 000000000..b004d8b23 --- /dev/null +++ b/tests/runtime/fixed-size-list/runner.rs @@ -0,0 +1,72 @@ +include!(env!("BINDINGS")); + +use test::fixed_size_lists::to_test::*; + +struct Component; + +export!(Component); + +impl Guest for Component { + fn run() { + list_param([1, 2, 3, 4]); + list_param2([[1, 2], [3, 4]]); + list_param3([ + -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15, 16, -17, 18, -19, 20, + ]); + { + let result = list_result(); + assert_eq!(result, [b'0', b'1', b'A', b'B', b'a', b'b', 128, 255]); + } + { + let result = list_minmax16([0, 1024, 32768, 65535], [1, 2048, -32767, -2]); + assert_eq!(result, ([0, 1024, 32768, 65535], [1, 2048, -32767, -2])); + } + { + let result = list_minmax_float([2.0, -42.0], [0.25, -0.125]); + assert_eq!(result, ([2.0, -42.0], [0.25, -0.125])); + } + { + let result = + list_roundtrip([b'a', b'b', b'c', b'd', 0, 1, 2, 3, b'A', b'B', b'Y', b'Z']); + assert_eq!( + result, + [b'a', b'b', b'c', b'd', 0, 1, 2, 3, b'A', b'B', b'Y', b'Z'] + ); + } + { + let result = nested_roundtrip([[1, 5], [42, 1_000_000]], [[-1, 3], [-2_000_000, 4711]]); + assert_eq!( + result, + ([[1, 5], [42, 1_000_000]], [[-1, 3], [-2_000_000, 4711]]) + ); + } + { + let result = large_roundtrip( + [[1, 5], [42, 1_000_000]], + [ + [-1, 3, -2, 4], + [-2_000_000, 4711, 99_999, -5], + [-6, 7, 8, -9], + [50, -5, 500, -5000], + ], + ); + assert_eq!( + result, + ( + [[1, 5], [42, 1_000_000]], + [ + [-1, 3, -2, 4], + [-2_000_000, 4711, 99_999, -5], + [-6, 7, 8, -9], + [50, -5, 500, -5000] + ] + ) + ); + } + { + let result = nightmare_on_cpp([Nested { l: [1, -1] }, Nested { l: [2, -2] }]); + assert_eq!(result[0].l, [1, -1]); + assert_eq!(result[1].l, [2, -2]); + } + } +} diff --git a/tests/runtime/fixed-size-list/test.cpp b/tests/runtime/fixed-size-list/test.cpp new file mode 100644 index 000000000..abfeabbdd --- /dev/null +++ b/tests/runtime/fixed-size-list/test.cpp @@ -0,0 +1,51 @@ +#include +#include + +using namespace exports::test::fixed_size_lists; + +void to_test::ListParam(std::array a) { + std::array b = std::array{1, 2, 3, 4}; + assert(a == b); +} +void to_test::ListParam2(std::array, 2> a) { + std::array, 2> b = std::array, 2>{std::array{1, 2}, std::array{3, 4}}; + assert(a == b); +} +void to_test::ListParam3(std::array a) { + std::array b = std::array{-1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15, 16, -17, 18, -19, 20}; + assert(a == b); +} +std::array to_test::ListResult() { + return std::array{'0', '1', 'A', 'B', 'a', 'b', 128, 255}; +} +std::tuple, std::array> +to_test::ListMinmax16(std::array a, std::array b) { + return std::tuple, std::array>(a, b); +} +std::tuple, std::array> +to_test::ListMinmaxFloat(std::array a, std::array b) { + return std::tuple, std::array>(a,b); +} +std::array to_test::ListRoundtrip(std::array a) { + return a; +} + +std::tuple, 2>, + std::array, 2>> +to_test::NestedRoundtrip(std::array, 2> a, + std::array, 2> b) { + return std::tuple, 2>, + std::array, 2>>(a, b); +} + +std::tuple, 2>, + std::array, 4>> +to_test::LargeRoundtrip(std::array, 2> a, + std::array, 4> b) { + return std::tuple, 2>, + std::array, 4>>(a, b); +} +std::array +to_test::NightmareOnCpp(std::array a) { + return a; +} diff --git a/tests/runtime/fixed-size-list/test.rs b/tests/runtime/fixed-size-list/test.rs new file mode 100644 index 000000000..669e4b858 --- /dev/null +++ b/tests/runtime/fixed-size-list/test.rs @@ -0,0 +1,43 @@ +include!(env!("BINDINGS")); + +struct Component; + +export!(Component); + +use crate::exports::test::fixed_size_lists::to_test::Nested; + +impl exports::test::fixed_size_lists::to_test::Guest for Component { + fn list_param(a: [u32; 4]) { + assert_eq!(a, [1, 2, 3, 4]); + } + fn list_param2(a: [[u32; 2]; 2]) { + assert_eq!(a, [[1, 2], [3, 4]]); + } + fn list_param3(a: [i32; 20]) { + assert_eq!( + a, + [-1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15, 16, -17, 18, -19, 20] + ); + } + fn list_minmax16(a: [u16; 4], b: [i16; 4]) -> ([u16; 4], [i16; 4]) { + (a, b) + } + fn list_minmax_float(a: [f32; 2], b: [f64; 2]) -> ([f32; 2], [f64; 2]) { + (a, b) + } + fn list_roundtrip(a: [u8; 12]) -> [u8; 12] { + a + } + fn list_result() -> [u8; 8] { + [b'0', b'1', b'A', b'B', b'a', b'b', 128, 255] + } + fn nested_roundtrip(a: [[u32; 2]; 2], b: [[i32; 2]; 2]) -> ([[u32; 2]; 2], [[i32; 2]; 2]) { + (a, b) + } + fn large_roundtrip(a: [[u32; 2]; 2], b: [[i32; 4]; 4]) -> ([[u32; 2]; 2], [[i32; 4]; 4]) { + (a, b) + } + fn nightmare_on_cpp(a: [Nested; 2]) -> [Nested; 2] { + a + } +} diff --git a/tests/runtime/fixed-size-list/test.wit b/tests/runtime/fixed-size-list/test.wit new file mode 100644 index 000000000..496e4470f --- /dev/null +++ b/tests/runtime/fixed-size-list/test.wit @@ -0,0 +1,35 @@ +// run with "--runner wasmtime -W component-model-fixed-size-list" + +package test:fixed-size-lists; + +interface to-test { + list-param: func(a: list); + list-param2: func(a: list, 2>); + list-param3: func(a: list); + list-result: func() -> list; + + list-minmax16: func(a: list, b: list) -> tuple, list>; + list-minmax-float: func(a: list, b: list) + -> tuple, list>; + + list-roundtrip: func(a: list) -> list; + + nested-roundtrip: func(a: list, 2>, b: list, 2>) -> tuple,2>, list, 2>>; + large-roundtrip: func(a: list, 2>, b: list, 4>) -> tuple,2>, list, 4>>; + + record nested { + l: list, + } + + nightmare-on-cpp: func(a: list) -> list; +} + +world test { + export to-test; +} + +world runner { + import to-test; + + export run: func(); +}