wiggle: get BorrowChecker from GuestMemory method

This commit is contained in:
Pat Hickey
2020-05-21 12:37:14 -07:00
parent 3920d8c1f3
commit 96d6884d33
13 changed files with 112 additions and 128 deletions

View File

@@ -26,7 +26,6 @@ pub fn define_func(
let abi_args = quote!( let abi_args = quote!(
ctx: &#ctx_type, ctx: &#ctx_type,
memory: &dyn #rt::GuestMemory, memory: &dyn #rt::GuestMemory,
bc: &#rt::BorrowChecker,
#(#params),* #(#params),*
); );
let abi_ret = if let Some(ret) = &coretype.ret { let abi_ret = if let Some(ret) = &coretype.ret {
@@ -212,7 +211,7 @@ fn marshal_arg(
let arg_name = names.func_ptr_binding(&param.name); let arg_name = names.func_ptr_binding(&param.name);
let name = names.func_param(&param.name); let name = names.func_param(&param.name);
quote! { quote! {
let #name = match #rt::GuestPtr::<#pointee_type>::new(memory, bc, #arg_name as u32).read() { let #name = match #rt::GuestPtr::<#pointee_type>::new(memory, #arg_name as u32).read() {
Ok(r) => r, Ok(r) => r,
Err(e) => { Err(e) => {
#error_handling #error_handling
@@ -258,7 +257,7 @@ fn marshal_arg(
let len_name = names.func_len_binding(&param.name); let len_name = names.func_len_binding(&param.name);
let name = names.func_param(&param.name); let name = names.func_param(&param.name);
quote! { quote! {
let #name = #rt::GuestPtr::<#lifetime, str>::new(memory, bc, (#ptr_name as u32, #len_name as u32)); let #name = #rt::GuestPtr::<#lifetime, str>::new(memory, (#ptr_name as u32, #len_name as u32));
} }
} }
}, },
@@ -266,7 +265,7 @@ fn marshal_arg(
let pointee_type = names.type_ref(pointee, anon_lifetime()); let pointee_type = names.type_ref(pointee, anon_lifetime());
let name = names.func_param(&param.name); let name = names.func_param(&param.name);
quote! { quote! {
let #name = #rt::GuestPtr::<#pointee_type>::new(memory, bc, #name as u32); let #name = #rt::GuestPtr::<#pointee_type>::new(memory, #name as u32);
} }
} }
witx::Type::Struct(_) => read_conversion, witx::Type::Struct(_) => read_conversion,
@@ -276,7 +275,7 @@ fn marshal_arg(
let len_name = names.func_len_binding(&param.name); let len_name = names.func_len_binding(&param.name);
let name = names.func_param(&param.name); let name = names.func_param(&param.name);
quote! { quote! {
let #name = #rt::GuestPtr::<[#pointee_type]>::new(memory, bc, (#ptr_name as u32, #len_name as u32)); let #name = #rt::GuestPtr::<[#pointee_type]>::new(memory, (#ptr_name as u32, #len_name as u32));
} }
} }
witx::Type::Union(_u) => read_conversion, witx::Type::Union(_u) => read_conversion,
@@ -305,7 +304,7 @@ where
let ptr_name = names.func_ptr_binding(&result.name); let ptr_name = names.func_ptr_binding(&result.name);
let ptr_err_handling = error_handling(&format!("{}:result_ptr_mut", result.name.as_str())); let ptr_err_handling = error_handling(&format!("{}:result_ptr_mut", result.name.as_str()));
let pre = quote! { let pre = quote! {
let #ptr_name = #rt::GuestPtr::<#pointee_type>::new(memory, bc, #ptr_name as u32); let #ptr_name = #rt::GuestPtr::<#pointee_type>::new(memory, #ptr_name as u32);
}; };
// trait binding returns func_param name. // trait binding returns func_param name.
let val_name = names.func_param(&result.name); let val_name = names.func_param(&result.name);

View File

@@ -146,7 +146,7 @@ impl<'a, T> GuestType<'a> for GuestPtr<'a, T> {
fn read(ptr: &GuestPtr<'a, Self>) -> Result<Self, GuestError> { fn read(ptr: &GuestPtr<'a, Self>) -> Result<Self, GuestError> {
let offset = ptr.cast::<u32>().read()?; let offset = ptr.cast::<u32>().read()?;
Ok(GuestPtr::new(ptr.mem(), ptr.borrow_checker(), offset)) Ok(GuestPtr::new(ptr.mem(), offset))
} }
fn write(ptr: &GuestPtr<'_, Self>, val: Self) -> Result<(), GuestError> { fn write(ptr: &GuestPtr<'_, Self>, val: Self) -> Result<(), GuestError> {

View File

@@ -65,7 +65,7 @@ pub use region::Region;
/// into the memory region given by a `GuestMemory`. /// into the memory region given by a `GuestMemory`.
/// ///
/// These smart pointers are dynamically borrow-checked by the `BorrowChecker` /// These smart pointers are dynamically borrow-checked by the `BorrowChecker`
/// passed to the wiggle-generated ABI-level functions. While a `GuestSlice` /// given by [`GuestMemory::borrow_checker()`]. While a `GuestSlice`
/// or a `GuestStr` are live, the [`BorrowChecker::has_outstanding_borrows()`] /// or a `GuestStr` are live, the [`BorrowChecker::has_outstanding_borrows()`]
/// method will always return `true`. If you need to re-enter the guest or /// method will always return `true`. If you need to re-enter the guest or
/// otherwise read or write to the contents of a WebAssembly memory, all /// otherwise read or write to the contents of a WebAssembly memory, all
@@ -84,6 +84,11 @@ pub unsafe trait GuestMemory {
/// [`GuestMemory`] documentation. /// [`GuestMemory`] documentation.
fn base(&self) -> (*mut u8, u32); fn base(&self) -> (*mut u8, u32);
/// Gives a reference to the [`BorrowChecker`] used to keep track of each
/// outstanding borrow of the memory region. [`BorrowChecker::new`] safety
/// rules require that exactly one checker exist for each memory region.
fn borrow_checker(&self) -> &BorrowChecker;
/// Validates a guest-relative pointer given various attributes, and returns /// Validates a guest-relative pointer given various attributes, and returns
/// the corresponding host pointer. /// the corresponding host pointer.
/// ///
@@ -138,12 +143,12 @@ pub unsafe trait GuestMemory {
/// Note that `T` can be almost any type, and typically `offset` is a `u32`. /// Note that `T` can be almost any type, and typically `offset` is a `u32`.
/// The exception is slices and strings, in which case `offset` is a `(u32, /// The exception is slices and strings, in which case `offset` is a `(u32,
/// u32)` of `(offset, length)`. /// u32)` of `(offset, length)`.
fn ptr<'a, T>(&'a self, bc: &'a BorrowChecker, offset: T::Pointer) -> GuestPtr<'a, T> fn ptr<'a, T>(&'a self, offset: T::Pointer) -> GuestPtr<'a, T>
where where
Self: Sized, Self: Sized,
T: ?Sized + Pointee, T: ?Sized + Pointee,
{ {
GuestPtr::new(self, bc, offset) GuestPtr::new(self, offset)
} }
} }
@@ -153,30 +158,45 @@ unsafe impl<'a, T: ?Sized + GuestMemory> GuestMemory for &'a T {
fn base(&self) -> (*mut u8, u32) { fn base(&self) -> (*mut u8, u32) {
T::base(self) T::base(self)
} }
fn borrow_checker(&self) -> &BorrowChecker {
T::borrow_checker(self)
}
} }
unsafe impl<'a, T: ?Sized + GuestMemory> GuestMemory for &'a mut T { unsafe impl<'a, T: ?Sized + GuestMemory> GuestMemory for &'a mut T {
fn base(&self) -> (*mut u8, u32) { fn base(&self) -> (*mut u8, u32) {
T::base(self) T::base(self)
} }
fn borrow_checker(&self) -> &BorrowChecker {
T::borrow_checker(self)
}
} }
unsafe impl<T: ?Sized + GuestMemory> GuestMemory for Box<T> { unsafe impl<T: ?Sized + GuestMemory> GuestMemory for Box<T> {
fn base(&self) -> (*mut u8, u32) { fn base(&self) -> (*mut u8, u32) {
T::base(self) T::base(self)
} }
fn borrow_checker(&self) -> &BorrowChecker {
T::borrow_checker(self)
}
} }
unsafe impl<T: ?Sized + GuestMemory> GuestMemory for Rc<T> { unsafe impl<T: ?Sized + GuestMemory> GuestMemory for Rc<T> {
fn base(&self) -> (*mut u8, u32) { fn base(&self) -> (*mut u8, u32) {
T::base(self) T::base(self)
} }
fn borrow_checker(&self) -> &BorrowChecker {
T::borrow_checker(self)
}
} }
unsafe impl<T: ?Sized + GuestMemory> GuestMemory for Arc<T> { unsafe impl<T: ?Sized + GuestMemory> GuestMemory for Arc<T> {
fn base(&self) -> (*mut u8, u32) { fn base(&self) -> (*mut u8, u32) {
T::base(self) T::base(self)
} }
fn borrow_checker(&self) -> &BorrowChecker {
T::borrow_checker(self)
}
} }
/// A *guest* pointer into host memory. /// A *guest* pointer into host memory.
@@ -229,7 +249,6 @@ unsafe impl<T: ?Sized + GuestMemory> GuestMemory for Arc<T> {
/// already-attached helper methods. /// already-attached helper methods.
pub struct GuestPtr<'a, T: ?Sized + Pointee> { pub struct GuestPtr<'a, T: ?Sized + Pointee> {
mem: &'a (dyn GuestMemory + 'a), mem: &'a (dyn GuestMemory + 'a),
bc: &'a BorrowChecker,
pointer: T::Pointer, pointer: T::Pointer,
_marker: marker::PhantomData<&'a Cell<T>>, _marker: marker::PhantomData<&'a Cell<T>>,
} }
@@ -240,14 +259,9 @@ impl<'a, T: ?Sized + Pointee> GuestPtr<'a, T> {
/// Note that for sized types like `u32`, `GuestPtr<T>`, etc, the `pointer` /// Note that for sized types like `u32`, `GuestPtr<T>`, etc, the `pointer`
/// vlue is a `u32` offset into guest memory. For slices and strings, /// vlue is a `u32` offset into guest memory. For slices and strings,
/// `pointer` is a `(u32, u32)` offset/length pair. /// `pointer` is a `(u32, u32)` offset/length pair.
pub fn new( pub fn new(mem: &'a (dyn GuestMemory + 'a), pointer: T::Pointer) -> GuestPtr<'a, T> {
mem: &'a (dyn GuestMemory + 'a),
bc: &'a BorrowChecker,
pointer: T::Pointer,
) -> GuestPtr<'a, T> {
GuestPtr { GuestPtr {
mem, mem,
bc,
pointer, pointer,
_marker: marker::PhantomData, _marker: marker::PhantomData,
} }
@@ -268,7 +282,7 @@ impl<'a, T: ?Sized + Pointee> GuestPtr<'a, T> {
/// Returns the borrow checker that this pointer uses /// Returns the borrow checker that this pointer uses
pub fn borrow_checker(&self) -> &'a BorrowChecker { pub fn borrow_checker(&self) -> &'a BorrowChecker {
self.bc self.mem.borrow_checker()
} }
/// Casts this `GuestPtr` type to a different type. /// Casts this `GuestPtr` type to a different type.
@@ -281,7 +295,7 @@ impl<'a, T: ?Sized + Pointee> GuestPtr<'a, T> {
where where
T: Pointee<Pointer = u32>, T: Pointee<Pointer = u32>,
{ {
GuestPtr::new(self.mem, self.bc, self.pointer) GuestPtr::new(self.mem, self.pointer)
} }
/// Safely read a value from this pointer. /// Safely read a value from this pointer.
@@ -348,7 +362,7 @@ impl<'a, T: ?Sized + Pointee> GuestPtr<'a, T> {
Some(o) => o, Some(o) => o,
None => return Err(GuestError::PtrOverflow), None => return Err(GuestError::PtrOverflow),
}; };
Ok(GuestPtr::new(self.mem, self.bc, offset)) Ok(GuestPtr::new(self.mem, offset))
} }
/// Returns a `GuestPtr` for an array of `T`s using this pointer as the /// Returns a `GuestPtr` for an array of `T`s using this pointer as the
@@ -357,7 +371,7 @@ impl<'a, T: ?Sized + Pointee> GuestPtr<'a, T> {
where where
T: GuestType<'a> + Pointee<Pointer = u32>, T: GuestType<'a> + Pointee<Pointer = u32>,
{ {
GuestPtr::new(self.mem, self.bc, (self.pointer, elems)) GuestPtr::new(self.mem, (self.pointer, elems))
} }
} }
@@ -410,7 +424,7 @@ impl<'a, T> GuestPtr<'a, [T]> {
self.mem self.mem
.validate_size_align(self.pointer.0, T::guest_align(), len)? as *mut T; .validate_size_align(self.pointer.0, T::guest_align(), len)? as *mut T;
let borrow = self.bc.borrow(Region { let borrow = self.mem.borrow_checker().borrow(Region {
start: self.pointer.0, start: self.pointer.0,
len, len,
})?; })?;
@@ -426,7 +440,7 @@ impl<'a, T> GuestPtr<'a, [T]> {
Ok(GuestSlice { Ok(GuestSlice {
ptr, ptr,
bc: self.bc, bc: self.mem.borrow_checker(),
borrow, borrow,
}) })
} }
@@ -461,7 +475,7 @@ impl<'a, T> GuestPtr<'a, [T]> {
/// Returns a `GuestPtr` pointing to the base of the array for the interior /// Returns a `GuestPtr` pointing to the base of the array for the interior
/// type `T`. /// type `T`.
pub fn as_ptr(&self) -> GuestPtr<'a, T> { pub fn as_ptr(&self) -> GuestPtr<'a, T> {
GuestPtr::new(self.mem, self.bc, self.offset_base()) GuestPtr::new(self.mem, self.offset_base())
} }
} }
@@ -480,7 +494,7 @@ impl<'a> GuestPtr<'a, str> {
/// Returns a raw pointer for the underlying slice of bytes that this /// Returns a raw pointer for the underlying slice of bytes that this
/// pointer points to. /// pointer points to.
pub fn as_bytes(&self) -> GuestPtr<'a, [u8]> { pub fn as_bytes(&self) -> GuestPtr<'a, [u8]> {
GuestPtr::new(self.mem, self.bc, self.pointer) GuestPtr::new(self.mem, self.pointer)
} }
/// Attempts to create a [`GuestStr<'_>`] from this pointer, performing /// Attempts to create a [`GuestStr<'_>`] from this pointer, performing
@@ -497,7 +511,7 @@ impl<'a> GuestPtr<'a, str> {
.mem .mem
.validate_size_align(self.pointer.0, 1, self.pointer.1)?; .validate_size_align(self.pointer.0, 1, self.pointer.1)?;
let borrow = self.bc.borrow(Region { let borrow = self.mem.borrow_checker().borrow(Region {
start: self.pointer.0, start: self.pointer.0,
len: self.pointer.1, len: self.pointer.1,
})?; })?;
@@ -509,7 +523,7 @@ impl<'a> GuestPtr<'a, str> {
match str::from_utf8_mut(ptr) { match str::from_utf8_mut(ptr) {
Ok(ptr) => Ok(GuestStr { Ok(ptr) => Ok(GuestStr {
ptr, ptr,
bc: self.bc, bc: self.mem.borrow_checker(),
borrow, borrow,
}), }),
Err(e) => Err(GuestError::InvalidUtf8(e)), Err(e) => Err(GuestError::InvalidUtf8(e)),

View File

@@ -1,7 +1,7 @@
use proptest::prelude::*; use proptest::prelude::*;
use std::cell::UnsafeCell; use std::cell::UnsafeCell;
use std::marker; use std::marker;
use wiggle::GuestMemory; use wiggle::{BorrowChecker, GuestMemory};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct MemAreas(Vec<MemArea>); pub struct MemAreas(Vec<MemArea>);
@@ -45,11 +45,13 @@ impl Into<Vec<MemArea>> for MemAreas {
#[repr(align(4096))] #[repr(align(4096))]
pub struct HostMemory { pub struct HostMemory {
buffer: UnsafeCell<[u8; 4096]>, buffer: UnsafeCell<[u8; 4096]>,
bc: BorrowChecker,
} }
impl HostMemory { impl HostMemory {
pub fn new() -> Self { pub fn new() -> Self {
HostMemory { HostMemory {
buffer: UnsafeCell::new([0; 4096]), buffer: UnsafeCell::new([0; 4096]),
bc: unsafe { BorrowChecker::new() },
} }
} }
@@ -111,6 +113,9 @@ unsafe impl GuestMemory for HostMemory {
((*ptr).as_mut_ptr(), (*ptr).len() as u32) ((*ptr).as_mut_ptr(), (*ptr).len() as u32)
} }
} }
fn borrow_checker(&self) -> &BorrowChecker {
&self.bc
}
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]

View File

@@ -1,5 +1,5 @@
use proptest::prelude::*; use proptest::prelude::*;
use wiggle::{BorrowChecker, GuestMemory, GuestPtr}; use wiggle::{GuestMemory, GuestPtr};
use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx};
wiggle::from_witx!({ wiggle::from_witx!({
@@ -77,25 +77,22 @@ impl ReduceExcusesExcercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
// Populate memory with pointers to generated Excuse values // Populate memory with pointers to generated Excuse values
for (&excuse, ptr) in self.excuse_values.iter().zip(self.excuse_ptr_locs.iter()) { for (&excuse, ptr) in self.excuse_values.iter().zip(self.excuse_ptr_locs.iter()) {
host_memory host_memory
.ptr(&bc, ptr.ptr) .ptr(ptr.ptr)
.write(excuse) .write(excuse)
.expect("deref ptr mut to Excuse value"); .expect("deref ptr mut to Excuse value");
} }
// Populate the array with pointers to generated Excuse values // Populate the array with pointers to generated Excuse values
{ {
let array: GuestPtr<'_, [GuestPtr<types::Excuse>]> = host_memory.ptr( let array: GuestPtr<'_, [GuestPtr<types::Excuse>]> =
&bc, host_memory.ptr((self.array_ptr_loc.ptr, self.excuse_ptr_locs.len() as u32));
(self.array_ptr_loc.ptr, self.excuse_ptr_locs.len() as u32),
);
for (slot, ptr) in array.iter().zip(&self.excuse_ptr_locs) { for (slot, ptr) in array.iter().zip(&self.excuse_ptr_locs) {
let slot = slot.expect("array should be in bounds"); let slot = slot.expect("array should be in bounds");
slot.write(host_memory.ptr(&bc, ptr.ptr)) slot.write(host_memory.ptr(ptr.ptr))
.expect("should succeed in writing array"); .expect("should succeed in writing array");
} }
} }
@@ -103,7 +100,6 @@ impl ReduceExcusesExcercise {
let res = arrays::reduce_excuses( let res = arrays::reduce_excuses(
&ctx, &ctx,
&host_memory, &host_memory,
&bc,
self.array_ptr_loc.ptr as i32, self.array_ptr_loc.ptr as i32,
self.excuse_ptr_locs.len() as i32, self.excuse_ptr_locs.len() as i32,
self.return_ptr_loc.ptr as i32, self.return_ptr_loc.ptr as i32,
@@ -116,7 +112,7 @@ impl ReduceExcusesExcercise {
.last() .last()
.expect("generated vec of excuses should be non-empty"); .expect("generated vec of excuses should be non-empty");
let given: types::Excuse = host_memory let given: types::Excuse = host_memory
.ptr(&bc, self.return_ptr_loc.ptr) .ptr(self.return_ptr_loc.ptr)
.read() .read()
.expect("deref ptr to returned value"); .expect("deref ptr to returned value");
assert_eq!(expected, given, "reduce excuses return val"); assert_eq!(expected, given, "reduce excuses return val");
@@ -169,30 +165,28 @@ impl PopulateExcusesExcercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
// Populate array with valid pointers to Excuse type in memory // Populate array with valid pointers to Excuse type in memory
let ptr = host_memory.ptr::<[GuestPtr<'_, types::Excuse>]>( let ptr = host_memory.ptr::<[GuestPtr<'_, types::Excuse>]>((
&bc, self.array_ptr_loc.ptr,
(self.array_ptr_loc.ptr, self.elements.len() as u32), self.elements.len() as u32,
); ));
for (ptr, val) in ptr.iter().zip(&self.elements) { for (ptr, val) in ptr.iter().zip(&self.elements) {
ptr.expect("should be valid pointer") ptr.expect("should be valid pointer")
.write(host_memory.ptr(&bc, val.ptr)) .write(host_memory.ptr(val.ptr))
.expect("failed to write value"); .expect("failed to write value");
} }
let res = arrays::populate_excuses( let res = arrays::populate_excuses(
&ctx, &ctx,
&host_memory, &host_memory,
&bc,
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, types::Errno::Ok.into(), "populate excuses errno");
let arr: GuestPtr<'_, [GuestPtr<'_, types::Excuse>]> = let arr: GuestPtr<'_, [GuestPtr<'_, types::Excuse>]> =
host_memory.ptr(&bc, (self.array_ptr_loc.ptr, self.elements.len() as u32)); host_memory.ptr((self.array_ptr_loc.ptr, self.elements.len() as u32));
for el in arr.iter() { for el in arr.iter() {
let ptr_to_ptr = el let ptr_to_ptr = el
.expect("valid ptr to ptr") .expect("valid ptr to ptr")

View File

@@ -1,5 +1,5 @@
use proptest::prelude::*; use proptest::prelude::*;
use wiggle::{BorrowChecker, GuestMemory}; use wiggle::GuestMemory;
use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx};
wiggle::from_witx!({ wiggle::from_witx!({
@@ -31,9 +31,8 @@ impl IntFloatExercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
let e = atoms::int_float_args(&ctx, &host_memory, &bc, 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, types::Errno::Ok.into(), "int_float_args error");
} }
@@ -61,18 +60,16 @@ impl DoubleIntExercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
let e = atoms::double_int_return_float( let e = atoms::double_int_return_float(
&ctx, &ctx,
&host_memory, &host_memory,
&bc,
self.input as i32, self.input as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); );
let return_val = host_memory let return_val = host_memory
.ptr::<types::AliasToFloat>(&bc, 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, types::Errno::Ok.into(), "errno");

View File

@@ -1,6 +1,6 @@
use proptest::prelude::*; use proptest::prelude::*;
use std::convert::TryFrom; use std::convert::TryFrom;
use wiggle::{BorrowChecker, GuestMemory, GuestPtr}; use wiggle::{GuestMemory, GuestPtr};
use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx};
wiggle::from_witx!({ wiggle::from_witx!({
@@ -65,18 +65,16 @@ impl ConfigureCarExercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
// Populate input ptr // Populate input ptr
host_memory host_memory
.ptr(&bc, self.other_config_by_ptr.ptr) .ptr(self.other_config_by_ptr.ptr)
.write(self.other_config) .write(self.other_config)
.expect("deref ptr mut to CarConfig"); .expect("deref ptr mut to CarConfig");
let res = flags::configure_car( let res = flags::configure_car(
&ctx, &ctx,
&host_memory, &host_memory,
&bc,
self.old_config.into(), self.old_config.into(),
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,
@@ -84,7 +82,7 @@ impl ConfigureCarExercise {
assert_eq!(res, types::Errno::Ok.into(), "configure car errno"); assert_eq!(res, types::Errno::Ok.into(), "configure car errno");
let res_config = host_memory let res_config = host_memory
.ptr::<types::CarConfig>(&bc, self.return_ptr_loc.ptr) .ptr::<types::CarConfig>(self.return_ptr_loc.ptr)
.read() .read()
.expect("deref to CarConfig value"); .expect("deref to CarConfig value");

View File

@@ -1,5 +1,5 @@
use proptest::prelude::*; use proptest::prelude::*;
use wiggle::{BorrowChecker, GuestMemory, GuestType}; use wiggle::{GuestMemory, GuestType};
use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx};
const FD_VAL: u32 = 123; const FD_VAL: u32 = 123;
@@ -34,24 +34,23 @@ impl HandleExercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
let e = handle_examples::fd_create(&ctx, &host_memory, &bc, 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, types::Errno::Ok.into(), "fd_create error");
let h_got: u32 = host_memory let h_got: u32 = host_memory
.ptr(&bc, self.return_loc.ptr) .ptr(self.return_loc.ptr)
.read() .read()
.expect("return ref_mut"); .expect("return ref_mut");
assert_eq!(h_got, 123, "fd_create return val"); assert_eq!(h_got, 123, "fd_create return val");
let e = handle_examples::fd_consume(&ctx, &host_memory, &bc, 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, types::Errno::Ok.into(), "fd_consume error");
let e = handle_examples::fd_consume(&ctx, &host_memory, &bc, 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,

View File

@@ -1,6 +1,6 @@
use proptest::prelude::*; use proptest::prelude::*;
use std::convert::TryFrom; use std::convert::TryFrom;
use wiggle::{BorrowChecker, GuestMemory}; use wiggle::GuestMemory;
use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx};
wiggle::from_witx!({ wiggle::from_witx!({
@@ -46,19 +46,17 @@ impl CookieCutterExercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
let res = ints::cookie_cutter( let res = ints::cookie_cutter(
&ctx, &ctx,
&host_memory, &host_memory,
&bc,
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, types::Errno::Ok.into(), "cookie cutter errno");
let is_cookie_start = host_memory let is_cookie_start = host_memory
.ptr::<types::Bool>(&bc, self.return_ptr_loc.ptr) .ptr::<types::Bool>(self.return_ptr_loc.ptr)
.read() .read()
.expect("deref to Bool value"); .expect("deref to Bool value");

View File

@@ -1,5 +1,5 @@
use proptest::prelude::*; use proptest::prelude::*;
use wiggle::{BorrowChecker, GuestMemory, GuestPtr}; use wiggle::{GuestMemory, GuestPtr};
use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx};
wiggle::from_witx!({ wiggle::from_witx!({
@@ -128,32 +128,30 @@ impl PointersAndEnumsExercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
host_memory host_memory
.ptr(&bc, self.input2_loc.ptr) .ptr(self.input2_loc.ptr)
.write(self.input2) .write(self.input2)
.expect("input2 ref_mut"); .expect("input2 ref_mut");
host_memory host_memory
.ptr(&bc, self.input3_loc.ptr) .ptr(self.input3_loc.ptr)
.write(self.input3) .write(self.input3)
.expect("input3 ref_mut"); .expect("input3 ref_mut");
host_memory host_memory
.ptr(&bc, self.input4_loc.ptr) .ptr(self.input4_loc.ptr)
.write(self.input4) .write(self.input4)
.expect("input4 ref_mut"); .expect("input4 ref_mut");
host_memory host_memory
.ptr(&bc, self.input4_ptr_loc.ptr) .ptr(self.input4_ptr_loc.ptr)
.write(self.input4_loc.ptr) .write(self.input4_loc.ptr)
.expect("input4 ptr ref_mut"); .expect("input4 ptr ref_mut");
let e = pointers::pointers_and_enums( let e = pointers::pointers_and_enums(
&ctx, &ctx,
&host_memory, &host_memory,
&bc,
self.input1.into(), self.input1.into(),
self.input2_loc.ptr as i32, self.input2_loc.ptr as i32,
self.input3_loc.ptr as i32, self.input3_loc.ptr as i32,
@@ -163,7 +161,7 @@ impl PointersAndEnumsExercise {
// 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
.ptr(&bc, self.input2_loc.ptr) .ptr(self.input2_loc.ptr)
.read() .read()
.expect("input2 ref"); .expect("input2 ref");
@@ -175,7 +173,7 @@ impl PointersAndEnumsExercise {
// Implementation of pointers_and_enums writes input2_loc to input4_ptr_loc: // Implementation of pointers_and_enums writes input2_loc to input4_ptr_loc:
let written_to_input4_ptr: u32 = host_memory let written_to_input4_ptr: u32 = host_memory
.ptr(&bc, self.input4_ptr_loc.ptr) .ptr(self.input4_ptr_loc.ptr)
.read() .read()
.expect("input4_ptr_loc ref"); .expect("input4_ptr_loc ref");

View File

@@ -1,5 +1,5 @@
use proptest::prelude::*; use proptest::prelude::*;
use wiggle::{BorrowChecker, GuestMemory, GuestPtr}; use wiggle::{GuestMemory, GuestPtr};
use wiggle_test::{impl_errno, HostMemory, MemArea, MemAreas, WasiCtx}; use wiggle_test::{impl_errno, HostMemory, MemArea, MemAreas, WasiCtx};
wiggle::from_witx!({ wiggle::from_witx!({
@@ -69,11 +69,9 @@ impl HelloStringExercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
// Populate string in guest's memory // Populate string in guest's memory
let ptr = let ptr = host_memory.ptr::<str>((self.string_ptr_loc.ptr, self.test_word.len() as u32));
host_memory.ptr::<str>(&bc, (self.string_ptr_loc.ptr, self.test_word.len() as u32));
for (slot, byte) in ptr.as_bytes().iter().zip(self.test_word.bytes()) { for (slot, byte) in ptr.as_bytes().iter().zip(self.test_word.bytes()) {
slot.expect("should be valid pointer") slot.expect("should be valid pointer")
.write(byte) .write(byte)
@@ -83,7 +81,6 @@ impl HelloStringExercise {
let res = strings::hello_string( let res = strings::hello_string(
&ctx, &ctx,
&host_memory, &host_memory,
&bc,
self.string_ptr_loc.ptr as i32, self.string_ptr_loc.ptr as i32,
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,
@@ -91,7 +88,7 @@ impl HelloStringExercise {
assert_eq!(res, types::Errno::Ok.into(), "hello string errno"); assert_eq!(res, types::Errno::Ok.into(), "hello string errno");
let given = host_memory let given = host_memory
.ptr::<u32>(&bc, self.return_ptr_loc.ptr) .ptr::<u32>(self.return_ptr_loc.ptr)
.read() .read()
.expect("deref ptr to return value"); .expect("deref ptr to return value");
assert_eq!(self.test_word.len() as u32, given); assert_eq!(self.test_word.len() as u32, given);
@@ -178,10 +175,9 @@ impl MultiStringExercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
let write_string = |val: &str, loc: MemArea| { let write_string = |val: &str, loc: MemArea| {
let ptr = host_memory.ptr::<str>(&bc, (loc.ptr, val.len() as u32)); let ptr = host_memory.ptr::<str>((loc.ptr, val.len() as u32));
for (slot, byte) in ptr.as_bytes().iter().zip(val.bytes()) { for (slot, byte) in ptr.as_bytes().iter().zip(val.bytes()) {
slot.expect("should be valid pointer") slot.expect("should be valid pointer")
.write(byte) .write(byte)
@@ -196,7 +192,6 @@ impl MultiStringExercise {
let res = strings::multi_string( let res = strings::multi_string(
&ctx, &ctx,
&host_memory, &host_memory,
&bc,
self.sa_ptr_loc.ptr as i32, self.sa_ptr_loc.ptr as i32,
self.a.len() as i32, self.a.len() as i32,
self.sb_ptr_loc.ptr as i32, self.sb_ptr_loc.ptr as i32,
@@ -208,7 +203,7 @@ impl MultiStringExercise {
assert_eq!(res, types::Errno::Ok.into(), "multi string errno"); assert_eq!(res, types::Errno::Ok.into(), "multi string errno");
let given = host_memory let given = host_memory
.ptr::<u32>(&bc, self.return_ptr_loc.ptr) .ptr::<u32>(self.return_ptr_loc.ptr)
.read() .read()
.expect("deref ptr to return value"); .expect("deref ptr to return value");
assert_eq!((self.a.len() + self.b.len() + self.c.len()) as u32, given); assert_eq!((self.a.len() + self.b.len() + self.c.len()) as u32, given);

View File

@@ -1,5 +1,5 @@
use proptest::prelude::*; use proptest::prelude::*;
use wiggle::{BorrowChecker, GuestMemory, GuestPtr}; use wiggle::{GuestMemory, GuestPtr};
use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx};
wiggle::from_witx!({ wiggle::from_witx!({
@@ -83,20 +83,18 @@ impl SumOfPairExercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
host_memory host_memory
.ptr(&bc, self.input_loc.ptr) .ptr(self.input_loc.ptr)
.write(self.input.first) .write(self.input.first)
.expect("input ref_mut"); .expect("input ref_mut");
host_memory host_memory
.ptr(&bc, self.input_loc.ptr + 4) .ptr(self.input_loc.ptr + 4)
.write(self.input.second) .write(self.input.second)
.expect("input ref_mut"); .expect("input ref_mut");
let sum_err = structs::sum_of_pair( let sum_err = structs::sum_of_pair(
&ctx, &ctx,
&host_memory, &host_memory,
&bc,
self.input_loc.ptr as i32, self.input_loc.ptr as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); );
@@ -104,7 +102,7 @@ impl SumOfPairExercise {
assert_eq!(sum_err, types::Errno::Ok.into(), "sum errno"); assert_eq!(sum_err, types::Errno::Ok.into(), "sum errno");
let return_val: i64 = host_memory let return_val: i64 = host_memory
.ptr(&bc, self.return_loc.ptr) .ptr(self.return_loc.ptr)
.read() .read()
.expect("return ref"); .expect("return ref");
@@ -173,30 +171,28 @@ impl SumPairPtrsExercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
host_memory host_memory
.ptr(&bc, self.input_first_loc.ptr) .ptr(self.input_first_loc.ptr)
.write(self.input_first) .write(self.input_first)
.expect("input_first ref"); .expect("input_first ref");
host_memory host_memory
.ptr(&bc, self.input_second_loc.ptr) .ptr(self.input_second_loc.ptr)
.write(self.input_second) .write(self.input_second)
.expect("input_second ref"); .expect("input_second ref");
host_memory host_memory
.ptr(&bc, self.input_struct_loc.ptr) .ptr(self.input_struct_loc.ptr)
.write(self.input_first_loc.ptr) .write(self.input_first_loc.ptr)
.expect("input_struct ref"); .expect("input_struct ref");
host_memory host_memory
.ptr(&bc, self.input_struct_loc.ptr + 4) .ptr(self.input_struct_loc.ptr + 4)
.write(self.input_second_loc.ptr) .write(self.input_second_loc.ptr)
.expect("input_struct ref"); .expect("input_struct ref");
let res = structs::sum_of_pair_of_ptrs( let res = structs::sum_of_pair_of_ptrs(
&ctx, &ctx,
&host_memory, &host_memory,
&bc,
self.input_struct_loc.ptr as i32, self.input_struct_loc.ptr as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); );
@@ -204,7 +200,7 @@ impl SumPairPtrsExercise {
assert_eq!(res, types::Errno::Ok.into(), "sum of pair of ptrs errno"); assert_eq!(res, types::Errno::Ok.into(), "sum of pair of ptrs errno");
let doubled: i64 = host_memory let doubled: i64 = host_memory
.ptr(&bc, self.return_loc.ptr) .ptr(self.return_loc.ptr)
.read() .read()
.expect("return ref"); .expect("return ref");
@@ -259,25 +255,23 @@ impl SumIntAndPtrExercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
host_memory host_memory
.ptr(&bc, self.input_first_loc.ptr) .ptr(self.input_first_loc.ptr)
.write(self.input_first) .write(self.input_first)
.expect("input_first ref"); .expect("input_first ref");
host_memory host_memory
.ptr(&bc, self.input_struct_loc.ptr) .ptr(self.input_struct_loc.ptr)
.write(self.input_first_loc.ptr) .write(self.input_first_loc.ptr)
.expect("input_struct ref"); .expect("input_struct ref");
host_memory host_memory
.ptr(&bc, self.input_struct_loc.ptr + 4) .ptr(self.input_struct_loc.ptr + 4)
.write(self.input_second) .write(self.input_second)
.expect("input_struct ref"); .expect("input_struct ref");
let res = structs::sum_of_int_and_ptr( let res = structs::sum_of_int_and_ptr(
&ctx, &ctx,
&host_memory, &host_memory,
&bc,
self.input_struct_loc.ptr as i32, self.input_struct_loc.ptr as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); );
@@ -285,7 +279,7 @@ impl SumIntAndPtrExercise {
assert_eq!(res, types::Errno::Ok.into(), "sum of int and ptr errno"); assert_eq!(res, types::Errno::Ok.into(), "sum of int and ptr errno");
let doubled: i64 = host_memory let doubled: i64 = host_memory
.ptr(&bc, self.return_loc.ptr) .ptr(self.return_loc.ptr)
.read() .read()
.expect("return ref"); .expect("return ref");
@@ -318,14 +312,13 @@ impl ReturnPairInts {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
let err = structs::return_pair_ints(&ctx, &host_memory, &bc, 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, types::Errno::Ok.into(), "return struct errno");
let return_struct: types::PairInts = host_memory let return_struct: types::PairInts = host_memory
.ptr(&bc, self.return_loc.ptr) .ptr(self.return_loc.ptr)
.read() .read()
.expect("return ref"); .expect("return ref");
@@ -384,21 +377,19 @@ impl ReturnPairPtrsExercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
host_memory host_memory
.ptr(&bc, self.input_first_loc.ptr) .ptr(self.input_first_loc.ptr)
.write(self.input_first) .write(self.input_first)
.expect("input_first ref"); .expect("input_first ref");
host_memory host_memory
.ptr(&bc, self.input_second_loc.ptr) .ptr(self.input_second_loc.ptr)
.write(self.input_second) .write(self.input_second)
.expect("input_second ref"); .expect("input_second ref");
let res = structs::return_pair_of_ptrs( let res = structs::return_pair_of_ptrs(
&ctx, &ctx,
&host_memory, &host_memory,
&bc,
self.input_first_loc.ptr as i32, self.input_first_loc.ptr as i32,
self.input_second_loc.ptr as i32, self.input_second_loc.ptr as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
@@ -407,7 +398,7 @@ impl ReturnPairPtrsExercise {
assert_eq!(res, types::Errno::Ok.into(), "return pair of ptrs errno"); assert_eq!(res, 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(&bc, self.return_loc.ptr) .ptr(self.return_loc.ptr)
.read() .read()
.expect("failed to read return location"); .expect("failed to read return location");
let ret_first_ptr = ptr_pair_int_ptrs.first; let ret_first_ptr = ptr_pair_int_ptrs.first;

View File

@@ -1,5 +1,5 @@
use proptest::prelude::*; use proptest::prelude::*;
use wiggle::{BorrowChecker, GuestMemory, GuestType}; use wiggle::{GuestMemory, GuestType};
use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx};
wiggle::from_witx!({ wiggle::from_witx!({
@@ -107,22 +107,21 @@ impl GetTagExercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
let discriminant: u8 = reason_tag(&self.input).into(); let discriminant: u8 = reason_tag(&self.input).into();
host_memory host_memory
.ptr(&bc, self.input_loc.ptr) .ptr(self.input_loc.ptr)
.write(discriminant) .write(discriminant)
.expect("input discriminant ptr"); .expect("input discriminant ptr");
match self.input { match self.input {
types::Reason::DogAte(f) => { types::Reason::DogAte(f) => {
host_memory host_memory
.ptr(&bc, self.input_loc.ptr + 4) .ptr(self.input_loc.ptr + 4)
.write(f) .write(f)
.expect("input contents ref_mut"); .expect("input contents ref_mut");
} }
types::Reason::Traffic(v) => host_memory types::Reason::Traffic(v) => host_memory
.ptr(&bc, self.input_loc.ptr + 4) .ptr(self.input_loc.ptr + 4)
.write(v) .write(v)
.expect("input contents ref_mut"), .expect("input contents ref_mut"),
types::Reason::Sleeping => {} // Do nothing types::Reason::Sleeping => {} // Do nothing
@@ -130,7 +129,6 @@ impl GetTagExercise {
let e = union_example::get_tag( let e = union_example::get_tag(
&ctx, &ctx,
&host_memory, &host_memory,
&bc,
self.input_loc.ptr as i32, self.input_loc.ptr as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); );
@@ -138,7 +136,7 @@ impl GetTagExercise {
assert_eq!(e, types::Errno::Ok.into(), "get_tag errno"); assert_eq!(e, types::Errno::Ok.into(), "get_tag errno");
let return_val: types::Excuse = host_memory let return_val: types::Excuse = host_memory
.ptr(&bc, self.return_loc.ptr) .ptr(self.return_loc.ptr)
.read() .read()
.expect("return ref"); .expect("return ref");
@@ -186,28 +184,27 @@ impl ReasonMultExercise {
pub fn test(&self) { pub fn test(&self) {
let ctx = WasiCtx::new(); let ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let bc = unsafe { BorrowChecker::new() };
let discriminant: u8 = reason_tag(&self.input).into(); let discriminant: u8 = reason_tag(&self.input).into();
host_memory host_memory
.ptr(&bc, self.input_loc.ptr) .ptr(self.input_loc.ptr)
.write(discriminant) .write(discriminant)
.expect("input discriminant ref_mut"); .expect("input discriminant ref_mut");
host_memory host_memory
.ptr(&bc, self.input_loc.ptr + 4) .ptr(self.input_loc.ptr + 4)
.write(self.input_pointee_loc.ptr) .write(self.input_pointee_loc.ptr)
.expect("input pointer ref_mut"); .expect("input pointer ref_mut");
match self.input { match self.input {
types::Reason::DogAte(f) => { types::Reason::DogAte(f) => {
host_memory host_memory
.ptr(&bc, self.input_pointee_loc.ptr) .ptr(self.input_pointee_loc.ptr)
.write(f) .write(f)
.expect("input contents ref_mut"); .expect("input contents ref_mut");
} }
types::Reason::Traffic(v) => { types::Reason::Traffic(v) => {
host_memory host_memory
.ptr(&bc, self.input_pointee_loc.ptr) .ptr(self.input_pointee_loc.ptr)
.write(v) .write(v)
.expect("input contents ref_mut"); .expect("input contents ref_mut");
} }
@@ -216,7 +213,6 @@ impl ReasonMultExercise {
let e = union_example::reason_mult( let e = union_example::reason_mult(
&ctx, &ctx,
&host_memory, &host_memory,
&bc,
self.input_loc.ptr as i32, self.input_loc.ptr as i32,
self.multiply_by as i32, self.multiply_by as i32,
); );
@@ -226,7 +222,7 @@ impl ReasonMultExercise {
match self.input { match self.input {
types::Reason::DogAte(f) => { types::Reason::DogAte(f) => {
let f_result: f32 = host_memory let f_result: f32 = host_memory
.ptr(&bc, self.input_pointee_loc.ptr) .ptr(self.input_pointee_loc.ptr)
.read() .read()
.expect("input contents ref_mut"); .expect("input contents ref_mut");
assert_eq!( assert_eq!(
@@ -237,7 +233,7 @@ impl ReasonMultExercise {
} }
types::Reason::Traffic(v) => { types::Reason::Traffic(v) => {
let v_result: i32 = host_memory let v_result: i32 = host_memory
.ptr(&bc, self.input_pointee_loc.ptr) .ptr(self.input_pointee_loc.ptr)
.read() .read()
.expect("input contents ref_mut"); .expect("input contents ref_mut");
assert_eq!( assert_eq!(