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.
This commit is contained in:
Pat Hickey
2021-01-05 18:19:31 -08:00
parent 4018a06da2
commit f8f9b14c6f
5 changed files with 70 additions and 46 deletions

View File

@@ -36,12 +36,6 @@ pub fn define_func(
witx::CoreParamSignifies::Value(atom) => names.atom_type(atom), witx::CoreParamSignifies::Value(atom) => names.atom_type(atom),
_ => unreachable!("ret should always be passed by value"), _ => 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 { } else {
quote!(()) quote!(())
}; };
@@ -174,25 +168,42 @@ pub fn define_func(
let mod_name = &module.name.as_str(); let mod_name = &module.name.as_str();
let func_name = &func.name.as_str(); let func_name = &func.name.as_str();
quote!(pub fn #ident(#abi_args) -> Result<#abi_ret, String> { if func.noreturn {
let _span = #rt::tracing::span!( quote!(pub fn #ident(#abi_args) -> Result<#abi_ret, wiggle::Trap> {
#rt::tracing::Level::TRACE, let _span = #rt::tracing::span!(
"wiggle abi", #rt::tracing::Level::TRACE,
module = #mod_name, "wiggle abi",
function = #func_name module = #mod_name,
); function = #func_name
let _enter = _span.enter(); );
let _enter = _span.enter();
#(#marshal_args)* #(#marshal_args)*
#(#marshal_rets_pre)* #log_marshalled_args
#log_marshalled_args let trap = #trait_name::#ident(ctx, #(#trait_args),*);
let #trait_bindings = match #trait_name::#ident(ctx, #(#trait_args),*) { Err(trap)
Ok(#trait_bindings) => { #trait_rets }, })
Err(e) => { #ret_err }, } else {
}; quote!(pub fn #ident(#abi_args) -> Result<#abi_ret, wiggle::Trap> {
#(#marshal_rets_post)* let _span = #rt::tracing::span!(
#success #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( fn marshal_arg(

View File

@@ -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 abi_typename = names.type_ref(&errtype.abi_type(), anon_lifetime());
let user_typename = errtype.typename(); let user_typename = errtype.typename();
let methodname = names.user_error_conversion_method(&errtype); 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! { let user_error_conversion = quote! {
pub trait UserErrorConversion { pub trait UserErrorConversion {

View File

@@ -48,28 +48,34 @@ pub fn define_module_trait(names: &Names, m: &Module, errxform: &ErrorTransform)
}; };
quote!(#arg_name: #arg_type) quote!(#arg_name: #arg_type)
}); });
let rets = f
.results let result = if !f.noreturn {
.iter() let rets = f
.skip(1) .results
.map(|ret| names.type_ref(&ret.tref, lifetime.clone())); .iter()
let err = f .skip(1)
.results .map(|ret| names.type_ref(&ret.tref, lifetime.clone()));
.get(0) let err = f
.map(|err_result| { .results
if let Some(custom_err) = errxform.for_abi_error(&err_result.tref) { .get(0)
let tn = custom_err.typename(); .map(|err_result| {
quote!(super::#tn) if let Some(custom_err) = errxform.for_abi_error(&err_result.tref) {
} else { let tn = custom_err.typename();
names.type_ref(&err_result.tref, lifetime.clone()) quote!(super::#tn)
} } else {
}) names.type_ref(&err_result.tref, lifetime.clone())
.unwrap_or(quote!(())); }
})
.unwrap_or(quote!(()));
quote!( Result<(#(#rets),*), #err> )
} else {
quote!(wiggle::Trap)
};
if is_anonymous { if is_anonymous {
quote!(fn #funcname(&self, #(#args),*) -> Result<(#(#rets),*), #err>;) quote!(fn #funcname(&self, #(#args),*) -> #result; )
} else { } else {
quote!(fn #funcname<#lifetime>(&self, #(#args),*) -> Result<(#(#rets),*), #err>;) quote!(fn #funcname<#lifetime>(&self, #(#args),*) -> #result;)
} }
}); });
quote! { quote! {

View File

@@ -928,3 +928,9 @@ impl Pointee for str {
<[u8]>::debug(pointer, f) <[u8]>::debug(pointer, f)
} }
} }
#[derive(Debug, Clone)]
pub enum Trap {
I32(i32),
String(String),
}

View File

@@ -199,8 +199,9 @@ fn generate_func(
#(#arg_names),* #(#arg_names),*
); );
match result { match result {
Ok(r) => {return Ok(r.into());}, Ok(r) => Ok(r.into()),
Err(err) => { return Err(wasmtime::Trap::new(err)); }, Err(wasmtime_wiggle::Trap::String(err)) => Err(wasmtime::Trap::new(err)),
Err(wasmtime_wiggle::Trap::I32(err)) => Err(wasmtime::Trap::i32_exit(err)),
} }
} }
} }