diff --git a/crates/wasi/src/lib.rs b/crates/wasi/src/lib.rs index ff04a257d6..73e5481fbc 100644 --- a/crates/wasi/src/lib.rs +++ b/crates/wasi/src/lib.rs @@ -9,6 +9,7 @@ pub use wasi_common::{WasiCtx, WasiCtxBuilder}; wasmtime_wiggle::define_struct_for_wiggle!({ witx: ["../wasi-common/WASI/phases/snapshot/witx/wasi_snapshot_preview1.witx"], ctx: WasiCtx, + instance: Wasi, }); pub fn is_wasi_module(name: &str) -> bool { diff --git a/crates/wiggle/wasmtime/macro/src/config.rs b/crates/wiggle/wasmtime/macro/src/config.rs index 82839dd360..c9783925f2 100644 --- a/crates/wiggle/wasmtime/macro/src/config.rs +++ b/crates/wiggle/wasmtime/macro/src/config.rs @@ -4,7 +4,7 @@ use { braced, parse::{Parse, ParseStream}, punctuated::Punctuated, - Error, Result, Token, + Error, Ident, Result, Token, }, wiggle_generate::config::{CtxConf, WitxConf}, }; @@ -13,18 +13,21 @@ use { pub struct Config { pub witx: WitxConf, pub ctx: CtxConf, + pub instance_typename: InstanceTypenameConf, } #[derive(Debug, Clone)] pub enum ConfigField { Witx(WitxConf), Ctx(CtxConf), + InstanceTypename(InstanceTypenameConf), } mod kw { syn::custom_keyword!(witx); syn::custom_keyword!(witx_literal); syn::custom_keyword!(ctx); + syn::custom_keyword!(instance); } impl Parse for ConfigField { @@ -42,6 +45,10 @@ impl Parse for ConfigField { input.parse::()?; input.parse::()?; Ok(ConfigField::Ctx(input.parse()?)) + } else if lookahead.peek(kw::instance) { + input.parse::()?; + input.parse::()?; + Ok(ConfigField::InstanceTypename(input.parse()?)) } else { Err(lookahead.error()) } @@ -52,6 +59,7 @@ impl Config { pub fn build(fields: impl Iterator, err_loc: Span) -> Result { let mut witx = None; let mut ctx = None; + let mut instance_typename = None; for f in fields { match f { ConfigField::Witx(c) => { @@ -66,6 +74,12 @@ impl Config { } ctx = Some(c); } + ConfigField::InstanceTypename(c) => { + if instance_typename.is_some() { + return Err(Error::new(err_loc, "duplicate `instance` field")); + } + instance_typename = Some(c); + } } } Ok(Config { @@ -75,6 +89,9 @@ impl Config { ctx: ctx .take() .ok_or_else(|| Error::new(err_loc, "`ctx` field required"))?, + instance_typename: instance_typename + .take() + .ok_or_else(|| Error::new(err_loc, "`instance` field required"))?, }) } @@ -97,3 +114,16 @@ impl Parse for Config { Ok(Config::build(fields.into_iter(), input.span())?) } } + +#[derive(Debug, Clone)] +pub struct InstanceTypenameConf { + pub name: Ident, +} + +impl Parse for InstanceTypenameConf { + fn parse(input: ParseStream) -> Result { + Ok(InstanceTypenameConf { + name: input.parse()?, + }) + } +} diff --git a/crates/wiggle/wasmtime/macro/src/lib.rs b/crates/wiggle/wasmtime/macro/src/lib.rs index f709eb177c..d80626f4b6 100644 --- a/crates/wiggle/wasmtime/macro/src/lib.rs +++ b/crates/wiggle/wasmtime/macro/src/lib.rs @@ -6,6 +6,8 @@ use wiggle_generate::Names; mod config; +use config::InstanceTypenameConf; + #[proc_macro] pub fn define_struct_for_wiggle(args: TokenStream) -> TokenStream { let mut config = parse_macro_input!(args as config::Config); @@ -15,7 +17,7 @@ pub fn define_struct_for_wiggle(args: TokenStream) -> TokenStream { let doc = config.load_document(); let names = Names::new(&config.ctx.name, quote!(wasmtime_wiggle)); - generate(&doc, &names).into() + generate(&doc, &names, &config.instance_typename).into() } enum Abi { @@ -25,7 +27,11 @@ enum Abi { F64, } -fn generate(doc: &witx::Document, names: &Names) -> TokenStream2 { +fn generate( + doc: &witx::Document, + names: &Names, + instance_typename: &InstanceTypenameConf, +) -> TokenStream2 { let mut fields = Vec::new(); let mut get_exports = Vec::new(); let mut ctor_externs = Vec::new(); @@ -233,6 +239,7 @@ fn generate(doc: &witx::Document, names: &Names) -> TokenStream2 { } } + let inst_type = instance_typename.name.clone(); let ctx_type = names.ctx_type(); quote! { @@ -241,23 +248,23 @@ fn generate(doc: &witx::Document, names: &Names) -> TokenStream2 { /// This represents a wasi module which can be used to instantiate other /// wasm modules. This structure exports all that various fields of the /// wasi instance as fields which can be used to implement your own - /// instantiation logic, if necessary. Additionally [`Wasi::get_export`] + /// instantiation logic, if necessary. Additionally [`#inst_type::get_export`] /// can be used to do name-based resolution. - pub struct Wasi { + pub struct #inst_type { #(#fields,)* } - impl Wasi { - /// Creates a new [`Wasi`] instance. + impl #inst_type { + /// Creates a new [`#inst_type`] instance. /// /// External values are allocated into the `store` provided and /// configuration of the wasi instance itself should be all /// contained in the `cx` parameter. - pub fn new(store: &wasmtime::Store, cx: #ctx_type) -> Wasi { + pub fn new(store: &wasmtime::Store, cx: #ctx_type) -> Self { let cx = std::rc::Rc::new(std::cell::RefCell::new(cx)); #(#ctor_externs)* - Wasi { + Self { #(#ctor_fields,)* } }