From f8f9b14c6fd0b4cac07b599cc3c8b057f77449ec Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Tue, 5 Jan 2021 18:19:31 -0800 Subject: [PATCH] wiggle: introduce wiggle::Trap, which can be either a String or I32 also, make noreturn functions always return a Trap wasmtime-wiggle can trivially turn a wiggle::Trap into a wasmtime::Trap. lucet will have to do the same. --- crates/wiggle/generate/src/funcs.rs | 59 +++++++++++++--------- crates/wiggle/generate/src/lib.rs | 2 +- crates/wiggle/generate/src/module_trait.rs | 44 +++++++++------- crates/wiggle/src/lib.rs | 6 +++ crates/wiggle/wasmtime/macro/src/lib.rs | 5 +- 5 files changed, 70 insertions(+), 46 deletions(-) diff --git a/crates/wiggle/generate/src/funcs.rs b/crates/wiggle/generate/src/funcs.rs index e6551b17dd..5cdf59eda0 100644 --- a/crates/wiggle/generate/src/funcs.rs +++ b/crates/wiggle/generate/src/funcs.rs @@ -36,12 +36,6 @@ pub fn define_func( witx::CoreParamSignifies::Value(atom) => names.atom_type(atom), _ => unreachable!("ret should always be passed by value"), } - } else if func.noreturn { - // Ideally we would return `quote!(!)` here, but, we'd have to change - // the error handling logic in all the marshalling code to never return, - // and instead provide some other way to bail to the context... - // noreturn func - unimplemented!("noreturn funcs not supported yet!") } else { quote!(()) }; @@ -174,25 +168,42 @@ pub fn define_func( let mod_name = &module.name.as_str(); let func_name = &func.name.as_str(); - quote!(pub fn #ident(#abi_args) -> Result<#abi_ret, String> { - let _span = #rt::tracing::span!( - #rt::tracing::Level::TRACE, - "wiggle abi", - module = #mod_name, - function = #func_name - ); - let _enter = _span.enter(); + if func.noreturn { + quote!(pub fn #ident(#abi_args) -> Result<#abi_ret, wiggle::Trap> { + let _span = #rt::tracing::span!( + #rt::tracing::Level::TRACE, + "wiggle abi", + module = #mod_name, + function = #func_name + ); + let _enter = _span.enter(); - #(#marshal_args)* - #(#marshal_rets_pre)* - #log_marshalled_args - let #trait_bindings = match #trait_name::#ident(ctx, #(#trait_args),*) { - Ok(#trait_bindings) => { #trait_rets }, - Err(e) => { #ret_err }, - }; - #(#marshal_rets_post)* - #success - }) + #(#marshal_args)* + #log_marshalled_args + let trap = #trait_name::#ident(ctx, #(#trait_args),*); + Err(trap) + }) + } else { + quote!(pub fn #ident(#abi_args) -> Result<#abi_ret, wiggle::Trap> { + let _span = #rt::tracing::span!( + #rt::tracing::Level::TRACE, + "wiggle abi", + module = #mod_name, + function = #func_name + ); + let _enter = _span.enter(); + + #(#marshal_args)* + #(#marshal_rets_pre)* + #log_marshalled_args + let #trait_bindings = match #trait_name::#ident(ctx, #(#trait_args),*) { + Ok(#trait_bindings) => { #trait_rets }, + Err(e) => { #ret_err }, + }; + #(#marshal_rets_post)* + #success + }) + } } fn marshal_arg( diff --git a/crates/wiggle/generate/src/lib.rs b/crates/wiggle/generate/src/lib.rs index 206ded711b..1ba4b6ebae 100644 --- a/crates/wiggle/generate/src/lib.rs +++ b/crates/wiggle/generate/src/lib.rs @@ -40,7 +40,7 @@ pub fn generate(doc: &witx::Document, names: &Names, errs: &ErrorTransform) -> T let abi_typename = names.type_ref(&errtype.abi_type(), anon_lifetime()); let user_typename = errtype.typename(); let methodname = names.user_error_conversion_method(&errtype); - quote!(fn #methodname(&self, e: super::#user_typename) -> Result<#abi_typename, String>;) + quote!(fn #methodname(&self, e: super::#user_typename) -> Result<#abi_typename, wiggle::Trap>;) }); let user_error_conversion = quote! { pub trait UserErrorConversion { diff --git a/crates/wiggle/generate/src/module_trait.rs b/crates/wiggle/generate/src/module_trait.rs index c73cd052bb..e42551a70b 100644 --- a/crates/wiggle/generate/src/module_trait.rs +++ b/crates/wiggle/generate/src/module_trait.rs @@ -48,28 +48,34 @@ pub fn define_module_trait(names: &Names, m: &Module, errxform: &ErrorTransform) }; quote!(#arg_name: #arg_type) }); - let rets = f - .results - .iter() - .skip(1) - .map(|ret| names.type_ref(&ret.tref, lifetime.clone())); - let err = f - .results - .get(0) - .map(|err_result| { - if let Some(custom_err) = errxform.for_abi_error(&err_result.tref) { - let tn = custom_err.typename(); - quote!(super::#tn) - } else { - names.type_ref(&err_result.tref, lifetime.clone()) - } - }) - .unwrap_or(quote!(())); + + let result = if !f.noreturn { + let rets = f + .results + .iter() + .skip(1) + .map(|ret| names.type_ref(&ret.tref, lifetime.clone())); + let err = f + .results + .get(0) + .map(|err_result| { + if let Some(custom_err) = errxform.for_abi_error(&err_result.tref) { + let tn = custom_err.typename(); + quote!(super::#tn) + } else { + names.type_ref(&err_result.tref, lifetime.clone()) + } + }) + .unwrap_or(quote!(())); + quote!( Result<(#(#rets),*), #err> ) + } else { + quote!(wiggle::Trap) + }; if is_anonymous { - quote!(fn #funcname(&self, #(#args),*) -> Result<(#(#rets),*), #err>;) + quote!(fn #funcname(&self, #(#args),*) -> #result; ) } else { - quote!(fn #funcname<#lifetime>(&self, #(#args),*) -> Result<(#(#rets),*), #err>;) + quote!(fn #funcname<#lifetime>(&self, #(#args),*) -> #result;) } }); quote! { diff --git a/crates/wiggle/src/lib.rs b/crates/wiggle/src/lib.rs index 063ab5bd4b..47b5c681e5 100644 --- a/crates/wiggle/src/lib.rs +++ b/crates/wiggle/src/lib.rs @@ -928,3 +928,9 @@ impl Pointee for str { <[u8]>::debug(pointer, f) } } + +#[derive(Debug, Clone)] +pub enum Trap { + I32(i32), + String(String), +} diff --git a/crates/wiggle/wasmtime/macro/src/lib.rs b/crates/wiggle/wasmtime/macro/src/lib.rs index 095dcd16c5..582a471f31 100644 --- a/crates/wiggle/wasmtime/macro/src/lib.rs +++ b/crates/wiggle/wasmtime/macro/src/lib.rs @@ -199,8 +199,9 @@ fn generate_func( #(#arg_names),* ); match result { - Ok(r) => {return Ok(r.into());}, - Err(err) => { return Err(wasmtime::Trap::new(err)); }, + Ok(r) => Ok(r.into()), + Err(wasmtime_wiggle::Trap::String(err)) => Err(wasmtime::Trap::new(err)), + Err(wasmtime_wiggle::Trap::I32(err)) => Err(wasmtime::Trap::i32_exit(err)), } } }