Implement RFC 11: Redesigning Wasmtime's APIs (#2897)

Implement Wasmtime's new API as designed by RFC 11. This is quite a large commit which has had lots of discussion externally, so for more information it's best to read the RFC thread and the PR thread.
This commit is contained in:
Alex Crichton
2021-06-03 09:10:53 -05:00
committed by GitHub
parent a5a28b1c5b
commit 7a1b7cdf92
233 changed files with 13349 additions and 11997 deletions

View File

@@ -9,11 +9,14 @@ wiggle::from_witx!({
impl_errno!(types::Errno);
impl<'a> atoms::Atoms for WasiCtx<'a> {
fn int_float_args(&self, an_int: u32, an_float: f32) -> Result<(), types::Errno> {
fn int_float_args(&mut self, an_int: u32, an_float: f32) -> Result<(), types::Errno> {
println!("INT FLOAT ARGS: {} {}", an_int, an_float);
Ok(())
}
fn double_int_return_float(&self, an_int: u32) -> Result<types::AliasToFloat, types::Errno> {
fn double_int_return_float(
&mut self,
an_int: u32,
) -> Result<types::AliasToFloat, types::Errno> {
Ok((an_int as f32) * 2.0)
}
}
@@ -28,10 +31,10 @@ struct IntFloatExercise {
impl IntFloatExercise {
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
let e = atoms::int_float_args(&ctx, &host_memory, self.an_int as i32, self.an_float);
let e = atoms::int_float_args(&mut ctx, &host_memory, self.an_int as i32, self.an_float);
assert_eq!(e, Ok(types::Errno::Ok as i32), "int_float_args error");
}
@@ -57,11 +60,11 @@ struct DoubleIntExercise {
impl DoubleIntExercise {
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
let e = atoms::double_int_return_float(
&ctx,
&mut ctx,
&host_memory,
self.input as i32,
self.return_loc.ptr as i32,

View File

@@ -14,12 +14,12 @@ impl_errno!(types::Errno);
#[wiggle::async_trait]
impl<'a> atoms::Atoms for WasiCtx<'a> {
async fn int_float_args(&self, an_int: u32, an_float: f32) -> Result<(), types::Errno> {
async fn int_float_args(&mut self, an_int: u32, an_float: f32) -> Result<(), types::Errno> {
println!("INT FLOAT ARGS: {} {}", an_int, an_float);
Ok(())
}
async fn double_int_return_float(
&self,
&mut self,
an_int: u32,
) -> Result<types::AliasToFloat, types::Errno> {
Ok((an_int as f32) * 2.0)
@@ -36,11 +36,11 @@ struct IntFloatExercise {
impl IntFloatExercise {
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
let e = run(atoms::int_float_args(
&ctx,
&mut ctx,
&host_memory,
self.an_int as i32,
self.an_float,
@@ -70,11 +70,11 @@ struct DoubleIntExercise {
impl DoubleIntExercise {
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
let e = run(atoms::double_int_return_float(
&ctx,
&mut ctx,
&host_memory,
self.input as i32,
self.return_loc.ptr as i32,

View File

@@ -31,7 +31,7 @@ mod convert_just_errno {
/// When the `errors` mapping in witx is non-empty, we need to impl the
/// types::UserErrorConversion trait that wiggle generates from that mapping.
impl<'a> types::UserErrorConversion for WasiCtx<'a> {
fn errno_from_rich_error(&self, e: RichError) -> Result<types::Errno, wiggle::Trap> {
fn errno_from_rich_error(&mut self, e: RichError) -> Result<types::Errno, wiggle::Trap> {
// WasiCtx can collect a Vec<String> log so we can test this. We're
// logging the Display impl that `thiserror::Error` provides us.
self.log.borrow_mut().push(e.to_string());
@@ -44,7 +44,7 @@ mod convert_just_errno {
}
impl<'a> one_error_conversion::OneErrorConversion for WasiCtx<'a> {
fn foo(&self, strike: u32) -> Result<(), RichError> {
fn foo(&mut self, strike: u32) -> Result<(), RichError> {
// We use the argument to this function to exercise all of the
// possible error cases we could hit here
match strike {
@@ -57,12 +57,12 @@ mod convert_just_errno {
#[test]
fn one_error_conversion_test() {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
// Exercise each of the branches in `foo`.
// Start with the success case:
let r0 = one_error_conversion::foo(&ctx, &host_memory, 0);
let r0 = one_error_conversion::foo(&mut ctx, &host_memory, 0);
assert_eq!(
r0,
Ok(types::Errno::Ok as i32),
@@ -71,7 +71,7 @@ mod convert_just_errno {
assert!(ctx.log.borrow().is_empty(), "No error log for strike=0");
// First error case:
let r1 = one_error_conversion::foo(&ctx, &host_memory, 1);
let r1 = one_error_conversion::foo(&mut ctx, &host_memory, 1);
assert_eq!(
r1,
Ok(types::Errno::PicketLine as i32),
@@ -84,7 +84,7 @@ mod convert_just_errno {
);
// Second error case:
let r2 = one_error_conversion::foo(&ctx, &host_memory, 2);
let r2 = one_error_conversion::foo(&mut ctx, &host_memory, 2);
assert_eq!(
r2,
Ok(types::Errno::InvalidArg as i32),
@@ -140,11 +140,11 @@ mod convert_multiple_error_types {
// each member of the `errors` mapping.
// Bodies elided.
impl<'a> types::UserErrorConversion for WasiCtx<'a> {
fn errno_from_rich_error(&self, _e: RichError) -> Result<types::Errno, wiggle::Trap> {
fn errno_from_rich_error(&mut self, _e: RichError) -> Result<types::Errno, wiggle::Trap> {
unimplemented!()
}
fn errno2_from_another_rich_error(
&self,
&mut self,
_e: AnotherRichError,
) -> Result<types::Errno2, wiggle::Trap> {
unimplemented!()
@@ -153,13 +153,13 @@ mod convert_multiple_error_types {
// And here's the witx module trait impl, bodies elided
impl<'a> two_error_conversions::TwoErrorConversions for WasiCtx<'a> {
fn foo(&self, _: u32) -> Result<(), RichError> {
fn foo(&mut self, _: u32) -> Result<(), RichError> {
unimplemented!()
}
fn bar(&self, _: u32) -> Result<(), AnotherRichError> {
fn bar(&mut self, _: u32) -> Result<(), AnotherRichError> {
unimplemented!()
}
fn baz(&self, _: u32) -> wiggle::Trap {
fn baz(&mut self, _: u32) -> wiggle::Trap {
unimplemented!()
}
}

View File

@@ -11,7 +11,7 @@ impl_errno!(types::Errno);
impl<'a> flags::Flags for WasiCtx<'a> {
fn configure_car(
&self,
&mut self,
old_config: types::CarConfig,
other_config_ptr: &GuestPtr<types::CarConfig>,
) -> Result<types::CarConfig, types::Errno> {
@@ -62,7 +62,7 @@ impl ConfigureCarExercise {
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
// Populate input ptr
@@ -72,7 +72,7 @@ impl ConfigureCarExercise {
.expect("deref ptr mut to CarConfig");
let res = flags::configure_car(
&ctx,
&mut ctx,
&host_memory,
self.old_config.bits() as i32,
self.other_config_by_ptr.ptr as i32,

View File

@@ -11,10 +11,10 @@ wiggle::from_witx!({
impl_errno!(types::Errno);
impl<'a> handle_examples::HandleExamples for WasiCtx<'a> {
fn fd_create(&self) -> Result<types::Fd, types::Errno> {
fn fd_create(&mut self) -> Result<types::Fd, types::Errno> {
Ok(types::Fd::from(FD_VAL))
}
fn fd_consume(&self, fd: types::Fd) -> Result<(), types::Errno> {
fn fd_consume(&mut self, fd: types::Fd) -> Result<(), types::Errno> {
println!("FD_CONSUME {}", fd);
if fd == types::Fd::from(FD_VAL) {
Ok(())
@@ -31,10 +31,10 @@ struct HandleExercise {
impl HandleExercise {
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
let e = handle_examples::fd_create(&ctx, &host_memory, self.return_loc.ptr as i32);
let e = handle_examples::fd_create(&mut ctx, &host_memory, self.return_loc.ptr as i32);
assert_eq!(e, Ok(types::Errno::Ok as i32), "fd_create error");
@@ -45,11 +45,11 @@ impl HandleExercise {
assert_eq!(h_got, 123, "fd_create return val");
let e = handle_examples::fd_consume(&ctx, &host_memory, h_got as i32);
let e = handle_examples::fd_consume(&mut ctx, &host_memory, h_got as i32);
assert_eq!(e, Ok(types::Errno::Ok as i32), "fd_consume error");
let e = handle_examples::fd_consume(&ctx, &host_memory, h_got as i32 + 1);
let e = handle_examples::fd_consume(&mut ctx, &host_memory, h_got as i32 + 1);
assert_eq!(
e,

View File

@@ -10,7 +10,7 @@ wiggle::from_witx!({
impl_errno!(types::Errno);
impl<'a> ints::Ints for WasiCtx<'a> {
fn cookie_cutter(&self, init_cookie: types::Cookie) -> Result<types::Bool, types::Errno> {
fn cookie_cutter(&mut self, init_cookie: types::Cookie) -> Result<types::Bool, types::Errno> {
let res = if init_cookie == types::COOKIE_START {
types::Bool::True
} else {
@@ -43,11 +43,11 @@ impl CookieCutterExercise {
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
let res = ints::cookie_cutter(
&ctx,
&mut ctx,
&host_memory,
self.cookie as i64,
self.return_ptr_loc.ptr as i32,

View File

@@ -33,7 +33,7 @@ mod module_trait_fn_and_arg_test {
});
impl<'a> self_::Self_ for WasiCtx<'a> {
#[allow(unused_variables)]
fn fn_(&self, use_: u32, virtual_: u32) {
fn fn_(&mut self, use_: u32, virtual_: u32) {
unimplemented!();
}
}

View File

@@ -10,7 +10,7 @@ impl_errno!(types::Errno);
impl<'a> lists::Lists for WasiCtx<'a> {
fn reduce_excuses(
&self,
&mut self,
excuses: &types::ConstExcuseArray,
) -> Result<types::Excuse, types::Errno> {
let last = &excuses
@@ -23,7 +23,7 @@ impl<'a> lists::Lists for WasiCtx<'a> {
Ok(last.read().expect("dereferencing ptr should succeed"))
}
fn populate_excuses(&self, excuses: &types::ExcuseArray) -> Result<(), types::Errno> {
fn populate_excuses(&mut self, excuses: &types::ExcuseArray) -> Result<(), types::Errno> {
for excuse in excuses.iter() {
let ptr_to_excuse = excuse
.expect("valid ptr to ptr")
@@ -74,7 +74,7 @@ impl ReduceExcusesExcercise {
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
// Populate memory with pointers to generated Excuse values
@@ -97,7 +97,7 @@ impl ReduceExcusesExcercise {
}
let res = lists::reduce_excuses(
&ctx,
&mut ctx,
&host_memory,
self.array_ptr_loc.ptr as i32,
self.excuse_ptr_locs.len() as i32,
@@ -162,7 +162,7 @@ impl PopulateExcusesExcercise {
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
// Populate array with valid pointers to Excuse type in memory
@@ -177,7 +177,7 @@ impl PopulateExcusesExcercise {
}
let res = lists::populate_excuses(
&ctx,
&mut ctx,
&host_memory,
self.array_ptr_loc.ptr as i32,
self.elements.len() as i32,
@@ -210,7 +210,7 @@ proptest! {
impl<'a> array_traversal::ArrayTraversal for WasiCtx<'a> {
fn sum_of_element(
&self,
&mut self,
elements: &GuestPtr<[types::PairInts]>,
index: u32,
) -> Result<i32, types::Errno> {
@@ -219,7 +219,7 @@ impl<'a> array_traversal::ArrayTraversal for WasiCtx<'a> {
Ok(pair.first.wrapping_add(pair.second))
}
fn sum_of_elements(
&self,
&mut self,
elements: &GuestPtr<[types::PairInts]>,
start: u32,
end: u32,
@@ -288,7 +288,7 @@ impl SumElementsExercise {
.boxed()
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
// Populate array
@@ -301,7 +301,7 @@ impl SumElementsExercise {
}
let res = array_traversal::sum_of_element(
&ctx,
&mut ctx,
&host_memory,
self.element_loc.ptr as i32,
self.elements.len() as i32,
@@ -320,7 +320,7 @@ impl SumElementsExercise {
// Off the end of the array:
let res = array_traversal::sum_of_element(
&ctx,
&mut ctx,
&host_memory,
self.element_loc.ptr as i32,
self.elements.len() as i32,
@@ -334,7 +334,7 @@ impl SumElementsExercise {
);
let res = array_traversal::sum_of_elements(
&ctx,
&mut ctx,
&host_memory,
self.element_loc.ptr as i32,
self.elements.len() as i32,
@@ -373,7 +373,7 @@ impl SumElementsExercise {
// Index an array off the end of the array:
let res = array_traversal::sum_of_elements(
&ctx,
&mut ctx,
&host_memory,
self.element_loc.ptr as i32,
self.elements.len() as i32,

View File

@@ -10,7 +10,7 @@ impl_errno!(types::Errno);
impl<'a> pointers::Pointers for WasiCtx<'a> {
fn pointers_and_enums<'b>(
&self,
&mut self,
input1: types::Excuse,
input2_ptr: &GuestPtr<'b, types::Excuse>,
input3_ptr: &GuestPtr<'b, types::Excuse>,
@@ -125,7 +125,7 @@ impl PointersAndEnumsExercise {
.boxed()
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
host_memory
@@ -149,7 +149,7 @@ impl PointersAndEnumsExercise {
.expect("input4 ptr ref_mut");
let e = pointers::pointers_and_enums(
&ctx,
&mut ctx,
&host_memory,
self.input1 as i32,
self.input2_loc.ptr as i32,

View File

@@ -9,11 +9,11 @@ wiggle::from_witx!({
impl_errno!(types::Errno);
impl<'a> records::Records for WasiCtx<'a> {
fn sum_of_pair(&self, an_pair: &types::PairInts) -> Result<i64, types::Errno> {
fn sum_of_pair(&mut self, an_pair: &types::PairInts) -> Result<i64, types::Errno> {
Ok(an_pair.first as i64 + an_pair.second as i64)
}
fn sum_of_pair_of_ptrs(&self, an_pair: &types::PairIntPtrs) -> Result<i64, types::Errno> {
fn sum_of_pair_of_ptrs(&mut self, an_pair: &types::PairIntPtrs) -> Result<i64, types::Errno> {
let first = an_pair
.first
.read()
@@ -25,7 +25,7 @@ impl<'a> records::Records for WasiCtx<'a> {
Ok(first as i64 + second as i64)
}
fn sum_of_int_and_ptr(&self, an_pair: &types::PairIntAndPtr) -> Result<i64, types::Errno> {
fn sum_of_int_and_ptr(&mut self, an_pair: &types::PairIntAndPtr) -> Result<i64, types::Errno> {
let first = an_pair
.first
.read()
@@ -34,7 +34,7 @@ impl<'a> records::Records for WasiCtx<'a> {
Ok(first as i64 + second)
}
fn return_pair_ints(&self) -> Result<types::PairInts, types::Errno> {
fn return_pair_ints(&mut self) -> Result<types::PairInts, types::Errno> {
Ok(types::PairInts {
first: 10,
second: 20,
@@ -42,7 +42,7 @@ impl<'a> records::Records for WasiCtx<'a> {
}
fn return_pair_of_ptrs<'b>(
&self,
&mut self,
first: &GuestPtr<'b, i32>,
second: &GuestPtr<'b, i32>,
) -> Result<types::PairIntPtrs<'b>, types::Errno> {
@@ -52,7 +52,10 @@ impl<'a> records::Records for WasiCtx<'a> {
})
}
fn sum_array<'b>(&self, record_of_list: &types::RecordOfList<'b>) -> Result<u16, types::Errno> {
fn sum_array<'b>(
&mut self,
record_of_list: &types::RecordOfList<'b>,
) -> Result<u16, types::Errno> {
// my kingdom for try blocks
fn aux(record_of_list: &types::RecordOfList) -> Result<u16, wiggle::GuestError> {
let mut s = 0;
@@ -99,7 +102,7 @@ impl SumOfPairExercise {
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
host_memory
@@ -111,7 +114,7 @@ impl SumOfPairExercise {
.write(self.input.second)
.expect("input ref_mut");
let sum_err = records::sum_of_pair(
&ctx,
&mut ctx,
&host_memory,
self.input_loc.ptr as i32,
self.return_loc.ptr as i32,
@@ -187,7 +190,7 @@ impl SumPairPtrsExercise {
.boxed()
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
host_memory
@@ -209,7 +212,7 @@ impl SumPairPtrsExercise {
.expect("input_struct ref");
let res = records::sum_of_pair_of_ptrs(
&ctx,
&mut ctx,
&host_memory,
self.input_struct_loc.ptr as i32,
self.return_loc.ptr as i32,
@@ -275,7 +278,7 @@ impl SumIntAndPtrExercise {
.boxed()
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
host_memory
@@ -292,7 +295,7 @@ impl SumIntAndPtrExercise {
.expect("input_struct ref");
let res = records::sum_of_int_and_ptr(
&ctx,
&mut ctx,
&host_memory,
self.input_struct_loc.ptr as i32,
self.return_loc.ptr as i32,
@@ -332,10 +335,10 @@ impl ReturnPairInts {
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
let err = records::return_pair_ints(&ctx, &host_memory, self.return_loc.ptr as i32);
let err = records::return_pair_ints(&mut ctx, &host_memory, self.return_loc.ptr as i32);
assert_eq!(err, Ok(types::Errno::Ok as i32), "return struct errno");
@@ -397,7 +400,7 @@ impl ReturnPairPtrsExercise {
.boxed()
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
host_memory
@@ -410,7 +413,7 @@ impl ReturnPairPtrsExercise {
.expect("input_second ref");
let res = records::return_pair_of_ptrs(
&ctx,
&mut ctx,
&host_memory,
self.input_first_loc.ptr as i32,
self.input_second_loc.ptr as i32,
@@ -498,7 +501,7 @@ impl SumArrayExercise {
.boxed()
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
// Write inputs to memory as an array
@@ -522,7 +525,7 @@ impl SumArrayExercise {
// Call wiggle-generated func
let res = records::sum_array(
&ctx,
&mut ctx,
&host_memory,
self.input_struct_loc.ptr as i32,
self.output_loc.ptr as i32,

View File

@@ -9,14 +9,14 @@ wiggle::from_witx!({
impl_errno!(types::Errno);
impl<'a> strings::Strings for WasiCtx<'a> {
fn hello_string(&self, a_string: &GuestPtr<str>) -> Result<u32, types::Errno> {
fn hello_string(&mut self, a_string: &GuestPtr<str>) -> Result<u32, types::Errno> {
let s = a_string.as_str().expect("should be valid string");
println!("a_string='{}'", &*s);
Ok(s.len() as u32)
}
fn multi_string(
&self,
&mut self,
a: &GuestPtr<str>,
b: &GuestPtr<str>,
c: &GuestPtr<str>,
@@ -69,7 +69,7 @@ impl HelloStringExercise {
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
// Populate string in guest's memory
@@ -81,7 +81,7 @@ impl HelloStringExercise {
}
let res = strings::hello_string(
&ctx,
&mut ctx,
&host_memory,
self.string_ptr_loc.ptr as i32,
self.test_word.len() as i32,
@@ -181,7 +181,7 @@ impl MultiStringExercise {
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
let write_string = |val: &str, loc: MemArea| {
@@ -198,7 +198,7 @@ impl MultiStringExercise {
write_string(&self.c, self.sc_ptr_loc);
let res = strings::multi_string(
&ctx,
&mut ctx,
&host_memory,
self.sa_ptr_loc.ptr as i32,
self.a.len() as i32,
@@ -260,7 +260,7 @@ impl OverlappingStringExercise {
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
let write_string = |val: &str, loc: MemArea| {
@@ -276,7 +276,7 @@ impl OverlappingStringExercise {
let a_len = self.a.as_bytes().len() as i32;
let res = strings::multi_string(
&ctx,
&mut ctx,
&host_memory,
self.sa_ptr_loc.ptr as i32,
a_len,

View File

@@ -31,7 +31,7 @@ fn mult_zero_nan(a: f32, b: u32) -> f32 {
}
impl<'a> variant_example::VariantExample for WasiCtx<'a> {
fn get_tag(&self, u: &types::Reason) -> Result<types::Excuse, types::Errno> {
fn get_tag(&mut self, u: &types::Reason) -> Result<types::Excuse, types::Errno> {
println!("GET TAG: {:?}", u);
match u {
types::Reason::DogAte { .. } => Ok(types::Excuse::DogAte),
@@ -39,7 +39,11 @@ impl<'a> variant_example::VariantExample for WasiCtx<'a> {
types::Reason::Sleeping { .. } => Ok(types::Excuse::Sleeping),
}
}
fn reason_mult(&self, u: &types::ReasonMut<'_>, multiply_by: u32) -> Result<(), types::Errno> {
fn reason_mult(
&mut self,
u: &types::ReasonMut<'_>,
multiply_by: u32,
) -> Result<(), types::Errno> {
match u {
types::ReasonMut::DogAte(fptr) => {
let val = fptr.read().expect("valid pointer");
@@ -104,7 +108,7 @@ impl GetTagExercise {
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
let discriminant = reason_tag(&self.input) as u8;
@@ -126,7 +130,7 @@ impl GetTagExercise {
types::Reason::Sleeping => {} // Do nothing
}
let e = variant_example::get_tag(
&ctx,
&mut ctx,
&host_memory,
self.input_loc.ptr as i32,
self.return_loc.ptr as i32,
@@ -181,7 +185,7 @@ impl ReasonMultExercise {
}
pub fn test(&self) {
let ctx = WasiCtx::new();
let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new();
let discriminant = reason_tag(&self.input) as u8;
@@ -210,7 +214,7 @@ impl ReasonMultExercise {
types::Reason::Sleeping => {} // Do nothing
}
let e = variant_example::reason_mult(
&ctx,
&mut ctx,
&host_memory,
self.input_loc.ptr as i32,
self.multiply_by as i32,

View File

@@ -32,32 +32,32 @@ impl GuestErrorType for types::Errno {
}
impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
fn args_get(&self, _argv: &GuestPtr<GuestPtr<u8>>, _argv_buf: &GuestPtr<u8>) -> Result<()> {
fn args_get(&mut self, _argv: &GuestPtr<GuestPtr<u8>>, _argv_buf: &GuestPtr<u8>) -> Result<()> {
unimplemented!("args_get")
}
fn args_sizes_get(&self) -> Result<(types::Size, types::Size)> {
fn args_sizes_get(&mut self) -> Result<(types::Size, types::Size)> {
unimplemented!("args_sizes_get")
}
fn environ_get(
&self,
&mut self,
_environ: &GuestPtr<GuestPtr<u8>>,
_environ_buf: &GuestPtr<u8>,
) -> Result<()> {
unimplemented!("environ_get")
}
fn environ_sizes_get(&self) -> Result<(types::Size, types::Size)> {
fn environ_sizes_get(&mut self) -> Result<(types::Size, types::Size)> {
unimplemented!("environ_sizes_get")
}
fn clock_res_get(&self, _id: types::Clockid) -> Result<types::Timestamp> {
fn clock_res_get(&mut self, _id: types::Clockid) -> Result<types::Timestamp> {
unimplemented!("clock_res_get")
}
fn clock_time_get(
&self,
&mut self,
_id: types::Clockid,
_precision: types::Timestamp,
) -> Result<types::Timestamp> {
@@ -65,7 +65,7 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
}
fn fd_advise(
&self,
&mut self,
_fd: types::Fd,
_offset: types::Filesize,
_len: types::Filesize,
@@ -75,7 +75,7 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
}
fn fd_allocate(
&self,
&mut self,
_fd: types::Fd,
_offset: types::Filesize,
_len: types::Filesize,
@@ -83,24 +83,24 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
unimplemented!("fd_allocate")
}
fn fd_close(&self, _fd: types::Fd) -> Result<()> {
fn fd_close(&mut self, _fd: types::Fd) -> Result<()> {
unimplemented!("fd_close")
}
fn fd_datasync(&self, _fd: types::Fd) -> Result<()> {
fn fd_datasync(&mut self, _fd: types::Fd) -> Result<()> {
unimplemented!("fd_datasync")
}
fn fd_fdstat_get(&self, _fd: types::Fd) -> Result<types::Fdstat> {
fn fd_fdstat_get(&mut self, _fd: types::Fd) -> Result<types::Fdstat> {
unimplemented!("fd_fdstat_get")
}
fn fd_fdstat_set_flags(&self, _fd: types::Fd, _flags: types::Fdflags) -> Result<()> {
fn fd_fdstat_set_flags(&mut self, _fd: types::Fd, _flags: types::Fdflags) -> Result<()> {
unimplemented!("fd_fdstat_set_flags")
}
fn fd_fdstat_set_rights(
&self,
&mut self,
_fd: types::Fd,
_fs_rights_base: types::Rights,
_fs_rights_inherting: types::Rights,
@@ -108,16 +108,16 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
unimplemented!("fd_fdstat_set_rights")
}
fn fd_filestat_get(&self, _fd: types::Fd) -> Result<types::Filestat> {
fn fd_filestat_get(&mut self, _fd: types::Fd) -> Result<types::Filestat> {
unimplemented!("fd_filestat_get")
}
fn fd_filestat_set_size(&self, _fd: types::Fd, _size: types::Filesize) -> Result<()> {
fn fd_filestat_set_size(&mut self, _fd: types::Fd, _size: types::Filesize) -> Result<()> {
unimplemented!("fd_filestat_set_size")
}
fn fd_filestat_set_times(
&self,
&mut self,
_fd: types::Fd,
_atim: types::Timestamp,
_mtim: types::Timestamp,
@@ -127,7 +127,7 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
}
fn fd_pread(
&self,
&mut self,
_fd: types::Fd,
iovs: &types::IovecArray<'_>,
_offset: types::Filesize,
@@ -158,12 +158,12 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
unimplemented!("fd_pread")
}
fn fd_prestat_get(&self, _fd: types::Fd) -> Result<types::Prestat> {
fn fd_prestat_get(&mut self, _fd: types::Fd) -> Result<types::Prestat> {
unimplemented!("fd_prestat_get")
}
fn fd_prestat_dir_name(
&self,
&mut self,
_fd: types::Fd,
_path: &GuestPtr<u8>,
_path_len: types::Size,
@@ -172,7 +172,7 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
}
fn fd_pwrite(
&self,
&mut self,
_fd: types::Fd,
_ciovs: &types::CiovecArray<'_>,
_offset: types::Filesize,
@@ -180,12 +180,12 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
unimplemented!("fd_pwrite")
}
fn fd_read(&self, _fd: types::Fd, _iovs: &types::IovecArray<'_>) -> Result<types::Size> {
fn fd_read(&mut self, _fd: types::Fd, _iovs: &types::IovecArray<'_>) -> Result<types::Size> {
unimplemented!("fd_read")
}
fn fd_readdir(
&self,
&mut self,
_fd: types::Fd,
_buf: &GuestPtr<u8>,
_buf_len: types::Size,
@@ -194,12 +194,12 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
unimplemented!("fd_readdir")
}
fn fd_renumber(&self, _fd: types::Fd, _to: types::Fd) -> Result<()> {
fn fd_renumber(&mut self, _fd: types::Fd, _to: types::Fd) -> Result<()> {
unimplemented!("fd_renumber")
}
fn fd_seek(
&self,
&mut self,
_fd: types::Fd,
_offset: types::Filedelta,
_whence: types::Whence,
@@ -207,24 +207,24 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
unimplemented!("fd_seek")
}
fn fd_sync(&self, _fd: types::Fd) -> Result<()> {
fn fd_sync(&mut self, _fd: types::Fd) -> Result<()> {
unimplemented!("fd_sync")
}
fn fd_tell(&self, _fd: types::Fd) -> Result<types::Filesize> {
fn fd_tell(&mut self, _fd: types::Fd) -> Result<types::Filesize> {
unimplemented!("fd_tell")
}
fn fd_write(&self, _fd: types::Fd, _ciovs: &types::CiovecArray<'_>) -> Result<types::Size> {
fn fd_write(&mut self, _fd: types::Fd, _ciovs: &types::CiovecArray<'_>) -> Result<types::Size> {
unimplemented!("fd_write")
}
fn path_create_directory(&self, _fd: types::Fd, _path: &GuestPtr<'_, str>) -> Result<()> {
fn path_create_directory(&mut self, _fd: types::Fd, _path: &GuestPtr<'_, str>) -> Result<()> {
unimplemented!("path_create_directory")
}
fn path_filestat_get(
&self,
&mut self,
_fd: types::Fd,
_flags: types::Lookupflags,
_path: &GuestPtr<'_, str>,
@@ -233,7 +233,7 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
}
fn path_filestat_set_times(
&self,
&mut self,
_fd: types::Fd,
_flags: types::Lookupflags,
_path: &GuestPtr<'_, str>,
@@ -245,7 +245,7 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
}
fn path_link(
&self,
&mut self,
_old_fd: types::Fd,
_old_flags: types::Lookupflags,
_old_path: &GuestPtr<'_, str>,
@@ -256,7 +256,7 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
}
fn path_open(
&self,
&mut self,
_fd: types::Fd,
_dirflags: types::Lookupflags,
_path: &GuestPtr<'_, str>,
@@ -269,7 +269,7 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
}
fn path_readlink(
&self,
&mut self,
_fd: types::Fd,
_path: &GuestPtr<'_, str>,
_buf: &GuestPtr<u8>,
@@ -278,12 +278,12 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
unimplemented!("path_readlink")
}
fn path_remove_directory(&self, _fd: types::Fd, _path: &GuestPtr<'_, str>) -> Result<()> {
fn path_remove_directory(&mut self, _fd: types::Fd, _path: &GuestPtr<'_, str>) -> Result<()> {
unimplemented!("path_remove_directory")
}
fn path_rename(
&self,
&mut self,
_fd: types::Fd,
_old_path: &GuestPtr<'_, str>,
_new_fd: types::Fd,
@@ -293,7 +293,7 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
}
fn path_symlink(
&self,
&mut self,
_old_path: &GuestPtr<'_, str>,
_fd: types::Fd,
_new_path: &GuestPtr<'_, str>,
@@ -301,12 +301,12 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
unimplemented!("path_symlink")
}
fn path_unlink_file(&self, _fd: types::Fd, _path: &GuestPtr<'_, str>) -> Result<()> {
fn path_unlink_file(&mut self, _fd: types::Fd, _path: &GuestPtr<'_, str>) -> Result<()> {
unimplemented!("path_unlink_file")
}
fn poll_oneoff(
&self,
&mut self,
_in_: &GuestPtr<types::Subscription>,
_out: &GuestPtr<types::Event>,
_nsubscriptions: types::Size,
@@ -314,24 +314,24 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
unimplemented!("poll_oneoff")
}
fn proc_exit(&self, _rval: types::Exitcode) -> wiggle::Trap {
fn proc_exit(&mut self, _rval: types::Exitcode) -> wiggle::Trap {
unimplemented!("proc_exit")
}
fn proc_raise(&self, _sig: types::Signal) -> Result<()> {
fn proc_raise(&mut self, _sig: types::Signal) -> Result<()> {
unimplemented!("proc_raise")
}
fn sched_yield(&self) -> Result<()> {
fn sched_yield(&mut self) -> Result<()> {
unimplemented!("sched_yield")
}
fn random_get(&self, _buf: &GuestPtr<u8>, _buf_len: types::Size) -> Result<()> {
fn random_get(&mut self, _buf: &GuestPtr<u8>, _buf_len: types::Size) -> Result<()> {
unimplemented!("random_get")
}
fn sock_recv(
&self,
&mut self,
_fd: types::Fd,
_ri_data: &types::IovecArray<'_>,
_ri_flags: types::Riflags,
@@ -340,7 +340,7 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
}
fn sock_send(
&self,
&mut self,
_fd: types::Fd,
_si_data: &types::CiovecArray<'_>,
_si_flags: types::Siflags,
@@ -348,7 +348,7 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
unimplemented!("sock_send")
}
fn sock_shutdown(&self, _fd: types::Fd, _how: types::Sdflags) -> Result<()> {
fn sock_shutdown(&mut self, _fd: types::Fd, _how: types::Sdflags) -> Result<()> {
unimplemented!("sock_shutdown")
}
}

View File

@@ -0,0 +1,160 @@
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
use wasmtime::{Config, Engine, Linker, Module, Store};
wiggle::from_witx!({
witx: ["$CARGO_MANIFEST_DIR/tests/atoms.witx"],
async: {
atoms::{double_int_return_float}
}
});
pub struct Ctx;
impl wiggle::GuestErrorType for types::Errno {
fn success() -> Self {
types::Errno::Ok
}
}
#[wiggle::async_trait]
impl atoms::Atoms for Ctx {
fn int_float_args(&mut self, an_int: u32, an_float: f32) -> Result<(), types::Errno> {
println!("INT FLOAT ARGS: {} {}", an_int, an_float);
Ok(())
}
async fn double_int_return_float(
&mut self,
an_int: u32,
) -> Result<types::AliasToFloat, types::Errno> {
Ok((an_int as f32) * 2.0)
}
}
#[test]
fn test_sync_host_func() {
let mut store = async_store();
let mut linker = Linker::new(store.engine());
atoms::add_to_linker(&mut linker, |cx| cx).unwrap();
let shim_mod = shim_module(linker.engine());
let shim_inst = run(linker.instantiate_async(&mut store, &shim_mod)).unwrap();
let results = run(shim_inst
.get_func(&mut store, "int_float_args_shim")
.unwrap()
.call_async(&mut store, &[0i32.into(), 123.45f32.into()]))
.unwrap();
assert_eq!(results.len(), 1, "one return value");
assert_eq!(
results[0].unwrap_i32(),
types::Errno::Ok as i32,
"int_float_args errno"
);
}
#[test]
fn test_async_host_func() {
let mut store = async_store();
let mut linker = Linker::new(store.engine());
atoms::add_to_linker(&mut linker, |cx| cx).unwrap();
let shim_mod = shim_module(linker.engine());
let shim_inst = run(linker.instantiate_async(&mut store, &shim_mod)).unwrap();
let input: i32 = 123;
let result_location: i32 = 0;
let results = run(shim_inst
.get_func(&mut store, "double_int_return_float_shim")
.unwrap()
.call_async(&mut store, &[input.into(), result_location.into()]))
.unwrap();
assert_eq!(results.len(), 1, "one return value");
assert_eq!(
results[0].unwrap_i32(),
types::Errno::Ok as i32,
"double_int_return_float errno"
);
// The actual result is in memory:
let mem = shim_inst.get_memory(&mut store, "memory").unwrap();
let mut result_bytes: [u8; 4] = [0, 0, 0, 0];
mem.read(&store, result_location as usize, &mut result_bytes)
.unwrap();
let result = f32::from_le_bytes(result_bytes);
assert_eq!((input * 2) as f32, result);
}
fn run<F: Future>(future: F) -> F::Output {
let mut f = Pin::from(Box::new(future));
let waker = dummy_waker();
let mut cx = Context::from_waker(&waker);
loop {
match f.as_mut().poll(&mut cx) {
Poll::Ready(val) => break val,
Poll::Pending => {}
}
}
}
fn dummy_waker() -> Waker {
return unsafe { Waker::from_raw(clone(5 as *const _)) };
unsafe fn clone(ptr: *const ()) -> RawWaker {
assert_eq!(ptr as usize, 5);
const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);
RawWaker::new(ptr, &VTABLE)
}
unsafe fn wake(ptr: *const ()) {
assert_eq!(ptr as usize, 5);
}
unsafe fn wake_by_ref(ptr: *const ()) {
assert_eq!(ptr as usize, 5);
}
unsafe fn drop(ptr: *const ()) {
assert_eq!(ptr as usize, 5);
}
}
fn async_store() -> Store<Ctx> {
Store::new(
&Engine::new(Config::new().async_support(true)).unwrap(),
Ctx,
)
}
// Wiggle expects the caller to have an exported memory. Wasmtime can only
// provide this if the caller is a WebAssembly module, so we need to write
// a shim module:
fn shim_module(engine: &Engine) -> Module {
Module::new(
engine,
r#"
(module
(memory 1)
(export "memory" (memory 0))
(import "atoms" "int_float_args" (func $int_float_args (param i32 f32) (result i32)))
(import "atoms" "double_int_return_float" (func $double_int_return_float (param i32 i32) (result i32)))
(func $int_float_args_shim (param i32 f32) (result i32)
local.get 0
local.get 1
call $int_float_args
)
(func $double_int_return_float_shim (param i32 i32) (result i32)
local.get 0
local.get 1
call $double_int_return_float
)
(export "int_float_args_shim" (func $int_float_args_shim))
(export "double_int_return_float_shim" (func $double_int_return_float_shim))
)
"#,
)
.unwrap()
}

View File

@@ -0,0 +1,134 @@
use wasmtime::{Engine, Linker, Module, Store};
// from_witx invocation says the func is async. This context doesn't support async!
wiggle::from_witx!({
witx: ["$CARGO_MANIFEST_DIR/tests/atoms.witx"],
async: {
atoms::{double_int_return_float}
}
});
pub mod integration {
// The integration invocation says the func is blocking, so it will still work.
wiggle::wasmtime_integration!({
target: crate,
witx: ["$CARGO_MANIFEST_DIR/tests/atoms.witx"],
block_on: {
atoms::{double_int_return_float}
}
});
}
pub struct Ctx;
impl wiggle::GuestErrorType for types::Errno {
fn success() -> Self {
types::Errno::Ok
}
}
#[wiggle::async_trait]
impl atoms::Atoms for Ctx {
fn int_float_args(&mut self, an_int: u32, an_float: f32) -> Result<(), types::Errno> {
println!("INT FLOAT ARGS: {} {}", an_int, an_float);
Ok(())
}
async fn double_int_return_float(
&mut self,
an_int: u32,
) -> Result<types::AliasToFloat, types::Errno> {
Ok((an_int as f32) * 2.0)
}
}
#[test]
fn test_sync_host_func() {
let engine = Engine::default();
let mut linker = Linker::new(&engine);
integration::add_atoms_to_linker(&mut linker, |cx| cx).unwrap();
let mut store = store(&engine);
let shim_mod = shim_module(&engine);
let shim_inst = linker.instantiate(&mut store, &shim_mod).unwrap();
let results = shim_inst
.get_func(&mut store, "int_float_args_shim")
.unwrap()
.call(&mut store, &[0i32.into(), 123.45f32.into()])
.unwrap();
assert_eq!(results.len(), 1, "one return value");
assert_eq!(
results[0].unwrap_i32(),
types::Errno::Ok as i32,
"int_float_args errno"
);
}
#[test]
fn test_async_host_func() {
let engine = Engine::default();
let mut linker = Linker::new(&engine);
integration::add_atoms_to_linker(&mut linker, |cx| cx).unwrap();
let mut store = store(&engine);
let shim_mod = shim_module(&engine);
let shim_inst = linker.instantiate(&mut store, &shim_mod).unwrap();
let input: i32 = 123;
let result_location: i32 = 0;
let results = shim_inst
.get_func(&mut store, "double_int_return_float_shim")
.unwrap()
.call(&mut store, &[input.into(), result_location.into()])
.unwrap();
assert_eq!(results.len(), 1, "one return value");
assert_eq!(
results[0].unwrap_i32(),
types::Errno::Ok as i32,
"double_int_return_float errno"
);
// The actual result is in memory:
let mem = shim_inst.get_memory(&mut store, "memory").unwrap();
let mut result_bytes: [u8; 4] = [0, 0, 0, 0];
mem.read(&store, result_location as usize, &mut result_bytes)
.unwrap();
let result = f32::from_le_bytes(result_bytes);
assert_eq!((input * 2) as f32, result);
}
fn store(engine: &Engine) -> Store<Ctx> {
Store::new(engine, Ctx)
}
// Wiggle expects the caller to have an exported memory. Wasmtime can only
// provide this if the caller is a WebAssembly module, so we need to write
// a shim module:
fn shim_module(engine: &Engine) -> Module {
Module::new(
engine,
r#"
(module
(memory 1)
(export "memory" (memory 0))
(import "atoms" "int_float_args" (func $int_float_args (param i32 f32) (result i32)))
(import "atoms" "double_int_return_float" (func $double_int_return_float (param i32 i32) (result i32)))
(func $int_float_args_shim (param i32 f32) (result i32)
local.get 0
local.get 1
call $int_float_args
)
(func $double_int_return_float_shim (param i32 i32) (result i32)
local.get 0
local.get 1
call $double_int_return_float
)
(export "int_float_args_shim" (func $int_float_args_shim))
(export "double_int_return_float_shim" (func $double_int_return_float_shim))
)
"#,
)
.unwrap()
}

View File

@@ -0,0 +1,122 @@
use wasmtime::{Engine, Linker, Module, Store};
wiggle::from_witx!({
witx: ["$CARGO_MANIFEST_DIR/tests/atoms.witx"],
block_on: {
atoms::double_int_return_float
}
});
pub struct Ctx;
impl wiggle::GuestErrorType for types::Errno {
fn success() -> Self {
types::Errno::Ok
}
}
#[wiggle::async_trait]
impl atoms::Atoms for Ctx {
fn int_float_args(&mut self, an_int: u32, an_float: f32) -> Result<(), types::Errno> {
println!("INT FLOAT ARGS: {} {}", an_int, an_float);
Ok(())
}
async fn double_int_return_float(
&mut self,
an_int: u32,
) -> Result<types::AliasToFloat, types::Errno> {
Ok((an_int as f32) * 2.0)
}
}
#[test]
fn test_sync_host_func() {
let engine = Engine::default();
let mut linker = Linker::new(&engine);
atoms::add_to_linker(&mut linker, |cx| cx).unwrap();
let mut store = store(&engine);
let shim_mod = shim_module(&engine);
let shim_inst = linker.instantiate(&mut store, &shim_mod).unwrap();
let results = shim_inst
.get_func(&mut store, "int_float_args_shim")
.unwrap()
.call(&mut store, &[0i32.into(), 123.45f32.into()])
.unwrap();
assert_eq!(results.len(), 1, "one return value");
assert_eq!(
results[0].unwrap_i32(),
types::Errno::Ok as i32,
"int_float_args errno"
);
}
#[test]
fn test_async_host_func() {
let engine = Engine::default();
let mut linker = Linker::new(&engine);
atoms::add_to_linker(&mut linker, |cx| cx).unwrap();
let mut store = store(&engine);
let shim_mod = shim_module(&engine);
let shim_inst = linker.instantiate(&mut store, &shim_mod).unwrap();
let input: i32 = 123;
let result_location: i32 = 0;
let results = shim_inst
.get_func(&mut store, "double_int_return_float_shim")
.unwrap()
.call(&mut store, &[input.into(), result_location.into()])
.unwrap();
assert_eq!(results.len(), 1, "one return value");
assert_eq!(
results[0].unwrap_i32(),
types::Errno::Ok as i32,
"double_int_return_float errno"
);
// The actual result is in memory:
let mem = shim_inst.get_memory(&mut store, "memory").unwrap();
let mut result_bytes: [u8; 4] = [0, 0, 0, 0];
mem.read(&store, result_location as usize, &mut result_bytes)
.unwrap();
let result = f32::from_le_bytes(result_bytes);
assert_eq!((input * 2) as f32, result);
}
fn store(engine: &Engine) -> Store<Ctx> {
Store::new(engine, Ctx)
}
// Wiggle expects the caller to have an exported memory. Wasmtime can only
// provide this if the caller is a WebAssembly module, so we need to write
// a shim module:
fn shim_module(engine: &Engine) -> Module {
Module::new(
engine,
r#"
(module
(memory 1)
(export "memory" (memory 0))
(import "atoms" "int_float_args" (func $int_float_args (param i32 f32) (result i32)))
(import "atoms" "double_int_return_float" (func $double_int_return_float (param i32 i32) (result i32)))
(func $int_float_args_shim (param i32 f32) (result i32)
local.get 0
local.get 1
call $int_float_args
)
(func $double_int_return_float_shim (param i32 i32) (result i32)
local.get 0
local.get 1
call $double_int_return_float
)
(export "int_float_args_shim" (func $int_float_args_shim))
(export "double_int_return_float_shim" (func $double_int_return_float_shim))
)
"#,
)
.unwrap()
}