diff options
| -rw-r--r-- | Cargo.lock | 327 | ||||
| -rw-r--r-- | crates/cli/Cargo.toml | 4 | ||||
| -rw-r--r-- | crates/cli/bin.rs | 37 | ||||
| -rw-r--r-- | crates/cli/util.rs | 13 | ||||
| -rw-r--r-- | crates/parser/Cargo.toml | 2 | ||||
| -rw-r--r-- | crates/parser/src/conversion.rs | 178 | ||||
| -rw-r--r-- | crates/parser/src/error.rs | 1 | ||||
| -rw-r--r-- | crates/parser/src/lib.rs | 92 | ||||
| -rw-r--r-- | crates/parser/src/module.rs | 91 | ||||
| -rw-r--r-- | crates/tinywasm/Cargo.toml | 2 | ||||
| -rw-r--r-- | crates/tinywasm/src/lib.rs | 27 | ||||
| -rw-r--r-- | crates/tinywasm/src/module/reader.rs | 2 | ||||
| -rw-r--r-- | crates/tinywasm/src/naive/mod.rs | 108 | ||||
| -rw-r--r-- | crates/tinywasm/src/naive/module.rs | 92 | ||||
| -rw-r--r-- | crates/types/Cargo.toml | 2 | ||||
| -rw-r--r-- | crates/types/src/instructions.rs | 6 | ||||
| -rw-r--r-- | crates/types/src/lib.rs | 7 |
17 files changed, 562 insertions, 429 deletions
@@ -18,6 +18,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] name = "argh" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -64,6 +73,12 @@ dependencies = [ ] [[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -106,6 +121,29 @@ dependencies = [ ] [[package]] +name = "env_logger" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] name = "eyre" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -122,6 +160,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] name = "indenter" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -134,6 +184,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" [[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -146,6 +207,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[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" @@ -167,16 +234,6 @@ dependencies = [ ] [[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] name = "object" version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -192,12 +249,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] name = "owo-colors" version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -210,6 +261,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] +name = "pretty_env_logger" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" +dependencies = [ + "env_logger", + "log", +] + +[[package]] name = "proc-macro2" version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -248,6 +309,35 @@ dependencies = [ ] [[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] name = "rkyv" version = "0.7.42" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -276,6 +366,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] +name = "rustix" +version = "0.38.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] name = "seahash" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -311,12 +414,6 @@ dependencies = [ ] [[package]] -name = "smallvec" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" - -[[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -339,6 +436,15 @@ dependencies = [ ] [[package]] +name = "termcolor" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +dependencies = [ + "winapi-util", +] + +[[package]] name = "thread_local" version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -352,9 +458,9 @@ dependencies = [ name = "tinywasm" version = "0.0.0" dependencies = [ + "log", "tinywasm-parser", "tinywasm-types", - "tracing", "wasmparser-nostd", ] @@ -364,17 +470,17 @@ version = "0.0.0" dependencies = [ "argh", "color-eyre", + "log", + "pretty_env_logger", "tinywasm", - "tracing", - "tracing-subscriber", ] [[package]] name = "tinywasm-parser" version = "0.0.0" dependencies = [ + "log", "tinywasm-types", - "tracing", "wasmparser-nostd", ] @@ -382,8 +488,8 @@ dependencies = [ name = "tinywasm-types" version = "0.0.0" dependencies = [ + "log", "rkyv", - "tracing", ] [[package]] @@ -393,22 +499,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", - "tracing-attributes", "tracing-core", ] [[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] name = "tracing-core" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -429,28 +523,14 @@ dependencies = [ ] [[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] name = "tracing-subscriber" version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ - "nu-ansi-term", "sharded-slab", - "smallvec", "thread_local", "tracing-core", - "tracing-log", ] [[package]] @@ -491,7 +571,148 @@ 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" diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index bfe0391..783ead2 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -13,5 +13,5 @@ path="bin.rs" tinywasm={path="../tinywasm"} argh="0.1" color-eyre="0.6" -tracing="0.1" -tracing-subscriber="0.3" +log="0.4" +pretty_env_logger="0.5" diff --git a/crates/cli/bin.rs b/crates/cli/bin.rs index 2c554cd..9c6908d 100644 --- a/crates/cli/bin.rs +++ b/crates/cli/bin.rs @@ -2,9 +2,7 @@ use std::str::FromStr; use argh::FromArgs; use color_eyre::eyre::Result; -use tinywasm::{self, WasmValue}; -use util::install_tracing; - +use tinywasm::{self}; mod util; #[derive(FromArgs)] @@ -12,6 +10,10 @@ mod util; struct TinyWasmCli { #[argh(subcommand)] nested: TinyWasmSubcommand, + + /// log level + #[argh(option, short = 'l', default = "\"info\".to_string()")] + log_level: String, } #[derive(FromArgs)] @@ -22,7 +24,6 @@ enum TinyWasmSubcommand { enum Engine { Main, - Naive, } impl FromStr for Engine { @@ -30,7 +31,6 @@ impl FromStr for Engine { fn from_str(s: &str) -> Result<Self, Self::Err> { match s { - "naive" => Ok(Self::Naive), "main" => Ok(Self::Main), _ => Err(format!("unknown engine: {}", s)), } @@ -52,16 +52,26 @@ struct Run { fn main() -> Result<()> { color_eyre::install()?; - install_tracing(None); let args: TinyWasmCli = argh::from_env(); + let level = match args.log_level.as_str() { + "trace" => log::LevelFilter::Trace, + "debug" => log::LevelFilter::Debug, + "warn" => log::LevelFilter::Warn, + "error" => log::LevelFilter::Error, + "info" => log::LevelFilter::Info, + _ => log::LevelFilter::Info, + }; + + pretty_env_logger::formatted_builder() + .filter_level(level) + .init(); match args.nested { TinyWasmSubcommand::Run(Run { wasm_file, engine }) => { let wasm = std::fs::read(wasm_file)?; match engine { Engine::Main => run(&wasm), - Engine::Naive => run_naive(&wasm), } } } @@ -78,16 +88,3 @@ fn run(wasm: &[u8]) -> Result<()> { Ok(()) } - -fn run_naive(wasm: &[u8]) -> Result<()> { - let mut module = tinywasm::naive::Module::new(wasm)?; - let args = [WasmValue::I32(1), WasmValue::I32(2)]; - let res = tinywasm::naive::run(&mut module, "add", &args)?; - println!("res: {:?}", res); - - let args = [WasmValue::I64(1), WasmValue::I64(2)]; - let res = tinywasm::naive::run(&mut module, "add_64", &args)?; - println!("res: {:?}", res); - - Ok(()) -} diff --git a/crates/cli/util.rs b/crates/cli/util.rs index 2a8160a..8b13789 100644 --- a/crates/cli/util.rs +++ b/crates/cli/util.rs @@ -1,14 +1 @@ -pub fn install_tracing(log_level: Option<tracing::Level>) { - use tracing_subscriber::filter::LevelFilter; - use tracing_subscriber::prelude::*; - tracing_subscriber::registry() - .with( - tracing_subscriber::fmt::layer() - .compact() - .with_filter(LevelFilter::from( - log_level.unwrap_or(tracing::Level::DEBUG), - )), - ) - .init(); -} diff --git a/crates/parser/Cargo.toml b/crates/parser/Cargo.toml index 590b90c..b187886 100644 --- a/crates/parser/Cargo.toml +++ b/crates/parser/Cargo.toml @@ -7,7 +7,7 @@ edition="2021" # fork of wasmparser with no_std support, see https://github.com/bytecodealliance/wasmtime/issues/3495 # TODO: create dependency free parser wasmparser={version="0.100", package="wasmparser-nostd", default-features=false} -tracing={version="0.1.38", default-features=false} # logging +log="0.4.20" tinywasm-types={path="../types"} [features] diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index c75aaf1..ee30db9 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -1,18 +1,82 @@ -use alloc::{format, vec::Vec}; -use tinywasm_types::{BlockArgs, Instruction, MemArg, ValType}; +use alloc::{boxed::Box, format, string::ToString, vec::Vec}; +use tinywasm_types::{BlockArgs, Export, ExternalKind, FuncType, Instruction, MemArg, ValType}; -use crate::Result; +use crate::{module::CodeSection, Result}; -fn convert_blocktype(blocktype: wasmparser::BlockType) -> BlockArgs { +pub(crate) fn convert_module_export(export: wasmparser::Export) -> Result<Export> { + let kind = match export.kind { + wasmparser::ExternalKind::Func => ExternalKind::Func, + wasmparser::ExternalKind::Table => ExternalKind::Table, + wasmparser::ExternalKind::Memory => ExternalKind::Memory, + wasmparser::ExternalKind::Global => ExternalKind::Global, + wasmparser::ExternalKind::Tag => { + return Err(crate::ParseError::UnsupportedOperator(format!( + "Unsupported export kind: {:?}", + export.kind + ))) + } + }; + + Ok(Export { + index: export.index, + name: Box::from(export.name), + kind, + }) +} + +pub(crate) fn convert_module_code(func: wasmparser::FunctionBody) -> Result<CodeSection> { + let locals_reader = func.get_locals_reader()?; + let count = locals_reader.get_count(); + let mut locals = Vec::with_capacity(count as usize); + locals.extend( + locals_reader + .into_iter() + .filter_map(|l| l.ok()) + .map(|l| convert_valtype(&l.1)), + ); + + if locals.len() != count as usize { + return Err(crate::ParseError::Other("Invalid local index".to_string())); + } + + let body_reader = func.get_operators_reader()?; + let body = process_operators(body_reader.into_iter())?; + + Ok(CodeSection { + locals: locals.into_boxed_slice(), + body, + }) +} + +pub(crate) fn convert_module_type(ty: wasmparser::Type) -> Result<FuncType> { + let wasmparser::Type::Func(ty) = ty; + let params = ty + .params() + .iter() + .map(|p| Ok(convert_valtype(p))) + .collect::<Result<Vec<ValType>>>()? + .into_boxed_slice(); + + let results = ty + .results() + .iter() + .map(|p| Ok(convert_valtype(p))) + .collect::<Result<Vec<ValType>>>()? + .into_boxed_slice(); + + Ok(FuncType { params, results }) +} + +pub(crate) fn convert_blocktype(blocktype: &wasmparser::BlockType) -> BlockArgs { use wasmparser::BlockType::*; match blocktype { Empty => BlockArgs::Empty, Type(ty) => BlockArgs::Type(convert_valtype(ty)), - FuncType(ty) => BlockArgs::FuncType(ty), + FuncType(ty) => BlockArgs::FuncType(*ty), } } -fn convert_valtype(valtype: wasmparser::ValType) -> ValType { +pub(crate) fn convert_valtype(valtype: &wasmparser::ValType) -> ValType { use wasmparser::ValType::*; match valtype { I32 => ValType::I32, @@ -25,14 +89,38 @@ fn convert_valtype(valtype: wasmparser::ValType) -> ValType { } } -fn convert_memarg(memarg: wasmparser::MemArg) -> MemArg { +pub(crate) fn convert_memarg(memarg: wasmparser::MemArg) -> MemArg { MemArg { offset: memarg.offset, align: memarg.align, } } -pub fn process_operator(op: wasmparser::Operator<'_>) -> Result<Instruction> { +pub fn process_operators<'a>( + ops: impl Iterator<Item = Result<wasmparser::Operator<'a>, wasmparser::BinaryReaderError>>, +) -> Result<Box<[Instruction]>> { + let mut instructions = Vec::new(); + for op in ops { + match op? { + wasmparser::Operator::BrTable { targets } => { + instructions.push(Instruction::BrTable(targets.default())); + instructions.extend( + targets + .targets() + .collect::<Result<Vec<u32>, wasmparser::BinaryReaderError>>()? + .into_iter() + .map(Instruction::Br), + ); + } + op => instructions.push(process_operator(&op)?), + } + } + + Ok(instructions.into_boxed_slice()) +} + +#[inline] +pub(crate) fn process_operator(op: &wasmparser::Operator) -> Result<Instruction> { use wasmparser::Operator::*; let v = match op { Unreachable => Instruction::Unreachable, @@ -42,56 +130,48 @@ pub fn process_operator(op: wasmparser::Operator<'_>) -> Result<Instruction> { If { blockty } => Instruction::If(convert_blocktype(blockty)), Else => Instruction::Else, End => Instruction::End, - Br { relative_depth } => Instruction::Br(relative_depth), - BrIf { relative_depth } => Instruction::BrIf(relative_depth), - BrTable { targets } => { - let default = targets.default(); - let targets = targets - .targets() - .map(|t| Ok(t?)) - .collect::<Result<Vec<u32>>>()?; - - Instruction::BrTable(targets, default) - } + Br { relative_depth } => Instruction::Br(*relative_depth), + BrIf { relative_depth } => Instruction::BrIf(*relative_depth), + BrTable { targets } => Instruction::BrTable(targets.default()), Return => Instruction::Return, - Call { function_index } => Instruction::Call(function_index), + Call { function_index } => Instruction::Call(*function_index), CallIndirect { type_index, table_index, .. - } => Instruction::CallIndirect(type_index, table_index), + } => Instruction::CallIndirect(*type_index, *table_index), Drop => Instruction::Drop, Select => Instruction::Select, - LocalGet { local_index } => Instruction::LocalGet(local_index), - LocalSet { local_index } => Instruction::LocalSet(local_index), - LocalTee { local_index } => Instruction::LocalTee(local_index), - GlobalGet { global_index } => Instruction::GlobalGet(global_index), - GlobalSet { global_index } => Instruction::GlobalSet(global_index), + LocalGet { local_index } => Instruction::LocalGet(*local_index), + LocalSet { local_index } => Instruction::LocalSet(*local_index), + LocalTee { local_index } => Instruction::LocalTee(*local_index), + GlobalGet { global_index } => Instruction::GlobalGet(*global_index), + GlobalSet { global_index } => Instruction::GlobalSet(*global_index), MemorySize { .. } => Instruction::MemorySize, MemoryGrow { .. } => Instruction::MemoryGrow, - I32Load { memarg } => Instruction::I32Load(convert_memarg(memarg)), - I64Load { memarg } => Instruction::I64Load(convert_memarg(memarg)), - F32Load { memarg } => Instruction::F32Load(convert_memarg(memarg)), - F64Load { memarg } => Instruction::F64Load(convert_memarg(memarg)), - I32Load8S { memarg } => Instruction::I32Load8S(convert_memarg(memarg)), - I32Load8U { memarg } => Instruction::I32Load8U(convert_memarg(memarg)), - I32Load16S { memarg } => Instruction::I32Load16S(convert_memarg(memarg)), - I32Load16U { memarg } => Instruction::I32Load16U(convert_memarg(memarg)), - I64Load8S { memarg } => Instruction::I64Load8S(convert_memarg(memarg)), - I64Load8U { memarg } => Instruction::I64Load8U(convert_memarg(memarg)), - I64Load16S { memarg } => Instruction::I64Load16S(convert_memarg(memarg)), - I64Load16U { memarg } => Instruction::I64Load16U(convert_memarg(memarg)), - I64Load32S { memarg } => Instruction::I64Load32S(convert_memarg(memarg)), - I64Load32U { memarg } => Instruction::I64Load32U(convert_memarg(memarg)), - I32Store { memarg } => Instruction::I32Store(convert_memarg(memarg)), - I64Store { memarg } => Instruction::I64Store(convert_memarg(memarg)), - F32Store { memarg } => Instruction::F32Store(convert_memarg(memarg)), - F64Store { memarg } => Instruction::F64Store(convert_memarg(memarg)), - I32Store8 { memarg } => Instruction::I32Store8(convert_memarg(memarg)), - I32Store16 { memarg } => Instruction::I32Store16(convert_memarg(memarg)), - I64Store8 { memarg } => Instruction::I64Store8(convert_memarg(memarg)), - I64Store16 { memarg } => Instruction::I64Store16(convert_memarg(memarg)), - I64Store32 { memarg } => Instruction::I64Store32(convert_memarg(memarg)), + I32Load { memarg } => Instruction::I32Load(convert_memarg(*memarg)), + I64Load { memarg } => Instruction::I64Load(convert_memarg(*memarg)), + F32Load { memarg } => Instruction::F32Load(convert_memarg(*memarg)), + F64Load { memarg } => Instruction::F64Load(convert_memarg(*memarg)), + I32Load8S { memarg } => Instruction::I32Load8S(convert_memarg(*memarg)), + I32Load8U { memarg } => Instruction::I32Load8U(convert_memarg(*memarg)), + I32Load16S { memarg } => Instruction::I32Load16S(convert_memarg(*memarg)), + I32Load16U { memarg } => Instruction::I32Load16U(convert_memarg(*memarg)), + I64Load8S { memarg } => Instruction::I64Load8S(convert_memarg(*memarg)), + I64Load8U { memarg } => Instruction::I64Load8U(convert_memarg(*memarg)), + I64Load16S { memarg } => Instruction::I64Load16S(convert_memarg(*memarg)), + I64Load16U { memarg } => Instruction::I64Load16U(convert_memarg(*memarg)), + I64Load32S { memarg } => Instruction::I64Load32S(convert_memarg(*memarg)), + I64Load32U { memarg } => Instruction::I64Load32U(convert_memarg(*memarg)), + I32Store { memarg } => Instruction::I32Store(convert_memarg(*memarg)), + I64Store { memarg } => Instruction::I64Store(convert_memarg(*memarg)), + F32Store { memarg } => Instruction::F32Store(convert_memarg(*memarg)), + F64Store { memarg } => Instruction::F64Store(convert_memarg(*memarg)), + I32Store8 { memarg } => Instruction::I32Store8(convert_memarg(*memarg)), + I32Store16 { memarg } => Instruction::I32Store16(convert_memarg(*memarg)), + I64Store8 { memarg } => Instruction::I64Store8(convert_memarg(*memarg)), + I64Store16 { memarg } => Instruction::I64Store16(convert_memarg(*memarg)), + I64Store32 { memarg } => Instruction::I64Store32(convert_memarg(*memarg)), I32Eqz => Instruction::I32Eqz, I32Eq => Instruction::I32Eq, I32Ne => Instruction::I32Ne, diff --git a/crates/parser/src/error.rs b/crates/parser/src/error.rs index c99fa01..ee217c7 100644 --- a/crates/parser/src/error.rs +++ b/crates/parser/src/error.rs @@ -2,6 +2,7 @@ use alloc::string::{String, ToString}; use wasmparser::Encoding; pub enum ParseError { + InvalidType, UnsupportedSection(String), DuplicateSection(String), EmptySection(String), diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index d2b6d9c..5b17fb8 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -9,49 +9,101 @@ extern crate std; mod conversion; mod error; mod module; +use alloc::vec::Vec; pub use error::*; use module::ModuleReader; -use tinywasm_types::TinyWasmModule; +use tinywasm_types::{Function, TinyWasmModule}; +use wasmparser::Validator; pub struct Parser {} impl Parser { pub fn parse_module_bytes(wasm: &[u8]) -> Result<TinyWasmModule> { - let reader = ModuleReader::new(); - reader.try_into() - } + let mut validator = Validator::new(); + let mut reader = ModuleReader::new(); + + for payload in wasmparser::Parser::new(0).parse_all(wasm) { + reader.process_payload(payload?, &mut validator)?; + } + + if !reader.end_reached { + return Err(ParseError::EndNotReached); + } - pub fn parse_module_file(file_name: &str) -> Result<TinyWasmModule> { - let reader = ModuleReader::new(); reader.try_into() } #[cfg(feature = "std")] - pub fn parse_module_stream(stream: impl std::io::Read) -> Result<TinyWasmModule> { - let reader = ModuleReader::new(); - reader.try_into() - } + pub fn parse_module_file(path: impl AsRef<crate::std::path::Path>) -> Result<TinyWasmModule> { + use alloc::format; + let f = crate::std::fs::File::open("log.txt").map_err(|e| { + ParseError::Other(format!("Error opening file {:?}: {}", path.as_ref(), e)) + })?; - pub fn read_module_bytes(bytes: &[u8]) -> Result<TinyWasmModule> { - unimplemented!() - } - pub fn read_module_file(file_name: &str) -> Result<TinyWasmModule> { - unimplemented!() + let mut reader = crate::std::io::BufReader::new(f); + Self::parse_module_stream(&mut reader) } + #[cfg(feature = "std")] - pub fn read_module_stream(stream: impl std::io::Read) -> Result<TinyWasmModule> { - unimplemented!() + pub fn parse_module_stream(mut stream: impl std::io::Read) -> Result<TinyWasmModule> { + use alloc::format; + + let mut validator = Validator::new(); + let mut reader = ModuleReader::new(); + let mut buffer = Vec::new(); + let mut parser = wasmparser::Parser::new(0); + let mut eof = false; + + loop { + match parser.parse(&buffer, eof)? { + wasmparser::Chunk::NeedMoreData(hint) => { + let len = buffer.len(); + buffer.extend((0..hint).map(|_| 0u8)); + let read_bytes = stream.read(&mut buffer[len..]).map_err(|e| { + ParseError::Other(format!("Error reading from stream: {}", e)) + })?; + buffer.truncate(len + read_bytes); + eof = read_bytes == 0; + } + wasmparser::Chunk::Parsed { consumed, payload } => { + reader.process_payload(payload, &mut validator)?; + buffer.drain(..consumed); + if eof || reader.end_reached { + return reader.try_into(); + } + } + }; + } } } -impl TryFrom<ModuleReader<'_>> for TinyWasmModule { +impl TryFrom<ModuleReader> for TinyWasmModule { type Error = ParseError; - fn try_from(reader: ModuleReader<'_>) -> Result<Self> { + fn try_from(reader: ModuleReader) -> Result<Self> { if !reader.end_reached { return Err(ParseError::EndNotReached); } - unimplemented!() + let func_types = reader.function_section; + let funcs = reader + .code_section + .into_iter() + .zip(func_types) + .map(|(f, ty)| Function { + body: f.body, + locals: f.locals, + ty, + }) + .collect::<Vec<_>>() + .into_boxed_slice(); + + Ok(TinyWasmModule { + version: reader.version, + start_func: reader.start_func, + types: reader.type_section.into_boxed_slice(), + funcs, + exports: reader.export_section.into_boxed_slice(), + }) } } diff --git a/crates/parser/src/module.rs b/crates/parser/src/module.rs index e2e1bde..268bad7 100644 --- a/crates/parser/src/module.rs +++ b/crates/parser/src/module.rs @@ -1,21 +1,26 @@ -use alloc::{format, vec::Vec}; +use alloc::{boxed::Box, format, vec::Vec}; use core::fmt::Debug; -use tracing::debug; -use wasmparser::{ - ExportSectionReader, FunctionBody, FunctionSectionReader, Payload, TypeSectionReader, Validator, -}; +use log::debug; +use tinywasm_types::{Export, FuncType, Instruction, ValType}; +use wasmparser::{Payload, Validator}; -use crate::{ParseError, Result}; +use crate::{conversion, ParseError, Result}; + +#[derive(Debug, Clone, PartialEq)] +pub struct CodeSection { + pub locals: Box<[ValType]>, + pub body: Box<[Instruction]>, +} #[derive(Default)] -pub struct ModuleReader<'a> { +pub struct ModuleReader { pub version: Option<u16>, pub start_func: Option<u32>, - pub type_section: Option<TypeSectionReader<'a>>, - pub function_section: Option<FunctionSectionReader<'a>>, - pub export_section: Option<ExportSectionReader<'a>>, - pub code_section: Option<CodeSection<'a>>, + pub type_section: Vec<FuncType>, + pub function_section: Vec<u32>, + pub export_section: Vec<Export>, + pub code_section: Vec<CodeSection>, // pub table_section: Option<TableSectionReader<'a>>, // pub memory_section: Option<MemorySectionReader<'a>>, @@ -26,8 +31,8 @@ pub struct ModuleReader<'a> { pub end_reached: bool, } -impl Debug for ModuleReader<'_> { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { +impl Debug for ModuleReader { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct("ModuleReader") .field("version", &self.version) .field("type_section", &self.type_section) @@ -44,16 +49,12 @@ impl Debug for ModuleReader<'_> { } } -impl<'a> ModuleReader<'a> { - pub fn new() -> ModuleReader<'a> { +impl ModuleReader { + pub fn new() -> ModuleReader { Self::default() } - pub fn process_payload( - &mut self, - payload: Payload<'a>, - validator: &mut Validator, - ) -> Result<()> { + pub fn process_payload(&mut self, payload: Payload, validator: &mut Validator) -> Result<()> { use wasmparser::Payload::*; match payload { @@ -79,12 +80,18 @@ impl<'a> ModuleReader<'a> { TypeSection(reader) => { debug!("Found type section"); validator.type_section(&reader)?; - self.type_section = Some(reader); + self.type_section = reader + .into_iter() + .map(|t| conversion::convert_module_type(t?)) + .collect::<Result<Vec<FuncType>>>()?; } FunctionSection(reader) => { debug!("Found function section"); validator.function_section(&reader)?; - self.function_section = Some(reader); + self.function_section = reader + .into_iter() + .map(|f| Ok(f?)) + .collect::<Result<Vec<_>>>()?; } TableSection(_reader) => { return Err(ParseError::UnsupportedSection("Table section".into())); @@ -118,22 +125,18 @@ impl<'a> ModuleReader<'a> { } CodeSectionStart { count, range, .. } => { debug!("Found code section ({} functions)", count); - if self.code_section.is_some() { + if !self.code_section.is_empty() { return Err(ParseError::DuplicateSection("Code section".into())); } validator.code_section_start(count, &range)?; - self.code_section = Some(CodeSection::new()); } CodeSectionEntry(function) => { debug!("Found code section entry"); validator.code_section_entry(&function)?; - if let Some(code_section) = &mut self.code_section { - code_section.functions.push(function); - } else { - return Err(ParseError::EmptySection("Code section".into())); - } + self.code_section + .push(conversion::convert_module_code(function)?); } ImportSection(_reader) => { return Err(ParseError::UnsupportedSection("Import section".into())); @@ -145,7 +148,10 @@ impl<'a> ModuleReader<'a> { ExportSection(reader) => { debug!("Found export section"); validator.export_section(&reader)?; - self.export_section = Some(reader); + self.export_section = reader + .into_iter() + .map(|e| conversion::convert_module_export(e?)) + .collect::<Result<Vec<_>>>()?; } End(offset) => { debug!("Reached end of module"); @@ -156,26 +162,17 @@ impl<'a> ModuleReader<'a> { validator.end(offset)?; self.end_reached = true; } - UnknownSection { .. } | _ => { - return Err(ParseError::UnsupportedSection(format!("Unknown section"))) + UnknownSection { .. } => { + return Err(ParseError::UnsupportedSection("Unknown section".into())) + } + section => { + return Err(ParseError::UnsupportedSection(format!( + "Unsupported section: {:?}", + section + ))) } }; Ok(()) } } - -/// A WebAssembly code section -/// Can be cloned to read functions multiple times -#[derive(Debug, Clone)] -pub struct CodeSection<'a> { - pub(crate) functions: Vec<FunctionBody<'a>>, -} - -impl<'a> CodeSection<'a> { - fn new() -> Self { - Self { - functions: Vec::new(), - } - } -} diff --git a/crates/tinywasm/Cargo.toml b/crates/tinywasm/Cargo.toml index 0bae290..db4b659 100644 --- a/crates/tinywasm/Cargo.toml +++ b/crates/tinywasm/Cargo.toml @@ -7,7 +7,7 @@ edition="2021" path="src/lib.rs" [dependencies] -tracing={version="0.1.38", default-features=false} # logging +log="0.4.20" tinywasm-parser={path="../parser"} tinywasm-types={path="../types"} diff --git a/crates/tinywasm/src/lib.rs b/crates/tinywasm/src/lib.rs index c362526..da24d19 100644 --- a/crates/tinywasm/src/lib.rs +++ b/crates/tinywasm/src/lib.rs @@ -18,27 +18,24 @@ pub use module::ModuleInstance; pub mod types; pub use types::*; -pub mod naive; pub mod runtime; #[cfg(test)] mod tests { - use crate::std::println; - use crate::{error::Result, naive, WasmValue}; - #[test] - fn naive_add() -> Result<()> { - let wasm = include_bytes!("../../../examples/wasm/add.wasm"); - let mut module = naive::Module::new(wasm)?; + // #[test] + // fn naive_add() -> Result<()> { + // let wasm = include_bytes!("../../../examples/wasm/add.wasm"); + // let mut module = naive::Module::new(wasm)?; - let args = [WasmValue::I32(1), WasmValue::I32(2)]; - let res = naive::run(&mut module, "add", &args)?; - println!("res: {:?}", res); + // let args = [WasmValue::I32(1), WasmValue::I32(2)]; + // let res = naive::run(&mut module, "add", &args)?; + // println!("res: {:?}", res); - let args = [WasmValue::I64(1), WasmValue::I64(2)]; - let res = naive::run(&mut module, "add_64", &args)?; - println!("res: {:?}", res); + // let args = [WasmValue::I64(1), WasmValue::I64(2)]; + // let res = naive::run(&mut module, "add_64", &args)?; + // println!("res: {:?}", res); - Ok(()) - } + // Ok(()) + // } } diff --git a/crates/tinywasm/src/module/reader.rs b/crates/tinywasm/src/module/reader.rs index 7bcface..062cf45 100644 --- a/crates/tinywasm/src/module/reader.rs +++ b/crates/tinywasm/src/module/reader.rs @@ -1,6 +1,6 @@ use alloc::{format, vec::Vec}; use core::fmt::Debug; -use tracing::debug; +use log::debug; use wasmparser::{ ExportSectionReader, FunctionBody, FunctionSectionReader, Payload, TypeSectionReader, Validator, }; diff --git a/crates/tinywasm/src/naive/mod.rs b/crates/tinywasm/src/naive/mod.rs deleted file mode 100644 index e92bf7f..0000000 --- a/crates/tinywasm/src/naive/mod.rs +++ /dev/null @@ -1,108 +0,0 @@ -use alloc::{format, string::ToString, vec, vec::Vec}; -use tracing::info; -use wasmparser::Operator; - -mod module; -pub use self::module::Module; - -use crate::{Error, Result, WasmValue}; - -pub fn run(module: &mut Module, func_name: &str, args: &[WasmValue]) -> Result<Vec<WasmValue>> { - let func = module - .exports - .iter() - .find(|e| e.name == func_name) - .ok_or_else(|| Error::Other(format!("Function {} not found", func_name)))?; - - let func_type_index = module.functions[func.index as usize]; - let func_type = &module.types[func_type_index as usize]; - - info!("func_type: {:#?}", func_type); - let code = &mut module.code[func.index as usize]; - code.allow_memarg64(false); - - let mut locals = vec![]; - for ty in func_type.params() { - locals.push(*ty); - } - - let mut returns = vec![]; - for ty in func_type.results() { - returns.push(*ty); - } - - let locals_reader = code.get_locals_reader().unwrap(); - for local in locals_reader.into_iter() { - let local = local.unwrap(); - if locals.len() != local.0 as usize { - panic!("Invalid local index"); - } - locals.push(local.1); - } - - let mut local_values = vec![]; - let body = code.get_operators_reader().unwrap().into_iter(); - for (i, arg) in args.iter().enumerate() { - // if !arg.is(locals[i]) { - // return Error::other(&format!( - // "Invalid argument type for {}, index {}: expected {:?}, got {:?}", - // func_name, - // i, - // locals[i], - // arg.type_of() - // )); - // } - - local_values.push(arg); - } - - let mut stack: Vec<WasmValue> = vec![]; - for op in body { - let op = op.unwrap(); - info!("op: {:#?}", op); - - match op { - Operator::LocalGet { local_index } => { - let local = locals.get(local_index as usize).unwrap(); - let val = local_values[local_index as usize]; - info!("local: {:#?}", local); - stack.push(val.clone()); - } - Operator::I64Add => { - let a = stack.pop().unwrap(); - let b = stack.pop().unwrap(); - let (WasmValue::I64(a), WasmValue::I64(b)) = (a, b) else { - panic!("Invalid type"); - }; - let c = WasmValue::I64(a + b); - stack.push(c); - } - Operator::I32Add => { - let a = stack.pop().unwrap(); - let b = stack.pop().unwrap(); - let (WasmValue::I32(a), WasmValue::I32(b)) = (a, b) else { - panic!("Invalid type"); - }; - let c = WasmValue::I32(a + b); - stack.push(c); - } - Operator::End => { - info!("stack: {:#?}", stack); - let res = returns - .iter() - .map(|ty| { - let val = stack.pop()?; - // (val.is(*ty)).then_some(val) - Some(val) - }) - .collect::<Option<Vec<_>>>() - .ok_or_else(|| Error::Other("Invalid return type".to_string()))?; - - return Ok(res); - } - _ => {} - } - } - - Error::other("End not reached") -} diff --git a/crates/tinywasm/src/naive/module.rs b/crates/tinywasm/src/naive/module.rs deleted file mode 100644 index 24f2d55..0000000 --- a/crates/tinywasm/src/naive/module.rs +++ /dev/null @@ -1,92 +0,0 @@ -use core::fmt::Debug; - -use crate::{ - error::{Error, Result}, - module::reader::ModuleReader, -}; -use alloc::vec::Vec; -use wasmparser::*; - -#[derive(Debug)] -pub struct ModuleMetadata { - pub version: u16, -} - -pub struct Module<'data> { - pub meta: ModuleMetadata, - - pub types: Vec<FuncType>, - pub functions: Vec<u32>, - pub exports: Vec<Export<'data>>, - pub code: Vec<FunctionBody<'data>>, -} - -impl Debug for Module<'_> { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.debug_struct("Module") - .field("meta", &self.meta) - .field("types", &self.types) - .field("functions", &self.functions) - .field("exports", &self.exports) - .field("code", &self.code) - .finish() - } -} - -impl<'data> Module<'data> { - pub fn new(wasm: &'data [u8]) -> Result<Self> { - let mut validator = Validator::new(); - let mut reader = ModuleReader::new(); - - for payload in wasmparser::Parser::new(0).parse_all(wasm) { - reader.process_payload(payload?, &mut validator)?; - } - - if !reader.end_reached { - return Error::other("End not reached"); - } - - Self::from_reader(reader) - } - - fn from_reader(reader: ModuleReader<'data>) -> Result<Self> { - let types = reader - .type_section - .map(|s| { - s.into_iter() - .map(|ty| { - let Type::Func(func) = ty?; - Ok(func) - }) - .collect::<Result<Vec<_>>>() - }) - .transpose()? - .unwrap_or_default(); - - let functions = reader - .function_section - .map(|s| s.into_iter().map(|f| Ok(f?)).collect::<Result<Vec<_>>>()) - .transpose()? - .unwrap_or_default(); - - let exports = reader - .export_section - .map(|s| s.into_iter().map(|e| Ok(e?)).collect::<Result<Vec<_>>>()) - .transpose()? - .unwrap_or_default(); - - let code = reader.code_section.map(|s| s.functions).unwrap_or_default(); - - let meta = ModuleMetadata { - version: reader.version.unwrap_or(1), - }; - - Ok(Self { - meta, - types, - exports, - functions, - code, - }) - } -} diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index fa2fc6e..e34c474 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -4,7 +4,7 @@ version="0.0.0" edition="2021" [dependencies] -tracing={version="0.1.38", default-features=false} # logging +log="0.4.20" rkyv={version="0.7", optional=true, default-features=false} [features] diff --git a/crates/types/src/instructions.rs b/crates/types/src/instructions.rs index 993b260..dca99fe 100644 --- a/crates/types/src/instructions.rs +++ b/crates/types/src/instructions.rs @@ -1,5 +1,4 @@ use super::{FuncAddr, GlobalAddr, LabelAddr, LocalAddr, TableAddr, TypeAddr, ValType}; -use alloc::{format, vec::Vec}; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum BlockArgs { @@ -9,7 +8,7 @@ pub enum BlockArgs { } /// Represents a memory immediate in a WebAssembly memory instruction. -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct MemArg { pub align: u8, pub offset: u64, @@ -18,6 +17,7 @@ pub struct MemArg { /// A WebAssembly Instruction /// See https://webassembly.github.io/spec/core/binary/instructions.html /// Currently includes all instructions from the MVP (1.0) spec +#[derive(Debug, Clone, Copy, PartialEq)] pub enum Instruction { // Control Instructions // See https://webassembly.github.io/spec/core/binary/instructions.html#control-instructions @@ -30,7 +30,7 @@ pub enum Instruction { End, Br(LabelAddr), BrIf(LabelAddr), - BrTable(Vec<LabelAddr>, LabelAddr), // not to spec, instead of a vector of labels, we have a label and a count + BrTable(u32), // not to spec, has to be followed by multiple Br instructions with labels Return, Call(FuncAddr), CallIndirect(TypeAddr, TableAddr), diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index e793b26..af5cf1a 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -7,9 +7,9 @@ pub struct TinyWasmModule { pub version: Option<u16>, pub start_func: Option<u32>, - pub types: Option<Box<[FuncType]>>, - pub funcs: Option<Box<[Function]>>, - pub exports: Option<Box<[Export]>>, + pub types: Box<[FuncType]>, + pub funcs: Box<[Function]>, + pub exports: Box<[Export]>, // pub tables: Option<TableType>, // pub memories: Option<MemoryType>, // pub globals: Option<GlobalType>, @@ -98,6 +98,7 @@ pub struct FuncType { /// A WebAssembly Function pub struct Function { + pub ty: TypeAddr, pub locals: Box<[ValType]>, pub body: Box<[Instruction]>, } |
