From 6c87f4f9b8869cd64a7e9b0a91803f019d96fa47 Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Tue, 18 Jun 2024 23:21:09 -0400 Subject: [PATCH] more stuff --- Cargo.lock | 913 +++++++++++++++++++++++++++++++++- Cargo.toml | 2 +- waffle-func-reloop/Cargo.toml | 10 + waffle-func-reloop/src/lib.rs | 40 ++ wars-component/Cargo.toml | 14 + wars-component/src/lib.rs | 6 + wars-macro/Cargo.toml | 4 +- wars-macro/src/lib.rs | 64 ++- wars-macro/tests/b.rs | 2 + wars-rt/Cargo.toml | 2 + wars-rt/src/func.rs | 10 +- wars-rt/src/func/unsync.rs | 207 ++++++++ wars-rt/src/lib.rs | 144 ++++-- wars-rt/src/wasix.rs | 0 wars-rt/src/wrl.rs | 135 +++++ wars/Cargo.toml | 4 + wars/src/lib.rs | 701 ++++++++++++++++++++------ 17 files changed, 2055 insertions(+), 203 deletions(-) create mode 100644 waffle-func-reloop/Cargo.toml create mode 100644 waffle-func-reloop/src/lib.rs create mode 100644 wars-component/Cargo.toml create mode 100644 wars-component/src/lib.rs create mode 100644 wars-rt/src/func/unsync.rs create mode 100644 wars-rt/src/wasix.rs create mode 100644 wars-rt/src/wrl.rs diff --git a/Cargo.lock b/Cargo.lock index 30f419e..ca22fdc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,18 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -96,6 +108,12 @@ version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + [[package]] name = "atty" version = "0.2.14" @@ -113,6 +131,21 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -212,6 +245,115 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "cranelift-bforest" +version = "0.104.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b85034ffd0efe2f8c0ba73a55a021cd936e3f8526fa24adb50f168874a6b1db7" +dependencies = [ + "cranelift-entity", +] + +[[package]] +name = "cranelift-codegen" +version = "0.104.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6fc9bfd532123a1778ad154c03741c99028e983c3c053cd6a5d177cab3965e" +dependencies = [ + "bumpalo", + "cranelift-bforest", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-control", + "cranelift-entity", + "cranelift-isle", + "gimli", + "hashbrown 0.14.5", + "log", + "regalloc2", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.104.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea93c920184d2d79555c0dde829717180902f69b9983e30b121bbd88288c5e2f" +dependencies = [ + "cranelift-codegen-shared", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.104.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca5378154333193d6eb859514e0062c0c044f98acf8ff067d43aaaaa4e098ce6" + +[[package]] +name = "cranelift-control" +version = "0.104.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95f6f71863046b42c2e960b1156c86bae2b13842be90349103959a0db9a3c30" +dependencies = [ + "arbitrary", +] + +[[package]] +name = "cranelift-entity" +version = "0.104.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18e625456002617a44c8fbdf276b624639f75e6d11b83c62e64ab8659e352dd5" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "cranelift-frontend" +version = "0.104.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c74dde8da13ac38556bafb9c26c2842ec68964cfbe0d07ae40ef879bab7cbbba" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.104.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5683957e3c8fe5da47d0f23f185b86fb9826b2a10767a7df4ca1fb1dedf16e5e" + +[[package]] +name = "cranelift-native" +version = "0.104.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90167a436f69c210a68a8244c4078b918f9f01339c3c8a7322e72e5b3632a8" +dependencies = [ + "cranelift-codegen", + "libc", + "target-lexicon", +] + +[[package]] +name = "cranelift-wasm" +version = "0.104.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "073fa9fbb4c28804245b9daaa74975d712082deab0deebea1d92c3d43593cc91" +dependencies = [ + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "itertools", + "log", + "smallvec", + "wasmparser 0.118.2", + "wasmtime-types", +] + [[package]] name = "crc32fast" version = "1.4.2" @@ -286,6 +428,15 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + [[package]] name = "env_filter" version = "0.1.0" @@ -315,6 +466,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "expander" version = "2.1.0" @@ -392,20 +553,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" dependencies = [ "fallible-iterator", + "indexmap 2.2.6", "stable_deref_trait", ] +[[package]] +name = "golem-wasm-ast" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a73b7e97992db438181bc0884406e2066fbe8c22e6d288a960790221036a9da" +dependencies = [ + "leb128", + "mappable-rc", + "wasm-encoder 0.41.2", + "wasm-metadata", + "wasm-wave", + "wasmparser 0.121.2", +] + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", +] [[package]] name = "heck" @@ -416,6 +604,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -431,6 +625,12 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + [[package]] name = "indexmap" version = "1.9.3" @@ -449,6 +649,7 @@ checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.5", + "serde", ] [[package]] @@ -457,6 +658,21 @@ version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + [[package]] name = "lazy_static" version = "1.4.0" @@ -475,18 +691,80 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + [[package]] name = "log" version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +[[package]] +name = "logos" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c000ca4d908ff18ac99b93a062cb8958d331c3220719c52e77cb19cc6ac5d2c1" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-codegen" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc487311295e0002e452025d6b580b77bb17286de87b57138f3b5db711cded68" +dependencies = [ + "beef", + "fnv", + "proc-macro2", + "quote", + "regex-syntax 0.6.29", + "syn 2.0.66", +] + +[[package]] +name = "logos-derive" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbfc0d229f1f42d790440136d941afd806bc9e949e2bcb8faa813b0f00d1267e" +dependencies = [ + "logos-codegen", +] + +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + +[[package]] +name = "mappable-rc" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "204651f31b0a6a7b2128d2b92c372cd94607b210c3a6b6e542c57a8cfd4db996" + [[package]] name = "memchr" version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +[[package]] +name = "memfd" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" +dependencies = [ + "rustix", +] + [[package]] name = "memmap2" version = "0.5.10" @@ -496,6 +774,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "miniz_oxide" version = "0.7.3" @@ -511,11 +798,20 @@ version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ + "crc32fast", "flate2", + "hashbrown 0.14.5", + "indexmap 2.2.6", "memchr", "ruzstd", ] +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + [[package]] name = "paste" version = "1.0.15" @@ -550,7 +846,7 @@ dependencies = [ "stacker", "structopt", "wasm-encoder 0.202.0", - "wasmparser", + "wasmparser 0.202.0", ] [[package]] @@ -605,6 +901,28 @@ dependencies = [ "cc", ] +[[package]] +name = "quasiquote" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d7f3e24436387bc9ee9963246739f2a851d9ca85ed73a2c5b878bf908e9b34d" +dependencies = [ + "proc-macro2", + "quasiquote-proc-macro", + "quote", +] + +[[package]] +name = "quasiquote-proc-macro" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79bc0a2b2a185610156579070227676cf31d6282045d01273bbfc65804df6022" +dependencies = [ + "itertools", + "proc-macro2", + "quote", +] + [[package]] name = "quote" version = "1.0.36" @@ -634,6 +952,39 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "regalloc2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" +dependencies = [ + "hashbrown 0.13.2", + "log", + "rustc-hash", + "slice-group-by", + "smallvec", +] + [[package]] name = "regex" version = "1.10.4" @@ -643,7 +994,7 @@ dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax", + "regex-syntax 0.8.3", ] [[package]] @@ -654,9 +1005,15 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.3", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.8.3" @@ -679,6 +1036,12 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.4.0" @@ -688,6 +1051,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -705,18 +1081,76 @@ dependencies = [ "twox-hash", ] +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + [[package]] name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +[[package]] +name = "serde" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "serde_json" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "slice-group-by" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" + [[package]] name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "spdx" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47317bbaf63785b53861e1ae2d11b80d6b624211d42cb20efcd210ee6f8a14bc" +dependencies = [ + "smallvec", +] + +[[package]] +name = "sptr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -765,7 +1199,7 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro-error", "proc-macro2", "quote", @@ -800,6 +1234,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "target-lexicon" +version = "0.12.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" + [[package]] name = "textwrap" version = "0.11.0" @@ -809,6 +1249,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "tramp" version = "0.3.0" @@ -855,6 +1315,12 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "utf8parse" version = "0.2.1" @@ -874,14 +1340,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] -name = "wars" +name = "waffle-func-reloop" version = "0.1.0" dependencies = [ + "portal-pc-waffle", + "relooper", +] + +[[package]] +name = "wars" +version = "0.1.0" +dependencies = [ + "bitflags 2.5.0", "portal-pc-waffle", "proc-macro2", + "quasiquote", "quote", "relooper", "syn 2.0.66", + "waffle-func-reloop", + "witx", +] + +[[package]] +name = "wars-component" +version = "0.1.0" +dependencies = [ + "golem-wasm-ast", + "proc-macro2", + "quasiquote", + "quote", + "syn 2.0.66", + "wars", ] [[package]] @@ -907,12 +1397,32 @@ dependencies = [ "paste", "tramp", "tuple_list", + "wars-macro", + "wasm_runtime_layer", ] [[package]] name = "wars-test" version = "0.1.0" +[[package]] +name = "wasm-encoder" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad2b51884de9c7f4fe2fd1043fccb8dcad4b1e29558146ee57a144d15779f3f" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-encoder" +version = "0.41.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "972f97a5d8318f908dded23594188a90bcd09365986b1163e66d70170e5287ae" +dependencies = [ + "leb128", +] + [[package]] name = "wasm-encoder" version = "0.202.0" @@ -931,6 +1441,68 @@ dependencies = [ "leb128", ] +[[package]] +name = "wasm-metadata" +version = "0.10.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18ebaa7bd0f9e7a5e5dd29b9a998acf21c4abed74265524dd7e85934597bfb10" +dependencies = [ + "anyhow", + "indexmap 2.2.6", + "serde", + "serde_derive", + "serde_json", + "spdx", + "wasm-encoder 0.41.2", + "wasmparser 0.121.2", +] + +[[package]] +name = "wasm-wave" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "132211e87e40f5470a159f6f44aa87c37f0e24321c42cb1d957d18de1ff576cd" +dependencies = [ + "indexmap 2.2.6", + "logos", + "thiserror", + "wasmtime", + "wit-parser", +] + +[[package]] +name = "wasm_runtime_layer" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb3c4a317e94b170cd61e5943b3f80bcc5c4052398a271e6e2118a3e63a34433" +dependencies = [ + "anyhow", + "fxhash", + "ref-cast", + "smallvec", +] + +[[package]] +name = "wasmparser" +version = "0.118.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77f1154f1ab868e2a01d9834a805faca7bf8b50d041b4ca714d005d0dab1c50c" +dependencies = [ + "indexmap 2.2.6", + "semver", +] + +[[package]] +name = "wasmparser" +version = "0.121.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" +dependencies = [ + "bitflags 2.5.0", + "indexmap 2.2.6", + "semver", +] + [[package]] name = "wasmparser" version = "0.202.0" @@ -942,6 +1514,271 @@ dependencies = [ "semver", ] +[[package]] +name = "wasmprinter" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60e73986a6b7fdfedb7c5bf9e7eb71135486507c8fbc4c0c42cffcb6532988b7" +dependencies = [ + "anyhow", + "wasmparser 0.121.2", +] + +[[package]] +name = "wasmtime" +version = "17.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2788dbd0a2f9786cfae5590d2ca6103c82e0fd6ce0b192107e472bcf367ec180" +dependencies = [ + "anyhow", + "bincode", + "bumpalo", + "cfg-if", + "encoding_rs", + "indexmap 2.2.6", + "libc", + "log", + "object", + "once_cell", + "paste", + "serde", + "serde_derive", + "serde_json", + "target-lexicon", + "wasmparser 0.118.2", + "wasmtime-component-macro", + "wasmtime-component-util", + "wasmtime-cranelift", + "wasmtime-environ", + "wasmtime-jit", + "wasmtime-runtime", + "wasmtime-winch", + "windows-sys", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "17.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced200bb566dd3e3b044bafc837f978233a6f220f627e29605b4b35c222817fd" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "wasmtime-component-macro" +version = "17.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7f911378d94bfed1360d971f084aa73840d0ea26fc892ed4be0b7da278dc15" +dependencies = [ + "anyhow", + "proc-macro2", + "quote", + "syn 2.0.66", + "wasmtime-component-util", + "wasmtime-wit-bindgen", + "wit-parser", +] + +[[package]] +name = "wasmtime-component-util" +version = "17.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ad8115f66c9f061c79e5d45a26288229749e013630aa32596750ef0f9e9807" + +[[package]] +name = "wasmtime-cranelift" +version = "17.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac4bed315d4299d46db5217509f7a7d6e0313c8c8d06cf76cb4cf0a8ce0fa3ee" +dependencies = [ + "anyhow", + "cfg-if", + "cranelift-codegen", + "cranelift-control", + "cranelift-entity", + "cranelift-frontend", + "cranelift-native", + "cranelift-wasm", + "gimli", + "log", + "object", + "target-lexicon", + "thiserror", + "wasmparser 0.118.2", + "wasmtime-cranelift-shared", + "wasmtime-environ", + "wasmtime-versioned-export-macros", +] + +[[package]] +name = "wasmtime-cranelift-shared" +version = "17.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "473a4abcf1df827f85e150b970c95e2c6c52f5b2fbb967b730eb1d52aac24dfb" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-control", + "cranelift-native", + "gimli", + "object", + "target-lexicon", + "wasmtime-environ", +] + +[[package]] +name = "wasmtime-environ" +version = "17.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eacc3e408248e0eb4da5daa60a0948f91432124b494b887557fcafd04fe1f5c" +dependencies = [ + "anyhow", + "cranelift-entity", + "gimli", + "indexmap 2.2.6", + "log", + "object", + "serde", + "serde_derive", + "target-lexicon", + "thiserror", + "wasm-encoder 0.38.1", + "wasmparser 0.118.2", + "wasmprinter", + "wasmtime-component-util", + "wasmtime-types", +] + +[[package]] +name = "wasmtime-jit" +version = "17.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167290150d5ed13918ca400bc7e0b9ebb915a1066fb61dd7c1d079e0b22b28c0" +dependencies = [ + "anyhow", + "bincode", + "cfg-if", + "gimli", + "log", + "object", + "rustix", + "serde", + "serde_derive", + "target-lexicon", + "wasmtime-environ", + "wasmtime-jit-icache-coherence", + "wasmtime-runtime", + "windows-sys", +] + +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "17.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58b8bf27c96c254626746b8f1893819e19d0cd4182041377c783ae62e624d821" +dependencies = [ + "cfg-if", + "libc", + "windows-sys", +] + +[[package]] +name = "wasmtime-runtime" +version = "17.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6248d4e41dad5da93c3e7b88878ca98cae3a07397fe19adc23a9a506db007ed" +dependencies = [ + "anyhow", + "cc", + "cfg-if", + "encoding_rs", + "indexmap 2.2.6", + "libc", + "log", + "mach", + "memfd", + "memoffset", + "paste", + "psm", + "rustix", + "sptr", + "wasm-encoder 0.38.1", + "wasmtime-asm-macros", + "wasmtime-environ", + "wasmtime-versioned-export-macros", + "wasmtime-wmemcheck", + "windows-sys", +] + +[[package]] +name = "wasmtime-types" +version = "17.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c47002670e3d0dbfab240a672b8f6890493a9f9a3cd19fa5006fd5e5ede3b0f6" +dependencies = [ + "cranelift-entity", + "serde", + "serde_derive", + "thiserror", + "wasmparser 0.118.2", +] + +[[package]] +name = "wasmtime-versioned-export-macros" +version = "17.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e04682ce587aa8fa9311d3c95148381f08a1db274ad6bcd3553f7c97c8c2debb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "wasmtime-winch" +version = "17.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d752d7e08654b106f299e1900fe9ef9fa400138d1e1c7adf848b8fb4f31c5466" +dependencies = [ + "anyhow", + "cranelift-codegen", + "gimli", + "object", + "target-lexicon", + "wasmparser 0.118.2", + "wasmtime-cranelift-shared", + "wasmtime-environ", + "winch-codegen", +] + +[[package]] +name = "wasmtime-wit-bindgen" +version = "17.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af5fbb1adaadad70271fe18a3f938741edb2b5178bf2fc164ab20544018626b8" +dependencies = [ + "anyhow", + "heck 0.4.1", + "indexmap 2.2.6", + "wit-parser", +] + +[[package]] +name = "wasmtime-wmemcheck" +version = "17.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8425f923a58d18de2912d569c59bfa94bbd789074a459d018c62531d5111037c" + +[[package]] +name = "wast" +version = "35.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ef140f1b49946586078353a453a1d28ba90adfc54dde75710bc1931de204d68" +dependencies = [ + "leb128", +] + [[package]] name = "wast" version = "209.0.1" @@ -961,7 +1798,7 @@ version = "1.209.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42203ec0271d113f8eb1f77ebc624886530cecb35915a7f63a497131f16e4d24" dependencies = [ - "wast", + "wast 209.0.1", ] [[package]] @@ -986,6 +1823,22 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "winch-codegen" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1744366f80ea8121569f5e9c403beaebabcbfc089a6a3634c048019f8ef425f0" +dependencies = [ + "anyhow", + "cranelift-codegen", + "gimli", + "regalloc2", + "smallvec", + "target-lexicon", + "wasmparser 0.118.2", + "wasmtime-environ", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -1058,3 +1911,51 @@ name = "windows_x86_64_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "wit-parser" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "316b36a9f0005f5aa4b03c39bc3728d045df136f8c13a73b7db4510dec725e08" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.2.6", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", +] + +[[package]] +name = "witx" +version = "0.9.1" +source = "git+https://github.com/wasix-org/wasix-witx.git?branch=main#ad9d3c9a2fa6ef13cde11466b7e3f93ba1293c49" +dependencies = [ + "anyhow", + "log", + "thiserror", + "wast 35.0.2", +] + +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] diff --git a/Cargo.toml b/Cargo.toml index 67a4751..8440bb2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members=[ "wars", "wars-macro","wars-rt", "wars-test"] +members=[ "waffle-func-reloop", "wars", "wars-component", "wars-macro","wars-rt", "wars-test"] resolver="2" [workspace.dependencies] diff --git a/waffle-func-reloop/Cargo.toml b/waffle-func-reloop/Cargo.toml new file mode 100644 index 0000000..c265b0e --- /dev/null +++ b/waffle-func-reloop/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "waffle-func-reloop" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +portal-pc-waffle.workspace = true +relooper = "0.1.0" diff --git a/waffle-func-reloop/src/lib.rs b/waffle-func-reloop/src/lib.rs new file mode 100644 index 0000000..b4c652d --- /dev/null +++ b/waffle-func-reloop/src/lib.rs @@ -0,0 +1,40 @@ +use relooper::ShapedBlock; +use waffle::{cfg::CFGInfo, Block, FunctionBody}; + +pub fn go(b: &FunctionBody) -> Box> { + let cfg = CFGInfo::new(b); + let reloop = std::panic::catch_unwind(|| { + relooper::reloop( + b.blocks + .entries() + .filter(|k| cfg.dominates(b.entry, k.0)) + .map(|(k, l)| { + ( + k, + l.succs + .iter() + .cloned() + .chain(b.blocks.iter().filter(|x| cfg.dominates(*x, k))) + .collect(), + ) + }) + // .chain(once((Block::invalid(), vec![b.entry]))) + .collect(), + // Block::invalid(), + b.entry, + ) + }); + let reloop = match reloop { + Ok(a) => a, + Err(e) => { + panic!( + "reloop failure ({}) in {}", + e.downcast_ref::<&str>() + .map(|a| *a) + .unwrap_or("unknown panic"), + b.display("", None) + ); + } + }; + reloop +} diff --git a/wars-component/Cargo.toml b/wars-component/Cargo.toml new file mode 100644 index 0000000..20465aa --- /dev/null +++ b/wars-component/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "wars-component" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +golem-wasm-ast = "0.2.2" +proc-macro2 = "1.0.85" +quasiquote = "0.1.1" +quote = "1.0.36" +syn = "2.0.66" +wars = { version = "0.1.0", path = "../wars" } diff --git a/wars-component/src/lib.rs b/wars-component/src/lib.rs new file mode 100644 index 0000000..39f4634 --- /dev/null +++ b/wars-component/src/lib.rs @@ -0,0 +1,6 @@ +pub trait Component{ + +} +impl Component for Opts{ + +} \ No newline at end of file diff --git a/wars-macro/Cargo.toml b/wars-macro/Cargo.toml index 79c3e43..93686e9 100644 --- a/wars-macro/Cargo.toml +++ b/wars-macro/Cargo.toml @@ -11,9 +11,9 @@ proc-macro2 = "1.0.85" quote = "1.0.36" syn = "2.0.66" wars = { version = "0.1.0", path = "../wars" } -wars-rt = { version = "0.1.0", path = "../wars-rt" } wat = "1.209.1" - +[dev-dependencies] +wars-rt = { version = "0.1.0", path = "../wars-rt" } [lib] proc-macro = true diff --git a/wars-macro/src/lib.rs b/wars-macro/src/lib.rs index eb60eb8..ba1b671 100644 --- a/wars-macro/src/lib.rs +++ b/wars-macro/src/lib.rs @@ -1,17 +1,19 @@ -use std::sync::Arc; +use std::{collections::BTreeMap, sync::Arc}; use expander::{Edition, Expander}; use proc_macro::TokenStream; use proc_macro2::Span; use quote::quote; -use syn::{parse::Parse, parse_macro_input, Ident, Path, Token}; -use wars::Opts; +use syn::{parse::Parse, parse_macro_input, Ident, LitBool, Path, Token}; +use wars::{Flags, Opts}; struct O { pub crate_path: syn::Path, pub module: Vec, pub name: Ident, - // pub cfg: Arc, + pub flags: Flags, + pub embed: proc_macro2::TokenStream, + pub data: BTreeMap, // pub cfg: Arc, } // struct NoopCfg {} // impl ImportCfg for NoopCfg { @@ -27,6 +29,9 @@ impl Parse for O { crate_path: syn::parse(quote! {::wars_rt}.into())?, module: vec![], name: Ident::new("Wars", Span::call_site()), + flags: Default::default(), + embed: Default::default(), + data: BTreeMap::new(), // cfg: Arc::new(NoopCfg {}), }; while input.lookahead1().peek(Ident) { @@ -59,6 +64,22 @@ impl Parse for O { "name" => { o.name = input.parse()?; } + "r#async" => { + let b: LitBool = input.parse()?; + if b.value { + o.flags |= Flags::ASYNC + } else { + o.flags &= Flags::ASYNC.complement(); + } + } + "legacy_host" => { + let b: LitBool = input.parse()?; + if b.value { + o.flags |= Flags::LEGACY + } else { + o.flags &= Flags::LEGACY.complement(); + } + } _ => return Err(syn::Error::new(i.span(), "unexpected type")), }; let _comma: Token![,] = input.parse()?; @@ -73,12 +94,18 @@ impl Parse for O { #[proc_macro] pub fn wars(a: TokenStream) -> TokenStream { let o = parse_macro_input!(a as O); - let x = wars::go(&Opts { - crate_path: o.crate_path, - module: o.module, - name: o.name, - // cfg: o.cfg, - }); + let x = wars::go( + &Opts { + crate_path: o.crate_path, + module: o.module, + name: o.name, + flags: o.flags, + embed: o.embed, + data: o.data, + // cfg: o.cfg, + } + .to_mod(), + ); let expanded = Expander::new("wars") .add_comment("This is generated code!".to_owned()) .fmt(Edition::_2021) @@ -92,3 +119,20 @@ pub fn wars(a: TokenStream) -> TokenStream { }); expanded.into() } + +// #[proc_macro] +// pub fn wasix(a: TokenStream) -> TokenStream { +// let x = wars::wasix::wasix(); +// let expanded = Expander::new("wars_wasix") +// .add_comment("This is generated code!".to_owned()) +// .fmt(Edition::_2021) +// .verbose(true) +// // common way of gating this, by making it part of the default feature set +// .dry(cfg!(feature = "no-file-expansion")) +// .write_to_out_dir(x.clone()) +// .unwrap_or_else(|e| { +// eprintln!("Failed to write to file: {:?}", e); +// x +// }); +// expanded.into() +// } diff --git a/wars-macro/tests/b.rs b/wars-macro/tests/b.rs index c188241..a25ffe7 100644 --- a/wars-macro/tests/b.rs +++ b/wars-macro/tests/b.rs @@ -1,7 +1,9 @@ wars_macro::wars!( file = "target/wasm32-unknown-unknown/debug/wars_test.wasm", + r#async = true, ); fn x(){ } + diff --git a/wars-rt/Cargo.toml b/wars-rt/Cargo.toml index f41c4de..247ea37 100644 --- a/wars-rt/Cargo.toml +++ b/wars-rt/Cargo.toml @@ -12,3 +12,5 @@ derive_more = "0.99.17" paste = "1.0.15" tramp = "0.3.0" tuple_list = "0.1.3" +wars-macro = { version = "0.1.0", path = "../wars-macro" } +wasm_runtime_layer = "0.4.0" diff --git a/wars-rt/src/func.rs b/wars-rt/src/func.rs index 01fa693..b2e5b11 100644 --- a/wars-rt/src/func.rs +++ b/wars-rt/src/func.rs @@ -2,6 +2,10 @@ use std::sync::Arc; use anyhow::Context; use tramp::{tramp, BorrowRec, Thunk}; +pub mod unsync; +pub fn ret<'a,T>(a: T) -> BorrowRec<'a,T>{ + BorrowRec::Ret(a) +} pub trait CtxSpec: Sized { type ExternRef: Clone; } @@ -16,7 +20,7 @@ pub enum Value { &'a mut C, Vec>, ) -> tramp::BorrowRec<'a, anyhow::Result>>> - + 'static, + + Send + Sync + 'static, >, ), Null, @@ -140,13 +144,13 @@ pub fn map_rec<'a, T: 'a, U>( } } pub type Df = - Arc Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result> + 'static>; + Arc Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result> + Send + Sync + 'static>; pub fn da< A, B, C, - F: for<'a> Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result> + 'static, + F: for<'a> Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result> + Send + Sync + 'static, >( f: F, ) -> Df { diff --git a/wars-rt/src/func/unsync.rs b/wars-rt/src/func/unsync.rs new file mode 100644 index 0000000..a038dc6 --- /dev/null +++ b/wars-rt/src/func/unsync.rs @@ -0,0 +1,207 @@ +use std::{future::Future, pin::Pin, sync::Arc}; + +use anyhow::Context; +// use tramp::{tramp, BorrowRec, Thunk}; +pub fn ret<'a,T>(a: T) -> AsyncRec<'a,T>{ + AsyncRec::Ret(a) +} +pub enum AsyncRec<'a,T>{ + Ret(T), + Async(Pin> + Send + Sync + 'a>>) +} +impl<'a,T> AsyncRec<'a,T>{ + pub async fn go(mut self) -> T{ + loop{ + self = match self{ + AsyncRec::Ret(r) => return r, + AsyncRec::Async(a) => a.await, + } + } + } +} +pub trait CtxSpec: Sized { + type ExternRef: Clone; +} +pub enum Value { + I32(u32), + I64(u64), + F32(f32), + F64(f64), + FunRef( + Arc< + dyn for<'a> Fn( + &'a mut C, + Vec>, + ) -> AsyncRec<'a, anyhow::Result>>> + + Send + Sync + 'static, + >, + ), + Null, + ExRef(C::ExternRef), +} +pub fn call_ref<'a, A: CoeVec + 'static, B: CoeVec + 'static, C: CtxSpec + 'static>( + ctx: &'a mut C, + go: Df, + a: A, +) -> AsyncRec<'a, anyhow::Result> { + // let go: Df = cast(go); + go(ctx, a) +} + +impl Clone for Value { + fn clone(&self) -> Self { + match self { + Self::I32(arg0) => Self::I32(arg0.clone()), + Self::I64(arg0) => Self::I64(arg0.clone()), + Self::F32(arg0) => Self::F32(arg0.clone()), + Self::F64(arg0) => Self::F64(arg0.clone()), + Self::FunRef(arg0) => Self::FunRef(arg0.clone()), + Self::Null => Self::Null, + Self::ExRef(e) => Self::ExRef(e.clone()), + } + } +} +pub trait Coe: Sized { + fn coe(self) -> Value; + fn uncoe(x: Value) -> anyhow::Result; +} +pub fn cast + 'static, B: Coe + 'static, C: CtxSpec>(a: A) -> B { + let a = match castaway::cast!(a, B) { + Ok(b) => return b, + Err(a) => a, + }; + B::uncoe(A::coe(a)).unwrap() +} +impl Coe for Value { + fn coe(self) -> Value { + self + } + + fn uncoe(x: Value) -> anyhow::Result { + Ok(x) + } +} +impl> Coe for Option { + fn coe(self) -> Value { + match self { + None => Value::Null, + Some(d) => d.coe(), + } + } + + fn uncoe(x: Value) -> anyhow::Result { + if let Value::Null = x { + return Ok(None); + } + return Ok(Some(D::uncoe(x)?)); + } +} +macro_rules! coe_impl_prim { + ($a:tt in $b:ident) => { + impl Coe for $a { + fn coe(self) -> Value { + Value::$b(self) + } + fn uncoe(x: Value) -> anyhow::Result { + match x { + Value::$b(a) => Ok(a), + _ => anyhow::bail!("invalid type"), + } + } + } + }; +} +coe_impl_prim!(u32 in I32); +coe_impl_prim!(u64 in I64); +coe_impl_prim!(f32 in F32); +coe_impl_prim!(f64 in F64); +pub trait CoeVec: Sized { + fn coe(self) -> Vec>; + fn uncoe(a: Vec>) -> anyhow::Result; +} +impl CoeVec for () { + fn coe(self) -> Vec> { + vec![] + } + + fn uncoe(a: Vec>) -> anyhow::Result { + Ok(()) + } +} +impl, B: CoeVec> CoeVec for (A, B) { + fn coe(self) -> Vec> { + let mut a = self.1.coe(); + a.push(self.0.coe()); + return a; + } + + fn uncoe(mut a: Vec>) -> anyhow::Result { + let Some(x) = a.pop() else { + anyhow::bail!("list too small") + }; + let y = A::uncoe(x).context("invalid item (note coe lists are REVERSED)")?; + let z = B::uncoe(a)?; + Ok((y, z)) + } +} +pub fn map_rec<'a, T: 'a, U>( + r: AsyncRec<'a, T>, + go: impl FnOnce(T) -> U + Send + Sync + 'a, +) -> AsyncRec<'a, U> { + match r { + AsyncRec::Ret(x) => AsyncRec::Ret(go(x)), + AsyncRec::Async(a) => AsyncRec::Async(Box::pin(async move{ + let v = a.await; + map_rec(v, go) + })), + } +} +pub type Df = + Arc Fn(&'a mut C, A) -> AsyncRec<'a, anyhow::Result> + Send + Sync + 'static>; + +pub fn da< + A, + B, + C, + F: for<'a> Fn(&'a mut C, A) -> AsyncRec<'a, anyhow::Result> + Send + Sync + 'static, +>( + f: F, +) -> Df { + Arc::new(f) +} + +impl + 'static, B: CoeVec + 'static> Coe for Df { + fn coe(self) -> Value { + pub fn x< + C: CtxSpec, + T: for<'a> Fn( + &'a mut C, + Vec>, + ) -> AsyncRec<'a, anyhow::Result>>> + + 'static, + >( + a: T, + ) -> T { + return a; + } + Value::FunRef(Arc::new(x(move |ctx, x| { + let x = match A::uncoe(x) { + Ok(x) => x, + Err(e) => return AsyncRec::Ret(Err(e)), + }; + let x = self(ctx, x); + map_rec(x, |a| a.map(|b| b.coe())) + }))) + } + + fn uncoe(x: Value) -> anyhow::Result { + let Value::FunRef(x) = x else { + anyhow::bail!("invalid value") + }; + Ok(Arc::new(move |ctx, a| { + let v = a.coe(); + let v = x(ctx, v); + map_rec(v, |a| a.and_then(B::uncoe)) + })) + } +} diff --git a/wars-rt/src/lib.rs b/wars-rt/src/lib.rs index d3ef81b..0baf2d6 100644 --- a/wars-rt/src/lib.rs +++ b/wars-rt/src/lib.rs @@ -1,7 +1,85 @@ pub mod func; +pub mod wrl; +pub mod wasix; +use std::sync::{Arc, Mutex}; + +// use as_ref::AsSlice; use func::CtxSpec; pub use func::Value; +pub trait Memory { + fn read<'a>(&'a self, a: usize, s: usize) -> anyhow::Result + 'a>>; + fn write(&mut self, a: usize, x: &[u8]) -> anyhow::Result<()>; + fn size(&self) -> anyhow::Result; + fn grow(&mut self, x: usize) -> anyhow::Result<()>; +} +impl Memory for Vec { + fn read<'a>(&'a self, a: usize, s: usize) -> anyhow::Result + 'a>>{ + Ok(Box::new(&self[a..][..s])) + } + fn write(&mut self, a: usize, x: &[u8]) -> anyhow::Result<()> { + self[a..][..x.len()].copy_from_slice(x); + Ok(()) + } + + fn size(&self) -> anyhow::Result { + Ok(self.len()) + } + + fn grow(&mut self, x: usize) -> anyhow::Result<()> { + self.extend((0..x).map(|a| 0u8)); + Ok(()) + } +} +impl Memory for Arc>{ + fn read<'a>(&'a self, a: usize, s: usize) -> anyhow::Result + 'a>> { + let l = self.lock().unwrap(); + let r = l.read(a, s)?; + return Ok(Box::new(r.as_ref().as_ref().to_vec())); + } + + fn write(&mut self, a: usize, x: &[u8]) -> anyhow::Result<()> { + let mut l = self.lock().unwrap(); + return l.write(a, x); + } + + fn size(&self) -> anyhow::Result { + let l = self.lock().unwrap(); + return l.size(); + } + + fn grow(&mut self, x: usize) -> anyhow::Result<()> { + let mut l = self.lock().unwrap(); + return l.grow(x) + } +} +pub unsafe fn host_memory() -> impl Memory{ + struct W{} + impl Memory for W{ + fn read<'a>(&'a self, a: usize, s: usize) -> anyhow::Result + 'a>> { + return Ok(Box::new(unsafe{ + std::slice::from_raw_parts(a as *const u8, s) + })) + } + + fn write(&mut self, a: usize, x: &[u8]) -> anyhow::Result<()> { + let n = unsafe{ + std::slice::from_raw_parts_mut(a as *mut u8, x.len()) + }; + n.copy_from_slice(x); + return Ok(()); + } + + fn size(&self) -> anyhow::Result { + anyhow::bail!("host memory cannot use size") + } + + fn grow(&mut self, x: usize) -> anyhow::Result<()> { + anyhow::bail!("host memory cannot use grow") + } + } + return W{}; +} pub mod _rexport { pub use anyhow; pub use tramp; @@ -135,59 +213,61 @@ macro_rules! int_ty{ Ok(tuple_list::tuple_list!(a.wrapping_sub(b))) } //LOADS and STORES - pub fn [<$p load>]>(a: &mut Vec, b: T) -> anyhow::Result where T::Error: std::error::Error + Send + Sync + 'static{ - let r = &a[b.try_into()?..][..std::mem::size_of::<$int>()]; - Ok(tuple_list::tuple_list!($int::from_ne_bytes(r.try_into()?))) + pub fn [<$p load>],M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result where T::Error: std::error::Error + Send + Sync + 'static{ + let r = a.read(b.try_into()?,std::mem::size_of::<$int>())?; + Ok(tuple_list::tuple_list!($int::from_ne_bytes(r.as_ref().as_ref().try_into()?))) } - pub fn [<$p store>]>(a: &mut Vec, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{ - let mut r = &mut a[b.try_into()?..][..std::mem::size_of::<$int>()]; - r.copy_from_slice(&c.to_ne_bytes()); + pub fn [<$p store>],M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{ + // let mut r = &mut a[b.try_into()?..][..std::mem::size_of::<$int>()]; + // r.copy_from_slice(&c.to_ne_bytes()); + a.write(b.try_into()?,&c.to_ne_bytes())?; Ok(()) } //8 BIT - pub fn [<$p load8u>]>(a: &mut Vec, b: T) -> anyhow::Result where T::Error: std::error::Error + Send + Sync + 'static{ - let r = a[b.try_into()?..][0]; + pub fn [<$p load8u>],M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result where T::Error: std::error::Error + Send + Sync + 'static{ + let r = a.read(b.try_into()?,1)?.as_ref().as_ref()[0]; Ok(tuple_list::tuple_list!(r as $int)) } - pub fn [<$p load8s>]>(a: &mut Vec, b: T) -> anyhow::Result where T::Error: std::error::Error + Send + Sync + 'static{ - let r = a[b.try_into()?..][0]; + pub fn [<$p load8s>],M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result where T::Error: std::error::Error + Send + Sync + 'static{ + let r = a.read(b.try_into()?,1)?.as_ref().as_ref()[0]; Ok(tuple_list::tuple_list!(r as i8 as $p as $int)) } - pub fn [<$p store8>]>(a: &mut Vec, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{ - let mut r = &mut a[b.try_into()?..][..1]; - r[0] = (c & 0xff) as u8; + pub fn [<$p store8>],M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{ + // let mut r = &mut a[b.try_into()?..][..1]; + // r[0] = (c & 0xff) as u8; + a.write(b.try_into()?,&[(c & 0xff) as u8])?; Ok(()) } //16 BIT - pub fn [<$p load16u>]>(a: &mut Vec, b: T) -> anyhow::Result where T::Error: std::error::Error + Send + Sync + 'static{ - let r = &a[b.try_into()?..][..2]; - let r = u16::from_ne_bytes(r.try_into()?); + pub fn [<$p load16u>],M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result where T::Error: std::error::Error + Send + Sync + 'static{ + let r = a.read(b.try_into()?,2)?; + let r = u16::from_ne_bytes(r.as_ref().as_ref().try_into()?); Ok(tuple_list::tuple_list!(r as $int)) } - pub fn [<$p load16s>]>(a: &mut Vec, b: T) -> anyhow::Result where T::Error: std::error::Error + Send + Sync + 'static{ - let r = &a[b.try_into()?..][..2]; - let r = u16::from_ne_bytes(r.try_into()?); + pub fn [<$p load16s>],M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result where T::Error: std::error::Error + Send + Sync + 'static{ + let r = a.read(b.try_into()?,2)?; + let r = u16::from_ne_bytes(r.as_ref().as_ref().try_into()?); Ok(tuple_list::tuple_list!(r as i16 as $p as $int)) } - pub fn [<$p store16>]>(a: &mut Vec, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{ - let mut r = &mut a[b.try_into()?..][..2]; - r.copy_from_slice(&((c & 0xff) as u16).to_ne_bytes()); + pub fn [<$p store16>],M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{ + // let mut r = &mut a[b.try_into()?..][..2]; + a.write(b.try_into()?,&((c & 0xffff) as u16).to_ne_bytes())?; Ok(()) } //32 BIT - pub fn [<$p load32u>]>(a: &mut Vec, b: T) -> anyhow::Result where T::Error: std::error::Error + Send + Sync + 'static{ - let r = &a[b.try_into()?..][..4]; - let r = u32::from_ne_bytes(r.try_into()?); + pub fn [<$p load32u>],M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result where T::Error: std::error::Error + Send + Sync + 'static{ + let r = a.read(b.try_into()?,4)?; + let r = u32::from_ne_bytes(r.as_ref().as_ref().try_into()?); Ok(tuple_list::tuple_list!(r as $int)) } - pub fn [<$p load32s>]>(a: &mut Vec, b: T) -> anyhow::Result where T::Error: std::error::Error + Send + Sync + 'static{ - let r = &a[b.try_into()?..][..4]; - let r = u32::from_ne_bytes(r.try_into()?); + pub fn [<$p load32s>],M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result where T::Error: std::error::Error + Send + Sync + 'static{ + let r = a.read(b.try_into()?,4)?; + let r = u32::from_ne_bytes(r.as_ref().as_ref().try_into()?); Ok(tuple_list::tuple_list!(r as i32 as $p as $int)) } - pub fn [<$p store32>]>(a: &mut Vec, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{ - let mut r = &mut a[b.try_into()?..][..4]; - r.copy_from_slice(&((c & 0xffffff) as u32).to_ne_bytes()); + pub fn [<$p store32>],M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{ + // let mut r = &mut a[b.try_into()?..][..4]; + a.write(b.try_into()?,&((c & 0xffffffff) as u32).to_ne_bytes())?; Ok(()) } } @@ -200,4 +280,4 @@ pub fn select(u: u32, t: T, t2: T) -> anyhow::Result anyhow::Result { return Ok(tuple_list::tuple_list!((a & 0xffffffff) as u32)); -} \ No newline at end of file +} diff --git a/wars-rt/src/wasix.rs b/wars-rt/src/wasix.rs new file mode 100644 index 0000000..e69de29 diff --git a/wars-rt/src/wrl.rs b/wars-rt/src/wrl.rs new file mode 100644 index 0000000..443c963 --- /dev/null +++ b/wars-rt/src/wrl.rs @@ -0,0 +1,135 @@ +use std::sync::Arc; + +use wasm_runtime_layer::{AsContextMut, ExternRef, FuncType}; + +use crate::func::CtxSpec; +#[derive(Clone)] +pub enum MetaType { + I32, + I64, + F32, + F64, + ExternRef, + FunRef { + params: Vec, + returns: Vec, + }, +} +impl MetaType { + fn wrl(&self) -> wasm_runtime_layer::ValueType { + match self { + MetaType::I32 => wasm_runtime_layer::ValueType::I32, + MetaType::I64 => wasm_runtime_layer::ValueType::I64, + MetaType::F32 => wasm_runtime_layer::ValueType::F32, + MetaType::F64 => wasm_runtime_layer::ValueType::F64, + MetaType::ExternRef => wasm_runtime_layer::ValueType::ExternRef, + MetaType::FunRef { params, returns } => wasm_runtime_layer::ValueType::FuncRef, + } + } +} +pub fn translate_in + 'static, D: AsMut>( + val: &crate::func::Value, + ctx: &mut C, + wrl_ty: &MetaType, +) -> anyhow::Result +where + C::ExternRef: Send + Sync + 'static, +{ + Ok(match val { + crate::Value::I32(a) => wasm_runtime_layer::Value::I32(*a as i32), + crate::Value::I64(a) => wasm_runtime_layer::Value::I64(*a as i64), + crate::Value::F32(a) => wasm_runtime_layer::Value::F32(*a), + crate::Value::F64(a) => wasm_runtime_layer::Value::F64(*a), + crate::Value::FunRef(f) => { + // let wasm_runtime_layer::ValueType::FuncRef() + let MetaType::FunRef { params, returns } = wrl_ty.clone() else { + unreachable!() + }; + let ty = FuncType::new( + params.iter().map(|a| a.wrl()), + returns.iter().map(|a| a.wrl()), + ); + let f = f.clone(); + wasm_runtime_layer::Value::FuncRef(Some(wasm_runtime_layer::Func::new( + ctx, + ty, + move |mut ctx, args, rets| { + let args2 = args + .iter() + .zip(params.iter()) + .rev() + .map(|(x, y)| translate_out(x, ctx.data_mut().as_mut(), y)) + .collect::>>()?; + let v = tramp::tramp(f(ctx.data_mut().as_mut(), args2))?; + for ((w, v), t) in v.iter().rev().zip(rets.iter_mut()).zip(returns.iter()) { + *v = translate_in(w, ctx.data_mut().as_mut(), t)?; + } + + Ok(()) + }, + ))) + } + crate::Value::Null => match wrl_ty{ + MetaType::ExternRef => wasm_runtime_layer::Value::ExternRef(None), + MetaType::FunRef { params, returns } => wasm_runtime_layer::Value::FuncRef(None), + _ => anyhow::bail!("invalid null") + }, + crate::Value::ExRef(e) => { + wasm_runtime_layer::Value::ExternRef(Some(ExternRef::new(ctx, e.clone()))) + } + }) +} +pub fn translate_out + 'static, D: AsMut>( + val: &wasm_runtime_layer::Value, + ctx: &mut C, + wrl_ty: &MetaType, +) -> anyhow::Result> +where + C::ExternRef: Send + Sync + 'static, +{ + Ok(match val { + wasm_runtime_layer::Value::I32(i) => crate::Value::I32(*i as u32), + wasm_runtime_layer::Value::I64(i) => crate::Value::I64(*i as u64), + wasm_runtime_layer::Value::F32(f) => crate::Value::F32(*f), + wasm_runtime_layer::Value::F64(f) => crate::Value::F64(*f), + wasm_runtime_layer::Value::FuncRef(f) => match f { + None => crate::Value::Null, + Some(a) => { + let a = a.clone(); + let MetaType::FunRef { params, returns } = wrl_ty.clone() else { + unreachable!() + }; + crate::Value::FunRef(Arc::new(move |ctx, args| { + let args_in: anyhow::Result> = args + .iter() + .rev() + .zip(params.iter()) + .map(|(x, y)| translate_in(x, &mut *ctx, y)) + .collect(); + let mut results = + vec![wasm_runtime_layer::Value::I32(0); a.ty(&mut *ctx).results().len()]; + let args_in = match args_in { + Ok(a) => a, + Err(e) => return tramp::BorrowRec::Ret(Err(e)), + }; + tramp::BorrowRec::Ret(match a.call(&mut *ctx, &args_in, &mut results) { + Err(e) => Err(e), + Ok(_) => results + .iter() + .zip(returns.iter()) + .rev() + .map(|(x, y)| translate_out(x, ctx, y)) + .collect(), + }) + })) + } + }, + wasm_runtime_layer::Value::ExternRef(x) => match x + .as_ref() + .and_then(|a| a.downcast::(ctx.as_context()).ok()) + { + None => crate::Value::Null, + Some(x) => crate::Value::ExRef(x.clone()), + }, + }) +} diff --git a/wars/Cargo.toml b/wars/Cargo.toml index b881052..ec17fac 100644 --- a/wars/Cargo.toml +++ b/wars/Cargo.toml @@ -6,9 +6,13 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +bitflags = "2.5.0" portal-pc-waffle.workspace = true proc-macro2 = "1.0.85" +quasiquote = "0.1.1" quote = "1.0.36" relooper = "0.1.0" syn = "2.0.66" +waffle-func-reloop = { version = "0.1.0", path = "../waffle-func-reloop" } +witx = {git="https://github.com/wasix-org/wasix-witx.git",branch="main"} diff --git a/wars/src/lib.rs b/wars/src/lib.rs index fdc514e..7d7ec71 100644 --- a/wars/src/lib.rs +++ b/wars/src/lib.rs @@ -1,14 +1,25 @@ -use std::{convert::Infallible, iter::once, sync::Arc}; +use std::{collections::BTreeMap, convert::Infallible, iter::once, sync::Arc}; use proc_macro2::{Span, TokenStream}; -use quote::{format_ident, quote}; +use quasiquote::quasiquote; +use quote::{format_ident, quote, ToTokens}; use relooper::{reloop, BranchMode, ShapedBlock}; use syn::{Ident, Lifetime}; use waffle::{ - cfg::CFGInfo, entity::EntityRef, Block, BlockTarget, ExportKind, Func, ImportKind, Memory, - Module, Operator, Signature, SignatureData, Type, Value, + cfg::CFGInfo, entity::EntityRef, Block, BlockTarget, Export, ExportKind, Func, ImportKind, Memory, Module, Operator, Signature, SignatureData, Type, Value }; +bitflags::bitflags! { + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + pub struct Flags: u32{ + const HOST_MEMORY = 0x1; + const ASYNC = 0x2; + const LEGACY = 0x4; + // const WASIX = 0x8; + // const UNSANDBOXED = 0x2; + } +} pub mod unswitch; +// pub mod wasix; pub fn mangle_value(a: Value, b: usize) -> Ident { if b == 0 { format_ident!("{a}") @@ -32,20 +43,123 @@ pub fn bindname(a: &str) -> String { // } pub const INTRINSIC: &'static str = "wars_intrinsic/"; impl Opts> { + pub fn fp(&self) -> TokenStream { + let root = self.crate_path.clone(); + if self.flags.contains(Flags::ASYNC) { + quote! { + #root::func::unsync + } + } else { + quote! { + #root::func + } + } + } + pub fn mem(&self, m: Memory) -> TokenStream { + if let Some(i) = self + .module + .imports + .iter() + .find(|x| x.kind == ImportKind::Memory(m)) + { + if i.module == "!!unsafe" && i.name == "host" && self.flags.contains(Flags::HOST_MEMORY) + { + return quote! { + unsafe{ + ::std::slice::from_raw_parts_mut(::std::ptr::null(),usize::MAX) + } + }; + } + } + let m2 = format_ident!("{m}"); + quote! { + ctx.#m2() + } + } pub fn import( &self, module: &str, name: &str, - params: impl Iterator, + mut params: impl Iterator, ) -> TokenStream { let root = self.crate_path.clone(); - let Some(a) = module.strip_prefix(INTRINSIC) else { - let id = format_ident!("{}_{}", bindname(module), bindname(name)); - return quote! { - ctx.#id(#(#params),*) - }; + // if self.flags.contains(Flags::UNSANDBOXED) { + if self.flags.contains(Flags::HOST_MEMORY) { + if module == "wars/memory/host" { + match name { + _ => {} + } + } + } + // if a == "fs" { + // match name { + // "open" => { + // let p0 = params.next().unwrap(); + // let l = params.next().unwrap(); + // return quote! { + // #root::_rexport::tramp::BorrowRec::Ret({ + // let f = #p0; + // let l = #l; + // let f = ::std::str::from_utf8(&ctx.memory()[(f as usize)..][..(l as usize)]); + // let f = match f{ + // Ok(a) => a, + // Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Er(e.into())); + // }; + // let f = ::std::fs::open(f); + // let f = match f{ + // Ok(a) => alloc(&mut ctx.data().files,::std::sync::Arc::new(a)) * 2, + // Err(e) => alloc(&mut ctx.data().io_errors,::std::sync::Arc::new(e)) * 2 + 1; + // }; + // f + // }) + // }; + // } + // "read" => { + // let fd = params.next().unwrap(); + // let p0 = params.next().unwrap(); + // let l = params.next().unwrap(); + // return quote! { + // { + // let f = #p0; + // let l = #l; + // let fd = #fd; + // let fd = ctx.data().files.get(&fd).unwrap().clone(); + // let f = &mut ctx.memory()[(f as usize)..][..(l as usize)]; + // let f = ::std::io::Read::read(&mut fd.as_ref(),f); + // match f{ + // Ok(a) => #root::_rexport::tuple_list::tuple_list!(a as u64 * 2), + // Err(e) => #root::_rexport::tuple_list::tuple_list!(alloc(&mut ctx.data().io_errors,::std::sync::Arc::new(e)) as u64 * 2 + 1); + // } + // } + // }; + // } + // "write" => { + // let fd = params.next().unwrap(); + // let p0 = params.next().unwrap(); + // let l = params.next().unwrap(); + // return quote! { + // { + // let f = #p0; + // let l = #l; + // let fd = #fd; + // let fd = ctx.data().files.get(&fd).unwrap().clone(); + // let f = &ctx.memory()[(f as usize)..][..(l as usize)]; + // let f = ::std::io::Write::write(&mut fd.as_ref(),f); + // match f{ + // Ok(a) => #root::_rexport::tuple_list::tuple_list!(a as u64 * 2), + // Err(e) => #root::_rexport::tuple_list::tuple_list!(alloc(&mut ctx.data().io_errors,::std::sync::Arc::new(e)) as u64 * 2 + 1); + // } + // } + // }; + // } + // _ => {} + // } + // } + // } + let id = format_ident!("{}_{}", bindname(module), bindname(name)); + return quote! { + ctx.#id(#(#params),*) }; - quote! {} } pub fn render_ty(&self, ctx: &TokenStream, ty: Type) -> TokenStream { let root = self.crate_path.clone(); @@ -62,8 +176,14 @@ impl Opts> { let data = &self.module.signatures[sig_index]; let params = data.params.iter().map(|x| self.render_ty(ctx, *x)); let returns = data.returns.iter().map(|x| self.render_ty(ctx, *x)); - let mut x = quote! { - #root::func::Df<#root::_rexport::tuple_list::tuple_list_type!(#(#params),*),#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*),#ctx> + let mut x = if self.flags.contains(Flags::ASYNC) { + quote! { + #root::func::unsync::Df<#root::_rexport::tuple_list::tuple_list_type!(#(#params),*),#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*),#ctx> + } + } else { + quote! { + #root::func::Df<#root::_rexport::tuple_list::tuple_list_type!(#(#params),*),#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*),#ctx> + } }; if nullable { x = quote! { @@ -72,7 +192,7 @@ impl Opts> { } x } - _ => quote! {#root::func::Value<#ctx>}, + _ => quasiquote! {#{self.fp()}::Value<#ctx>}, } } pub fn render_generics(&self, ctx: &TokenStream, data: &SignatureData) -> TokenStream { @@ -100,23 +220,28 @@ impl Opts> { .enumerate() .map(|(a, _)| format_ident!("p{a}")); let returns = data.returns.iter().map(|x| self.render_ty(&ctx, *x)); - - quote! { - fn #name<'a,C: #base + 'static>(ctx: &'a mut C, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>> + if self.flags.contains(Flags::ASYNC) { + quote! { + fn #name<'a,C: #base + 'static>(ctx: &'a mut C, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::func::unsync::AsyncRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>> + } + } else { + quote! { + fn #name<'a,C: #base + 'static>(ctx: &'a mut C, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>> + } } } pub fn render_fun_ref(&self, ctx: &TokenStream, x: Func) -> TokenStream { let root = self.crate_path.clone(); if x.is_invalid() { - return quote! { - #root::func::da::<(),(),C,_>(|ctx,arg|panic!("invalid func")) + return quasiquote! { + #{self.fp()}::da::<(),(),C,_>(|ctx,arg|panic!("invalid func")) }; } let generics = self.render_generics(ctx, &self.module.signatures[self.module.funcs[x].sig()]); let x = format_ident!("{x}"); - quote! { - #root::func::da::<#generics,C,_>(|ctx,arg|#x(ctx,arg)) + quasiquote! { + #{self.fp()}::da::<#generics,C,_>(|ctx,arg|#x(ctx,arg)) } } pub fn render_self_sig( @@ -138,10 +263,17 @@ impl Opts> { .collect::>(); let returns = data.returns.iter().map(|x| self.render_ty(&ctx, *x)); - - quote! { - fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>> where Self: 'static{ - return #wrapped(self,#root::_rexport::tuple_list::tuple_list!(#(#param_ids),*)); + if self.flags.contains(Flags::ASYNC) { + quote! { + fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::func::unsync::AsyncRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>> where Self: 'static{ + return #wrapped(self,#root::_rexport::tuple_list::tuple_list!(#(#param_ids),*)); + } + } + } else { + quote! { + fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>> where Self: 'static{ + return #wrapped(self,#root::_rexport::tuple_list::tuple_list!(#(#param_ids),*)); + } } } } @@ -159,9 +291,14 @@ impl Opts> { .collect::>(); let returns = data.returns.iter().map(|x| self.render_ty(&ctx, *x)); - - quote! { - fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>>; + if self.flags.contains(Flags::ASYNC) { + quote! { + fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::func::unsync::AsyncRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>>; + } + } else { + quote! { + fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>>; + } } } pub fn render_relooped_block(&self, f: Func, x: &ShapedBlock) -> TokenStream { @@ -228,6 +365,7 @@ impl Opts> { #next; }; } + let fp = self.fp(); let stmts = b.blocks[stmts].params.iter().map(|a|&a.1).chain(b.blocks[stmts].insts.iter()).map(|a|{ let av = b.values[*a].tys(&b.type_pool).iter().enumerate().map(|b|mangle_value(*a,b.0)); let b = match &b.values[*a]{ @@ -251,10 +389,21 @@ impl Opts> { Some(_) => { let func = format_ident!("{function_index}"); let vals = vals.iter().map(|a|format_ident!("{a}")); - quote! { - match #root::_rexport::tramp::tramp(#func(ctx,#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))){ - Ok(a) => a, - Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e)) + quasiquote! { + { + let x = #func(ctx,#root::_rexport::tuple_list::tuple_list!(#(#fp::cast::<_,_,C>(#vals .clone())),*)); + match #{if self.flags.contains(Flags::ASYNC){ + quote!{ + x.go().await + } + }else{ + quote!{ + #root::_rexport::tramp::tramp(x) + } + }}{ + Ok(a) => a, + Err(e) => return #{self.fp()}::ret(Err(e)) + } } } }, @@ -270,10 +419,18 @@ impl Opts> { i.name.as_str(), vals.iter().map(|a|format_ident!("{a}")).map(|a| quote! {#a}), ); - quote!{ - match #root::_rexport::tramp::tramp(x){ + quasiquote!{ + match #{if self.flags.contains(Flags::ASYNC){ + quote!{ + #x.go().await + } + }else{ + quote!{ + #root::_rexport::tramp::tramp(#x) + } + }}{ Ok(a) => a, - Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e)) + Err(e) => return #{self.fp()}::ret(Err(e)) } } } @@ -286,12 +443,23 @@ impl Opts> { let vals = vals.iter().map(|a|format_ident!("{a}")); let r = format_ident!("{r}"); let g = self.render_generics("e! {c}, &self.module.signatures[*sig_index]); - quote! { - match #root::_rexport::tramp::tramp(#root::func::call_ref::<#g,C>(ctx,#root::func::cast(#r.clone()),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))){ + quasiquote! { + { + let x = #{self.fp()}::call_ref::<#g,C>(ctx,#{self.fp()}(#r.clone()),#root::_rexport::tuple_list::tuple_list!(#(#fp::cast::<_,_,C>(#vals .clone())),*)); + match #{if self.flags.contains(Flags::ASYNC){ + quote!{ + x.go().await + } + }else{ + quote!{ + #root::_rexport::tramp::tramp(x) + } + }}{ Ok(a) => a, - Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e)) + Err(e) => return #{self.fp()}::ret(Err(e)) } } + } }, Operator::CallIndirect { sig_index, table_index } => { let t = format_ident!("{table_index}"); @@ -304,12 +472,21 @@ impl Opts> { ctx.#t()[#r as usize] }; let g = self.render_generics("e! {c}, &self.module.signatures[*sig_index]); - quote! { + quasiquote! { { let r = #r.clone(); - match #root::_rexport::tramp::tramp(#root::func::call_ref::<#g,C>(ctx,#root::func::cast(r),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))){ + let x = #{self.fp()}::call_ref::<#g,C>(ctx,#{self.fp()}::cast(r),#root::_rexport::tuple_list::tuple_list!(#(#fp::cast::<_,_,C>(#vals .clone())),*)); + match #{if self.flags.contains(Flags::ASYNC){ + quote!{ + x.go().await + } + }else{ + quote!{ + #root::_rexport::tramp::tramp(x) + } + }}{ Ok(a) => a, - Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e)) + Err(e) => return #{self.fp()}::ret(Err(e)) } } } @@ -324,8 +501,11 @@ impl Opts> { quote! {u32} }; let m = Ident::new(&mem.to_string(), Span::call_site()); - quote! { - #root::_rexport::tuple_list::tuple_list!((ctx.#m().len() / 65536) as #rt) + quasiquote! { + #root::_rexport::tuple_list::tuple_list!(((match #root::Memory::size(ctx.#m()){ + Ok(a) => a, + Err(e) => return #{self.fp()}::ret(Err(e)) + }) / 65536) as #rt) } } waffle::Operator::MemoryGrow { mem } => { @@ -337,25 +517,30 @@ impl Opts> { }else{ quote! {u32} }; - quote! { + quasiquote! { { - let vn = ctx.#m().len() / 65536; - let l = ctx.#m().len(); - ctx.#m().resize(l + (#a .clone() as usize) * 65536,0); + let vn = (match #root::Memory::size(ctx.#m()){ + Ok(a) => a, + Err(e) => return #{self.fp()}::ret(Err(e)) + }) / 65536; + match #root::Memory::grow(ctx.#m(),(#a .clone() as usize) * 65536){ + Ok(a) => a, + Err(e) => return #{self.fp()}::ret(Err(e)) + }; #root::_rexport::tuple_list::tuple_list!(vn as #rt) } } }, waffle::Operator::MemoryCopy { dst_mem, src_mem } => { - let dst = format_ident!("{dst_mem}"); - let src = format_ident!("{src_mem}"); + let dst = self.mem(*dst_mem); + let src = self.mem(*src_mem); let dst_ptr = format_ident!("{}",vals[0].to_string()); let src_ptr = format_ident!("{}",vals[1].to_string()); let len = format_ident!("{}",vals[2].to_string()); quote!{ { - let m = ctx.#src()[(#src_ptr as usize)..][..(#len as usize)].to_owned(); - ctx.#dst()[(#dst_ptr as usize)..][..(#len as usize)].copy_from_slice(&m); + let m = #src[(#src_ptr as usize)..][..(#len as usize)].to_owned(); + #dst[(#dst_ptr as usize)..][..(#len as usize)].copy_from_slice(&m); () } } @@ -377,6 +562,55 @@ impl Opts> { } } } + Operator::TableGet { table_index } => { + let table = format_ident!("{table_index}"); + let [i,..] = vals else{ + unreachable!() + }; + let i = format_ident!("{i}"); + // let j = format_ident!("{j}"); + quasiquote!{ + { + (ctx.#table()[#i as usize].clone(),()) + } + } + }, + Operator::TableSet { table_index } => { + let table = format_ident!("{table_index}"); + let [i,j,..] = vals else{ + unreachable!() + }; + let i = format_ident!("{i}"); + let j = format_ident!("{j}"); + quasiquote!{ + { + ctx.#table()[#i as usize] = #{self.fp()}::cast::<_,_,C>(#j.clone()); + () + } + } + }, + Operator::TableSize { table_index } => { + let table = format_ident!("{table_index}"); + quote!{ + (ctx.#table().len() as u32,()) + } + }, + Operator::TableGrow { table_index } => { + let table = format_ident!("{table_index}"); + let [i,j,..] = vals else{ + unreachable!() + }; + let i = format_ident!("{i}"); + let j = format_ident!("{j}"); + quasiquote!{ + { + for _ in 0..#i{ + ctx.#table().push(#{self.fp()}::cast::<_,_,C>(#j.clone())); + } + () + } + } + }, _ if waffle::op_traits::mem_count(o) == 1 => { let mut mem = Memory::invalid(); waffle::op_traits::rewrite_mem(&mut o.clone(), &mut [();4], |m,_|{ @@ -386,7 +620,7 @@ impl Opts> { // let clean = o.to_string(); let clean = format_ident!("{}",o.to_string().split_once("<").unwrap().0); let m2 = mem; - let mem = format_ident!("{mem}"); + let mem = self.mem(m2); let mut vals = vals.iter().map(|a|format_ident!("{a}")); let rt = if self.module.memories[m2].memory64{ quote! {u64} @@ -402,10 +636,10 @@ impl Opts> { }; let val = vals.next().unwrap(); let vals = once(quote! {(#val.clone() + #offset)}).chain(vals.map(|w|quote!{#w})); - quote! { - match #root::#clean::<#rt>(ctx.#mem(),#(#root::func::cast::<_,_,C>(#vals .clone())),*){ + quasiquote! { + match #root::#clean::<#rt,_>(#mem,#(#fp::cast::<_,_,C>(#vals .clone())),*){ Ok(a) => a, - Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e)) + Err(e) => return #{self.fp()}::ret(Err(e)) } } }, @@ -426,10 +660,10 @@ impl Opts> { // let clean = o.to_string(); let clean = format_ident!("{o}"); let vals = vals.iter().map(|a|format_ident!("{a}")); - quote! { - match #root::#clean(#(#root::func::cast::<_,_,C>(#vals .clone())),*){ + quasiquote! { + match #root::#clean(#(#fp::cast::<_,_,C>(#vals .clone())),*){ Ok(a) => a, - Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e)) + Err(e) => return #{self.fp()}::ret(Err(e)) } } } @@ -459,8 +693,8 @@ impl Opts> { let vars = k.args.iter().enumerate().map(|(i, a)| { let a = format_ident!("{a}"); let i = format_ident!("{}param{i}", k.block.to_string()); - quote! { - #i = #a; + quasiquote! { + #i = #{self.fp()}::cast::<_,_,C>(#a); } }); let br = term( @@ -523,8 +757,8 @@ impl Opts> { let values = b.rets.iter().enumerate().map(|(a, _)| match values.get(a) { Some(v) => { let v = format_ident!("{v}"); - quote! { - #v + quasiquote! { + #{self.fp()}::cast::<_,_,C>(#v) } } None => { @@ -533,19 +767,29 @@ impl Opts> { } } }); - quote! { - return #root::_rexport::tramp::BorrowRec::Ret(Ok(#root::_rexport::tuple_list::tuple_list!(#(#values),*))) + quasiquote! { + return #{self.fp()}::ret(Ok(#root::_rexport::tuple_list::tuple_list!(#(#values),*))) } } waffle::Terminator::ReturnCall { func, args } => { match self.module.funcs[*func].body() { Some(_) => { - let values = args.iter().map(|v| format_ident!("{v}")); + let values = args.iter().map(|v| format_ident!("{v}")).map(|a| { + quasiquote! { + #{self.fp()}::cast::<_,_,C>(#a) + } + }); let func = format_ident!("{func}"); - quote! { - return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{ + if self.flags.contains(Flags::ASYNC) { + quote! { #func(ctx,#root::_rexport::tuple_list::tuple_list!(#(#values),*)) - })) + } + } else { + quote! { + return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{ + #func(ctx,#root::_rexport::tuple_list::tuple_list!(#(#values),*)) + })) + } } } None => { @@ -562,8 +806,12 @@ impl Opts> { .map(|a| format_ident!("{a}")) .map(|a| quote! {#a}), ); - quote! { - return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{#x})) + if self.flags.contains(Flags::ASYNC) { + x + } else { + quote! { + return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{#x})) + } } } } @@ -573,30 +821,50 @@ impl Opts> { let mut vals = args.to_owned(); let r = vals.pop().unwrap(); // let func = format_ident!("{function_index}"); - let vals = vals.iter().map(|a| format_ident!("{a}")); + let vals = vals.iter().map(|a| format_ident!("{a}")).map(|a| { + quasiquote! { + #{self.fp()}::cast::<_,_,C>(#a) + } + }); let r = format_ident!("{r}"); let r = quote! { ctx.#t()[#r as usize] }; let g = self.render_generics("e! {c}, &self.module.signatures[*sig]); - quote! { - let r = #r.clone(); - return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{ - #root::func::call_ref::<#g,C>(ctx,#root::func::cast(r),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*)) - })) + if self.flags.contains(Flags::ASYNC) { + quasiquote! { + return #{self.fp()}::call_ref::<#g,C>(ctx,#{self.fp()}::cast(r),#root::_rexport::tuple_list::tuple_list!(#(#{self.fp()}::cast::<_,_,C>(#vals .clone())),*)) + } + } else { + quasiquote! { + let r = #r.clone(); + return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{ + #{self.fp()}::call_ref::<#g,C>(ctx,#{self.fp()}::cast(r),#root::_rexport::tuple_list::tuple_list!(#(#{self.fp()}::cast::<_,_,C>(#vals .clone())),*)) + })) + } } } waffle::Terminator::ReturnCallRef { sig, args } => { let mut vals = args.clone(); let r = vals.pop().unwrap(); // let func = format_ident!("{function_index}"); - let vals = vals.iter().map(|a| format_ident!("{a}")); + let vals = vals.iter().map(|a| format_ident!("{a}")).map(|a| { + quasiquote! { + #{self.fp()}::cast::<_,_,C>(#a) + } + }); let r = format_ident!("{r}"); let g = self.render_generics("e! {c}, &self.module.signatures[*sig]); - quote! { - return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{ - #root::func::call_ref::<#g,C>(ctx,#root::func::cast(#r.clone()),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*)) - })) + if self.flags.contains(Flags::ASYNC) { + quasiquote! { + return #{self.fp()}::call_ref::<#g,C>(ctx,#root::func::cast(#r.clone()),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*)) + } + } else { + quasiquote! { + return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{ + #{self.fp()}::call_ref::<#g,C>(ctx,#root::func::cast(#r.clone()),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*)) + })) + } } } waffle::Terminator::Unreachable => quote! { @@ -753,45 +1021,56 @@ impl Opts> { } }) }); - let reloop = std::panic::catch_unwind(|| { - reloop( - b.blocks - .entries() - .filter(|k| cfg.dominates(b.entry, k.0)) - .map(|(k, l)| { - ( - k, - l.succs - .iter() - .cloned() - .chain(b.blocks.iter().filter(|x| cfg.dominates(*x, k))) - .collect(), - ) - }) - .chain(once((Block::invalid(), vec![b.entry]))) - .collect(), - Block::invalid(), - ) - }); - let reloop = match reloop { - Ok(a) => a, - Err(e) => { - panic!( - "reloop failure ({}) in {}", - e.downcast_ref::<&str>() - .map(|a| *a) - .unwrap_or("unknown panic"), - b.display("", None) - ); - } - }; + let reloop = waffle_func_reloop::go(b); + // let reloop = std::panic::catch_unwind(|| { + // reloop( + // b.blocks + // .entries() + // .filter(|k| cfg.dominates(b.entry, k.0)) + // .map(|(k, l)| { + // ( + // k, + // l.succs + // .iter() + // .cloned() + // .chain(b.blocks.iter().filter(|x| cfg.dominates(*x, k))) + // .collect(), + // ) + // }) + // .chain(once((Block::invalid(), vec![b.entry]))) + // .collect(), + // Block::invalid(), + // ) + // }); + // let reloop = match reloop { + // Ok(a) => a, + // Err(e) => { + // panic!( + // "reloop failure ({}) in {}", + // e.downcast_ref::<&str>() + // .map(|a| *a) + // .unwrap_or("unknown panic"), + // b.display("", None) + // ); + // } + // }; let x = self.render_relooped_block(f, reloop.as_ref()); + let mut b = quote! { + let mut cff: usize = 0; + #(let mut #bpvalues);*; + #x; + panic!("should have returned"); + }; + if self.flags.contains(Flags::ASYNC) { + b = quasiquote! { + return #{self.fp()}::AsyncRec::Async(Box::pin(async move{ + #b + })) + } + } quote! { #sig { - let mut cff: usize = 0; - #(let mut #bpvalues);*; - #x; - panic!("should have returned"); + #b } } } @@ -800,45 +1079,92 @@ pub struct Opts { pub crate_path: syn::Path, pub module: B, pub name: Ident, + pub flags: Flags, + pub embed: TokenStream, + pub data: BTreeMap, // pub cfg: Arc, } -pub fn go(opts: &Opts>) -> proc_macro2::TokenStream { - let mut module = waffle::Module::from_wasm_bytes(&opts.module, &Default::default()).unwrap(); - module.expand_all_funcs().unwrap(); - let mut module = module.without_orig_bytes(); - // module.per_func_body(|b|unswitch::go(b)); //TODO: reloop better and make it not needed - // eprintln!("{}",module.display()); - module.per_func_body(|f| f.convert_to_max_ssa(None)); +impl> Opts { + pub fn to_mod(&self) -> Opts> { + let opts = self; + let mut module = + waffle::Module::from_wasm_bytes(opts.module.as_ref(), &Default::default()).unwrap(); + module.expand_all_funcs().unwrap(); + let mut module = module.without_orig_bytes(); + // module.per_func_body(|b|unswitch::go(b)); //TODO: reloop better and make it not needed + // eprintln!("{}",module.display()); + module.per_func_body(|f| f.convert_to_max_ssa(None)); + let internal_path = format_ident!("_{}_internal", opts.name); + let data = format_ident!("{}Data", opts.name); + let name = opts.name.clone(); + let opts = Opts { + crate_path: opts.crate_path.clone(), + module, + name: name.clone(), + flags: opts.flags, + embed: opts.embed.clone(), + data: opts.data.clone(), + // cfg: opts.cfg.clone(), + }; + return opts; + } +} +impl ToTokens for Opts> { + fn to_tokens(&self, tokens: &mut TokenStream) { + go(self).to_tokens(tokens) + } +} +pub fn go(opts: &Opts>) -> proc_macro2::TokenStream { + // let mut module = waffle::Module::from_wasm_bytes(&opts.module, &Default::default()).unwrap(); + // module.expand_all_funcs().unwrap(); + // let mut module = module.without_orig_bytes(); + // // module.per_func_body(|b|unswitch::go(b)); //TODO: reloop better and make it not needed + // // eprintln!("{}",module.display()); + // module.per_func_body(|f| f.convert_to_max_ssa(None)); let internal_path = format_ident!("_{}_internal", opts.name); let data = format_ident!("{}Data", opts.name); let name = opts.name.clone(); - let opts = Opts { - crate_path: opts.crate_path.clone(), - module, - name: name.clone(), - // cfg: opts.cfg.clone(), - }; + // let opts = Opts { + // crate_path: opts.crate_path.clone(), + // module, + // name: name.clone(), + // flags: opts.flags, + // // cfg: opts.cfg.clone(), + // }; let root = opts.crate_path.clone(); let funcs = opts.module.funcs.iter().map(|a| opts.render_fn(a)); let mut z = vec![]; let mut fields = vec![]; let mut fs = vec![]; + fs.push(opts.embed.clone()); + for (k, v) in opts.data.iter() { + fields.push(k.clone()); + z.push(quote! { + #k : #v + }); + } let mut init = vec![]; for (t, d) in opts.module.tables.entries() { // let dty = opts.render_ty("e! {Target}, d.ty.clone()); let n = Ident::new(&t.to_string(), Span::call_site()); - z.push(quote! { - #n: Vec<#root::func::Value> + z.push(quasiquote! { + #n: Vec<#{opts.fp()}::Value> }); fields.push(n.clone()); if let Some(e) = d.func_elements.as_ref() { let e = e.iter().map(|x| opts.render_fun_ref("e! {C}, *x)); - init.push(quote! { - #(ctx.data().#n.push(#root::func::Coe::coe(#e)));*; + init.push(if opts.flags.contains(Flags::ASYNC) { + quote! { + #(ctx.data().#n.push(#root::func::unsync::Coe::coe(#e)));*; + } + } else { + quote! { + #(ctx.data().#n.push(#root::func::Coe::coe(#e)));*; + } }) } - fs.push(quote! { - fn #n(&mut self) -> &mut Vec<#root::func::Value>{ + fs.push(quasiquote! { + fn #n(&mut self) -> &mut Vec<#{opts.fp()}::Value>{ &mut self.data().#n } }) @@ -893,15 +1219,25 @@ pub fn go(opts: &Opts>) -> proc_macro2::TokenStream { }); } Some((a, b)) => { - // let a = bindname(&a); - // let b = bindname(&b); - let m = Ident::new(&format!("{a}_{b}"), Span::call_site()); - fs.push(quote! { - fn #m<'a>(&'a mut self) -> &'a mut Vec; - fn #n<'a>(&'a mut self) -> &'a mut Vec{ - return self.#m(); - } - }); + if a == "!!unsafe" && b == "host" && opts.flags.contains(Flags::HOST_MEMORY) { + } else { + // let a = bindname(&a); + // let b = bindname(&b); + let m = Ident::new(&format!("{a}_{b}"), Span::call_site()); + let p = if opts.flags.contains(Flags::LEGACY) { + quote! {dyn #root::Memory} + } else { + quote! { + impl #root::Memory + } + }; + fs.push(quote! { + fn #m<'a>(&'a mut self) -> &'a mut #p; + fn #n<'a>(&'a mut self) -> &'a mut #p{ + return self.#m(); + } + }); + } } } let pk = d.initial_pages * 65536; @@ -930,6 +1266,10 @@ pub fn go(opts: &Opts>) -> proc_macro2::TokenStream { } } for xp in opts.module.exports.iter() { + let xp = Export{ + name: bindname(&xp.name), + kind: xp.kind.clone() + }; match &xp.kind { ExportKind::Func(f) => { let f = *f; @@ -969,8 +1309,14 @@ pub fn go(opts: &Opts>) -> proc_macro2::TokenStream { ExportKind::Memory(m) => { let x = Ident::new(&m.to_string(), Span::call_site()); let mn = Ident::new(&xp.name, Span::call_site()); - let i = quote! { - fn #mn(&mut self) -> &mut Vec{ + let i = quasiquote! { + fn #mn(&mut self) -> &mut #{if opts.flags.contains(Flags::LEGACY) { + quote! {dyn #root::Memory} + } else { + quote! { + impl #root::Memory + } + }}{ return self.#x() } }; @@ -990,13 +1336,56 @@ pub fn go(opts: &Opts>) -> proc_macro2::TokenStream { )); } } - quote! { + // if opts.flags.contains(Flags::UNSANDBOXED) { + // for (x, y) in [ + // ( + // format_ident!("files"), + // quote! { + // ::std::collections::BTreeMap> + // }, + // ), + // ( + // format_ident!("io_errors"), + // quote! { + // ::std::collections::BTreeMap> + // }, + // ), + // ] { + // fields.push(x.clone()); + // z.push(quote! { + // #x: #y + // }) + // } + // } + let defaults = fields.iter().map(|a| { + quote! { + #a: Default::default() + } + }); + let clones = fields.iter().map(|a| { + quote! { + #a: self.#a.clone() + } + }); + quasiquote! { mod #internal_path{ #(#funcs)* + pub fn alloc(m: &mut ::std::collections::BTreeMap, x: T) -> u32{ + let mut u = 0; + while m.contains_key(&u){ + u += 1; + }; + m.insert(u,x); + return u; + } pub struct #data{ #(#z),* } - pub trait #name: #root::func::CtxSpec{ + pub trait #name: #{opts.fp()}::CtxSpec #{if opts.flags.contains(Flags::ASYNC){ + quote! {+ Send + Sync} + }else{ + quote! {} + }}{ fn data(&mut self) -> &mut #data; #(#fs)* @@ -1005,6 +1394,20 @@ pub fn go(opts: &Opts>) -> proc_macro2::TokenStream { #(#init);*; return Ok(()) } + impl Default for #data{ + fn default() -> Self{ + Self{ + #(#defaults),* + } + } + } + impl Clone for #data{ + fn clone(&self) -> Self{ + Self{ + #(#clones),* + } + } + } } use #internal_path::{#name,#data}; }