Fixes #2418: Enhance wiggle to generate its UserErrorConverstion trait with a function that returns Result<abi_err, String> (#2419)

* 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.
This commit is contained in:
Tanya L. Crenshaw
2020-11-24 12:06:57 -08:00
committed by GitHub
parent 128c3bd749
commit b06ed39c1e
18 changed files with 84 additions and 84 deletions

View File

@@ -23,9 +23,9 @@ impl types::GuestErrorConversion for WasiCtx {
} }
impl types::UserErrorConversion for WasiCtx { impl types::UserErrorConversion for WasiCtx {
fn errno_from_error(&self, e: Error) -> Errno { fn errno_from_error(&self, e: Error) -> Result<Errno, String> {
debug!("Error: {:?}", e); debug!("Error: {:?}", e);
e.into() Ok(e.into())
} }
} }

View File

@@ -13,8 +13,6 @@ pub fn define(args: TokenStream) -> TokenStream {
let mut ret = TokenStream::new(); let mut ret = TokenStream::new();
let old = true;
for module in doc.modules() { for module in doc.modules() {
for func in module.funcs() { for func in module.funcs() {
// `proc_exit` is special; it's essentially an unwinding primitive, // `proc_exit` is special; it's essentially an unwinding primitive,
@@ -24,14 +22,14 @@ pub fn define(args: TokenStream) -> TokenStream {
continue; continue;
} }
ret.extend(generate_wrappers(&func, old)); ret.extend(generate_wrappers(&func));
} }
} }
return ret; return ret;
} }
fn generate_wrappers(func: &witx::InterfaceFunc, old: bool) -> TokenStream { fn generate_wrappers(func: &witx::InterfaceFunc) -> TokenStream {
let name = format_ident!("{}", func.name.as_str()); let name = format_ident!("{}", func.name.as_str());
let mut arg_declarations = Vec::new(); let mut arg_declarations = Vec::new();
let mut arg_names = Vec::new(); let mut arg_names = Vec::new();
@@ -101,33 +99,13 @@ fn generate_wrappers(func: &witx::InterfaceFunc, old: bool) -> TokenStream {
} }
}; };
let c_abi_name = if old {
format_ident!("old_wasi_common_{}", name)
} else {
format_ident!("wasi_common_{}", name)
};
quote! { quote! {
pub unsafe fn #name( pub unsafe fn #name(
wasi_ctx: &mut super::WasiCtx, wasi_ctx: &mut super::WasiCtx,
memory: &mut [u8], memory: &mut [u8],
#(#arg_declarations,)* #(#arg_declarations,)*
) -> #ret { ) -> Result<#ret, String> {
#body Ok({#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,)*
)
} }
} }
} }

View File

@@ -168,7 +168,7 @@ pub fn define_struct(args: TokenStream) -> TokenStream {
// The first result is returned bare right now... // The first result is returned bare right now...
if let Some(ret) = results.next() { if let Some(ret) = results.next() {
handle_early_error = quote! { return e.into() }; handle_early_error = quote! { return Ok(e.into()) };
match &*ret.tref.type_() { match &*ret.tref.type_() {
// Eventually we'll want to add support for more returned // Eventually we'll want to add support for more returned
// types, but for now let's just conform to what `*.witx` // types, but for now let's just conform to what `*.witx`
@@ -200,7 +200,7 @@ pub fn define_struct(args: TokenStream) -> TokenStream {
let my_cx = cx.clone(); let my_cx = cx.clone();
let #name_ident = wasmtime::Func::wrap( let #name_ident = wasmtime::Func::wrap(
store, store,
move |caller: wasmtime::Caller<'_> #(,#shim_arg_decls)*| -> #ret_ty { move |caller: wasmtime::Caller<'_> #(,#shim_arg_decls)*| -> Result<#ret_ty, wasmtime::Trap> {
tracing::trace!( tracing::trace!(
#format_str, #format_str,
#(#format_args),* #(#format_args),*
@@ -214,11 +214,15 @@ pub fn define_struct(args: TokenStream) -> TokenStream {
#handle_early_error #handle_early_error
} }
}; };
hostcalls::#name_ident( let result = hostcalls::#name_ident(
&mut my_cx.borrow_mut(), &mut my_cx.borrow_mut(),
memory.data_unchecked_mut(), memory.data_unchecked_mut(),
#(#hostcall_args),* #(#hostcall_args),*
) #cvt_ret );
match result {
Ok(r) => { return Ok(r #cvt_ret); },
Err(err) => { return Err(wasmtime::Trap::new(err)); },
}
} }
} }
); );

