2019-04-01 16:34:18 -07:00
|
|
|
use crate::syscalls::types::{__wasi_errno_t, __WASI_EFAULT};
|
2019-03-28 17:00:10 -07:00
|
|
|
use std::{cell::Cell, fmt, marker::PhantomData, mem};
|
|
|
|
use wasmer_runtime_core::{
|
|
|
|
memory::Memory,
|
2019-04-01 15:52:35 -07:00
|
|
|
types::{Type, ValueType, WasmExternType},
|
2019-03-28 17:00:10 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
pub struct Array;
|
|
|
|
pub struct Item;
|
|
|
|
|
|
|
|
#[repr(transparent)]
|
|
|
|
pub struct WasmPtr<T: Copy, Ty = Item> {
|
|
|
|
offset: u32,
|
|
|
|
_phantom: PhantomData<(T, Ty)>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Copy, Ty> WasmPtr<T, Ty> {
|
2019-03-28 22:10:11 -07:00
|
|
|
#[inline]
|
2019-03-28 17:00:10 -07:00
|
|
|
pub fn new(offset: u32) -> Self {
|
|
|
|
Self {
|
|
|
|
offset,
|
|
|
|
_phantom: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-28 22:10:11 -07:00
|
|
|
#[inline]
|
2019-03-28 17:00:10 -07:00
|
|
|
pub fn offset(self) -> u32 {
|
|
|
|
self.offset
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Copy + ValueType> WasmPtr<T, Item> {
|
2019-03-28 22:10:11 -07:00
|
|
|
#[inline]
|
2019-04-01 16:34:18 -07:00
|
|
|
pub fn deref<'a>(self, memory: &'a Memory) -> Result<&'a Cell<T>, __wasi_errno_t> {
|
2019-03-28 17:00:10 -07:00
|
|
|
if (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0 {
|
2019-04-01 16:34:18 -07:00
|
|
|
return Err(__WASI_EFAULT);
|
2019-03-28 17:00:10 -07:00
|
|
|
}
|
|
|
|
unsafe {
|
|
|
|
let cell_ptr = memory
|
|
|
|
.view::<T>()
|
|
|
|
.get_unchecked((self.offset() as usize) / mem::size_of::<T>())
|
|
|
|
as *const _;
|
2019-04-01 16:34:18 -07:00
|
|
|
Ok(&*cell_ptr)
|
2019-03-28 17:00:10 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
2019-03-28 22:10:11 -07:00
|
|
|
#[inline]
|
2019-04-01 16:34:18 -07:00
|
|
|
pub fn deref<'a>(
|
|
|
|
self,
|
|
|
|
memory: &'a Memory,
|
|
|
|
index: u32,
|
|
|
|
length: u32,
|
|
|
|
) -> Result<&'a [Cell<T>], __wasi_errno_t> {
|
2019-03-28 22:10:11 -07:00
|
|
|
if (self.offset as usize) + (mem::size_of::<T>() * ((index + length) as usize))
|
2019-03-28 17:00:10 -07:00
|
|
|
>= memory.size().bytes().0
|
|
|
|
{
|
2019-04-01 16:34:18 -07:00
|
|
|
return Err(__WASI_EFAULT);
|
2019-03-28 17:00:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
let cell_ptrs = memory.view::<T>().get_unchecked(
|
2019-03-28 22:22:46 -07:00
|
|
|
((self.offset as usize) / mem::size_of::<T>()) + (index as usize)
|
|
|
|
..((self.offset() as usize) / mem::size_of::<T>())
|
|
|
|
+ ((index + length) as usize),
|
2019-03-28 17:00:10 -07:00
|
|
|
) as *const _;
|
2019-04-01 16:34:18 -07:00
|
|
|
Ok(&*cell_ptrs)
|
2019-03-28 17:00:10 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl<T: Copy, Ty> WasmExternType for WasmPtr<T, Ty> {
|
|
|
|
const TYPE: Type = Type::I32;
|
2019-04-09 16:07:09 -07:00
|
|
|
|
|
|
|
fn to_bits(self) -> u64 {
|
|
|
|
self.offset as u64
|
|
|
|
}
|
|
|
|
fn from_bits(n: u64) -> Self {
|
|
|
|
Self {
|
|
|
|
offset: n as u32,
|
|
|
|
_phantom: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
2019-03-28 17:00:10 -07:00
|
|
|
}
|
|
|
|
|
2019-04-01 15:52:35 -07:00
|
|
|
unsafe impl<T: Copy, Ty> ValueType for WasmPtr<T, Ty> {}
|
2019-03-28 22:10:11 -07:00
|
|
|
|
2019-03-28 17:00:10 -07:00
|
|
|
impl<T: Copy, Ty> Clone for WasmPtr<T, Ty> {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
Self {
|
|
|
|
offset: self.offset,
|
|
|
|
_phantom: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Copy, Ty> Copy for WasmPtr<T, Ty> {}
|
|
|
|
|
|
|
|
impl<T: Copy, Ty> PartialEq for WasmPtr<T, Ty> {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
self.offset == other.offset
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Copy, Ty> Eq for WasmPtr<T, Ty> {}
|
|
|
|
|
|
|
|
impl<T: Copy, Ty> fmt::Debug for WasmPtr<T, Ty> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(f, "WasmPtr({:#x})", self.offset)
|
|
|
|
}
|
|
|
|
}
|