diff --git a/.gitignore b/.gitignore index 5b8f187..61446f9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ *~ /generated -/target +target +.vscode +*.wat \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index d71e4b9..94434f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.17.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -17,6 +17,41 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "anyhow" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" + +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + +[[package]] +name = "async-trait" +version = "0.1.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "atty" version = "0.2.14" @@ -36,9 +71,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -49,17 +84,63 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.21.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c79fed4cdb43e993fcdadc7e58a09fd0e3e649c4436fa11da71c9f1f3ee7feb9" + +[[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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[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 = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[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.73" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "jobserver", + "libc", +] [[package]] name = "cfg-if" @@ -69,15 +150,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.2.22" +version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "atty", - "bitflags", + "bitflags 1.3.2", "clap_derive", "clap_lex", - "indexmap", + "indexmap 1.9.3", "once_cell", "strsim", "termcolor", @@ -86,15 +167,15 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.2.18" +version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" +checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" dependencies = [ "heck", "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -123,9 +204,9 @@ dependencies = [ [[package]] name = "color-spantrace" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" dependencies = [ "once_cell", "owo-colors", @@ -134,311 +215,1516 @@ dependencies = [ ] [[package]] -name = "eyre" -version = "0.6.8" +name = "colored" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" dependencies = [ - "indenter", - "once_cell", + "lazy_static", + "windows-sys 0.48.0", ] [[package]] -name = "gimli" -version = "0.26.2" +name = "cpp_demangle" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" +dependencies = [ + "cfg-if", +] [[package]] -name = "hashbrown" -version = "0.12.3" +name = "cpufeatures" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] [[package]] -name = "heck" -version = "0.4.0" +name = "cranelift-bforest" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "7c22542c0b95bd3302f7ed6839869c561f2324bac2fd5e7e99f5cfa65fdc8b92" +dependencies = [ + "cranelift-entity", +] [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "cranelift-codegen" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "6b3db903ef2e9c8a4de2ea6db5db052c7857282952f9df604aa55d169e6000d8" dependencies = [ - "libc", + "bumpalo", + "cranelift-bforest", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-control", + "cranelift-entity", + "cranelift-isle", + "gimli", + "hashbrown 0.14.3", + "log", + "regalloc2", + "smallvec", + "target-lexicon", ] [[package]] -name = "indenter" -version = "0.3.3" +name = "cranelift-codegen-meta" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +checksum = "6590feb5a1d6438f974bf6a5ac4dddf69fca14e1f07f3265d880f69e61a94463" +dependencies = [ + "cranelift-codegen-shared", +] [[package]] -name = "indexmap" -version = "1.9.1" +name = "cranelift-codegen-shared" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7239038c56fafe77fddc8788fc8533dd6c474dc5bdc5637216404f41ba807330" + +[[package]] +name = "cranelift-control" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "f7dc9c595341404d381d27a3d950160856b35b402275f0c3990cd1ad683c8053" dependencies = [ - "autocfg", - "hashbrown", + "arbitrary", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "cranelift-entity" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "44e3ee532fc4776c69bcedf7e62f9632cbb3f35776fa9a525cdade3195baa3f7" +dependencies = [ + "serde", + "serde_derive", +] [[package]] -name = "libc" -version = "0.2.133" +name = "cranelift-frontend" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" +checksum = "a612c94d09e653662ec37681dc2d6fd2b9856e6df7147be0afc9aabb0abf19df" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] [[package]] -name = "memchr" -version = "2.5.0" +name = "cranelift-isle" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "85db9830abeb1170b7d29b536ffd55af1d4d26ac8a77570b5d1aca003bf225cc" [[package]] -name = "miniz_oxide" -version = "0.5.4" +name = "cranelift-native" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" +checksum = "301ef0edafeaeda5771a5d2db64ac53e1818ae3111220a185677025fe91db4a1" dependencies = [ - "adler", + "cranelift-codegen", + "libc", + "target-lexicon", ] [[package]] -name = "object" -version = "0.29.0" +name = "cranelift-wasm" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +checksum = "380f0abe8264e4570ac615fc31cef32a3b90a77f7eb97b08331f9dd357b1f500" dependencies = [ - "memchr", + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "itertools", + "log", + "smallvec", + "wasmparser", + "wasmtime-types", ] [[package]] -name = "once_cell" -version = "1.14.0" +name = "crc32fast" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] [[package]] -name = "os_str_bytes" -version = "6.3.0" +name = "crossbeam-deque" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] [[package]] -name = "owo-colors" -version = "3.5.0" +name = "crossbeam-epoch" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] [[package]] -name = "pin-project-lite" -version = "0.2.9" +name = "crossbeam-utils" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] -name = "proc-macro-error" -version = "1.0.4" +name = "crypto-common" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", + "generic-array", + "typenum", ] [[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +name = "debugid" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" dependencies = [ - "proc-macro2", - "quote", - "version_check", + "uuid", ] [[package]] -name = "proc-macro2" -version = "1.0.43" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "unicode-ident", + "block-buffer", + "crypto-common", ] [[package]] -name = "quote" -version = "1.0.21" +name = "directories-next" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" dependencies = [ - "proc-macro2", + "cfg-if", + "dirs-sys-next", ] [[package]] -name = "rustc-demangle" -version = "0.1.21" +name = "dirs-sys-next" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] [[package]] -name = "rwasm" +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "equivalent" version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "clap", - "color-eyre", + "libc", + "windows-sys 0.52.0", ] [[package]] -name = "sharded-slab" -version = "0.1.4" +name = "eyre" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799" dependencies = [ - "lazy_static", + "indenter", + "once_cell", ] [[package]] -name = "strsim" -version = "0.10.0" +name = "fallible-iterator" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] -name = "syn" -version = "1.0.100" +name = "fxhash" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "byteorder", ] [[package]] -name = "termcolor" -version = "1.1.3" +name = "fxprof-processed-profile" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "27d12c0aed7f1e24276a241aadc4cb8ea9f83000f34bc062b7cc2d51e3b0fabd" dependencies = [ - "winapi-util", + "bitflags 2.4.1", + "debugid", + "fxhash", + "serde", + "serde_json", ] [[package]] -name = "textwrap" -version = "0.15.1" +name = "generic-array" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] [[package]] -name = "thread_local" -version = "1.1.4" +name = "getrandom" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ - "once_cell", + "cfg-if", + "libc", + "wasi", ] [[package]] -name = "tracing" -version = "0.1.36" +name = "gimli" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" dependencies = [ - "cfg-if", - "pin-project-lite", - "tracing-core", + "fallible-iterator", + "indexmap 2.1.0", + "stable_deref_trait", ] [[package]] -name = "tracing-core" -version = "0.1.29" +name = "hashbrown" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "once_cell", - "valuable", + "ahash", ] [[package]] -name = "tracing-error" -version = "0.2.0" +name = "hashbrown" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ - "tracing", - "tracing-subscriber", + "ahash", ] [[package]] -name = "tracing-subscriber" -version = "0.3.15" +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" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ - "sharded-slab", - "thread_local", - "tracing-core", + "libc", ] [[package]] -name = "unicode-ident" -version = "1.0.4" +name = "id-arena" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" [[package]] -name = "valuable" -version = "0.1.0" +name = "indenter" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] -name = "version_check" -version = "0.9.4" +name = "indexmap" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] [[package]] -name = "winapi" -version = "0.3.9" +name = "indexmap" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "equivalent", + "hashbrown 0.14.3", + "serde", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "itertools" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] [[package]] -name = "winapi-util" -version = "0.1.5" +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "ittapi" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "6b996fe614c41395cdaedf3cf408a9534851090959d90d54a535f675550b64b1" dependencies = [ - "winapi", + "anyhow", + "ittapi-sys", + "log", ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" +name = "ittapi-sys" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "52f5385394064fa2c886205dba02598013ce83d3e92d33dbdc0c52fe0e7bf4fc" +dependencies = [ + "cc", +] + +[[package]] +name = "jobserver" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +dependencies = [ + "libc", +] + +[[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.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "memfd" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" +dependencies = [ + "rustix", +] + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "crc32fast", + "hashbrown 0.14.3", + "indexmap 2.1.0", + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "os_str_bytes" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pkg-config" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" + +[[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.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +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 = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[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 = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rwasm" +version = "1.0.1" +dependencies = [ + "clap", + "color-eyre", + "colored", + "wasmtime", +] + +[[package]] +name = "ryu" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + +[[package]] +name = "semver" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" + +[[package]] +name = "serde" +version = "1.0.195" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.195" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "serde_json" +version = "1.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[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.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[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.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-lexicon" +version = "0.12.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" + +[[package]] +name = "termcolor" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + +[[package]] +name = "thiserror" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", +] + +[[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-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "uuid" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-encoder" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad2b51884de9c7f4fe2fd1043fccb8dcad4b1e29558146ee57a144d15779f3f" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasmparser" +version = "0.118.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ee9723b928e735d53000dec9eae7b07a60e490c85ab54abb66659fc61bfcd9" +dependencies = [ + "indexmap 2.1.0", + "semver", +] + +[[package]] +name = "wasmtime" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8e539fded2495422ea3c4dfa7beeddba45904eece182cf315294009e1a323bf" +dependencies = [ + "anyhow", + "async-trait", + "bincode", + "bumpalo", + "cfg-if", + "fxprof-processed-profile", + "indexmap 2.1.0", + "libc", + "log", + "object", + "once_cell", + "paste", + "rayon", + "serde", + "serde_derive", + "serde_json", + "target-lexicon", + "wasm-encoder", + "wasmparser", + "wasmtime-cache", + "wasmtime-component-macro", + "wasmtime-cranelift", + "wasmtime-environ", + "wasmtime-fiber", + "wasmtime-jit", + "wasmtime-runtime", + "wat", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "660ba9143e15a2acd921820df221b73aee256bd3ca2d208d73d8adc9587ccbb9" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "wasmtime-cache" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3ce373743892002f9391c6741ef0cb0335b55ec899d874f311222b7e36f4594" +dependencies = [ + "anyhow", + "base64", + "bincode", + "directories-next", + "log", + "rustix", + "serde", + "serde_derive", + "sha2", + "toml", + "windows-sys 0.48.0", + "zstd", +] + +[[package]] +name = "wasmtime-component-macro" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ef32643324e564e1c359e9044daa06cbf90d7e2d6c99a738d17a12959f01a5" +dependencies = [ + "anyhow", + "proc-macro2", + "quote", + "syn 2.0.48", + "wasmtime-component-util", + "wasmtime-wit-bindgen", + "wit-parser", +] + +[[package]] +name = "wasmtime-component-util" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c87d06c18d21a4818f354c00a85f4ebc62b2270961cd022968452b0e4dbed9d" + +[[package]] +name = "wasmtime-cranelift" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d648c8b4064a7911093b02237cd5569f71ca171d3a0a486bf80600b19e1cba2" +dependencies = [ + "anyhow", + "cfg-if", + "cranelift-codegen", + "cranelift-control", + "cranelift-entity", + "cranelift-frontend", + "cranelift-native", + "cranelift-wasm", + "gimli", + "log", + "object", + "target-lexicon", + "thiserror", + "wasmparser", + "wasmtime-cranelift-shared", + "wasmtime-environ", + "wasmtime-versioned-export-macros", +] + +[[package]] +name = "wasmtime-cranelift-shared" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290a89027688782da8ff60b12bb95695494b1874e0d0ba2ba387d23dace6d70c" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-control", + "cranelift-native", + "gimli", + "object", + "target-lexicon", + "wasmtime-environ", +] + +[[package]] +name = "wasmtime-environ" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61eb64fb3e0da883e2df4a13a81d6282e072336e6cb6295021d0f7ab2e352754" +dependencies = [ + "anyhow", + "cranelift-entity", + "gimli", + "indexmap 2.1.0", + "log", + "object", + "serde", + "serde_derive", + "target-lexicon", + "thiserror", + "wasmparser", + "wasmtime-types", +] + +[[package]] +name = "wasmtime-fiber" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecf1d3a838b0956b71ad3f8cb80069a228339775bf02dd35d86a5a68bbe443" +dependencies = [ + "anyhow", + "cc", + "cfg-if", + "rustix", + "wasmtime-asm-macros", + "wasmtime-versioned-export-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-jit" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f485336add49267d8859e8f8084d2d4b9a4b1564496b6f30ba5b168d50c10ceb" +dependencies = [ + "addr2line", + "anyhow", + "bincode", + "cfg-if", + "cpp_demangle", + "gimli", + "ittapi", + "log", + "object", + "rustc-demangle", + "rustix", + "serde", + "serde_derive", + "target-lexicon", + "wasmtime-environ", + "wasmtime-jit-debug", + "wasmtime-jit-icache-coherence", + "wasmtime-runtime", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-jit-debug" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65e119affec40edb2fab9044f188759a00c2df9c3017278d047012a2de1efb4f" +dependencies = [ + "object", + "once_cell", + "rustix", + "wasmtime-versioned-export-macros", +] + +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b6d197fcc34ad32ed440e1f9552fd57d1f377d9699d31dee1b5b457322c1f8a" +dependencies = [ + "cfg-if", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-runtime" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794b2bb19b99ef8322ff0dd9fe1ba7e19c41036dfb260b3f99ecce128c42ff92" +dependencies = [ + "anyhow", + "cc", + "cfg-if", + "indexmap 2.1.0", + "libc", + "log", + "mach", + "memfd", + "memoffset", + "paste", + "psm", + "rustix", + "sptr", + "wasm-encoder", + "wasmtime-asm-macros", + "wasmtime-environ", + "wasmtime-fiber", + "wasmtime-jit-debug", + "wasmtime-versioned-export-macros", + "wasmtime-wmemcheck", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-types" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d995db8bb56f2cd8d2dc0ed5ffab94ffb435283b0fe6747f80f7aab40b2d06a1" +dependencies = [ + "cranelift-entity", + "serde", + "serde_derive", + "thiserror", + "wasmparser", +] + +[[package]] +name = "wasmtime-versioned-export-macros" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55c5565959287c21dd0f4277ae3518dd2ae62679f655ee2dbc4396e19d210db" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "wasmtime-wit-bindgen" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f328b2d4a690270324756e886ed5be3a4da4c00be0eea48253f4595ad068062b" +dependencies = [ + "anyhow", + "heck", + "indexmap 2.1.0", + "wit-parser", +] + +[[package]] +name = "wasmtime-wmemcheck" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67761d8f8c0b3c13a5d34356274b10a40baba67fe9cfabbfc379a8b414e45de2" + +[[package]] +name = "wast" +version = "69.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ee37317321afde358e4d7593745942c48d6d17e0e6e943704de9bbee121e7a" +dependencies = [ + "leb128", + "memchr", + "unicode-width", + "wasm-encoder", +] + +[[package]] +name = "wat" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeb338ee8dee4d4cd05e6426683f21c5087dc7cfc8903e839ccf48d43332da3c" +dependencies = [ + "wast", +] + +[[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-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[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.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "wit-parser" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15df6b7b28ce94b8be39d8df5cb21a08a4f3b9f33b631aedb4aa5776f785ead3" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.1.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.9+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index 4db28f0..790d16a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,11 @@ edition = "2018" [dependencies] clap = { version = "3.2.22", features = ["derive"] } color-eyre = "0.6.2" +colored = "2.1.0" # Speed up `backtrace` even on a debug build. Suggested by `color-eyre`. [profile.dev.package.backtrace] opt-level = 3 + +[dev-dependencies] +wasmtime = "16.0.0" \ No newline at end of file diff --git a/examples/fib.wasm b/examples/fib.wasm new file mode 100755 index 0000000..61a5ec5 Binary files /dev/null and b/examples/fib.wasm differ diff --git a/src/main.rs b/src/main.rs index ef0d8b7..7fd1894 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,6 +34,10 @@ pub struct CmdLineOpts { /// Path to output directory #[clap(default_value = "./generated")] output_directory: std::path::PathBuf, + /// Customize the name of the generated Rust crate. + /// Default: sandboxed- + #[clap(long)] + crate_name: Option, /// Prevent reformatting, for debug purposes #[clap(short, long)] prevent_reformat: bool, @@ -81,13 +85,22 @@ pub struct CmdLineOpts { /// Generate a `no_std` library, limiting usage to `core` and `alloc` #[clap(long)] no_std_library: bool, + /// Instead of returning a vector of return values from indirect function calls, + /// return a fixed-length array of return values, whose length is determined by the + /// maximum number of return values of any function in the module. (Warning: experimental + /// performance impact) + #[clap(long)] + static_func_rets: bool, + /// Generate statically allocated, heapless code (implies --no-std-library + /// and --static-func-rets, requires --fixed-mem-size) + /// (Warning: experimental performance impact) + #[clap(long)] + no_alloc: bool, } -fn main() -> Maybe<()> { +pub fn run_app(mut opts: CmdLineOpts) -> Maybe<()> { color_eyre::install()?; - let mut opts = CmdLineOpts::parse(); - DEBUG_PRINT_LEVEL.store(opts.debug, std::sync::atomic::Ordering::Relaxed); if opts.prevent_extra_mem_for_wrapping && !opts.memory_wrapping { @@ -106,6 +119,13 @@ fn main() -> Maybe<()> { if opts.generate_as_wasi_library { opts.generate_wasi_executable = true; } + if opts.no_alloc { + if opts.fixed_mem_size.is_none() { + return Err(eyre!("Must use --fixed-mem-size when using --no-alloc")); + } + opts.no_std_library = true; + opts.static_func_rets = true; + } let inp = std::fs::read(&opts.input_path)?; println!("Finished reading"); @@ -117,3 +137,7 @@ fn main() -> Maybe<()> { Ok(()) } + +fn main() -> Maybe<()> { + run_app(CmdLineOpts::parse()) +} diff --git a/src/parser.rs b/src/parser.rs index 1ac91eb..0d907ed 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,96 +1,45 @@ +// parser macros yield unused assignments in the last parser +#![allow(dead_code, unused_assignments)] + use crate::wasm::syntax::*; use crate::Maybe; use color_eyre::eyre::eyre; +use colored::Colorize; use std::collections::HashMap; use std::convert::TryInto; type Parsed<'a, T> = crate::Maybe<(&'a [u8], T)>; -macro_rules! trace { - ($($body:tt)*) => { - dbgprintln!(3, $($body)*) +/* + There are two ways to write a parser: + a) + - Write a function that takes a byte array and returns a `Parsed`. + - Use the `run_parser!` macro to run other parsers. + b) + - For simple parsers, use the `generate!` macro. + - Define a function body that returns the parsed type, and the macro will + generate a parser function. + - Use the `run!` macro to run other parsers. +*/ + +macro_rules! run_parser { + ($fn:ident ( $inp:ident ) ) => { + run_parser!($fn($inp,)) }; + ($fn:ident ( $inp:ident, $($arg:expr),* ) ) => {{ + let (inp1, v) = $fn( $inp, $($arg,)*)?; + $inp = inp1; + v + }}; } -macro_rules! with_dollar_sign { - ($($body:tt)*) => { - macro_rules! __with_dollar_sign { $($body)* } - __with_dollar_sign!($); - } -} - -macro_rules! generate { - ($id:ident -> $ty:ty = $body:expr) => { - generate!{$id() -> $ty = $body} - }; - - ($id:ident($($fnarg:ident : $fntyp:ty),*) -> $ty:ty = $body: expr ) => { - fn $id(mut inp: &[u8], $($fnarg : $fntyp,)*) -> Parsed<$ty> { - with_dollar_sign! { - ($d:tt) => { - #[allow(unused_macros)] - macro_rules! run { - ($fn:ident) => { run!($fn()) }; - ($fn:ident ($d($arg:expr),* ) ) => {{ - let (inp1, v) = $fn( inp, $d($arg,)*)?; - inp = inp1; - v - }}; - } - } - } - +/* + utils +*/ - with_dollar_sign! { - ($d:tt) => { - #[allow(unused_macros)] - macro_rules! try_run { - ($fn:ident) => { try_run!($fn()) }; - ($fn:ident ($d($arg:expr),* ) ) => {{ - match $fn( inp, $d($arg,)*) { - Ok((inp1, v)) => { - inp = inp1; - Ok(v) - } - Err(e) => Err(e), - } - }}; - } - } - } - - #[allow(unused_macros)] - macro_rules! dump { - () => {{ - trace!("Remaining: {:#x?}", inp) - }} - } - - #[allow(unused_macros)] - macro_rules! peek_inp { - (@@@length@@@) => {{ - inp.len() - }}; - (..$end:expr) => {{ - inp.get(..$end).ok_or(eyre!("Insufficient data for parsing"))? - }}; - ($pos:expr) => {{ - inp.get($pos).ok_or(eyre!("Insufficient data for parsing"))? - }}; - } - - #[allow(unused_macros)] - macro_rules! inp { - (..$end:expr) => {{ - let e = peek_inp!(..$end); - inp = &inp[$end..]; - e - }}; - } - - let v = $body; - Ok((inp, v)) - } +macro_rules! trace { + ($($body:tt)*) => { + dbgprintln!(3, $($body)*) }; } @@ -100,19 +49,13 @@ macro_rules! err { }} } -macro_rules! run_manual { - ($fn:ident ( $inp:ident, $($arg:expr),* ) ) => {{ - let (inp1, v) = $fn( $inp, $($arg,)*)?; - $inp = inp1; - v - }}; - ($fn:ident ( $inp:ident ) ) => {{ - let (inp1, v) = $fn( $inp )?; - $inp = inp1; - v - }}; +macro_rules! warn { + ($($args:tt)*) => {{ + eprintln!("{}", format_args!("WARNING -- {}", $($args)*).to_string().green()); + }} } +/// Little Endian Base 128 encoding of unsigned ints. Parses `bits` bits into a `u64`. fn leb128_u(mut inp: &[u8], bits: usize) -> Parsed { let n = inp[0] as u64; inp = &inp[1..]; @@ -129,6 +72,7 @@ fn leb128_u(mut inp: &[u8], bits: usize) -> Parsed { } } +/// Little Endian Base 128 encoding of signed ints. Parses `bits` bits into a `i64`. fn leb128_s(mut inp: &[u8], bits: usize) -> Parsed { let n = inp[0] as u64; inp = &inp[1..]; @@ -166,11 +110,121 @@ mod test_leb128 { } } +/* + parser generator +*/ + +/// This is a hack to allow for macros generating new macro definitions making use of +/// repetition arguments, see +/// https://github.com/rust-lang/rust/issues/35853#issuecomment-415993963 +/// An alternative would be to use macro metavariables on nightly. +macro_rules! with_dollar_sign { + ($($body:tt)*) => { + macro_rules! __with_dollar_sign { $($body)* } + __with_dollar_sign!($); + } +} + +/// Generate a parser function. Example: +/// ```ignore +/// generate! { double_peek (n:u32) -> &[u8] = run!(peek(2*n))} +/// ``` +/// expands to +/// ```ignore +/// fn double_peek(mut inp: &[u8], n:u32) -> Parsed<&[u32]> { +/// let v = { +/// let (inp1, v) = peek(inp, 2*n)?; +/// inp = inp1; +/// v +/// }; +/// Ok((inp, v)) +/// } +/// ``` +macro_rules! generate { + ($id:ident -> $ty:ty = $body:expr) => { + generate!{$id() -> $ty = $body} + }; + + ($id:ident($($fnarg:ident : $fntyp:ty),*) -> $ty:ty = $body: expr ) => { + fn $id(mut inp: &[u8], $($fnarg : $fntyp,)*) -> Parsed<$ty> { + + with_dollar_sign! { + ($d:tt) => { + /// Runs a parser. + #[allow(unused_macros)] + macro_rules! run { + ($fn:ident) => { run!($fn()) }; + ($fn:ident ($d($arg:expr),* ) ) => {{ + let (inp1, v) = $fn( inp, $d($arg,)*)?; + inp = inp1; + v + }}; + } + } + } + + + with_dollar_sign! { + ($d:tt) => { + /// Similar to `run!`, but doesn't expect successful parsing. + /// Returns a `Result, E>` instead of `Parsed`. + #[allow(unused_macros)] + macro_rules! try_run { + ($fn:ident) => { try_run!($fn()) }; + ($fn:ident ($d($arg:expr),* ) ) => {{ + match $fn( inp, $d($arg,)*) { + Ok((inp1, v)) => { + inp = inp1; + Ok(v) + }, + Err(e) => Err(e), + } + }}; + } + } + } + + let v = $body; + Ok((inp, v)) + } + }; +} + +/* + Parsers +*/ + +fn peek(inp: &[u8], n: usize) -> Parsed<&[u8]> { + let v = inp.get(..n).ok_or(eyre!("Insufficient data for parsing"))?; + Ok((inp, v)) +} + +#[allow(unused)] // could be useful in the future +fn peek_at(inp: &[u8], pos: usize) -> Parsed<&u8> { + let v = inp.get(pos).ok_or(eyre!("Insufficient data for parsing"))?; + Ok((inp, v)) +} + +fn length(inp: &[u8]) -> Parsed { + Ok((inp, inp.len())) +} + +fn inp(inp: &[u8], n: usize) -> Parsed<&[u8]> { + let v = inp.get(..n).ok_or(eyre!("Insufficient data for parsing"))?; + Ok((&inp[n..], v)) +} + +#[allow(unused)] // could be useful in the future +fn inp_dump(inp: &[u8]) -> Parsed<()> { + trace!("Remaining: {:#x?}", inp); + Ok((inp, ())) +} + generate! {u32 -> u32 = run!(leb128_u(32)) as u32} generate! {i32 -> i32 = run!(leb128_s(32)) as i32} generate! {i64 -> i64 = run!(leb128_s(64)) as i64} -generate! {f32 -> f32 = f32::from_le_bytes(inp![..4].try_into()?)} -generate! {f64 -> f64 = f64::from_le_bytes(inp![..8].try_into()?)} +generate! {f32 -> f32 = f32::from_le_bytes(run!(inp(4)).try_into()?)} +generate! {f64 -> f64 = f64::from_le_bytes(run!(inp(8)).try_into()?)} generate! {s33 -> i64 = run!(leb128_s(33))} @@ -178,15 +232,15 @@ fn vec(mut inp: &[u8], elem: F) -> Parsed> where F: Fn(&[u8]) -> Parsed, { - let len = run_manual!(u32(inp)); + let len = run_parser!(u32(inp)); let l = (0..len) - .map(|_| Ok(run_manual!(elem(inp)))) + .map(|_| Ok(run_parser!(elem(inp)))) .collect::>>()?; Ok((inp, l)) } -generate! {byte -> u8 = inp![..1][0]} +generate! {byte -> u8 = run!(inp(1))[0]} generate! {name -> String = String::from_utf8(run!(vec(byte)))?} @@ -273,7 +327,7 @@ where let mut res = vec![]; while !until.contains(&v) { - res.push(run_manual!(elem(inp))); + res.push(run_parser!(elem(inp))); v = inp[0]; } inp = &inp[1..]; @@ -576,13 +630,13 @@ generate! { memarg -> MemArg = { generate! { expr -> Expr = Expr(run!(vec_until(instr, 0x0b))) } -generate! { typeidx -> TypeIdx = TypeIdx(run!(u32)) } -generate! { funcidx -> FuncIdx = FuncIdx(run!(u32)) } -generate! { tableidx -> TableIdx = TableIdx(run!(u32)) } -generate! { memidx -> MemIdx = MemIdx(run!(u32)) } +generate! { typeidx -> TypeIdx = TypeIdx(run!(u32)) } +generate! { funcidx -> FuncIdx = FuncIdx(run!(u32)) } +generate! { tableidx -> TableIdx = TableIdx(run!(u32)) } +generate! { memidx -> MemIdx = MemIdx(run!(u32)) } generate! { globalidx -> GlobalIdx = GlobalIdx(run!(u32)) } -generate! { localidx -> LocalIdx = LocalIdx(run!(u32)) } -generate! { labelidx -> LabelIdx = LabelIdx(run!(u32)) } +generate! { localidx -> LocalIdx = LocalIdx(run!(u32)) } +generate! { labelidx -> LabelIdx = LabelIdx(run!(u32)) } macro_rules! section { ($n:literal, $name:ident -> Option<$ty:ty> = $body:expr) => { @@ -610,7 +664,7 @@ macro_rules! section { err!("Insufficient bytes for section {}", $n) } let mut inp_inner = &inp[..size]; - let v = run_manual!(aux(inp_inner)); + let v = run_parser!(aux(inp_inner)); if inp_inner.len() != 0 { err!( "Unexpected {} bytes remain for section {:#x}", @@ -626,13 +680,13 @@ macro_rules! section { generate! { customsec -> (String, &[u8]) = { run!(expect_byte(0)); let size = run!(u32) as usize; - let mut inp = inp![..size]; - let name = run_manual!(name(inp)); + let mut inp = run!(inp(size)); + let name = run_parser!(name(inp)); (name, inp) }} generate! { customsecs -> Vec<(String, &[u8])> = { let mut ret = vec![]; - while peek_inp!(@@@length@@@) != 0 && peek_inp![..1][0] == 0 { + while run!(length) != 0 && run!(peek(1))[0] == 0 { ret.push(run!(customsec)); } ret @@ -689,7 +743,7 @@ generate! { exportdesc -> ExportDesc = { }} section! { 8, startsec -> Option = { - if peek_inp!(@@@length@@@) == 0 { + if run!(length) == 0 { None } else { Some(run!(start)) @@ -750,7 +804,18 @@ generate! { names -> Names = { functions: HashMap::new(), locals: HashMap::new(), }; - let name_type = run!(u32); // module = 0, function = 1, local = 2 + + /* + As per the 1.0 spec, the type field is only one byte, so I think run!(u32) is + technically wrong here. It should always work because the type can only be + 0, 1, or 2, and since integers are leb encoded, reading the first 32 bit int + will only read the first byte. Still, I think it's confusing, we should only + read one byte. + */ + + // let name_type = run!(u32); // module = 0, function = 1, local = 2 + let name_type = run!(byte) as u32; + if name_type != 1 { // We don't support non-function names just yet. Might add it // in the future. @@ -758,9 +823,9 @@ generate! { names -> Names = { } let subsection_size = run!(u32); if subsection_size > 0 { - let mut inp = inp![..subsection_size as usize]; - names.functions = run_manual!(vec(inp, function_name)).into_iter().collect(); - if inp.len() != 0 { + let mut inp_ = run!(inp(subsection_size as usize)); + names.functions = run_parser!(vec(inp_, function_name)).into_iter().collect(); + if inp_.len() != 0 { err!("Unused bytes in custom name section") } } @@ -781,53 +846,51 @@ generate! { module -> Module = { let mut custom = vec![]; - // The sections - custom.append(&mut run!(customsecs)); - let types = run!(typesec); - trace!("types {}", types.len()); - custom.append(&mut run!(customsecs)); - let imports = run!(importsec); - trace!("imports {}", imports.len()); - custom.append(&mut run!(customsecs)); - let funcsec = run!(funcsec); - trace!("funcsec {}", funcsec.len()); - custom.append(&mut run!(customsecs)); - let tables = run!(tablesec); - trace!("tables {}", tables.len()); - custom.append(&mut run!(customsecs)); - let mems = run!(memsec); - trace!("mems {}", mems.len()); - custom.append(&mut run!(customsecs)); - let globals = run!(globalsec); - trace!("globals {}", globals.len()); - custom.append(&mut run!(customsecs)); - let exports = run!(exportsec); - trace!("exports {}", exports.len()); - custom.append(&mut run!(customsecs)); - let start = run!(startsec); - trace!("start {}", start.is_some()); - custom.append(&mut run!(customsecs)); - let elem = run!(elemsec); - trace!("elem {}", elem.len()); - custom.append(&mut run!(customsecs)); - let codesec = run!(codesec); - trace!("codesec {}", codesec.len()); - custom.append(&mut run!(customsecs)); - let data = run!(datasec); - trace!("data {}", data.len()); - custom.append(&mut run!(customsecs)); + // declare sections + let ( + mut types, mut imports, mut functions, mut tables, + mut mems, mut globals, mut exports, mut start, + mut elem, mut code, mut data + ) = ( + vec![], vec![], vec![], vec![], + vec![], vec![], vec![], None, + vec![], vec![], vec![] + ); + + // parse sections + loop { + if run!(length) == 0 { + break; + } + match run!(peek(1)) { + &[0u8] => custom.append(&mut run!(customsecs)), + &[1u8] => types = run!(typesec), + &[2u8] => imports = run!(importsec), + &[3u8] => functions = run!(funcsec), + &[4u8] => tables = run!(tablesec), + &[5u8] => mems = run!(memsec), + &[6u8] => globals = run!(globalsec), + &[7u8] => exports = run!(exportsec), + &[8u8] => start = run!(startsec), + &[9u8] => elem = run!(elemsec), + &[10u8] => code = run!(codesec), + &[11u8] => data = run!(datasec), + &[b] => err!("Unknown section {:#x}", b), + _ => unreachable!(), + } + } let custom: HashMap = custom.into_iter().collect(); let names = { if let Some(data) = custom.get("name") { let mut data: &[u8] = data; - let names = run_manual!(names(data)); - if data.len() == 0 { - names - } else { - err!("Unused bytes in the custom name section") + let names = run_parser!(names(data)); + // below check seems broken, see https://github.com/secure-foundations/rWasm/issues/2 + if data.len() != 0 { + warn!("Unused bytes in the custom name section; ingoring") } + names } else { Names { module: None, @@ -845,9 +908,9 @@ generate! { module -> Module = { // per the spec. So why are they kept separated? Anyways, we // simply zip them together and wrap them into the `Func` that we // need it to be. - if funcsec.len() != codesec.len() { + if functions.len() != code.len() { err!("funcsec and codesec are not the same length -- {} vs {}", - funcsec.len(), codesec.len()) + functions.len(), code.len()) } let imported_funcs = imports.iter().filter_map(|i| { @@ -865,8 +928,8 @@ generate! { module -> Module = { } }).collect::>(); - let internal_funcs = funcsec.into_iter() - .zip(codesec.into_iter()) + let internal_funcs = functions.into_iter() + .zip(code.into_iter()) .map(|(typ, (locals, body))| Func { typ, internals: FuncInternals::LocalFunc { locals, body } diff --git a/src/printer.rs b/src/printer.rs index 42b01ca..3bb775d 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -3,6 +3,32 @@ use crate::CmdLineOpts; use crate::Maybe; use color_eyre::eyre::eyre; +fn mem_type( + m: &wasm::syntax::Module, + opts: &CmdLineOpts +) -> String { + let ext_mem = mem_imported(m); + let fixed_size = opts.fixed_mem_size.is_some(); + + match (ext_mem, fixed_size) { + (true, true) => format!("&'a mut [u8]"), + (true, false) => format!("&'a mut Vec"), + (false, true) => format!("[u8; {}]", get_memory_backing_size(m, opts).unwrap().0), + (false, false) => format!("Vec"), + } +} + +fn mem_imported( + m: &wasm::syntax::Module, +) -> bool { + m.imports.iter().any(|i| { + match &i.desc { + wasm::syntax::ImportDesc::Mem(_) => true, + _ => false, + } + }) +} + fn print_iunop( bs: &wasm::syntax::BitSize, o: &wasm::syntax::instructions::intop::UnOp, @@ -541,19 +567,19 @@ fn print_instr( let dynamic_offset = pop!(i32); let dst = push!(); let ea = format!("({} + {})", dynamic_offset, mem.memarg.offset); - let self_mem = if opts.fixed_mem_size.is_some() { + let self_mem = if opts.fixed_mem_size.is_some() && !opts.no_alloc { "*self.memory" } else { "self.memory" }; let mem_reader = match &mem.extend { - None => format!("read_mem_{}(&{}, {} as usize)", mem.typ, self_mem, ea), + None => format!("read_mem_{}({}.as_ref(), {} as usize)", mem.typ, self_mem, ea), Some((n, sx)) => { if mem.typ == wasm::syntax::ValType::I32 || mem.typ == wasm::syntax::ValType::I64 { format!( - "read_mem_{}{}(&{}, {} as usize).and_then(|x| Some(x as {}))", + "read_mem_{}{}({}.as_ref(), {} as usize).and_then(|x| Some(x as {}))", sx, n, self_mem, ea, mem.typ ) } else { @@ -615,14 +641,14 @@ fn print_instr( } else { "".into() }; - let self_mem = if opts.fixed_mem_size.is_some() { + let self_mem = if opts.fixed_mem_size.is_some() && !opts.no_alloc { "*self.memory" } else { "self.memory" }; match &mem.bitwidth { None => Ok(format!( - "{}write_mem_{}(&mut {}, {} as usize, {})?;", + "{}write_mem_{}({}.as_mut(), {} as usize, {})?;", mem_trace, mem.typ, self_mem, ea, src )), Some(n) => { @@ -630,7 +656,7 @@ fn print_instr( || mem.typ == wasm::syntax::ValType::I64 { Ok(format!( - "{}write_mem_u{}(&mut {}, {} as usize, {} as u{})?;", + "{}write_mem_u{}({}.as_mut(), {} as usize, {} as u{})?;", mem_trace, n, self_mem, ea, src, n )) } else { @@ -1357,7 +1383,7 @@ fn print_function( // the whole process to exit at this point. result += "std::process::exit(arg_0)"; } else { - let self_mem = if opts.fixed_mem_size.is_some() { + let self_mem = if opts.fixed_mem_size.is_some() && !opts.no_alloc { "*self.memory" } else { "self.memory" @@ -1404,7 +1430,7 @@ fn print_global_initializer(g: &wasm::syntax::Global) -> Maybe { ))?; } if let wasm::syntax::Instr::Const(c) = &g.init.0[0] { - Ok(c.to_string()) + Ok(c.to_variant_string()) } else { Err(eyre!( "Currently unsupported expression for global initialization" @@ -1412,7 +1438,11 @@ fn print_global_initializer(g: &wasm::syntax::Global) -> Maybe { } } -fn print_elem(self_name: &str, e: &wasm::syntax::Elem) -> Maybe { +fn print_elem( + self_name: &str, + e: &wasm::syntax::Elem, + opts: &CmdLineOpts, +) -> Maybe { if e.table.0 != 0 { return Err(eyre!("Current version of WASM supports only 1 table"))?; } @@ -1427,13 +1457,17 @@ fn print_elem(self_name: &str, e: &wasm::syntax::Elem) -> Maybe { return Err(eyre!("Invalid floating offset"))?; } }; - let setup = format!( - "if {}.indirect_call_table.len() < {} {{ {}.indirect_call_table.resize({}, None) }}", - self_name, - offset + e.init.len(), - self_name, - offset + e.init.len(), - ); + let setup = if !opts.no_alloc { + format!( + "if {}.indirect_call_table.len() < {} {{ {}.indirect_call_table.resize({}, None) }}", + self_name, + offset + e.init.len(), + self_name, + offset + e.init.len(), + ) + } else { + "".into() + }; let insertions = e .init .iter() @@ -1603,7 +1637,7 @@ fn print_inline_indirect_call( )) } -fn print_indirect_call_dispatch(m: &wasm::syntax::Module) -> Maybe { +fn print_indirect_call_dispatch(m: &wasm::syntax::Module, opts: &CmdLineOpts) -> Maybe { let targets = m .funcs .iter() @@ -1629,7 +1663,8 @@ fn print_indirect_call_dispatch(m: &wasm::syntax::Module) -> Maybe { .map(|(i, _t)| format!("a{}", i)) .collect::>() .join(", "); - let rets = match typ.to.0.len() { + let num_rets = typ.to.0.len(); + let rets = match num_rets { 0 => "".into(), 1 => "TaggedVal::from(rets)".into(), _ => typ @@ -1646,6 +1681,11 @@ fn print_indirect_call_dispatch(m: &wasm::syntax::Module) -> Maybe { } else { "let rets = " }; + let ret = if !opts.static_func_rets { + format!("vec![{}]", rets) + } else { + format!("IndirectFuncRet::Ret{}([{}])", num_rets, rets) + }; Ok(format!( "{} => {{ if args.len() != {} {{ @@ -1653,7 +1693,7 @@ fn print_indirect_call_dispatch(m: &wasm::syntax::Module) -> Maybe { }} {} {}self.func_{}({})?; - Some(vec![{}]) + Some({}) }}", i, typ.from.0.len(), @@ -1661,24 +1701,32 @@ fn print_indirect_call_dispatch(m: &wasm::syntax::Module) -> Maybe { store_rets, i, args, - rets, + ret, )) }) .collect::>>()? .join("\n"); Ok(format!( - "impl WasmModule {{ + "impl WasmModule{lifetime} {{ #[allow(dead_code)] fn indirect_call(&mut self, idx: usize, args: &[TaggedVal]) -> - Option> {{ + Option<{}> {{ let call_target = (*self.indirect_call_table.get(idx)?)?; match call_target {{ {} _ => None, }} }} - }}", - targets + }}", + { + if !opts.static_func_rets { + "Vec" + } else { + "IndirectFuncRet" + } + }, + targets, + lifetime = if !mem_imported(m) { "" } else { "<'_>" }, )) } @@ -1737,7 +1785,9 @@ fn print_type_based_indirect_call_dispatch(m: &wasm::syntax::Module) -> Maybe>() .join("\n"); - Ok(format!("impl WasmModule {{ {} }}", dispatchers)) + let lifetime = if !mem_imported(m) { "" } else { "<'_>" }; + + Ok(format!("impl WasmModule{lifetime} {{ {} }}", dispatchers)) } fn is_snake_case(s: &str) -> bool { @@ -1784,7 +1834,7 @@ fn print_export( format!("{}", e.name) }; Ok(format!( - "impl WasmModule {{ + "impl WasmModule{lifetime} {{ {}pub fn {}{} {{ self.func_{}({}) }} @@ -1806,6 +1856,7 @@ fn print_export( .map(|i| format!("arg_{}", i)) .collect::>() .join(", "), + lifetime = if !mem_imported(m) { "" } else { "<'_>" }, )) } wasm::syntax::ExportDesc::Table(_tbl_idx) => { @@ -1813,22 +1864,24 @@ fn print_export( } wasm::syntax::ExportDesc::Mem(mem_idx) => { assert_eq!(mem_idx.0, 0); + let lifetime = if !mem_imported(m) { "" } else { "<'_>" }; if opts.generate_as_wasi_library { - Ok("impl WasmModule { + Ok(format!("impl WasmModule{lifetime} {{ #[allow(dead_code)] - pub fn get_memory(&mut self) -> &mut [u8] { + pub fn get_memory(&mut self) -> &mut [u8] {{ &mut self.memory - } - }" - .to_string()) + }} + }}")) } else { - Ok("impl WasmModule { + Ok(format!("impl WasmModule{lifetime} {{ #[allow(dead_code)] - pub fn get_memory(&mut self) -> *mut u8 { + pub fn get_memory(&mut self) -> *mut u8 {{ self.memory.as_mut_ptr() - } - }" - .to_string()) + }} + pub fn get_memory_size(&self) -> usize {{ + self.memory.len() + }} + }}")) } } wasm::syntax::ExportDesc::Global(glb_idx) => { @@ -1844,8 +1897,9 @@ fn print_export( .get(glb_idx.0 as usize) .ok_or(eyre!("Invalid global for export"))? .typ; + let lifetime = if !mem_imported(m) { "" } else { "<'_>" }; let getter = format!( - "impl WasmModule {{ + "impl WasmModule{lifetime} {{ {}pub fn get_{}(&self) -> Option<{}> {{ self.globals[{}].try_as_{}() }} @@ -1853,7 +1907,7 @@ fn print_export( non_snake_case_suppression, e.name, typ, glb_idx.0, typ ); let setter = format!( - "impl WasmModule {{ + "impl WasmModule{lifetime} {{ {}pub fn set_{}(&mut self, v: {}) {{ self.globals[{}] = TaggedVal::from(v); }} @@ -1870,11 +1924,22 @@ fn print_export( fn print_cargo_toml(opts: &CmdLineOpts) -> Maybe<()> { let cargo_toml_path = opts.output_directory.join("Cargo.toml"); - let package_name = opts - .input_path - .file_stem() - .and_then(|n| n.to_str()) - .unwrap_or("wasmmodule".into()); + if cargo_toml_path.exists() { + println!( + "WARNING: Cargo.toml already exists at {}. \ + Not overwriting it.", + cargo_toml_path.display() + ); + return Ok(()); + } + let package_name = match &opts.crate_name { + Some(n) => n.clone(), + None => "sandboxed-".to_owned() + opts + .input_path + .file_stem() + .and_then(|n| n.to_str()) + .unwrap_or("wasmmodule".into()) + }; let dependencies = if opts.generate_wasi_executable { "\ wasi-common = \"0.20.0\"\n\ @@ -1888,7 +1953,7 @@ fn print_cargo_toml(opts: &CmdLineOpts) -> Maybe<()> { format!( r#" [package] -name = "sandboxed-{name}" +name = "{name}" version = "{version}" authors = ["generated-by-{generator}-{version}"] edition = "2018" @@ -1922,7 +1987,7 @@ fn get_memory_backing_size( if size < m { return Err(eyre!("Module requires at least {} blocks of memory", m)); } - } else { + } else if size != 0 { return Err(eyre!("Module does not use any memory")); } if let Some(m) = max_allowed_blocks { @@ -1963,21 +2028,86 @@ fn print_generated_code_prefix(m: &wasm::syntax::Module, opts: &CmdLineOpts) -> } else { "" }; + // If we need to avoid alloc dependency, we need to generate + // arrays for the return values of functions (can't use `Vec`). + let static_function_return_def = if opts.static_func_rets { + // Find the maximum number of return values of all functions + let max_rets = m + .funcs + .iter() + .map(|f| { + let ftyp = m.types.get(f.typ.0 as usize).ok_or( + eyre!("Invalid type index {} for function", f.typ.0), + )?; + Ok(ftyp.to.0.len()) + }) + .collect::>>()? + .into_iter() + .max().unwrap_or(0); + let template = include_str!("../templates-for-generation/static_func_returns.rs"); + template.replace( + "<>", + &(0..=max_rets) + .map(|i| format!("Ret{}([TaggedVal; {}])", i, i)) + .collect::>() + .join(",\n") + ) + .replace( + "<>", + &(0..=max_rets) + .map(|i| format!("Ret{}(_) => {}", i, i)) + .collect::>() + .join(",\n") + ) + .replace( + "<>", + &(0..=max_rets) + .map(|i| format!("Ret{}(v) => &v[i]", i)) + .collect::>() + .join(",\n") + ) + .replace( + "<>", + &(0..=max_rets) + .map(|i| format!("Ret{}(v) => &mut v[i]", i)) + .collect::>() + .join(",\n") + ) + } else { + // Otherwise, we can use `Vec` for the return values of functions + "".into() + }; let wasm_module = format!( "#[allow(dead_code)] - pub struct WasmModule {{ + pub struct WasmModule{lifetime} {{ {memory}, - globals: Vec, - indirect_call_table: Vec>, + {globals}, + {indirect_call_table}, {wasi_context} - }}", - memory = if opts.fixed_mem_size.is_some() { + }}", + lifetime = { + if !mem_imported(m) { + "" + } else { + "<'a>" + } + }, + memory = format!("pub memory: {}", mem_type(m, opts)), + globals = if opts.no_alloc { format!( - "memory: Box<[u8; {}]>, memory_size_to_vm: usize", - get_memory_backing_size(m, opts)?.0 + "globals: [TaggedVal; {}]", + m.globals.len() ) } else { - "memory: Vec".to_string() + "globals: Vec".to_string() + }, + indirect_call_table = if !opts.no_alloc { + "indirect_call_table: Vec>".into() + } else { + format!( + "indirect_call_table: [Option; {}]", + m.funcs.len() + ) }, wasi_context = if opts.generate_wasi_executable { "context: wasi_common::WasiCtx," @@ -2025,17 +2155,21 @@ fn print_generated_code_prefix(m: &wasm::syntax::Module, opts: &CmdLineOpts) -> "{module_prefix}{no_std}\n\n\ {imports}\n\n\ {tagged_value_definitions}\n\n\ + {static_function_return_def} {wasm_module}\n\n\ {memory_accessors}\n", module_prefix = module_prefix, no_std = no_std, - imports = if opts.no_std_library { + imports = if opts.no_alloc { + include_str!("../templates-for-generation/imports_no_alloc.rs") + } else if opts.no_std_library { include_str!("../templates-for-generation/imports_no_std.rs") } else { include_str!("../templates-for-generation/imports.rs") }, tagged_value_definitions = include_str!("../templates-for-generation/tagged_value_definitions.rs"), + static_function_return_def = static_function_return_def, wasm_module = wasm_module, memory_accessors = memory_accessors, )) @@ -2058,31 +2192,50 @@ pub fn print_module(m: &wasm::syntax::Module, opts: &CmdLineOpts) -> Maybe<()> { let mut generated: String = print_generated_code_prefix(m, opts)?; - let (mem_size, mem_size_to_vm) = get_memory_backing_size(m, opts)?; + let extern_mem_arg = if mem_imported(m) { + format!("mem_buf: {}", mem_type(m, opts)) + } else { + "".into() + }; + let memory_init = if mem_imported(m) { + "memory: mem_buf".into() + } else { + let (mem_size, _) = get_memory_backing_size(m, opts)?; + if opts.fixed_mem_size.is_some() { + format!("memory: [0u8; {}]", mem_size) + } else { + format!("memory: vec![0u8; {}]", mem_size) + } + }; - let memory_init = if opts.fixed_mem_size.is_some() { - format!( - "memory: Box::new([0u8; {}]), memory_size_to_vm: {}", - mem_size, - mem_size_to_vm.unwrap() - ) + let globals_init = if !opts.no_alloc { + "globals: vec![]".into() } else { - format!("memory: vec![0u8; {}]", mem_size) + format!("globals: [TaggedVal::Undefined; {}]", globals.len()) }; + let indirect_call_table_init = if !opts.no_alloc { + "indirect_call_table: vec![]".into() + } else { + format!("indirect_call_table: [None; {}]", m.funcs.len()) + }; + + let lifetime = if !mem_imported(m) { "" } else { "<'a>" }; + let lifetime_elided = if !mem_imported(m) { "" } else { "<'_>" }; + // Print the module initializer generated += "\n"; generated += &format!( - "impl WasmModule {{ + "impl{lifetime} WasmModule{lifetime} {{ #[allow(unused_mut)] - pub fn new() -> Self {{ + pub fn new({extern_mem_arg}) -> Self {{ let mut m = WasmModule {{ {memory_init}, - globals: vec![], - indirect_call_table: vec![], + {globals_init}, + {indirect_call_table_init}, {context} \ }}; - m.globals.resize_with({globals_size}, Default::default); + {globals_resize} {printed_globals} {printed_elems} {printed_data} @@ -2096,12 +2249,22 @@ pub fn print_module(m: &wasm::syntax::Module, opts: &CmdLineOpts) -> Maybe<()> { "" }, memory_init = memory_init, - globals_size = globals.len(), + globals_init = globals_init, + globals_resize = { + if !opts.no_alloc { + format!( + "m.globals.resize_with({globals_size}, Default::default);", + globals_size = globals.len() + ) + } else { + "".into() + } + }, printed_globals = globals .iter() .enumerate() .map(|(i, g)| Ok(format!( - "m.globals[{}] = TaggedVal::from({});", + "m.globals[{}] = {};", i, print_global_initializer(g)? ))) @@ -2109,7 +2272,7 @@ pub fn print_module(m: &wasm::syntax::Module, opts: &CmdLineOpts) -> Maybe<()> { .join("\n"), printed_elems = elem .iter() - .map(|e| print_elem("m", e)) + .map(|e| print_elem("m", e, opts)) .collect::>>()? .join("\n"), printed_data = data @@ -2122,7 +2285,7 @@ pub fn print_module(m: &wasm::syntax::Module, opts: &CmdLineOpts) -> Maybe<()> { // Print the functions generated += "\n"; - generated += "impl WasmModule {\n"; + generated += &format!("impl WasmModule{lifetime_elided} {{\n"); for (i, _f) in funcs.iter().enumerate() { generated += &print_function(&m, wasm::syntax::FuncIdx(i as u32), opts)?; } @@ -2134,7 +2297,7 @@ pub fn print_module(m: &wasm::syntax::Module, opts: &CmdLineOpts) -> Maybe<()> { if opts.type_based_indirect_calls { generated += &print_type_based_indirect_call_dispatch(m)?; } else { - generated += &print_indirect_call_dispatch(m)?; + generated += &print_indirect_call_dispatch(m, opts)?; } generated += "\n"; dbgprintln!(0, "Generated CallIndirect redirector"); diff --git a/src/wasm.rs b/src/wasm.rs index b03c314..c8ac257 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -186,6 +186,22 @@ pub mod syntax { } } + impl Const { + /// Convert to a string and include the variant name. + /// Example: `Const::I32(42).to_variant_str()` returns `"I32(42i32)"` + /// whereas `Const::I32(42).to_string()` returns `"42i32"`. + pub fn to_variant_string(&self) -> String { + use Const::*; + let variant_str: String = match self { + I32(_) => "I32".into(), + I64(_) => "I64".into(), + F32(_) => "F32".into(), + F64(_) => "F64".into(), + }; + format!("{}({})", variant_str, self.to_string()) + } + } + #[derive(Debug)] pub enum BitSize { B32, diff --git a/templates-for-generation/imports_no_alloc.rs b/templates-for-generation/imports_no_alloc.rs new file mode 100644 index 0000000..00f0b37 --- /dev/null +++ b/templates-for-generation/imports_no_alloc.rs @@ -0,0 +1,3 @@ +use core::convert::TryInto; +use core::ops::Index; +use core::ops::IndexMut; \ No newline at end of file diff --git a/templates-for-generation/static_func_returns.rs b/templates-for-generation/static_func_returns.rs new file mode 100644 index 0000000..ac629c3 --- /dev/null +++ b/templates-for-generation/static_func_returns.rs @@ -0,0 +1,37 @@ +/// A common heapless return type for indirect calls. +/// Notice wasm functions have multi-returns. In order to +/// avoid heap allocation, call_indirect() returns this type +/// instead of Vec. +#[derive(Copy, Clone, Debug)] +enum IndirectFuncRet { + <> +} + +impl IndirectFuncRet { + #[allow(dead_code)] + fn len(&self) -> usize { + use IndirectFuncRet::*; + match self { + <> + } + } +} + +impl Index for IndirectFuncRet { + type Output = TaggedVal; + fn index<'a>(&'a self, i: usize) -> &'a TaggedVal { + use IndirectFuncRet::*; + match self { + <> + } + } +} + +impl IndexMut for IndirectFuncRet { + fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut TaggedVal { + use IndirectFuncRet::*; + match self { + <> + } + } +} diff --git a/tests/generated-wrapper/Cargo.toml b/tests/generated-wrapper/Cargo.toml new file mode 100644 index 0000000..02c3e78 --- /dev/null +++ b/tests/generated-wrapper/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "generated-wrapper" +version = "0.1.0" +edition = "2021" + +[dependencies] +sandbox-generated = { path = "../../generated" } \ No newline at end of file diff --git a/tests/generated-wrapper/src/main.rs b/tests/generated-wrapper/src/main.rs new file mode 100644 index 0000000..5a12e4d --- /dev/null +++ b/tests/generated-wrapper/src/main.rs @@ -0,0 +1,6 @@ +use sandbox_generated::WasmModule; + +fn main() { + let mut module = WasmModule::new(); + println!("{}", module.run(12).unwrap_or(-1)); +} diff --git a/tests/test.rs b/tests/test.rs new file mode 100644 index 0000000..16f9674 --- /dev/null +++ b/tests/test.rs @@ -0,0 +1,84 @@ +use std::path::Path; +use std::process::Command; +use wasmtime::{ + Engine, + Module, + Store, + Instance, +}; + +fn print_output(output: &std::process::Output) { + let stderr = String::from_utf8(output.stderr.clone()).unwrap(); + let stdout = String::from_utf8(output.stdout.clone()).unwrap(); + println!("\nSTDERR:\n\n{}", stderr); + println!("\nSTDOUT:\n\n{}", stdout); +} + +/// Compiles a wasm module with rWasm using the given arguments, then runs it +/// using a small wrapper crate, and compares the result with the result of +/// running the original wasm module with wasmtime. +/// The module must export a `run` function of type `i32 -> i32`. +fn run_test(path: &Path, args: &[String]) { + + // remove ./generated + let _ = Command::new("rm") + .arg("-r") + .arg("./generated") + .output() + .expect("Failed to remove ./generated"); + + // transpile with rWasm + let output = Command::new("cargo") + .arg("run") + .arg("--") + .arg(path) + .arg("./generated") // TODO why does it not work without this? + .arg("--crate-name") + .arg("sandbox-generated") + .args(args) + .output() + .expect("Failed to transpile"); + print_output(&output); + assert!(output.status.success()); + + // run the wasm module + let output = Command::new("cargo") + .arg("run") + .current_dir(Path::new("tests/generated-wrapper")) + .output() + .expect("Failed to build generated Rust crate"); + print_output(&output); + assert!(output.status.success()); + + // extract the result + let res1 = String::from_utf8(output.stdout.clone()) + .unwrap() + .trim() + .parse::() + .unwrap(); + + // run the original wasm module with wasmtime + let engine = Engine::default(); + let mut store = Store::new(&engine, ()); + let module = Module::from_file(store.engine(), path).unwrap(); + let instance = Instance::new(&mut store, &module, &[]).unwrap(); + let run = instance.get_typed_func::(&mut store, "run").unwrap(); + let res2 = run.call(&mut store, 12).unwrap(); + + assert_eq!(res1, res2); +} + +#[test] +fn fibonacci() { + let p = Path::new("examples/fib.wasm"); + run_test(&p, &[]); + run_test(&p, &[ + "--fixed-mem-size".to_string(), + "16".to_string(), + ]); + run_test(&p, &[ + "--fixed-mem-size".to_string(), + "32".to_string(), + "--no-alloc".to_string(), + ]); +} \ No newline at end of file