* Move back to only one WASI submodule This commit fixes the issue where we have two WASI submodules for build reasons in this repository. The fix was to place the submodule in the `wasi-common` crate, and then anyone using the `wig` crate has to be sure to define a `WASI_ROOT` env var in a build script to be able to parse witx files. With all that in place `wasi-common` becomes the source of truth for the witx files we're parsing, and crates like `wasmtime-wasi` use build-scripts shenanigans to read the same witx files. This should hopefully get us so we're compatible with publishing and still only have one submodule! * rustfmt
127 lines
3.8 KiB
Rust
127 lines
3.8 KiB
Rust
use crate::utils;
|
|
use proc_macro2::TokenStream;
|
|
use quote::{format_ident, quote};
|
|
|
|
pub fn define(args: TokenStream) -> TokenStream {
|
|
let path = utils::witx_path_from_args(args);
|
|
let doc = match witx::load(&[&path]) {
|
|
Ok(doc) => doc,
|
|
Err(e) => {
|
|
panic!("error opening file {}: {}", path.display(), e);
|
|
}
|
|
};
|
|
|
|
let mut ret = TokenStream::new();
|
|
|
|
let old = true;
|
|
|
|
for module in doc.modules() {
|
|
for func in module.funcs() {
|
|
ret.extend(generate_wrappers(&func, old));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
fn generate_wrappers(func: &witx::InterfaceFunc, old: bool) -> TokenStream {
|
|
let name = format_ident!("{}", func.name.as_str());
|
|
let mut arg_declarations = Vec::new();
|
|
let mut arg_names = Vec::new();
|
|
|
|
for param in func.params.iter() {
|
|
let name = utils::param_name(param);
|
|
|
|
if let witx::TypePassedBy::PointerLengthPair = param.tref.type_().passed_by() {
|
|
let ptr = format_ident!("{}_ptr", name);
|
|
let len = format_ident!("{}_len", name);
|
|
arg_declarations.push(quote! { #ptr: super::wasi32::uintptr_t });
|
|
arg_declarations.push(quote! { #len: super::wasi32::size_t });
|
|
arg_names.push(ptr);
|
|
arg_names.push(len);
|
|
continue;
|
|
}
|
|
|
|
match ¶m.tref {
|
|
witx::TypeRef::Name(n) => {
|
|
if n.name.as_str() == "size" {
|
|
arg_declarations.push(quote! { #name: super::wasi32::size_t });
|
|
} else {
|
|
let ty_name = format_ident!("__wasi_{}_t", n.name.as_str());
|
|
arg_declarations.push(quote! { #name: super::wasi::#ty_name });
|
|
}
|
|
}
|
|
witx::TypeRef::Value(v) => match &**v {
|
|
witx::Type::ConstPointer(_) | witx::Type::Pointer(_) => {
|
|
arg_declarations.push(quote! { #name: super::wasi32::uintptr_t });
|
|
}
|
|
_ => panic!("unexpected value type"),
|
|
},
|
|
}
|
|
arg_names.push(name);
|
|
}
|
|
|
|
let mut ret = quote!(());
|
|
|
|
for (i, result) in func.results.iter().enumerate() {
|
|
if i == 0 {
|
|
match &result.tref {
|
|
witx::TypeRef::Name(n) => {
|
|
let ty_name = format_ident!("__wasi_{}_t", n.name.as_str());
|
|
ret = quote! { super::wasi::#ty_name };
|
|
}
|
|
witx::TypeRef::Value(_) => panic!("unexpected value type"),
|
|
}
|
|
continue;
|
|
}
|
|
let name = utils::param_name(result);
|
|
arg_declarations.push(quote! { #name: super::wasi32::uintptr_t });
|
|
arg_names.push(name);
|
|
}
|
|
|
|
let call = quote! {
|
|
super::hostcalls_impl::#name(wasi_ctx, memory, #(#arg_names,)*)
|
|
};
|
|
let body = if func.results.len() == 0 {
|
|
call
|
|
} else {
|
|
quote! {
|
|
let ret = #call
|
|
.err()
|
|
.unwrap_or(super::wasi::WasiError::ESUCCESS);
|
|
log::trace!(" | errno={}", ret);
|
|
ret.as_raw_errno()
|
|
}
|
|
};
|
|
|
|
let c_abi_name = if old {
|
|
format_ident!("old_wasi_common_{}", name)
|
|
} else {
|
|
format_ident!("wasi_common_{}", name)
|
|
};
|
|
|
|
quote! {
|
|
pub unsafe fn #name(
|
|
wasi_ctx: &mut super::WasiCtx,
|
|
memory: &mut [u8],
|
|
#(#arg_declarations,)*
|
|
) -> #ret {
|
|
#body
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe fn #c_abi_name(
|
|
wasi_ctx: *mut super::WasiCtx,
|
|
memory: *mut u8,
|
|
memory_len: usize,
|
|
#(#arg_declarations,)*
|
|
) -> #ret {
|
|
#name(
|
|
&mut *wasi_ctx,
|
|
std::slice::from_raw_parts_mut(memory, memory_len),
|
|
#(#arg_names,)*
|
|
)
|
|
}
|
|
}
|
|
}
|