From 7e642e1f85046ca89a66c1fd894556b856339c88 Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Mon, 24 Jun 2024 07:21:05 -0400 Subject: [PATCH] stuff --- .gitignore | 1 + Cargo.lock | 1024 ++++++++++++++++++++++++++++++++++ Cargo.toml | 7 + pit-core/Cargo.toml | 12 + pit-core/src/lib.rs | 157 ++++++ pit-patch/Cargo.toml | 13 + pit-patch/src/canon.rs | 164 ++++++ pit-patch/src/lib.rs | 33 ++ pit-patch/src/lower.rs | 309 ++++++++++ pit-patch/src/util.rs | 129 +++++ pit-rust-guest/Cargo.toml | 15 + pit-rust-guest/src/lib.rs | 142 +++++ pit-rust-host-lib/Cargo.toml | 11 + pit-rust-host-lib/src/lib.rs | 182 ++++++ pit-rust-host/Cargo.toml | 14 + pit-rust-host/src/lib.rs | 291 ++++++++++ 16 files changed, 2504 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 pit-core/Cargo.toml create mode 100644 pit-core/src/lib.rs create mode 100644 pit-patch/Cargo.toml create mode 100644 pit-patch/src/canon.rs create mode 100644 pit-patch/src/lib.rs create mode 100644 pit-patch/src/lower.rs create mode 100644 pit-patch/src/util.rs create mode 100644 pit-rust-guest/Cargo.toml create mode 100644 pit-rust-guest/src/lib.rs create mode 100644 pit-rust-host-lib/Cargo.toml create mode 100644 pit-rust-host-lib/src/lib.rs create mode 100644 pit-rust-host/Cargo.toml create mode 100644 pit-rust-host/src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1de5659 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..5144e45 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1024 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "cpp_demangle", + "fallible-iterator", + "gimli", + "memmap2", + "object", + "rustc-demangle", + "smallvec", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "cpp_demangle" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8227005286ec39567949b33df9896bcadfa6051bccca2488129f108ca23119" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.66", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" + +[[package]] +name = "env_filter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "flate2" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +dependencies = [ + "fallible-iterator", + "stable_deref_trait", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is_terminal_polyfill" +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 = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +dependencies = [ + "adler", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "flate2", + "memchr", + "ruzstd", +] + +[[package]] +name = "pit-core" +version = "0.1.0" +dependencies = [ + "derive_more", + "hex", + "nom", + "sha3", +] + +[[package]] +name = "pit-patch" +version = "0.1.0" +dependencies = [ + "anyhow", + "nom", + "pit-core", + "portal-pc-waffle", + "waffle-ast", +] + +[[package]] +name = "pit-rust-guest" +version = "0.1.0" +dependencies = [ + "hex", + "pit-core", + "proc-macro2", + "quasiquote", + "quote", + "sha3", + "syn 2.0.66", +] + +[[package]] +name = "pit-rust-host" +version = "0.1.0" +dependencies = [ + "hex", + "pit-core", + "proc-macro2", + "quasiquote", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "pit-rust-host-lib" +version = "0.1.0" +dependencies = [ + "anyhow", + "pit-core", + "wasm_runtime_layer", +] + +[[package]] +name = "portal-pc-waffle" +version = "0.0.27+portal" +source = "git+https://github.com/portal-co/waffle-.git?branch=pr/changes2#3f9e7a560f40c29c1de6389f1f6371cde261adb7" +dependencies = [ + "addr2line", + "anyhow", + "env_logger", + "fxhash", + "indexmap", + "lazy_static", + "libc", + "log", + "rayon", + "smallvec", + "stacker", + "structopt", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "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 = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "ruzstd" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d" +dependencies = [ + "byteorder", + "derive_more", + "twox-hash", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stacker" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "winapi", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "structopt" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" +dependencies = [ + "clap", + "lazy_static", + "structopt-derive", +] + +[[package]] +name = "structopt-derive" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "waffle-ast" +version = "0.1.0" +source = "git+https://github.com/portal-co/more_waffle.git?branch=master#6a2532653fae1294517c76e53853540eb1290c55" +dependencies = [ + "anyhow", + "portal-pc-waffle", +] + +[[package]] +name = "wasm-encoder" +version = "0.202.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfd106365a7f5f7aa3c1916a98cbb3ad477f5ff96ddb130285a91c6e7429e67a" +dependencies = [ + "leb128", +] + +[[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.202.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6998515d3cf3f8b980ef7c11b29a9b1017d4cf86b99ae93b546992df9931413" +dependencies = [ + "bitflags 2.5.0", + "indexmap", + "semver", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..6a07888 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[workspace] +members=["pit-core", "pit-patch", "pit-rust-guest", "pit-rust-host", "pit-rust-host-lib"] +resolver="2" + +[workspace.dependencies] +portal-pc-waffle = {git="https://github.com/portal-co/waffle-.git",branch="pr/changes2"} +waffle-ast = {git="https://github.com/portal-co/more_waffle.git",branch="master"} \ No newline at end of file diff --git a/pit-core/Cargo.toml b/pit-core/Cargo.toml new file mode 100644 index 0000000..1274da3 --- /dev/null +++ b/pit-core/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "pit-core" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +derive_more = "0.99.18" +hex = "0.4.3" +nom = "7.1.3" +sha3 = "0.10.8" diff --git a/pit-core/src/lib.rs b/pit-core/src/lib.rs new file mode 100644 index 0000000..9a61528 --- /dev/null +++ b/pit-core/src/lib.rs @@ -0,0 +1,157 @@ +use derive_more::Display; +use nom::{ + bytes::complete::{is_not, tag, take, take_while_m_n}, + character::complete::{alpha1, char, multispace0}, + combinator::opt, + multi::{many0, separated_list0}, + sequence::{delimited, tuple}, + IResult, +}; +use sha3::{Digest, Sha3_256}; +use std::{collections::BTreeMap, fmt::Display}; +#[derive(Display, Clone, Eq, PartialEq, PartialOrd, Ord)] +pub enum ResTy { + #[display(fmt = "")] + None, + #[display(fmt = "{}", "hex::encode(_0)")] + Of([u8; 32]), + #[display(fmt = "this")] + This, +} +pub fn parse_resty(a: &str) -> IResult<&str, ResTy> { + if let Some(a) = a.strip_prefix("this") { + // let (a, k) = opt(tag("n"))(a)?; + return Ok((a, ResTy::This)); + } + let (a, d) = opt(take_while_m_n(64, 64, |a: char| a.is_digit(16)))(a)?; + return Ok(( + a, + match d { + Some(d) => { + let mut b = [0u8; 32]; + hex::decode_to_slice(d, &mut b).unwrap(); + ResTy::Of(b) + } + None => ResTy::None, + }, + )); +} +#[derive(Display, Clone, Eq, PartialEq, PartialOrd, Ord)] +pub enum Arg { + I32, + I64, + F32, + F64, + #[display(fmt = "R{}{}{}", "ty", "if *nullable{\"n\"}else{\"\"}","if *take{\"\"}else{\"&\"}")] + Resource { + ty: ResTy, + nullable: bool, + take: bool, + }, + // #[display(fmt = "{}", _0)] + // Func(Sig), +} +pub fn parse_arg(a: &str) -> IResult<&str, Arg> { + let (_, a) = multispace0(a)?; + let (b, c) = take(1usize)(a)?; + match c { + "R" => { + // if let Some(a) = b.strip_prefix("this"){ + // let (a, k) = opt(tag("n"))(a)?; + // return Ok(( + // a, + // Arg::Resource { + // ty: ResTy::This, + // nullable: k.is_some(), + // }, + // )); + // } + let (a, d) = parse_resty(b)?; + let (a, k) = opt(tag("n"))(a)?; + let (a, take) = opt(tag("&"))(a)?; + return Ok(( + a, + Arg::Resource { + ty: d, + nullable: k.is_some(), + take: take.is_none(), + }, + )); + } + // "(" => { + // let (a, x) = parse_sig(a)?; + // return Ok((a, Arg::Func(x))); + // } + _ => { + let (c, a) = take(3usize)(a)?; + match c { + "I32" => return Ok((a, Arg::I32)), + "I64" => return Ok((a, Arg::I64)), + "F32" => return Ok((a, Arg::F32)), + "F64" => return Ok((a, Arg::F64)), + _ => {} + } + } + } + todo!() +} +#[derive(Display, Clone, Eq, PartialEq, PartialOrd, Ord)] +#[display( + fmt = "({}) -> ({})", + "params.iter().map(|a|a.to_string()).collect::>().join(\",\")", + "rets.iter().map(|a|a.to_string()).collect::>().join(\",\")" +)] +pub struct Sig { + pub params: Vec, + pub rets: Vec, +} +pub fn parse_sig(a: &str) -> IResult<&str, Sig> { + let (a, _) = multispace0(a)?; + let mut d = delimited(char('('), separated_list0(char(','), parse_arg), char(')')); + let (a, params) = d(a)?; + let (a, _) = multispace0(a)?; + let (a, _) = tag("->")(a)?; + let (a, _) = multispace0(a)?; + let (a, rets) = d(a)?; + return Ok((a, Sig { params, rets })); +} +#[derive(Clone, Eq, PartialEq, PartialOrd, Ord)] +pub struct Interface { + pub methods: BTreeMap, +} +impl Display for Interface { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{{")?; + for (i, (a, b)) in self.methods.iter().enumerate() { + if i != 0 { + write!(f, ";")?; + } + write!(f, "{}{}", a, b)?; + } + return write!(f, "}}"); + } +} +pub fn parse_interface(a: &str) -> IResult<&str, Interface> { + pub fn go(a: &str) -> IResult<&str, Interface> { + let (a, s) = separated_list0(char(';'), tuple((multispace0, alpha1, parse_sig)))(a)?; + return Ok(( + a, + Interface { + methods: s.into_iter().map(|(_, a, b)| (a.to_owned(), b)).collect(), + }, + )); + } + let (a, _) = multispace0(a)?; + return delimited(char('{'), go, char('}'))(a); +} +impl Interface { + pub fn rid(&self) -> [u8; 32] { + use std::io::Write; + let mut s = Sha3_256::default(); + write!(s, "{}", self); + return s.finalize().try_into().unwrap(); + } + pub fn rid_str(&self) -> String { + return hex::encode(self.rid()); + } +} diff --git a/pit-patch/Cargo.toml b/pit-patch/Cargo.toml new file mode 100644 index 0000000..1b89a92 --- /dev/null +++ b/pit-patch/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "pit-patch" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.86" +nom = "7.1.3" +pit-core = { version = "0.1.0", path = "../pit-core" } +portal-pc-waffle.workspace = true +waffle-ast.workspace = true diff --git a/pit-patch/src/canon.rs b/pit-patch/src/canon.rs new file mode 100644 index 0000000..a3c5b54 --- /dev/null +++ b/pit-patch/src/canon.rs @@ -0,0 +1,164 @@ +use std::{collections::BTreeMap, iter::once, mem::take}; + +use anyhow::Context; +use waffle::{ + entity::EntityRef, util::new_sig, BlockTarget, Export, ExportKind, Func, FuncDecl, + FunctionBody, Import, ImportKind, Module, Operator, SignatureData, Type, +}; +use waffle_ast::{Builder, Expr}; + +pub fn canon(m: &mut Module, rid: &str, target: &str) -> anyhow::Result<()> { + let mut xs = vec![]; + for i in m.imports.iter() { + if i.module == format!("pit/{rid}") { + if let Some(a) = i.name.strip_prefix("~") { + xs.push(a.to_owned()) + } + } + } + let s = new_sig( + m, + SignatureData { + params: vec![Type::I32], + returns: vec![Type::ExternRef], + }, + ); + let f2 = m + .funcs + .push(waffle::FuncDecl::Import(s, format!("pit/{rid}.~{target}"))); + for i in take(&mut m.imports) { + if i.module == format!("pit/{rid}") { + if let Some(a) = i.name.strip_prefix("~") { + if let Ok(x) = xs.binary_search(&a.to_owned()) { + if let ImportKind::Func(f) = i.kind { + let fs = m.funcs[f].sig(); + let fname = m.funcs[f].name().to_owned(); + let mut b = FunctionBody::new(&m, fs); + let k = b.entry; + let mut e = Expr::Bind( + Operator::I32Add, + vec![ + Expr::Bind(Operator::I32Const { value: x as u32 }, vec![]), + Expr::Bind( + Operator::I32Mul, + vec![ + Expr::Bind( + Operator::I32Const { + value: xs.len() as u32, + }, + vec![], + ), + Expr::Leaf(b.blocks[k].params[0].1), + ], + ), + ], + ); + let (a, k) = e.build(m, &mut b, k)?; + let args = once(a) + .chain(b.blocks[b.entry].params[1..].iter().map(|a| a.1)) + .collect(); + b.set_terminator(k, waffle::Terminator::ReturnCall { func: f2, args }); + m.funcs[f] = FuncDecl::Body(fs, fname, b); + continue; + } + } + } + } + m.imports.push(i) + } + m.imports.push(Import { + module: format!("pit/{rid}"), + name: format!("~{target}"), + kind: ImportKind::Func(f2), + }); + let mut b = BTreeMap::new(); + for x in take(&mut m.exports) { + for x2 in xs.iter() { + if let Some(a) = x.name.strip_prefix(&format!("pit/{rid}/~{x2}")) { + let mut b = b.entry(a.to_owned()).or_insert_with(|| BTreeMap::new()); + let mut e = b.entry(x2.clone()).or_insert_with(|| Func::invalid()); + if let ExportKind::Func(f) = x.kind { + *e = f; + continue; + } + } + } + m.exports.push(x) + } + for (method, inner) in b.into_iter() { + let sig = *inner.iter().next().context("in getting an instance")?.1; + let funcs: Vec = xs + .iter() + .filter_map(|f| inner.get(f)) + .cloned() + .collect::>(); + let sig = m.funcs[sig].sig(); + let mut b = FunctionBody::new(&m, sig); + let k = b.entry; + let mut e = Expr::Bind( + Operator::I32DivU, + vec![ + Expr::Leaf(b.blocks[k].params[0].1), + Expr::Bind( + Operator::I32Const { + value: funcs.len() as u32, + }, + vec![], + ), + ], + ); + let (a, k) = e.build(m, &mut b, k)?; + let mut e = Expr::Bind( + Operator::I32RemU, + vec![ + Expr::Leaf(b.blocks[k].params[0].1), + Expr::Bind( + Operator::I32Const { + value: funcs.len() as u32, + }, + vec![], + ), + ], + ); + let (c, k) = e.build(m, &mut b, k)?; + let args = once(a) + .chain(b.blocks[b.entry].params[1..].iter().map(|a| a.1)) + .collect::>(); + let blocks = funcs + .iter() + .map(|f| { + let k = b.add_block(); + b.set_terminator( + k, + waffle::Terminator::ReturnCall { + func: *f, + args: args.clone(), + }, + ); + BlockTarget { + block: k, + args: vec![], + } + }) + .collect::>(); + b.set_terminator( + k, + waffle::Terminator::Select { + value: c, + targets: blocks, + default: BlockTarget { + block: b.entry, + args, + }, + }, + ); + let f = m + .funcs + .push(FuncDecl::Body(sig, format!("pit/{rid}/~{target}{method}"), b)); + m.exports.push(Export { + name: format!("pit/{rid}/~{target}{method}"), + kind: ExportKind::Func(f), + }); + } + Ok(()) +} diff --git a/pit-patch/src/lib.rs b/pit-patch/src/lib.rs new file mode 100644 index 0000000..aa61a30 --- /dev/null +++ b/pit-patch/src/lib.rs @@ -0,0 +1,33 @@ +use std::{ + collections::{BTreeMap, BTreeSet}, + iter::once, + mem::take, +}; + +use anyhow::Context; +use pit_core::{Arg, Interface, Sig}; +use util::tfree; +use waffle::{ + util::new_sig, ExportKind, FuncDecl, FunctionBody, ImportKind, Module, SignatureData, + TableData, Type, +}; +use waffle_ast::add_op; + +pub mod util; +pub mod canon; +pub mod lower; +pub fn get_interfaces(m: &Module) -> anyhow::Result> { + let c = m + .custom_sections + .get(".pit-types") + .context("in getting type section")?; + let mut is = vec![]; + for b in c.split(|a| *a == 0) { + let s = std::str::from_utf8(b)?; + let (s, i) = pit_core::parse_interface(s) + .map_err(|e: nom::Err>| anyhow::anyhow!("invalid pit"))?; + is.push(i); + } + + return Ok(is); +} diff --git a/pit-patch/src/lower.rs b/pit-patch/src/lower.rs new file mode 100644 index 0000000..31abe47 --- /dev/null +++ b/pit-patch/src/lower.rs @@ -0,0 +1,309 @@ +use std::{collections::BTreeSet, iter::once, mem::take}; + +use anyhow::Context; +use waffle::{ + entity::EntityRef, util::new_sig, ExportKind, Func, FuncDecl, FunctionBody, Import, ImportKind, + Module, Operator, SignatureData, TableData, Type, ValueDef, +}; +use waffle_ast::{ + add_op, + fcopy::{obf_mod, DontObf, Obfuscate}, + Builder, Expr, +}; + +use crate::canon::canon; +pub fn patch_ty(t: &mut Type) { + if let Type::ExternRef = t.clone() { + *t = Type::I32 + } +} +pub fn import_fn(m: &mut Module, mo: String, n: String, s: SignatureData) -> Func { + for i in m.imports.iter() { + if i.module == mo && i.name == n { + if let ImportKind::Func(f) = &i.kind { + return *f; + } + } + } + let s = new_sig(m, s); + let f = m + .funcs + .push(waffle::FuncDecl::Import(s, format!("{mo}.{n}"))); + m.imports.push(Import { + module: mo, + name: n, + kind: ImportKind::Func(f), + }); + return f; +} +pub fn instantiate(m: &mut Module, root: &str) -> anyhow::Result<()> { + let i = crate::get_interfaces(m)?; + let interfaces = i + .into_iter() + .collect::>() + .into_iter() + .collect::>(); + for j in interfaces.iter() { + canon(m, &j.rid_str(), root)?; + } + for s in m.signatures.values_mut() { + for p in s.params.iter_mut().chain(s.returns.iter_mut()) { + patch_ty(p) + } + } + m.try_take_per_func_body(|m, b| { + let x = b.type_pool.from_iter(once(Type::I32)); + for p in b + .blocks + .values_mut() + .flat_map(|a| a.params.iter_mut().map(|a| &mut a.0)) + .chain(b.rets.iter_mut()) + { + patch_ty(p) + } + for v in b.values.iter().collect::>() { + if let ValueDef::Operator(o, _1, tys) = &mut b.values[v] { + match o.clone() { + Operator::RefNull { ty } => { + if ty == Type::ExternRef { + *o = Operator::I32Const { value: 0 } + } + } + Operator::RefIsNull => { + if b.type_pool[*tys][0] == Type::ExternRef { + *o = Operator::I32Eqz + } + } + _ => {} + } + } + } + for t in b.type_pool.storage.iter_mut() { + patch_ty(t) + } + Ok::<_, anyhow::Error>(()) + })?; + struct X {} + impl Obfuscate for X { + fn obf( + &mut self, + o: Operator, + f: &mut waffle::FunctionBody, + b: waffle::Block, + args: &[waffle::Value], + types: &[Type], + module: &mut Module, + ) -> anyhow::Result<(waffle::Value, waffle::Block)> { + match o { + Operator::TableGet { table_index } + | Operator::TableSet { table_index } + | Operator::TableSize { table_index } + | Operator::TableGrow { table_index } => { + if module.tables[table_index].ty == Type::ExternRef { + // let x = b.arg_pool[*_1].to_vec(); + let w = add_op( + f, + &[], + &[Type::I32], + Operator::I32Const { + value: table_index.index() as u32, + }, + ); + f.append_to_block(b, w); + let id = format!("pit-patch-rt/{}", o.to_string().split_once("<").unwrap().0); + let mut a = module.exports.iter(); + let a = loop{ + let Some(b) = a.next() else{ + anyhow::bail!("pit patch rt not found") + }; + if b.name != id{ + continue; + } + let ExportKind::Func(a) = &b.kind else{ + continue; + }; + break *a; + }; + DontObf {}.obf( + Operator::Call { function_index: a }, + f, + b, + &once(w).chain(args.iter().cloned()).collect::>(), + types, + module, + ) + } else { + DontObf {}.obf(o, f, b, args, types, module) + } + } + _ => DontObf {}.obf(o, f, b, args, types, module), + } + } + } + obf_mod(m, &mut X {})?; + for t in m.tables.values_mut() { + if t.ty == Type::ExternRef { + t.ty = Type::FuncRef; + } + } + for i in take(&mut m.imports) { + if let Some(rid) = i.module.strip_prefix("pit/") { + let ridx = interfaces + .iter() + .enumerate() + .find_map(|x| { + if x.1.rid_str() == rid { + Some(x.0) + } else { + None + } + }) + .context("in getting the index")?; + let rl = interfaces.len(); + if i.name.ends_with(&format!("~{root}")) { + if let ImportKind::Func(f) = i.kind { + let fs = m.funcs[f].sig(); + let fname = m.funcs[f].name().to_owned(); + let mut b = FunctionBody::new(&m, fs); + let k = b.entry; + let mut values: Vec = + b.blocks[k].params.iter().map(|a| a.1).collect(); + let mut e = Expr::Bind( + Operator::I32Add, + vec![ + Expr::Bind(Operator::I32Const { value: ridx as u32 }, vec![]), + Expr::Bind( + Operator::I32Mul, + vec![ + Expr::Bind(Operator::I32Const { value: rl as u32 }, vec![]), + Expr::Leaf(values[0]), + ], + ), + ], + ); + let (v, k) = e.build(m, &mut b, k)?; + values[0] = v; + b.set_terminator(k, waffle::Terminator::Return { values }); + m.funcs[f] = FuncDecl::Body(fs, fname, b); + continue; + } + } else { + let ek = format!("{}/~{root}{}", i.module, i.name); + let mut ex = m.exports.iter(); + let ex = loop { + let Some(x) = ex.next() else { + anyhow::bail!("export not found") + }; + if x.name != ek { + continue; + }; + let ExportKind::Func(ef) = &x.kind else { + continue; + }; + break *ef; + }; + if let ImportKind::Func(f) = i.kind { + let fs = m.funcs[f].sig(); + let fname = m.funcs[f].name().to_owned(); + let mut b = FunctionBody::new(&m, fs); + let k = b.entry; + let mut args = b.blocks[b.entry] + .params + .iter() + .map(|a| a.1) + .collect::>(); + let mut e = Expr::Bind( + Operator::I32DivU, + vec![ + Expr::Leaf(args[0]), + Expr::Bind(Operator::I32Const { value: rl as u32 }, vec![]), + ], + ); + let (v, k) = e.build(m, &mut b, k)?; + args[0] = v; + b.set_terminator(k, waffle::Terminator::ReturnCall { func: ex, args }); + m.funcs[f] = FuncDecl::Body(fs, fname, b); + continue; + } + } + } + if i.module == "pit" && i.name == "drop" { + let fs = interfaces + .iter() + .filter_map(|i| { + let mut ex = m.exports.iter(); + let ex = loop { + let Some(x) = ex.next() else { + return None; + }; + if x.name != format!("pit/{}/{root}.drop", i.rid_str()) { + continue; + }; + let ExportKind::Func(ef) = &x.kind else { + continue; + }; + break *ef; + }; + return Some(ex); + }) + .collect::>(); + let t = m.tables.push(TableData { + ty: Type::FuncRef, + initial: fs.len() as u32, + max: Some(fs.len() as u32), + func_elements: Some(fs.clone()), + }); + if let ImportKind::Func(f) = i.kind { + let fsi = m.funcs[f].sig(); + let fname = m.funcs[f].name().to_owned(); + let mut b = FunctionBody::new(&m, fsi); + let k = b.entry; + let mut args = b.blocks[b.entry] + .params + .iter() + .map(|a| a.1) + .collect::>(); + let mut e = Expr::Bind( + Operator::I32DivU, + vec![ + Expr::Leaf(b.blocks[k].params[0].1), + Expr::Bind( + Operator::I32Const { + value: fs.len() as u32, + }, + vec![], + ), + ], + ); + let (a, k) = e.build(m, &mut b, k)?; + let mut e = Expr::Bind( + Operator::I32RemU, + vec![ + Expr::Leaf(b.blocks[k].params[0].1), + Expr::Bind( + Operator::I32Const { + value: fs.len() as u32, + }, + vec![], + ), + ], + ); + let (c, k) = e.build(m, &mut b, k)?; + args[0] = a; + args.push(c); + b.set_terminator( + k, + waffle::Terminator::ReturnCallIndirect { + sig: fsi, + table: t, + args, + }, + ); + m.funcs[f] = FuncDecl::Body(fsi, fname, b); + continue; + } + } + m.imports.push(i); + } + Ok(()) +} diff --git a/pit-patch/src/util.rs b/pit-patch/src/util.rs new file mode 100644 index 0000000..5bc0bf8 --- /dev/null +++ b/pit-patch/src/util.rs @@ -0,0 +1,129 @@ +use waffle::{util::new_sig, BlockTarget, Func, FunctionBody, Module, Operator, SignatureData, Table, Type}; +use waffle_ast::{add_op, Builder, Expr}; + + +pub fn talloc(m: &mut Module, t: Table) -> anyhow::Result { + let e = m.tables[t].ty.clone(); + let sig = new_sig( + m, + SignatureData { + params: vec![e], + returns: vec![Type::I32], + }, + ); + let mut f = FunctionBody::new(m, sig); + let n = f.add_block(); + let zero = add_op(&mut f, &[], &[Type::I32], Operator::I32Const { value: 0 }); + f.append_to_block(f.entry, zero); + f.set_terminator( + f.entry, + waffle::Terminator::Br { + target: BlockTarget { + block: n, + args: vec![zero], + }, + }, + ); + let idx = f.add_blockparam(n, Type::I32); + let mut e = Expr::Bind( + Operator::RefIsNull, + vec![Expr::Bind( + Operator::TableGet { table_index: t }, + vec![Expr::Leaf(idx)], + )], + ); + let (r, o) = e.build(m, &mut f, n)?; + let mut e = Expr::Bind( + Operator::I32Add, + vec![ + Expr::Bind(Operator::I32Const { value: 1 }, vec![]), + Expr::Leaf(idx), + ], + ); + let (s, o) = e.build(m, &mut f, o)?; + let p = f.add_block(); + f.set_terminator( + o, + waffle::Terminator::CondBr { + cond: r, + if_true: BlockTarget { + block: p, + args: vec![], + }, + if_false: BlockTarget { + block: n, + args: vec![s], + }, + }, + ); + let q = f.add_block(); + let r = f.add_block(); + let mut e = Expr::Bind( + Operator::I32Eq, + vec![ + Expr::Bind(Operator::TableSize { table_index: t }, vec![]), + Expr::Leaf(idx), + ], + ); + let (s, o) = e.build(m, &mut f, p)?; + f.set_terminator( + o, + waffle::Terminator::CondBr { + cond: s, + if_true: BlockTarget { + block: r, + args: vec![], + }, + if_false: BlockTarget { + block: q, + args: vec![], + }, + }, + ); + let mut e = Expr::Bind( + Operator::TableSet { table_index: t }, + vec![Expr::Leaf(idx), Expr::Leaf(f.blocks[f.entry].params[0].1)], + ); + let (s, o) = e.build(m, &mut f, q)?; + f.set_terminator(o, waffle::Terminator::Return { values: vec![idx] }); + let mut e = Expr::Bind( + Operator::TableGrow { table_index: t }, + vec![ + Expr::Bind(Operator::I32Const { value: 1 }, vec![]), + Expr::Leaf(f.blocks[f.entry].params[0].1), + ], + ); + let (s, o) = e.build(m, &mut f, r)?; + f.set_terminator(o, waffle::Terminator::Return { values: vec![idx] }); + return Ok(m + .funcs + .push(waffle::FuncDecl::Body(sig, format!("talloc"), f))); +} +pub fn tfree(m: &mut Module, t: Table) -> anyhow::Result { + let ety = m.tables[t].ty.clone(); + let sig = new_sig( + m, + SignatureData { + params: vec![Type::I32], + returns: vec![ety.clone()], + }, + ); + let mut f = FunctionBody::new(m, sig); + let o = f.entry; + let mut e = Expr::Bind( + Operator::TableGet { table_index: t }, + vec![Expr::Leaf(f.blocks[f.entry].params[0].1)], + ); + let (r, o) = e.build(m, &mut f, o)?; + let mut e = Expr::Bind( + Operator::TableSet { table_index: t }, + vec![ + Expr::Leaf(f.blocks[f.entry].params[0].1), + Expr::Bind(Operator::RefNull { ty: ety }, vec![]), + ], + ); + let (_, o) = e.build(m, &mut f, o)?; + return Ok(m + .funcs + .push(waffle::FuncDecl::Body(sig, format!("tfree"), f))); +} diff --git a/pit-rust-guest/Cargo.toml b/pit-rust-guest/Cargo.toml new file mode 100644 index 0000000..473f73f --- /dev/null +++ b/pit-rust-guest/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "pit-rust-guest" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +hex = "0.4.3" +pit-core = { version = "0.1.0", path = "../pit-core" } +proc-macro2 = "1.0.85" +quasiquote = "0.1.1" +quote = "1.0.36" +sha3 = "0.10.8" +syn = "2.0.66" diff --git a/pit-rust-guest/src/lib.rs b/pit-rust-guest/src/lib.rs new file mode 100644 index 0000000..0f29fd1 --- /dev/null +++ b/pit-rust-guest/src/lib.rs @@ -0,0 +1,142 @@ +use std::iter::once; + +use pit_core::{Arg, Interface, ResTy, Sig}; +use proc_macro2::TokenStream; +use quote::{format_ident, quote}; +use quasiquote::quasiquote; +use sha3::Digest; +use std::io::Write; +pub struct Opts{ + pub root: TokenStream, + pub salt: Vec +} +pub fn render(opts: &Opts, i: &Interface) -> TokenStream{ + let root = &opts.root; + let id = i.rid_str(); + let mut ha = sha3::Sha3_256::default(); + write!(ha,"~{}",id); + ha.write(&opts.salt); + let ha = hex::encode(ha.finalize()); + let id2 = format_ident!("R{}",i.rid_str()); + let internal = format_ident!("{id}_utils"); + let methods = i.methods.iter().map(|(a,b)|quasiquote! { + fn #{format_ident!("{a}")}#{render_sig(root,i,b,"e! {&self})} + }); + let impl_dyns = i.methods.iter().map(|(a,b)|quasiquote! { + fn #{format_ident!("{a}")}#{render_sig(root,i,b,"e! {&self})}{ + #[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})] + #[wasm_import_module = #{format!("pit/{}",i.rid_str())}] + extern "C"{ + #[wasm_import_name = #a] + fn go #{render_sig(root, i,b, "e! {&#root::externref::Resource>})} + }; + return go(self,#{ + let params = b.params.iter().enumerate().map(|(a,_)|format_ident!("p{a}")); + quote! { + #(#params),* + } + }); + } + }); + let chains2 = i.methods.iter().map(|(a,b)|quasiquote! { + #[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})] + #[export_name = #{format!("pit/{id}/~{ha}/{a}")}] + fn #{format_ident!("{a}")}#{render_sig(root,i,b,"e! {id: *mut Box})}{ + return unsafe{&mut *id}.#{format_ident!("{a}")}(#{ + let params = b.params.iter().enumerate().map(|(a,_)|format_ident!("p{a}")); + quote! { + #(#params),* + } + }); + } + }); + quasiquote!{ + pub trait #id2{ + #(#methods)* + } + mod #internal{ + const _: () = { + #[link_section = ".pit-types"] + static SECTION_CONTENT: [u8; _] = #{ + let b = i.to_string(); + let c = b.as_bytes().iter().cloned().chain(once(0u8)); + quote!{ + [#(#c),*] + } + }; + }; + use super::#id2; + impl #id2 for #root::externref::Resource>{ + #(#impl_dyns),* + } + #[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})] + #[export_name = #{format!("pit/{id}/~{ha}.drop")}] + fn _drop(a: *mut Box){ + unsafe{ + Box::from_raw(a) + } + } + #(#chains2);* + #[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})] + #[wasm_import_module = #{format!("pit/{}",i.rid_str())}] + extern "C"{ + #[wasm_import_name = #{format!("~{ha}")}] + fn _push(a: *mut Box) -> #root::externref::Resource>; + } + pub fn push(a: Box) -> #root::externref::Resource>{ + return unsafe{ + _push(Box::into_raw(Box::new(a))) + } + } + } + } +} +pub fn render_sig(root: &TokenStream,base: &Interface, s: &Sig, self_: &TokenStream) -> TokenStream{ + let params = s.params.iter().map(|a|render_ty(root,base,a)).enumerate().map(|(a,b)|quasiquote!(#{format_ident!("p{a}")} : #b)); + let params = once(self_).cloned().chain(params); + let rets = s.rets.iter().map(|a|render_ty(root,base,a)); + quote! { + (#(#params),*) -> (#(#rets),*) + } +} +pub fn render_ty(root: &TokenStream,base:&Interface, p: &Arg) -> TokenStream{ + match p{ + Arg::I32 => quote! { + u32 + }, + Arg::I64 => quote! { + u64 + }, + Arg::F32 => quote! { + f32 + }, + Arg::F64 => quote! { + f64 + }, + Arg::Resource{ty,nullable,take} => { + let ty = match ty{ + ResTy::Of(a) => quasiquote!{ + #root::externref::Resource> + }, + ResTy::None => quote! { + #root::externref::Resource<()> + }, + ResTy::This => quasiquote! { + #root::externref::Resource> + } + }; + let ty = if *nullable{ + quote! {Option<#ty>} + }else{ + ty + }; + let ty = if *take{ + ty + }else{ + quote! {&#ty} + }; + ty + }, + // Arg::Func(_) => todo!() + } +} \ No newline at end of file diff --git a/pit-rust-host-lib/Cargo.toml b/pit-rust-host-lib/Cargo.toml new file mode 100644 index 0000000..ee44a3f --- /dev/null +++ b/pit-rust-host-lib/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "pit-rust-host-lib" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.86" +pit-core = { version = "0.1.0", path = "../pit-core" } +wasm_runtime_layer = "0.4.0" diff --git a/pit-rust-host-lib/src/lib.rs b/pit-rust-host-lib/src/lib.rs new file mode 100644 index 0000000..e76785f --- /dev/null +++ b/pit-rust-host-lib/src/lib.rs @@ -0,0 +1,182 @@ +use std::{ + cell::UnsafeCell, + collections::BTreeMap, + env::vars, + iter::{empty, once}, + sync::{Arc, Mutex}, +}; + +use pit_core::{Arg, Interface}; +use wasm_runtime_layer::{ + backend::WasmEngine, AsContext, AsContextMut, Extern, ExternRef, Func, FuncType, Imports, + Instance, Module, StoreContext, StoreContextMut, Value, ValueType, +}; +pub fn init + 'static, E: WasmEngine>( + l: &mut Imports, + ctx: &mut impl AsContextMut, +){ + l.define("pit", "drop", Extern::Func(Func::new( + &mut *ctx, + FuncType::new( + once(ValueType::ExternRef), + empty(), + ), + move |mut ctx, args, rets| { + let Value::ExternRef(Some(a)) = args[0].clone() else { + anyhow::bail!("invalid type") + }; + let Ok(x): Result<&Wrapped, anyhow::Error> = a.downcast::<'_,'_,Wrapped,U,E>(ctx.as_context()) else{ + return Ok(()); + }; + let f = x.all[0].clone(); + f(ctx.as_context_mut(),vec![])?; + Ok(()) + }, + ))); +} +pub fn emit_ty(a: &Arg) -> ValueType { + match a { + Arg::I32 => ValueType::I32, + Arg::I64 => ValueType::I64, + Arg::F32 => ValueType::F32, + Arg::F64 => ValueType::F64, + Arg::Resource { ty, nullable, take } => ValueType::ExternRef, + // Arg::Func(f) => ValueType::FuncRef, + } +} +pub fn emit + 'static, E: WasmEngine>( + l: &mut Imports, + rid: Arc, + m: &Module, + ctx: &mut impl AsContextMut, +) { + let n = format!("pit/{}", rid.rid_str()); + for (j, (i, m)) in rid.methods.iter().enumerate() { + l.define( + &n, + i.as_str(), + Extern::Func(Func::new( + &mut *ctx, + FuncType::new( + once(ValueType::ExternRef).chain(m.params.iter().map(emit_ty)), + m.rets.iter().map(emit_ty), + ), + move |mut ctx, args, rets| { + let Value::ExternRef(Some(a)) = args[0].clone() else { + anyhow::bail!("invalid type") + }; + let x: &Wrapped = a.downcast(ctx.as_context())?; + let t = x.all[j + 1].clone(); + let rets2 = t(ctx.as_context_mut(),args[1..].iter().cloned().collect())?; + for (r, s) in rets2.into_iter().zip(rets.iter_mut()) { + *s = r; + } + Ok(()) + }, + )), + ) + } + let i = m.imports(ctx.as_context().engine()).map(|a|(a.module.to_owned(),a.name.to_owned())).collect::>(); + for i in i { + if i.0 == n{ + if let Some(t) = i.1.strip_prefix("~"){ + let t = t.to_owned(); + let rid = rid.clone(); + l.define( + &n, + &i.1, + Extern::Func(Func::new( + &mut *ctx, + FuncType::new(once(ValueType::I32), once(ValueType::ExternRef)), + move |mut ctx, args, rets| { + let Value::I32(a) = &args[0] else { + anyhow::bail!("invalid type"); + }; + let i = ctx.data().as_ref().clone(); + let object = Wrapped::new(*a as u32, rid.clone(),t.to_owned(), i, ctx.as_context_mut()); + rets[0] = Value::ExternRef(Some(ExternRef::new(ctx, object))); + Ok(()) + }, + )), + ) + }; + }; + }; +} +pub struct Wrapped { + pub rid: Arc, + pub all: Vec,Vec) -> anyhow::Result> + Send + Sync>>, + // }, +} +impl Wrapped { + pub fn new( + base: u32, + rid: Arc, + rs: String, + instance: ::wasm_runtime_layer::Instance, + store: ::wasm_runtime_layer::StoreContextMut<'_, U, E>, + ) -> Self { + // impl Copy for X {} + // let ctx: X = X { + // base: Arc::new(Mutex::new(unsafe { std::mem::transmute(store) })), + // }; + let rid2 = rid.clone(); + let instance2 = instance.clone(); + // let ctx2 = ctx.clone(); + let rs2 = rs.clone(); + return Self { + rid: rid.clone(), + all: once( + Arc::new(move |mut ctx:StoreContextMut<'_,U,E>,vals: Vec| -> anyhow::Result> { + // let _ = &ctx2; + // let mut b = ctx2.base.lock().unwrap(); + let vals: Vec<_> = vec![Value::I32(base as i32)] + .into_iter() + .chain(vals.into_iter()) + .collect(); + let mut rets = vec![]; + let f = instance2.get_export(ctx.as_context_mut(), &format!("pit/{}/~{rs2}.drop", rid2.rid_str())); + let Some(Extern::Func(f)) = f else { + anyhow::bail!("invalid func") + }; + f.call(ctx.as_context_mut(), &vals, &mut rets)?; + Ok(rets) + }) + as Arc,Vec) -> anyhow::Result> + Send + Sync> + ) + .chain(rid.methods.iter().map(|(a, b)| { + let rid = rid.clone(); + let a = a.clone(); + let instance = instance.clone(); + let b = Arc::new(b.clone()); + // let ctx = ctx.clone(); + let rs = rs.clone(); + (Arc::new(move |mut ctx:StoreContextMut<'_,U,E>,vals: Vec| -> anyhow::Result> { + // let _ = &ctx; + // let mut bi = ctx.base.lock().unwrap(); + let vals: Vec<_> = vec![Value::I32(base as i32)] + .into_iter() + .chain(vals.into_iter()) + .collect(); + let mut rets = vec![Value::I32(0); b.rets.len()]; + let f = instance.get_export(ctx.as_context_mut(), &format!("pit/{}/~{rs}/{a}", rid.rid_str())); + let Some(Extern::Func(f)) = f else { + anyhow::bail!("invalid func") + }; + f.call(ctx.as_context_mut(), &vals, &mut rets)?; + Ok(rets) + }) + as Arc,Vec) -> anyhow::Result> + Send + Sync>) + })) + .collect(), + }; + } +} +// impl Drop for Wrapped { +// fn drop(&mut self) { +// self.all[0](vec![]).unwrap(); +// } +// } +pub type RWrapped = ::std::sync::Arc>; +pub extern crate anyhow; +pub extern crate wasm_runtime_layer; diff --git a/pit-rust-host/Cargo.toml b/pit-rust-host/Cargo.toml new file mode 100644 index 0000000..7affd4e --- /dev/null +++ b/pit-rust-host/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "pit-rust-host" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +hex = "0.4.3" +pit-core = { version = "0.1.0", path = "../pit-core" } +proc-macro2 = "1.0.85" +quasiquote = "0.1.1" +quote = "1.0.36" +syn = "2.0.66" diff --git a/pit-rust-host/src/lib.rs b/pit-rust-host/src/lib.rs new file mode 100644 index 0000000..291eb6c --- /dev/null +++ b/pit-rust-host/src/lib.rs @@ -0,0 +1,291 @@ +use std::iter::once; + +use pit_core::{Arg, Interface, Sig}; +use proc_macro2::TokenStream; +use quasiquote::quasiquote; +use quote::{format_ident, quote, ToTokens}; +use syn::{spanned::Spanned, Ident, Index}; +pub fn render(root: &TokenStream, i: &Interface) -> TokenStream { + let id = format_ident!("R{}", i.rid_str()); + let internal = format_ident!("{id}_utils"); + let methods = i.methods.iter().map(|(a, b)| { + quasiquote! { + fn #{format_ident!("{a}")}#{render_sig(root,b,"e! {&self})} + } + }); + let impls = i.methods.iter().map(|(a, b)| { + let init = b.params.iter().enumerate().map(|(pi,a)|render_new_val(root, a, quasiquote!{#{format_ident!("p{pi}")}})); + let init = once(quote!{#root::wasm_runtime_layer::Value::I32(self.base as i32)}).chain(init); + let fini = b.rets.iter().enumerate().map(|(ri,r)|{ + quasiquote!{ + #{render_base_val(root, r, quote! {&rets[#ri]})} + } + }); + quasiquote! { + fn #{format_ident!("{a}")}#{render_sig(root,b,"e! {&self})}{ + let Some(#root::wasm_runtime_layer::Export::Func(f)) = self.instance.get_export(unsafe{ + &*::std::cell::UnsafeCell::raw_get(self.ctx) + },#{format!("pit/{}/{}",i.rid_str(),a)}) else{ + panic!("invalid func") + }; + let args = vec![#(#init),*]; + let mut rets = vec![#root::wasm_runtime_layer::Value::I32(0);#{b.rets.len()}]; + f.call(unsafe{ + &mut *::std::cell::UnsafeCell::raw_get(self.ctx) + },&args,&mut rets)?; + return Ok((#(#fini),*)) + } + } + }); + let injects = i.methods.iter().map(|(a,b)|{ + let init = b.params.iter().enumerate().map(|(pi,a)|quasiquote!{let #{format_ident!("p{pi}")} = #{render_base_val(root, a, quote! {&args[#pi + 1]})}}); + let fini = b.rets.iter().enumerate().map(|(ri,r)|{ + quasiquote!{ + rets[#ri] = #{render_new_val(root, r, quasiquote! {r . #{Index{index: ri as u32,span: root.span()}}})} + } + }); + quasiquote!{ + let f = #root::wasm_runtime_layer::Func::new(ctx,#{render_blit_sig(root, b)},|ctx,args,rets|{ + #(#init),* + let #root::wasm_runtime_layer::Value::ExternRef(t) = &args[0] else{ + #root::anyhow::bail!("invalid param") + } + let r = match t.downcast::<'_,'_, ::std::sync::Arc>,U,E>(ctx){ + Ok(t) => { + t.#{format_ident!("{a}")}(#{ + let p = b.params.iter().enumerate().map(|(a,_)|format_ident!("p{a}")); + quote! { + #(#p .clone()),* + } + })? + }, + Err(_) => match t.downcast::<'_,'_, ::std::sync::Arc<#root::Wrapped>,U,E>(ctx)?{ + Ok(t) => { + t.#{format_ident!("{a}")}(#{ + let p = b.params.iter().enumerate().map(|(a,_)|format_ident!("p{a}")); + quote! { + #(#p .clone()),* + } + })? + }, + Err(_) => #root::anyhow::bail!("invalid externref") + } + }; + #(#fini),* + Ok(()) + }); + i.define(#{format!("pit/{}",i.rid_str())},#a,f); + }}).chain(once( quasiquote!{ + let f = #root::wasm_runtime_layer::Func::new(ctx,#root::wasm_runtime_layer::FuncType::new([#root::wasm_runtime_layer::ValueType::I32],[#root::wasm_runtime_layer::ExternType]),|ctx,args,rets|{ + let #root::wasm_runtime_layer::Value::I32(i) = &args[0] else{ + unreachable!() + }; + let n = ctx.data().as_ref().clone(); + let v = #root::Wrapped::new(*i as u32,#{i.rid_str()},ctx.as_context_mut(),n); + // let v: ::std::sync::Arc> = ::std::sync::Arc::new(v); + rets[0] = #root::wasm_runtime_layer::Value::ExternRef(#root::wasm_runtime_layer::ExternRef::new(ctx,v)); + Ok(()) + }); + i.define(#{format!("pit/{}",i.rid_str())},"~push",f); + })); + quasiquote! { + pub trait #id{ + fn to_any(&self) -> &dyn ::std::any::Any; + #(#methods)* + } + mod #internal{ + use super::#id; + impl #id for #root::RWrapped{ + fn to_any(&self) -> &dyn ::std::any::Any{ + return self; + } + #(#impls)* + } + + fn inject,E: #root::wasm_runtime_layer::backend::WasmEngine>(ctx: impl #root::wasm_runtime_layer::AsContextMut, i: &mut #root::wasm_runtime_layer::Imports){ + #(#injects)* + } + } + } +} +pub fn render_sig(root: &TokenStream, s: &Sig, self_: &TokenStream) -> TokenStream { + let params = s + .params + .iter() + .map(|a| render_ty(root, a)) + .enumerate() + .map(|(a, b)| quasiquote!(#{format_ident!("p{a}")} : #b)); + let params = once(self_).cloned().chain(params); + let rets = s.rets.iter().map(|a| render_ty(root, a)); + quote! { + (#(#params),*) -> #root::anyhow::Result<(#(#rets),*)> + } +} +pub fn render_blit(root: &TokenStream, p: &Arg) -> TokenStream { + match p { + Arg::I32 => quote! { + #root::wasm_runtime_layer::ValueType::I32 + }, + Arg::I64 => quote! { + #root::wasm_runtime_layer::ValueType::I64 + }, + Arg::F32 => quote! { + #root::wasm_runtime_layer::ValueType::F32 + }, + Arg::F64 => quote! { + #root::wasm_runtime_layer::ValueType::F64 + }, + Arg::Resource { .. } => quote! { + #root::wasm_runtime_layer::ValueType::ExternRef + }, + } +} +pub fn render_blit_sig(root: &TokenStream, s: &Sig) -> TokenStream { + quasiquote! { + #root::wasm_runtime_layer::FuncType::new([#{ + let p = s.params.iter().map(|p|render_blit(root, p)); + let p = once(quote! {#root::wasm_runtime_layer::ValueType::ExternRef}).chain(p); + quote! { + #(#p),* + } + }].into_iter(),[#{ let p = s.rets.iter().map(|p|render_blit(root, p)); + quote! { + #(#p),* + }}].into_iter()) + } +} +pub fn render_ty(root: &TokenStream, p: &Arg) -> TokenStream { + match p { + Arg::I32 => quote! { + u32 + }, + Arg::I64 => quote! { + u64 + }, + Arg::F32 => quote! { + f32 + }, + Arg::F64 => quote! { + f64 + }, + Arg::Resource { ty, nullable } => match ty { + None => quote! { + #root::wasm_runtime_layer::ExternRef + }, + Some(a) => { + let a = quasiquote! { + ::std::sync::Arc> + }; + if *nullable { + quote! {Option<#a>} + } else { + a + } + } + }, + } +} +pub fn render_base_val(root: &TokenStream, p: &Arg, x: TokenStream) -> TokenStream { + let v = match p { + Arg::I32 => quote! { + let #root::wasm_runtime_layer::Value::I32(t) = #x else{ + #root::anyhow::bail!("invalid param") + } + }, + Arg::I64 => quote! { + let #root::wasm_runtime_layer::Value::I64(t) = #x else{ + #root::anyhow::bail!("invalid param") + } + }, + Arg::F32 => quote! { + let #root::wasm_runtime_layer::Value::F32(t) = #x else{ + #root::anyhow::bail!("invalid param") + } + }, + Arg::F64 => quote! { + let #root::wasm_runtime_layer::Value::F64(t) = #x else{ + #root::anyhow::bail!("invalid param") + } + }, + Arg::Resource { ty, nullable } => { + let mut a = quote! { + let #root::wasm_runtime_layer::Value::ExternRef(t) = #x else{ + #root::anyhow::bail!("invalid param") + } + }; + if let Some(r) = ty.as_ref() { + quasiquote!{ + let t = match t{None => None,Some(t) => Some(match t.downcast::<'_,'_, ::std::sync::Arc>,U,E>(ctx){ + Ok(t) => t.clone(), + Err(_) => match t.downcast::<'_,'_, ::std::sync::Arc<#root::Wrapped>,U,E>(ctx){ + Ok(t) => Arc::new(t.clone()), + Err(_) => #root::anyhow::bail!("invalid param") + } + })} + }.to_tokens(&mut a); + } + if !*nullable { + quote! { + let t = match t{ + Some(a) => a, + None => #root::anyhow::bail!("invalid param") + } + } + .to_tokens(&mut a) + } + a + } + }; + quote! { + { + #v;t + } + } +} +pub fn render_new_val(root: &TokenStream, p: &Arg, t: TokenStream) -> TokenStream { + match p { + Arg::I32 => quote! { + #root::wasm_runtime_layer::Value::I32(#t) + }, + Arg::I64 => quote! { + #root::wasm_runtime_layer::Value::I64(#t) + }, + Arg::F32 => quote! { + #root::wasm_runtime_layer::Value::F32(#t) + }, + Arg::F64 => quote! { + #root::wasm_runtime_layer::Value::F64(#t) + }, + Arg::Resource { ty, nullable } => { + let tq = |t:TokenStream|quasiquote! { + { + let t = #t; + #{match ty{ + None => quote! { #root::wasm_runtime_layer::ExternRef::new(ctx,t)}, + Some(_) => quote! { + match t.to_any().downcast_ref::<::std::sync::Arc<#root::Wrapped>>(){ + None => #root::wasm_runtime_layer::ExternRef::new(ctx,t), + Some(t) => #root::wasm_runtime_layer::ExternRef::new(ctx,t.clone()), + } + } + }} + } + }; + if !*nullable { + quasiquote! { + #root::wasm_runtime_layer::Value::ExternRef(Some(#{match ty{ + None => t, + Some(_) => tq(t) + }})) + } + } else { + quasiquote! { + #root::wasm_runtime_layer::Value::ExternRef(#{match ty{ + None => t, + Some(_) => quasiquote! {#t.map(|t|#{tq(quote! {t})})} + }}) + } + } + } + } +}