Merge branch 'feature/wasi' into feature/wasi-cross-platform-skeleton

This commit is contained in:
Mark McCaskey 2019-03-29 10:43:30 -07:00 committed by GitHub
commit d10d0285ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 428 additions and 69 deletions

View File

@ -77,6 +77,19 @@ where
{
const TYPE: Type;
}
unsafe impl WasmExternType for i8 {
const TYPE: Type = Type::I32;
}
unsafe impl WasmExternType for u8 {
const TYPE: Type = Type::I32;
}
unsafe impl WasmExternType for i16 {
const TYPE: Type = Type::I32;
}
unsafe impl WasmExternType for u16 {
const TYPE: Type = Type::I32;
}
unsafe impl WasmExternType for i32 {
const TYPE: Type = Type::I32;
}

View File

@ -1,3 +1,4 @@
mod ptr;
mod state;
mod syscalls;
mod utils;

112
lib/wasi/src/ptr.rs Normal file
View File

@ -0,0 +1,112 @@
use std::{cell::Cell, fmt, marker::PhantomData, mem};
use wasmer_runtime_core::{
memory::Memory,
types::{Type, ValueError, ValueType, WasmExternType},
};
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> {
#[inline]
pub fn new(offset: u32) -> Self {
Self {
offset,
_phantom: PhantomData,
}
}
#[inline]
pub fn offset(self) -> u32 {
self.offset
}
}
impl<T: Copy + ValueType> WasmPtr<T, Item> {
#[inline]
pub fn deref<'a>(self, memory: &'a Memory) -> Option<&'a Cell<T>> {
if (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0 {
return None;
}
unsafe {
let cell_ptr = memory
.view::<T>()
.get_unchecked((self.offset() as usize) / mem::size_of::<T>())
as *const _;
Some(&*cell_ptr)
}
}
}
impl<T: Copy + ValueType> WasmPtr<T, Array> {
#[inline]
pub fn deref<'a>(self, memory: &'a Memory, index: u32, length: u32) -> Option<&'a [Cell<T>]> {
if (self.offset as usize) + (mem::size_of::<T>() * ((index + length) as usize))
>= memory.size().bytes().0
{
return None;
}
unsafe {
let cell_ptrs = memory.view::<T>().get_unchecked(
((self.offset as usize) / mem::size_of::<T>()) + (index as usize)
..((self.offset() as usize) / mem::size_of::<T>())
+ ((index + length) as usize),
) as *const _;
Some(&*cell_ptrs)
}
}
}
unsafe impl<T: Copy, Ty> WasmExternType for WasmPtr<T, Ty> {
const TYPE: Type = Type::I32;
}
impl<T: Copy, Ty> ValueType for WasmPtr<T, Ty> {
fn into_le(self, buffer: &mut [u8]) {
buffer[..mem::size_of::<u32>()].copy_from_slice(&self.offset.to_le_bytes());
}
fn from_le(buffer: &[u8]) -> Result<Self, ValueError> {
if buffer.len() >= mem::size_of::<Self>() {
let mut array = [0u8; mem::size_of::<u32>()];
array.copy_from_slice(&buffer[..mem::size_of::<u32>()]);
Ok(Self {
offset: u32::from_le_bytes(array),
_phantom: PhantomData,
})
} else {
Err(ValueError::BufferTooSmall)
}
}
}
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)
}
}

View File

