diff --git a/Cargo.lock b/Cargo.lock index bd26b53ce1..9def63022c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1594,7 +1594,8 @@ dependencies = [ "quote", "syn 3.0.3", "tracing", - "wasmparser", + "wasmparser 0.255.0", + "wat", "wit-component", "wit-parser", ] @@ -4156,6 +4157,12 @@ version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + [[package]] name = "unicode-xid" version = "0.2.6" @@ -4337,7 +4344,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b524283fb5df62eec102ed0574838961bdd7ba5ac9c50d38e2756c51c971a42" dependencies = [ "leb128fmt", - "wasmparser", + "wasmparser 0.255.0", +] + +[[package]] +name = "wasm-encoder" +version = "0.256.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1492381bfd5ea51c2a99a919b676662559925cb8d7490547ec2e14c1ad3eb1" +dependencies = [ + "leb128fmt", + "wasmparser 0.256.0", ] [[package]] @@ -4348,8 +4365,8 @@ checksum = "4d3b0da506f1b8514517972fbc47057b21273cb619290f51ea31403c157f896c" dependencies = [ "anyhow", "indexmap", - "wasm-encoder", - "wasmparser", + "wasm-encoder 0.255.0", + "wasmparser 0.255.0", ] [[package]] @@ -4365,6 +4382,39 @@ dependencies = [ "serde", ] +[[package]] +name = "wasmparser" +version = "0.256.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60bd825ffedc6cba8a642924ba7ae424afbc47811cffbcb7b92031ec24e59b4c" +dependencies = [ + "bitflags 2.13.1", + "indexmap", + "semver", +] + +[[package]] +name = "wast" +version = "256.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3ad42723fc9222da007f05812a3249c9a4ee7af79d497fc2a2079579ad7efe6" +dependencies = [ + "bumpalo", + "leb128fmt", + "memchr", + "unicode-width", + "wasm-encoder 0.256.0", +] + +[[package]] +name = "wat" +version = "1.256.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37cc86c54d8011b3202e265bfebada440733ea3a788ffaf46d395f7d2fdeacfb" +dependencies = [ + "wast", +] + [[package]] name = "web-sys" version = "0.3.103" @@ -4587,9 +4637,9 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder", + "wasm-encoder 0.255.0", "wasm-metadata", - "wasmparser", + "wasmparser 0.255.0", "wit-parser", ] @@ -4609,7 +4659,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-ident", - "wasmparser", + "wasmparser 0.255.0", ] [[package]] diff --git a/src/hyperlight_component_macro/src/lib.rs b/src/hyperlight_component_macro/src/lib.rs index 3f2f19e49c..7e29ee983e 100644 --- a/src/hyperlight_component_macro/src/lib.rs +++ b/src/hyperlight_component_macro/src/lib.rs @@ -77,7 +77,7 @@ pub fn host_bindgen(input: proc_macro::TokenStream) -> proc_macro::TokenStream { rtypes::emit_toplevel(s, &kebab_name, ct); host::emit_toplevel(s, &kebab_name, ct); }); - util::emit_decls(decls).into() + util::emit_decls(decls, &kebab_name).into() }) } @@ -106,7 +106,7 @@ pub fn guest_bindgen(input: proc_macro::TokenStream) -> proc_macro::TokenStream // stream directly and emitting an include!() pointing at a // temporary file, depending on whether the user has requested // a debug temporary file be created. - util::emit_decls(decls).into() + util::emit_decls(decls, &kebab_name).into() }) } @@ -129,7 +129,7 @@ fn unknown_key_error(key: &Ident) -> syn::Error { syn::Error::new( key.span(), format!( - "unknown parameter '{}'; expected 'path', 'wit', 'wasm', 'inline', 'world', or 'world_name'", + "unknown parameter '{}'; expected 'path', 'wit', 'wasm', 'wat', 'inline', 'world', or 'world_name'", key ), ) @@ -146,6 +146,9 @@ fn source_from_key(key: &Ident, value: LitStr) -> Result { "wasm" => Ok(util::WitSource::Wasm(std::path::PathBuf::from( value.value(), ))), + "wat" => Ok(util::WitSource::Wat(std::path::PathBuf::from( + value.value(), + ))), "inline" => Ok(util::WitSource::Inline(value.value())), _ => Err(unknown_key_error(key)), } @@ -170,7 +173,7 @@ impl Parse for BindgenInputParams { let value: LitStr = content.parse()?; world_name = Some(value.value()); } - "path" | "wit" | "wasm" | "inline" => { + "path" | "wit" | "wasm" | "wat" | "inline" => { let value: LitStr = content.parse()?; if source.is_some() { return Err(syn::Error::new( @@ -193,7 +196,7 @@ impl Parse for BindgenInputParams { let value: LitStr = input.parse()?; match key.to_string().as_str() { "world" | "world_name" => world_name = Some(value.value()), - "path" | "wit" | "wasm" | "inline" => { + "path" | "wit" | "wasm" | "wat" | "inline" => { source = Some(source_from_key(&key, value)?); } _ => return Err(unknown_key_error(&key)), diff --git a/src/hyperlight_component_util/Cargo.toml b/src/hyperlight_component_util/Cargo.toml index d089473221..e0b7d4a459 100644 --- a/src/hyperlight_component_util/Cargo.toml +++ b/src/hyperlight_component_util/Cargo.toml @@ -16,6 +16,7 @@ name = "hyperlight_component_util" [dependencies] wasmparser = { version = "0.255.0" } +wat = { version = "1.256.0" } wit-component = { version = "0.255.0" } wit-parser = { version = "0.255.0" } quote = { version = "1.0.45" } diff --git a/src/hyperlight_component_util/src/util.rs b/src/hyperlight_component_util/src/util.rs index 4b23db88fc..45836f3348 100644 --- a/src/hyperlight_component_util/src/util.rs +++ b/src/hyperlight_component_util/src/util.rs @@ -21,6 +21,7 @@ use crate::etypes; #[derive(Debug)] pub enum WitSource { Wasm(std::path::PathBuf), + Wat(std::path::PathBuf), Wit(std::path::PathBuf), Inline(String), } @@ -44,6 +45,16 @@ impl WitSource { } bytes } + Self::Wat(path) => { + let path = manifest_path(&path); + let bytes = wat::parse_file(&path).unwrap_or_else(|err| { + panic!("failed to read wat input '{}': {err:#}", path.display()); + }); + if !wasmparser::Parser::is_component(&bytes) { + panic!("wat input '{}' is not a wasm component", path.display()); + } + bytes + } Self::Wit(path) => { let path = manifest_path(&path); let mut resolve = wit_parser::Resolve::default(); @@ -59,14 +70,33 @@ impl WitSource { }) } Self::Inline(contents) => { - let mut resolve = wit_parser::Resolve::default(); - let package = resolve - .push_str("inline.wit", &contents) - .unwrap_or_else(|err| panic!("failed to parse inline WIT input: {err:#}")); - - wit_component::encode(&resolve, package).unwrap_or_else(|err| { - panic!("failed to encode inline WIT input as a wasm component type: {err:#}") - }) + match wat::Detect::from_bytes(&contents) { + wat::Detect::WasmBinary => { + panic!("inline component type looks like a binary!") + } + wat::Detect::WasmText => { + let bytes = wat::parse_str(&contents).unwrap_or_else(|err| { + panic!("failed to read inline wat input: {err:#}") + }); + if !wasmparser::Parser::is_component(&bytes) { + panic!("inline wat input is not a wasm component"); + } + bytes + } + wat::Detect::Unknown => { + // It's probably WIT + let mut resolve = wit_parser::Resolve::default(); + let package = + resolve + .push_str("inline.wit", &contents) + .unwrap_or_else(|err| { + panic!("failed to parse inline WIT input: {err:#}") + }); + wit_component::encode(&resolve, package).unwrap_or_else(|err| { + panic!("failed to encode inline WIT input as a wasm component type: {err:#}") + }) + } + } } } } @@ -119,8 +149,12 @@ pub fn read_wit_type_from_file R>( /// Deal with `$HYPERLIGHT_COMPONENT_MACRO_DEBUG`: if it is present, /// save the given token stream (representing the result of /// macroexpansion) to the debug file and then return the token stream -pub fn emit_decls(decls: proc_macro2::TokenStream) -> proc_macro2::TokenStream { +pub fn emit_decls(decls: proc_macro2::TokenStream, for_kebab: &str) -> proc_macro2::TokenStream { if let Ok(dbg_out) = std::env::var("HYPERLIGHT_COMPONENT_MACRO_DEBUG") { + let fs_safe = for_kebab.replace("/", "_"); + #[cfg(windows)] + let fs_safe = fs_safe.replace(":", "+"); + let dbg_out = dbg_out.replace("#", &fs_safe); if let Ok(file) = syn::parse2(decls.clone()) { std::fs::write(&dbg_out, prettyplease::unparse(&file)).unwrap(); } else { diff --git a/src/tests/rust_guests/Cargo.lock b/src/tests/rust_guests/Cargo.lock index 189ce58caa..ffb8271dfc 100644 --- a/src/tests/rust_guests/Cargo.lock +++ b/src/tests/rust_guests/Cargo.lock @@ -88,6 +88,12 @@ dependencies = [ "spin 0.10.0", ] +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + [[package]] name = "bytemuck" version = "1.25.0" @@ -268,7 +274,8 @@ dependencies = [ "quote", "syn 3.0.2", "tracing", - "wasmparser", + "wasmparser 0.255.0", + "wat", "wit-component", "wit-parser", ] @@ -759,6 +766,12 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + [[package]] name = "utf8parse" version = "0.2.2" @@ -772,7 +785,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b524283fb5df62eec102ed0574838961bdd7ba5ac9c50d38e2756c51c971a42" dependencies = [ "leb128fmt", - "wasmparser", + "wasmparser 0.255.0", +] + +[[package]] +name = "wasm-encoder" +version = "0.256.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1492381bfd5ea51c2a99a919b676662559925cb8d7490547ec2e14c1ad3eb1" +dependencies = [ + "leb128fmt", + "wasmparser 0.256.0", ] [[package]] @@ -783,8 +806,8 @@ checksum = "4d3b0da506f1b8514517972fbc47057b21273cb619290f51ea31403c157f896c" dependencies = [ "anyhow", "indexmap", - "wasm-encoder", - "wasmparser", + "wasm-encoder 0.255.0", + "wasmparser 0.255.0", ] [[package]] @@ -800,6 +823,39 @@ dependencies = [ "serde", ] +[[package]] +name = "wasmparser" +version = "0.256.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60bd825ffedc6cba8a642924ba7ae424afbc47811cffbcb7b92031ec24e59b4c" +dependencies = [ + "bitflags 2.13.0", + "indexmap", + "semver", +] + +[[package]] +name = "wast" +version = "256.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3ad42723fc9222da007f05812a3249c9a4ee7af79d497fc2a2079579ad7efe6" +dependencies = [ + "bumpalo", + "leb128fmt", + "memchr", + "unicode-width", + "wasm-encoder 0.256.0", +] + +[[package]] +name = "wat" +version = "1.256.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37cc86c54d8011b3202e265bfebada440733ea3a788ffaf46d395f7d2fdeacfb" +dependencies = [ + "wast", +] + [[package]] name = "windows-link" version = "0.2.1" @@ -837,9 +893,9 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder", + "wasm-encoder 0.255.0", "wasm-metadata", - "wasmparser", + "wasmparser 0.255.0", "wit-parser", ] @@ -859,7 +915,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-ident", - "wasmparser", + "wasmparser 0.255.0", ] [[package]] @@ -877,4 +933,4 @@ dependencies = [ name = "zmij" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" \ No newline at end of file +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"