* Enhance wiggle to generate its UserErrorConverstion trait with a function that returns a Result<abi_err, String>. This enhancement allows hostcall implementations using wiggle to return an actionable error to the instance (the abi_err) or to terminate the instance using the String as fatal error information. * Enhance wiggle to generate its UserErrorConverstion trait with a function that returns a Result<abi_err, String>. This enhancement allows hostcall implementations using wiggle to return an actionable error to the instance (the abi_err) or to terminate the instance using the String as fatal error information. * Enhance the wiggle/wasmtime integration to leverage new work in ab7e9c6. Hostcall implementations generated by wiggle now return an Result<abi_error, Trap>. As a result, hostcalls experiencing fatal errors may trap, thereby terminating the wasmtime instance. This enhancement has been performed for both wasi snapshot1 and wasi snapshot0. * Update wasi-nn crate to reflect enhancement in issue #2418. * Update wiggle test-helpers for wiggle enhancement made in issue #2418. * Address PR feedback; omit verbose return statement. * Address PR feedback; manually format within a proc macro. * Address PR feedback; manually format proc macro. * Restore return statements to wasi.rs. * Restore return statements in funcs.rs. * Address PR feedback; omit TODO and fix formatting. * Ok-wrap error type in assert statement.
112 lines
3.5 KiB
Rust
112 lines
3.5 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();
|
|
|
|
for module in doc.modules() {
|
|
for func in module.funcs() {
|
|
// `proc_exit` is special; it's essentially an unwinding primitive,
|
|
// so we implement it in the runtime rather than use the implementation
|
|
// in wasi-common.
|
|
if func.name.as_str() == "proc_exit" {
|
|
continue;
|
|
}
|
|
|
|
ret.extend(generate_wrappers(&func));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
fn generate_wrappers(func: &witx::InterfaceFunc) -> 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);
|
|
tracing::trace!(" | errno={}", ret);
|
|
ret.as_raw_errno()
|
|
}
|
|
};
|
|
|
|
quote! {
|
|
pub unsafe fn #name(
|
|
wasi_ctx: &mut super::WasiCtx,
|
|
memory: &mut [u8],
|
|
#(#arg_declarations,)*
|
|
) -> Result<#ret, String> {
|
|
Ok({#body})
|
|
}
|
|
}
|
|
}
|