@ -1,11 +1,15 @@
#![allow(unused)]
pub mod types;
#[cfg(any(target_os = "linux", target_os = "macos"))]
pub mod unix;
#[cfg(any(target_os = "windows"))]
pub mod windows;
use crate::state::WasiState;
use types::*;
use self::types::*;
use crate::{
ptr::{Array, WasmPtr},
state::WasiState,
};
use wasmer_runtime_core::{memory::Memory, vm::Ctx};
#[cfg(any(target_os = "linux", target_os = "macos"))]
@ -19,23 +23,38 @@ fn get_wasi_state(ctx: &Ctx) -> &mut WasiState {
unsafe { &mut *(ctx.data as *mut WasiState) }
}
#[must_use]
fn write_buffer_array(
memory: &Memory,
from: &[Vec<u8>],
ptr_buffer_offset: u32,
buffer_offset: u32,
) {
let mut current_buffer_offset = buffer_offset;
for (i, sub_buffer) in from.iter().enumerate() {
memory.view::<u32>()[(ptr_buffer_offset as usize)..][i].set(current_buffer_offset);
for (cell, &byte) in memory.view()[(current_buffer_offset as usize)..]
.iter()
.zip(sub_buffer.iter())
ptr_buffer: WasmPtr<WasmPtr<u8, Array>, Array>,
buffer: WasmPtr<u8, Array>,
) -> __wasi_errno_t {
let ptrs = if let Some(cells) = ptr_buffer.deref(memory, 0, from.len() as u32) {
cells
} else {
return __WASI_EOVERFLOW;
};
let mut current_buffer_offset = 0;
for ((i, sub_buffer), ptr) in from.iter().enumerate().zip(ptrs.iter()) {
ptr.set(WasmPtr::new(buffer.offset() + current_buffer_offset));
let cells = if let Some(cells) =
buffer.deref(memory, current_buffer_offset, sub_buffer.len() as u32)
{
cells
} else {
return __WASI_EOVERFLOW;
};
for (cell, &byte) in cells.iter().zip(sub_buffer.iter()) {
cell.set(byte);
}
current_buffer_offset += sub_buffer.len() as u32;
}
__WASI_ESUCCESS
}
/// ### `args_get()`
@ -47,11 +66,15 @@ fn write_buffer_array(
/// - `char *argv_buf`
/// A pointer to a buffer to write the argument string data.
///
pub fn args_get(ctx: &mut Ctx, ptr_buffer_offset: u32, buffer_offset: u32) {
pub fn args_get(
ctx: &mut Ctx,
argv: WasmPtr<WasmPtr<u8, Array>, Array>,
argv_buf: WasmPtr<u8, Array>,
) -> __wasi_errno_t {
let state = get_wasi_state(ctx);
let memory = ctx.memory(0);
write_buffer_array(memory, &*state.args, ptr_buffer_offset, buffer_offset);
write_buffer_array(memory, &*state.args, argv, argv_buf)
}
/// ### `args_sizes_get()`
@ -61,15 +84,23 @@ pub fn args_get(ctx: &mut Ctx, ptr_buffer_offset: u32, buffer_offset: u32) {
/// The number of arguments.
/// - `size_t *argv_buf_size`
/// The size of the argument string data.
pub fn args_sizes_get(ctx: &mut Ctx, argc_out: u32, argv_buf_size_out: u32) {
let state = get_wasi_state(ctx);
pub fn args_sizes_get(
ctx: &mut Ctx,
argc: WasmPtr<u32>,
argv_buf_size: WasmPtr<u32>,
) -> __wasi_errno_t {
let memory = ctx.memory(0);
let arg_count = state.args.len();
let total_arg_size: usize = state.args.iter().map(|v| v.len()).sum();
if let (Some(argc), Some(argv_buf_size)) = (argc.deref(memory), argv_buf_size.deref(memory)) {
let state = get_wasi_state(ctx);
memory.view::<u32>()[(argc_out / 4) as usize].set(arg_count as u32);
memory.view::<u32>()[(argv_buf_size_out / 4) as usize].set(total_arg_size as u32);
argc.set(state.args.len() as u32);
argv_buf_size.set(state.args.iter().map(|v| v.len() as u32).sum());
__WASI_ESUCCESS
} else {
__WASI_EOVERFLOW
}
}
pub fn clock_res_get(
@ -97,11 +128,15 @@ pub fn clock_time_get(
/// A pointer to a buffer to write the environment variable pointers.
/// - `char *environ_buf`
/// A pointer to a buffer to write the environment variable string data.
pub fn environ_get(ctx: &mut Ctx, environ: u32, environ_buf: u32) {
pub fn environ_get(
ctx: &mut Ctx,
environ: WasmPtr<WasmPtr<u8, Array>, Array>,
environ_buf: WasmPtr<u8, Array>,
) -> __wasi_errno_t {
let state = get_wasi_state(ctx);
let memory = ctx.memory(0);
write_buffer_array(memory, &*state.args, environ, environ_buf);
write_buffer_array(memory, &*state.args, environ, environ_buf)
}
/// ### `environ_sizes_get()`
@ -111,131 +146,326 @@ pub fn environ_get(ctx: &mut Ctx, environ: u32, environ_buf: u32) {
/// The number of environment variables.
/// - `size_t *environ_buf_size`
/// The size of the environment variable string data.
pub fn environ_sizes_get(ctx: &mut Ctx, environ_count_out: u32, environ_buf_size_out: u32) {
let state = get_wasi_state(ctx);
pub fn environ_sizes_get(
ctx: &mut Ctx,
environ_count: WasmPtr<u32>,
environ_buf_size: WasmPtr<u32>,
) -> __wasi_errno_t {
let memory = ctx.memory(0);
let env_count = state.envs.len();
let total_env_size: usize = state.envs.iter().map(|v| v.len()).sum();
if let (Some(environ_count), Some(environ_buf_size)) =
(environ_count.deref(memory), environ_buf_size.deref(memory))
{
let state = get_wasi_state(ctx);
memory.view::<u32>()[(environ_count_out / 4) as usize].set(env_count as u32);
memory.view::<u32>()[(environ_buf_size_out / 4) as usize].set(total_env_size as u32);
environ_count.set(state.envs.len() as u32);
environ_buf_size.set(state.envs.iter().map(|v| v.len() as u32).sum());
__WASI_ESUCCESS
} else {
__WASI_EOVERFLOW
}
}
pub fn fd_advise(ctx: &mut Ctx) {
pub fn fd_advise(
ctx: &mut Ctx,
fd: __wasi_fd_t,
offset: __wasi_filesize_t,
len: __wasi_filesize_t,
advice: __wasi_advice_t,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_allocate(ctx: &mut Ctx) {
pub fn fd_allocate(
ctx: &mut Ctx,
fd: __wasi_fd_t,
offset: __wasi_filesize_t,
len: __wasi_filesize_t,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_close(ctx: &mut Ctx) {
pub fn fd_close(ctx: &mut Ctx, fd: __wasi_fd_t) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_datasync(ctx: &mut Ctx) {
pub fn fd_datasync(ctx: &mut Ctx, fd: __wasi_fd_t) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_fdstat_get(ctx: &mut Ctx) {
pub fn fd_fdstat_get(
ctx: &mut Ctx,
fd: __wasi_fd_t,
buf: WasmPtr<__wasi_fdstat_t>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_fdstat_set_flags(ctx: &mut Ctx) {
pub fn fd_fdstat_set_flags(
ctx: &mut Ctx,
fd: __wasi_fd_t,
flags: __wasi_fdflags_t,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_fdstat_set_rights(ctx: &mut Ctx) {
pub fn fd_fdstat_set_rights(
ctx: &mut Ctx,
fd: __wasi_fd_t,
fs_rights_base: __wasi_rights_t,
fs_rights_inheriting: __wasi_rights_t,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_filestat_get(ctx: &mut Ctx) {
pub fn fd_filestat_get(
ctx: &mut Ctx,
fd: __wasi_fd_t,
buf: WasmPtr<__wasi_filestat_t>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_filestat_set_size(ctx: &mut Ctx) {
pub fn fd_filestat_set_size(
ctx: &mut Ctx,
fd: __wasi_fd_t,
st_size: __wasi_filesize_t,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_filestat_set_times(ctx: &mut Ctx) {
pub fn fd_filestat_set_times(
ctx: &mut Ctx,
fd: __wasi_fd_t,
st_atim: __wasi_timestamp_t,
st_mtim: __wasi_timestamp_t,
fst_flags: __wasi_fstflags_t,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_pread(ctx: &mut Ctx) {
pub fn fd_pread(
ctx: &mut Ctx,
fd: __wasi_fd_t,
iovs: WasmPtr<__wasi_iovec_t, Array>,
iovs_len: u32,
offset: __wasi_filesize_t,
nread: WasmPtr<u32>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_prestat_get(ctx: &mut Ctx) {
pub fn fd_prestat_get(
ctx: &mut Ctx,
fd: __wasi_fd_t,
buf: WasmPtr<__wasi_fdstat_t>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_prestat_dir_name(ctx: &mut Ctx) {
pub fn fd_prestat_dir_name(
ctx: &mut Ctx,
fd: __wasi_fd_t,
path: WasmPtr<u8, Array>,
path_len: u32,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_pwrite(ctx: &mut Ctx) {
pub fn fd_pwrite(
ctx: &mut Ctx,
fd: __wasi_fd_t,
iovs: WasmPtr<__wasi_ciovec_t, Array>,
iovs_len: u32,
offset: __wasi_filesize_t,
nwritten: WasmPtr<u32>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_read(ctx: &mut Ctx) {
pub fn fd_read(
ctx: &mut Ctx,
fd: __wasi_fd_t,
iovs: WasmPtr<__wasi_iovec_t, Array>,
iovs_len: u32,
nread: WasmPtr<u32>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_readdir(ctx: &mut Ctx) {
pub fn fd_readdir(
ctx: &mut Ctx,
fd: __wasi_fd_t,
buf: WasmPtr<u8, Array>,
buf_len: u32,
cookie: __wasi_dircookie_t,
bufused: WasmPtr<u32>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_renumber(ctx: &mut Ctx) {
pub fn fd_renumber(ctx: &mut Ctx, from: __wasi_fd_t, to: __wasi_fd_t) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_seek(ctx: &mut Ctx) {
pub fn fd_seek(
ctx: &mut Ctx,
fd: __wasi_fd_t,
offset: __wasi_filedelta_t,
whence: __wasi_whence_t,
newoffset: WasmPtr<__wasi_filesize_t>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_sync(ctx: &mut Ctx) {
pub fn fd_sync(ctx: &mut Ctx, fd: __wasi_fd_t) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_tell(ctx: &mut Ctx) {
pub fn fd_tell(
ctx: &mut Ctx,
fd: __wasi_fd_t,
offset: WasmPtr<__wasi_filesize_t>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn fd_write(ctx: &mut Ctx) {
pub fn fd_write(
ctx: &mut Ctx,
fd: __wasi_fd_t,
iovs: WasmPtr<__wasi_ciovec_t, Array>,
iovs_len: u32,
nwritten: WasmPtr<u32>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn path_create_directory(ctx: &mut Ctx) {
pub fn path_create_directory(
ctx: &mut Ctx,
fd: __wasi_fd_t,
path: WasmPtr<u8, Array>,
path_len: u32,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn path_filestat_get(ctx: &mut Ctx) {
pub fn path_filestat_get(
ctx: &mut Ctx,
fd: __wasi_fd_t,
flags: __wasi_lookupflags_t,
path: WasmPtr<u8, Array>,
path_len: u32,
buf: WasmPtr<__wasi_filestat_t>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn path_filestat_set_times(ctx: &mut Ctx) {
pub fn path_filestat_set_times(
ctx: &mut Ctx,
fd: __wasi_fd_t,
flags: __wasi_lookupflags_t,
path: WasmPtr<u8, Array>,
path_len: u32,
st_atim: __wasi_timestamp_t,
st_mtim: __wasi_timestamp_t,
fst_flags: __wasi_fstflags_t,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn path_link(ctx: &mut Ctx) {
pub fn path_link(
ctx: &mut Ctx,
old_fd: __wasi_fd_t,
old_flags: __wasi_lookupflags_t,
old_path: WasmPtr<u8, Array>,
old_path_len: u32,
new_fd: __wasi_fd_t,
new_path: WasmPtr<u8, Array>,
new_path_len: u32,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn path_open(ctx: &mut Ctx) {
pub fn path_open(
ctx: &mut Ctx,
dirfd: __wasi_fd_t,
dirflags: __wasi_lookupflags_t,
path: WasmPtr<u8, Array>,
path_len: u32,
o_flags: __wasi_oflags_t,
fs_rights_base: __wasi_rights_t,
fs_rights_inheriting: __wasi_rights_t,
fs_flags: __wasi_fdflags_t,
fd: WasmPtr<__wasi_fd_t>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn path_readlink(ctx: &mut Ctx) {
pub fn path_readlink(
ctx: &mut Ctx,
fd: __wasi_fd_t,
path: WasmPtr<u8, Array>,
path_len: u32,
buf: WasmPtr<u8>,
buf_len: u32,
bufused: WasmPtr<u32>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn path_remove_directory(ctx: &mut Ctx) {
pub fn path_remove_directory(
ctx: &mut Ctx,
fd: __wasi_fd_t,
path: WasmPtr<u8, Array>,
path_len: u32,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn path_rename(ctx: &mut Ctx) {
pub fn path_rename(
ctx: &mut Ctx,
old_fd: __wasi_fd_t,
old_path: WasmPtr<u8, Array>,
old_path_len: u32,
new_fd: __wasi_fd_t,
new_path: WasmPtr<u8, Array>,
new_path_len: u32,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn path_symlink(ctx: &mut Ctx) {
pub fn path_symlink(
ctx: &mut Ctx,
old_path: WasmPtr<u8, Array>,
old_path_len: u32,
fd: __wasi_fd_t,
new_path: WasmPtr<u8, Array>,
new_path_len: u32,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn path_unlink_file(ctx: &mut Ctx) {
pub fn path_unlink_file(
ctx: &mut Ctx,
fd: __wasi_fd_t,
path: WasmPtr<u8, Array>,
path_len: u32,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn poll_oneoff(ctx: &mut Ctx) {
pub fn poll_oneoff(
ctx: &mut Ctx,
in_: WasmPtr<__wasi_subscription_t, Array>,
out_: WasmPtr<__wasi_event_t, Array>,
nsubscriptions: u32,
nevents: WasmPtr<u32>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn proc_exit(ctx: &mut Ctx) {
pub fn proc_exit(ctx: &mut Ctx, rval: __wasi_exitcode_t) {
unimplemented!()
}
pub fn proc_raise(ctx: &mut Ctx) {
pub fn proc_raise(ctx: &mut Ctx, sig: __wasi_signal_t) -> __wasi_errno_t {
unimplemented!()
}
pub fn random_get(ctx: &mut Ctx) {
pub fn random_get(ctx: &mut Ctx, buf: WasmPtr<u8, Array>, buf_len: u32) -> __wasi_errno_t {
unimplemented!()
}
pub fn sched_yield(ctx: &mut Ctx) {
pub fn sched_yield(ctx: &mut Ctx) -> __wasi_errno_t {
unimplemented!()
}
pub fn sock_recv(ctx: &mut Ctx) {
pub fn sock_recv(
ctx: &mut Ctx,
sock: __wasi_fd_t,
ri_data: WasmPtr<__wasi_iovec_t, Array>,
ri_data_len: u32,
ri_flags: __wasi_riflags_t,
ro_datalen: WasmPtr<u32>,
ro_flags: WasmPtr<__wasi_roflags_t>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn sock_send(ctx: &mut Ctx) {
pub fn sock_send(
ctx: &mut Ctx,
sock: __wasi_fd_t,
si_data: WasmPtr<__wasi_ciovec_t, Array>,
si_data_len: u32,
si_flags: __wasi_siflags_t,
so_datalen: WasmPtr<u32>,
) -> __wasi_errno_t {
unimplemented!()
}
pub fn sock_shutdown(ctx: &mut Ctx) {
pub fn sock_shutdown(ctx: &mut Ctx, sock: __wasi_fd_t, how: __wasi_sdflags_t) -> __wasi_errno_t {
unimplemented!()
}

View File

@ -1,5 +1,8 @@
#![allow(non_camel_case_types)]
use crate::ptr::{Array, WasmPtr};
use wasmer_runtime_core::types::{ValueError, ValueType};
pub type __wasi_advice_t = u8;
pub const __WASI_ADVICE_DONTNEED: u8 = 0;
pub const __WASI_ADVICE_NOREUSE: u8 = 1;
@ -11,7 +14,7 @@ pub const __WASI_ADVICE_WILLNEED: u8 = 5;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct __wasi_ciovec_t {
pub buf: u32,
pub buf: WasmPtr<u8, Array>,
pub buf_len: u32,
}
@ -205,7 +208,7 @@ pub type __wasi_inode_t = u64;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct __wasi_iovec_t {
pub buf: u32,
pub buf: WasmPtr<u8, Array>,
pub buf_len: u32,
}
@ -220,7 +223,7 @@ pub const __WASI_O_DIRECTORY: u16 = 1 << 1;
pub const __WASI_O_EXCL: u16 = 1 << 2;
pub const __WASI_O_TRUNC: u16 = 1 << 3;
pub type __wasi_riflags = u16;
pub type __wasi_riflags_t = u16;
pub const __WASI_SOCK_RECV_PEEK: u16 = 1 << 0;
pub const __WASI_SOCK_RECV_WAITALL: u16 = 1 << 1;