View File

@@ -22,7 +22,7 @@ impl types::GuestErrorConversion for WasiNnCtx {
} }
impl<'a> types::UserErrorConversion for WasiNnCtx { impl<'a> types::UserErrorConversion for WasiNnCtx {
fn errno_from_wasi_nn_error(&self, e: WasiNnError) -> Errno { fn errno_from_wasi_nn_error(&self, e: WasiNnError) -> Result<Errno, String> {
eprintln!("Host error: {:?}", e); eprintln!("Host error: {:?}", e);
match e { match e {
WasiNnError::OpenvinoError(_) => unimplemented!(), WasiNnError::OpenvinoError(_) => unimplemented!(),

View File

@@ -55,7 +55,7 @@ pub fn define_func(
let method = names.user_error_conversion_method(&user_err); let method = names.user_error_conversion_method(&user_err);
quote!(UserErrorConversion::#method(ctx, e)) quote!(UserErrorConversion::#method(ctx, e))
} else { } else {
quote!(e) quote!(Ok(e))
}; };
quote! { quote! {
let e = #conversion; let e = #conversion;
@@ -63,7 +63,10 @@ pub fn define_func(
#rt::tracing::Level::TRACE, #rt::tracing::Level::TRACE,
#name = #rt::tracing::field::debug(&e), #name = #rt::tracing::field::debug(&e),
); );
return #abi_ret::from(e); match e {
Ok(e) => { return Ok(#abi_ret::from(e)); },
Err(e) => { return Err(e); },
}
} }
}) })
.unwrap_or_else(|| quote!(())); .unwrap_or_else(|| quote!(()));
@@ -79,7 +82,7 @@ pub fn define_func(
quote! { quote! {
let e = #rt::GuestError::InFunc { funcname: #funcname, location: #location, err: Box::new(e.into()) }; let e = #rt::GuestError::InFunc { funcname: #funcname, location: #location, err: Box::new(e.into()) };
let err: #err_typename = GuestErrorConversion::#err_method(ctx, e); let err: #err_typename = GuestErrorConversion::#err_method(ctx, e);
return #abi_ret::from(err); return Ok(#abi_ret::from(err));
} }
} else { } else {
quote! { quote! {
@@ -161,17 +164,17 @@ pub fn define_func(
#rt::tracing::Level::TRACE, #rt::tracing::Level::TRACE,
success=#rt::tracing::field::display(&success) success=#rt::tracing::field::display(&success)
); );
#abi_ret::from(success) Ok(#abi_ret::from(success))
} }
} else { } else {
quote!() quote!(Ok(()))
}; };
let trait_name = names.trait_name(&module.name); let trait_name = names.trait_name(&module.name);
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) -> #abi_ret { quote!(pub fn #ident(#abi_args) -> Result<#abi_ret, String> {
let _span = #rt::tracing::span!( let _span = #rt::tracing::span!(
#rt::tracing::Level::TRACE, #rt::tracing::Level::TRACE,
"wiggle abi", "wiggle abi",

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) -> #abi_typename;) quote!(fn #methodname(&self, e: super::#user_typename) -> Result<#abi_typename, String>;)
}); });
let user_error_conversion = quote! { let user_error_conversion = quote! {
pub trait UserErrorConversion { pub trait UserErrorConversion {

View File

@@ -36,7 +36,7 @@ impl_errno!(types::Errno, types::GuestErrorConversion);
/// When the `errors` mapping in witx is non-empty, we need to impl the /// When the `errors` mapping in witx is non-empty, we need to impl the
/// types::UserErrorConversion trait that wiggle generates from that mapping. /// types::UserErrorConversion trait that wiggle generates from that mapping.
impl<'a> types::UserErrorConversion for WasiCtx<'a> { impl<'a> types::UserErrorConversion for WasiCtx<'a> {
fn errno_from_rich_error(&self, e: RichError) -> types::Errno { fn errno_from_rich_error(&self, e: RichError) -> Result<types::Errno, String> {
wiggle::tracing::debug!( wiggle::tracing::debug!(
rich_error = wiggle::tracing::field::debug(&e), rich_error = wiggle::tracing::field::debug(&e),
"error conversion" "error conversion"
@@ -46,8 +46,8 @@ impl<'a> types::UserErrorConversion for WasiCtx<'a> {
self.log.borrow_mut().push(e.to_string()); self.log.borrow_mut().push(e.to_string());
// Then do the trivial mapping down to the flat enum. // Then do the trivial mapping down to the flat enum.
match e { match e {
RichError::InvalidArg { .. } => types::Errno::InvalidArg, RichError::InvalidArg { .. } => Ok(types::Errno::InvalidArg),
RichError::PicketLine { .. } => types::Errno::PicketLine, RichError::PicketLine { .. } => Ok(types::Errno::PicketLine),
} }
} }
} }
@@ -90,7 +90,7 @@ fn main() {
let r0 = one_error_conversion::foo(&ctx, &host_memory, 0, 0, 8); let r0 = one_error_conversion::foo(&ctx, &host_memory, 0, 0, 8);
assert_eq!( assert_eq!(
r0, r0,
i32::from(types::Errno::Ok), Ok(i32::from(types::Errno::Ok)),
"Expected return value for strike=0" "Expected return value for strike=0"
); );
assert!(ctx.log.borrow().is_empty(), "No error log for strike=0"); assert!(ctx.log.borrow().is_empty(), "No error log for strike=0");
@@ -99,7 +99,7 @@ fn main() {
let r1 = one_error_conversion::foo(&ctx, &host_memory, 1, 0, 8); let r1 = one_error_conversion::foo(&ctx, &host_memory, 1, 0, 8);
assert_eq!( assert_eq!(
r1, r1,
i32::from(types::Errno::PicketLine), Ok(i32::from(types::Errno::PicketLine)),
"Expected return value for strike=1" "Expected return value for strike=1"
); );
assert_eq!( assert_eq!(
@@ -112,7 +112,7 @@ fn main() {
let r2 = one_error_conversion::foo(&ctx, &host_memory, 2, 0, 8); let r2 = one_error_conversion::foo(&ctx, &host_memory, 2, 0, 8);
assert_eq!( assert_eq!(
r2, r2,
i32::from(types::Errno::InvalidArg), Ok(i32::from(types::Errno::InvalidArg)),
"Expected return value for strike=2" "Expected return value for strike=2"
); );
assert_eq!( assert_eq!(

View File

@@ -105,7 +105,7 @@ impl ReduceExcusesExcercise {
self.return_ptr_loc.ptr as i32, self.return_ptr_loc.ptr as i32,
); );
assert_eq!(res, types::Errno::Ok.into(), "reduce excuses errno"); assert_eq!(res, Ok(types::Errno::Ok.into()), "reduce excuses errno");
let expected = *self let expected = *self
.excuse_values .excuse_values
@@ -183,7 +183,7 @@ impl PopulateExcusesExcercise {
self.array_ptr_loc.ptr as i32, self.array_ptr_loc.ptr as i32,
self.elements.len() as i32, self.elements.len() as i32,
); );
assert_eq!(res, types::Errno::Ok.into(), "populate excuses errno"); assert_eq!(res, Ok(types::Errno::Ok.into()), "populate excuses errno");
let arr: GuestPtr<'_, [GuestPtr<'_, types::Excuse>]> = let arr: GuestPtr<'_, [GuestPtr<'_, types::Excuse>]> =
host_memory.ptr((self.array_ptr_loc.ptr, self.elements.len() as u32)); host_memory.ptr((self.array_ptr_loc.ptr, self.elements.len() as u32));
@@ -309,7 +309,7 @@ impl SumElementsExercise {
self.start_ix as i32, self.start_ix as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); );
assert_eq!(res, types::Errno::Ok.into(), "sum_of_element errno"); assert_eq!(res, Ok(types::Errno::Ok.into()), "sum_of_element errno");
let result_ptr = host_memory.ptr::<i32>(self.return_loc.ptr); let result_ptr = host_memory.ptr::<i32>(self.return_loc.ptr);
let result = result_ptr.read().expect("read result"); let result = result_ptr.read().expect("read result");
@@ -330,7 +330,7 @@ impl SumElementsExercise {
); );
assert_eq!( assert_eq!(
res, res,
types::Errno::InvalidArg.into(), Ok(types::Errno::InvalidArg.into()),
"out of bounds sum_of_element errno" "out of bounds sum_of_element errno"
); );
@@ -346,7 +346,7 @@ impl SumElementsExercise {
if self.start_ix <= self.end_ix { if self.start_ix <= self.end_ix {
assert_eq!( assert_eq!(
res, res,
types::Errno::Ok.into(), Ok(types::Errno::Ok.into()),
"expected ok sum_of_elements errno" "expected ok sum_of_elements errno"
); );
let result_ptr = host_memory.ptr::<i32>(self.return_loc.ptr); let result_ptr = host_memory.ptr::<i32>(self.return_loc.ptr);
@@ -367,7 +367,7 @@ impl SumElementsExercise {
} else { } else {
assert_eq!( assert_eq!(
res, res,
types::Errno::InvalidArg.into(), Ok(types::Errno::InvalidArg.into()),
"expected error out-of-bounds sum_of_elements" "expected error out-of-bounds sum_of_elements"
); );
} }
@@ -384,7 +384,7 @@ impl SumElementsExercise {
); );
assert_eq!( assert_eq!(
res, res,
types::Errno::InvalidArg.into(), Ok(types::Errno::InvalidArg.into()),
"out of bounds sum_of_elements errno" "out of bounds sum_of_elements errno"
); );
} }

View File

@@ -34,7 +34,7 @@ impl IntFloatExercise {
let e = atoms::int_float_args(&ctx, &host_memory, self.an_int as i32, self.an_float); let e = atoms::int_float_args(&ctx, &host_memory, self.an_int as i32, self.an_float);
assert_eq!(e, types::Errno::Ok.into(), "int_float_args error"); assert_eq!(e, Ok(types::Errno::Ok.into()), "int_float_args error");
} }
pub fn strat() -> BoxedStrategy<Self> { pub fn strat() -> BoxedStrategy<Self> {
@@ -72,7 +72,7 @@ impl DoubleIntExercise {
.ptr::<types::AliasToFloat>(self.return_loc.ptr) .ptr::<types::AliasToFloat>(self.return_loc.ptr)
.read() .read()
.expect("failed to read return"); .expect("failed to read return");
assert_eq!(e, types::Errno::Ok.into(), "errno"); assert_eq!(e, Ok(types::Errno::Ok.into()), "errno");
assert_eq!(return_val, (self.input as f32) * 2.0, "return val"); assert_eq!(return_val, (self.input as f32) * 2.0, "return val");
} }

View File

@@ -34,14 +34,14 @@ mod convert_just_errno {
/// When the `errors` mapping in witx is non-empty, we need to impl the /// When the `errors` mapping in witx is non-empty, we need to impl the
/// types::UserErrorConversion trait that wiggle generates from that mapping. /// types::UserErrorConversion trait that wiggle generates from that mapping.
impl<'a> types::UserErrorConversion for WasiCtx<'a> { impl<'a> types::UserErrorConversion for WasiCtx<'a> {
fn errno_from_rich_error(&self, e: RichError) -> types::Errno { fn errno_from_rich_error(&self, e: RichError) -> Result<types::Errno, String> {
// WasiCtx can collect a Vec<String> log so we can test this. We're // WasiCtx can collect a Vec<String> log so we can test this. We're
// logging the Display impl that `thiserror::Error` provides us. // logging the Display impl that `thiserror::Error` provides us.
self.log.borrow_mut().push(e.to_string()); self.log.borrow_mut().push(e.to_string());
// Then do the trivial mapping down to the flat enum. // Then do the trivial mapping down to the flat enum.
match e { match e {
RichError::InvalidArg { .. } => types::Errno::InvalidArg, RichError::InvalidArg { .. } => Ok(types::Errno::InvalidArg),
RichError::PicketLine { .. } => types::Errno::PicketLine, RichError::PicketLine { .. } => Ok(types::Errno::PicketLine),
} }
} }
} }
@@ -68,7 +68,7 @@ mod convert_just_errno {
let r0 = one_error_conversion::foo(&ctx, &host_memory, 0); let r0 = one_error_conversion::foo(&ctx, &host_memory, 0);
assert_eq!( assert_eq!(
r0, r0,
i32::from(types::Errno::Ok), Ok(i32::from(types::Errno::Ok)),
"Expected return value for strike=0" "Expected return value for strike=0"
); );
assert!(ctx.log.borrow().is_empty(), "No error log for strike=0"); assert!(ctx.log.borrow().is_empty(), "No error log for strike=0");
@@ -77,7 +77,7 @@ mod convert_just_errno {
let r1 = one_error_conversion::foo(&ctx, &host_memory, 1); let r1 = one_error_conversion::foo(&ctx, &host_memory, 1);
assert_eq!( assert_eq!(
r1, r1,
i32::from(types::Errno::PicketLine), Ok(i32::from(types::Errno::PicketLine)),
"Expected return value for strike=1" "Expected return value for strike=1"
); );
assert_eq!( assert_eq!(
@@ -90,7 +90,7 @@ mod convert_just_errno {
let r2 = one_error_conversion::foo(&ctx, &host_memory, 2); let r2 = one_error_conversion::foo(&ctx, &host_memory, 2);
assert_eq!( assert_eq!(
r2, r2,
i32::from(types::Errno::InvalidArg), Ok(i32::from(types::Errno::InvalidArg)),
"Expected return value for strike=2" "Expected return value for strike=2"
); );
assert_eq!( assert_eq!(
@@ -159,10 +159,13 @@ mod convert_multiple_error_types {
// each member of the `errors` mapping. // each member of the `errors` mapping.
// Bodies elided. // Bodies elided.
impl<'a> types::UserErrorConversion for WasiCtx<'a> { impl<'a> types::UserErrorConversion for WasiCtx<'a> {
fn errno_from_rich_error(&self, _e: RichError) -> types::Errno { fn errno_from_rich_error(&self, _e: RichError) -> Result<types::Errno, String> {
unimplemented!() unimplemented!()
} }
fn errno2_from_another_rich_error(&self, _e: AnotherRichError) -> types::Errno2 { fn errno2_from_another_rich_error(
&self,
_e: AnotherRichError,
) -> Result<types::Errno2, String> {
unimplemented!() unimplemented!()
} }
} }

View File

@@ -79,7 +79,7 @@ impl ConfigureCarExercise {
self.other_config_by_ptr.ptr as i32, self.other_config_by_ptr.ptr as i32,
self.return_ptr_loc.ptr as i32, self.return_ptr_loc.ptr as i32,
); );
assert_eq!(res, types::Errno::Ok.into(), "configure car errno"); assert_eq!(res, Ok(types::Errno::Ok.into()), "configure car errno");
let res_config = host_memory let res_config = host_memory
.ptr::<types::CarConfig>(self.return_ptr_loc.ptr) .ptr::<types::CarConfig>(self.return_ptr_loc.ptr)

View File

@@ -37,7 +37,7 @@ impl HandleExercise {
let e = handle_examples::fd_create(&ctx, &host_memory, self.return_loc.ptr as i32); let e = handle_examples::fd_create(&ctx, &host_memory, self.return_loc.ptr as i32);
assert_eq!(e, types::Errno::Ok.into(), "fd_create error"); assert_eq!(e, Ok(types::Errno::Ok.into()), "fd_create error");
let h_got: u32 = host_memory let h_got: u32 = host_memory
.ptr(self.return_loc.ptr) .ptr(self.return_loc.ptr)
@@ -48,13 +48,13 @@ impl HandleExercise {
let e = handle_examples::fd_consume(&ctx, &host_memory, h_got as i32); let e = handle_examples::fd_consume(&ctx, &host_memory, h_got as i32);
assert_eq!(e, types::Errno::Ok.into(), "fd_consume error"); assert_eq!(e, Ok(types::Errno::Ok.into()), "fd_consume error");
let e = handle_examples::fd_consume(&ctx, &host_memory, h_got as i32 + 1); let e = handle_examples::fd_consume(&ctx, &host_memory, h_got as i32 + 1);
assert_eq!( assert_eq!(
e, e,
types::Errno::InvalidArg.into(), Ok(types::Errno::InvalidArg.into()),
"fd_consume invalid error" "fd_consume invalid error"
); );
} }

View File

@@ -53,7 +53,7 @@ impl CookieCutterExercise {
self.cookie.into(), self.cookie.into(),
self.return_ptr_loc.ptr as i32, self.return_ptr_loc.ptr as i32,
); );
assert_eq!(res, types::Errno::Ok.into(), "cookie cutter errno"); assert_eq!(res, Ok(types::Errno::Ok.into()), "cookie cutter errno");
let is_cookie_start = host_memory let is_cookie_start = host_memory
.ptr::<types::Bool>(self.return_ptr_loc.ptr) .ptr::<types::Bool>(self.return_ptr_loc.ptr)

View File

@@ -157,7 +157,7 @@ impl PointersAndEnumsExercise {
self.input3_loc.ptr as i32, self.input3_loc.ptr as i32,
self.input4_ptr_loc.ptr as i32, self.input4_ptr_loc.ptr as i32,
); );
assert_eq!(e, types::Errno::Ok.into(), "errno"); assert_eq!(e, Ok(types::Errno::Ok.into()), "errno");
// Implementation of pointers_and_enums writes input3 to the input2_loc: // Implementation of pointers_and_enums writes input3 to the input2_loc:
let written_to_input2_loc: i32 = host_memory let written_to_input2_loc: i32 = host_memory

View File

@@ -88,7 +88,7 @@ impl HelloStringExercise {
self.test_word.len() as i32, self.test_word.len() as i32,
self.return_ptr_loc.ptr as i32, self.return_ptr_loc.ptr as i32,
); );
assert_eq!(res, types::Errno::Ok.into(), "hello string errno"); assert_eq!(res, Ok(types::Errno::Ok.into()), "hello string errno");
let given = host_memory let given = host_memory
.ptr::<u32>(self.return_ptr_loc.ptr) .ptr::<u32>(self.return_ptr_loc.ptr)
@@ -209,7 +209,7 @@ impl MultiStringExercise {
self.c.len() as i32, self.c.len() as i32,
self.return_ptr_loc.ptr as i32, self.return_ptr_loc.ptr as i32,
); );
assert_eq!(res, types::Errno::Ok.into(), "multi string errno"); assert_eq!(res, Ok(types::Errno::Ok.into()), "multi string errno");
let given = host_memory let given = host_memory
.ptr::<u32>(self.return_ptr_loc.ptr) .ptr::<u32>(self.return_ptr_loc.ptr)
@@ -287,7 +287,7 @@ impl OverlappingStringExercise {
a_len - self.offset_c as i32, a_len - self.offset_c as i32,
self.return_ptr_loc.ptr as i32, self.return_ptr_loc.ptr as i32,
); );
assert_eq!(res, types::Errno::Ok.into(), "multi string errno"); assert_eq!(res, Ok(types::Errno::Ok.into()), "multi string errno");
let given = host_memory let given = host_memory
.ptr::<u32>(self.return_ptr_loc.ptr) .ptr::<u32>(self.return_ptr_loc.ptr)

View File

@@ -118,7 +118,7 @@ impl SumOfPairExercise {
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); );
assert_eq!(sum_err, types::Errno::Ok.into(), "sum errno"); assert_eq!(sum_err, Ok(types::Errno::Ok.into()), "sum errno");
let return_val: i64 = host_memory let return_val: i64 = host_memory
.ptr(self.return_loc.ptr) .ptr(self.return_loc.ptr)
@@ -216,7 +216,11 @@ impl SumPairPtrsExercise {
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); );
assert_eq!(res, types::Errno::Ok.into(), "sum of pair of ptrs errno"); assert_eq!(
res,
Ok(types::Errno::Ok.into()),
"sum of pair of ptrs errno"
);
let doubled: i64 = host_memory let doubled: i64 = host_memory
.ptr(self.return_loc.ptr) .ptr(self.return_loc.ptr)
@@ -295,7 +299,7 @@ impl SumIntAndPtrExercise {
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); );
assert_eq!(res, types::Errno::Ok.into(), "sum of int and ptr errno"); assert_eq!(res, Ok(types::Errno::Ok.into()), "sum of int and ptr errno");
let doubled: i64 = host_memory let doubled: i64 = host_memory
.ptr(self.return_loc.ptr) .ptr(self.return_loc.ptr)
@@ -334,7 +338,7 @@ impl ReturnPairInts {
let err = structs::return_pair_ints(&ctx, &host_memory, self.return_loc.ptr as i32); let err = structs::return_pair_ints(&ctx, &host_memory, self.return_loc.ptr as i32);
assert_eq!(err, types::Errno::Ok.into(), "return struct errno"); assert_eq!(err, Ok(types::Errno::Ok.into()), "return struct errno");
let return_struct: types::PairInts = host_memory let return_struct: types::PairInts = host_memory
.ptr(self.return_loc.ptr) .ptr(self.return_loc.ptr)
@@ -414,7 +418,11 @@ impl ReturnPairPtrsExercise {
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); );
assert_eq!(res, types::Errno::Ok.into(), "return pair of ptrs errno"); assert_eq!(
res,
Ok(types::Errno::Ok.into()),
"return pair of ptrs errno"
);
let ptr_pair_int_ptrs: types::PairIntPtrs<'_> = host_memory let ptr_pair_int_ptrs: types::PairIntPtrs<'_> = host_memory
.ptr(self.return_loc.ptr) .ptr(self.return_loc.ptr)
@@ -522,7 +530,7 @@ impl SumArrayExercise {
); );
// should be no error - if hostcall did a GuestError it should eprintln it. // should be no error - if hostcall did a GuestError it should eprintln it.
assert_eq!(res, types::Errno::Ok.into(), "reduce excuses errno"); assert_eq!(res, Ok(types::Errno::Ok.into()), "reduce excuses errno");
// Sum is inputs upcasted to u16 // Sum is inputs upcasted to u16
let expected: u16 = self.inputs.iter().map(|v| *v as u16).sum(); let expected: u16 = self.inputs.iter().map(|v| *v as u16).sum();

View File

@@ -133,7 +133,7 @@ impl GetTagExercise {
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); );
assert_eq!(e, types::Errno::Ok.into(), "get_tag errno"); assert_eq!(e, Ok(types::Errno::Ok.into()), "get_tag errno");
let return_val: types::Excuse = host_memory let return_val: types::Excuse = host_memory
.ptr(self.return_loc.ptr) .ptr(self.return_loc.ptr)
@@ -217,7 +217,7 @@ impl ReasonMultExercise {
self.multiply_by as i32, self.multiply_by as i32,
); );
assert_eq!(e, types::Errno::Ok.into(), "reason_mult errno"); assert_eq!(e, Ok(types::Errno::Ok.into()), "reason_mult errno");
match self.input { match self.input {
types::Reason::DogAte(f) => { types::Reason::DogAte(f) => {

View File

@@ -185,7 +185,7 @@ fn generate_func(
witx::CoreParamSignifies::Value(atom) => names.atom_type(atom), witx::CoreParamSignifies::Value(atom) => names.atom_type(atom),
_ => unreachable!("coretype ret should always be passed by value"), _ => unreachable!("coretype ret should always be passed by value"),
}; };
(quote! { #ret_ty }, quote! { return e.into(); }) (quote! { #ret_ty }, quote! { return Ok(e.into()); })
} else { } else {
( (
quote! {()}, quote! {()},
@@ -199,7 +199,7 @@ fn generate_func(
let my_cx = cx.clone(); let my_cx = cx.clone();
let #name_ident = wasmtime::Func::wrap( let #name_ident = wasmtime::Func::wrap(
store, store,
move |caller: wasmtime::Caller<'_> #(,#arg_decls)*| -> #ret_ty { move |caller: wasmtime::Caller<'_> #(,#arg_decls)*| -> Result<#ret_ty, wasmtime::Trap> {
unsafe { unsafe {
let mem = match caller.get_export("memory") { let mem = match caller.get_export("memory") {
Some(wasmtime::Extern::Memory(m)) => m, Some(wasmtime::Extern::Memory(m)) => m,
@@ -210,11 +210,15 @@ fn generate_func(
} }
}; };
let mem = #runtime::WasmtimeGuestMemory::new(mem); let mem = #runtime::WasmtimeGuestMemory::new(mem);
#target_module::#name_ident( let result = #target_module::#name_ident(
&mut my_cx.borrow_mut(), &mut my_cx.borrow_mut(),
&mem, &mem,
#(#arg_names),* #(#arg_names),*
) );
match result {
Ok(r) => {return Ok(r.into());},
Err(err) => { return Err(wasmtime::Trap::new(err)); },
}
} }
} }
); );