Skip to content

Commit

Permalink
Merge #299
Browse files Browse the repository at this point in the history
299: Support for the WASI ABI. r=xmclark a=lachlansneff

part of #297 

Co-authored-by: Lachlan Sneff <[email protected]>
Co-authored-by: Mark McCaskey <[email protected]>
Co-authored-by: bors[bot] <bors[bot]@users.noreply.github.com>
Co-authored-by: Mark McCaskey <[email protected]>
  • Loading branch information
4 people committed Apr 4, 2019
2 parents 0d8a190 + bbf663a commit b06b9ec
Show file tree
Hide file tree
Showing 20 changed files with 2,788 additions and 260 deletions.
422 changes: 223 additions & 199 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ wasmer-runtime-abi = { path = "lib/runtime-abi", optional = true }
wasmer-runtime-core = { path = "lib/runtime-core" }
wasmer-emscripten = { path = "lib/emscripten" }
wasmer-llvm-backend = { path = "lib/llvm-backend", optional = true }
wasmer-wasi = { path = "lib/wasi", optional = true }

[workspace]
members = ["lib/clif-backend", "lib/dynasm-backend", "lib/runtime", "lib/runtime-abi", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend"]
members = ["lib/clif-backend", "lib/dynasm-backend", "lib/runtime", "lib/runtime-abi", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend", "lib/wasi"]

[build-dependencies]
wabt = "0.7.2"
Expand All @@ -45,4 +46,5 @@ debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
fast-tests = []
llvm = ["wasmer-llvm-backend"]
dynasm = ["wasmer-dynasm-backend"]
wasi = ["wasmer-wasi"]
vfs = ["wasmer-runtime-abi"]
29 changes: 26 additions & 3 deletions lib/runtime-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ impl std::error::Error for LinkError {}
/// The main way to do this is `Instance.call`.
///
/// Comparing two `RuntimeError`s always evaluates to false.
#[derive(Debug)]
pub enum RuntimeError {
Trap { msg: Box<str> },
Exception { data: Box<[Value]> },
Expand All @@ -141,11 +140,27 @@ impl std::fmt::Display for RuntimeError {
RuntimeError::Exception { ref data } => {
write!(f, "Uncaught WebAssembly exception: {:?}", data)
}
RuntimeError::Panic { data: _ } => write!(f, "User-defined \"panic\""),
RuntimeError::Panic { data } => {
let msg = if let Some(s) = data.downcast_ref::<String>() {
s
} else if let Some(s) = data.downcast_ref::<&str>() {
s
} else {
"user-defined, opaque"
};

write!(f, "{}", msg)
}
}
}
}

impl std::fmt::Debug for RuntimeError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self)
}
}

impl std::error::Error for RuntimeError {}

/// This error type is produced by resolving a wasm function
Expand Down Expand Up @@ -197,7 +212,6 @@ impl std::error::Error for ResolveError {}
/// be the `CallError::Runtime(RuntimeError)` variant.
///
/// Comparing two `CallError`s always evaluates to false.
#[derive(Debug)]
pub enum CallError {
Resolve(ResolveError),
Runtime(RuntimeError),
Expand All @@ -218,6 +232,15 @@ impl std::fmt::Display for CallError {
}
}

impl std::fmt::Debug for CallError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
CallError::Resolve(resolve_err) => write!(f, "ResolveError: {:?}", resolve_err),
CallError::Runtime(runtime_err) => write!(f, "RuntimeError: {:?}", runtime_err),
}
}
}

impl std::error::Error for CallError {}

/// This error type is produced when creating something,
Expand Down
18 changes: 18 additions & 0 deletions lib/runtime-core/src/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use hashbrown::{hash_map::Entry, HashMap};
use std::collections::VecDeque;
use std::{
cell::{Ref, RefCell},
ffi::c_void,
rc::Rc,
};

Expand Down Expand Up @@ -45,16 +46,32 @@ impl IsExport for Export {
/// ```
pub struct ImportObject {
map: Rc<RefCell<HashMap<String, Box<dyn LikeNamespace>>>>,
state_creator: Option<Rc<Fn() -> (*mut c_void, fn(*mut c_void))>>,
}

impl ImportObject {
/// Create a new `ImportObject`.
pub fn new() -> Self {
Self {
map: Rc::new(RefCell::new(HashMap::new())),
state_creator: None,
}
}

pub fn new_with_data<F>(state_creator: F) -> Self
where
F: Fn() -> (*mut c_void, fn(*mut c_void)) + 'static,
{
Self {
map: Rc::new(RefCell::new(HashMap::new())),
state_creator: Some(Rc::new(state_creator)),
}
}

pub(crate) fn call_state_creator(&self) -> Option<(*mut c_void, fn(*mut c_void))> {
self.state_creator.as_ref().map(|state_gen| state_gen())
}

/// Register anything that implements `LikeNamespace` as a namespace.
///
/// # Usage:
Expand Down Expand Up @@ -98,6 +115,7 @@ impl ImportObject {
pub fn clone_ref(&self) -> Self {
Self {
map: Rc::clone(&self.map),
state_creator: self.state_creator.clone(),
}
}

Expand Down
11 changes: 10 additions & 1 deletion lib/runtime-core/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,16 @@ impl Instance {
// Initialize the vm::Ctx in-place after the backing
// has been boxed.
unsafe {
*inner.vmctx = vm::Ctx::new(&mut inner.backing, &mut inner.import_backing, &module)
*inner.vmctx = match imports.call_state_creator() {
Some((data, dtor)) => vm::Ctx::new_with_data(
&mut inner.backing,
&mut inner.import_backing,
&module,
data,
dtor,
),
None => vm::Ctx::new(&mut inner.backing, &mut inner.import_backing, &module),
};
};

let instance = Instance {
Expand Down
22 changes: 22 additions & 0 deletions lib/runtime-core/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ macro_rules! func {
/// },
/// };
///
/// let imports_with_state = imports! {
/// || (0 as _, |_a| {}),
/// "env" => {
/// "foo" => func!(foo),
/// },
/// };
///
/// fn foo(_: &mut Ctx, n: i32) -> i32 {
/// n
/// }
Expand All @@ -57,6 +64,21 @@ macro_rules! imports {
import_object.register($ns_name, ns);
})*

import_object
}};
($state_gen:expr, $( $ns_name:expr => $ns:tt, )* ) => {{
use $crate::{
import::{ImportObject, Namespace},
};

let mut import_object = ImportObject::new_with_data($state_gen);

$({
let ns = $crate::__imports_internal!($ns);

import_object.register($ns_name, ns);
})*

import_object
}};
}
Expand Down
56 changes: 16 additions & 40 deletions lib/runtime-core/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -113,34 +126,15 @@ unsafe impl WasmExternType for f64 {
// fn swap(&self, other: Self::Primitive) -> Self::Primitive;
// }

pub enum ValueError {
BufferTooSmall,
}

pub trait ValueType: Copy
pub unsafe trait ValueType: Copy
where
Self: Sized,
{
fn into_le(self, buffer: &mut [u8]);
fn from_le(buffer: &[u8]) -> Result<Self, ValueError>;
}

macro_rules! convert_value_impl {
($t:ty) => {
impl ValueType for $t {
fn into_le(self, buffer: &mut [u8]) {
buffer[..mem::size_of::<Self>()].copy_from_slice(&self.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::<Self>()];
array.copy_from_slice(&buffer[..mem::size_of::<Self>()]);
Ok(Self::from_le_bytes(array))
} else {
Err(ValueError::BufferTooSmall)
}
}
}
unsafe impl ValueType for $t {}
};
( $($t:ty),* ) => {
$(
Expand All @@ -149,25 +143,7 @@ macro_rules! convert_value_impl {
};
}

convert_value_impl!(u8, i8, u16, i16, u32, i32, u64, i64);

impl ValueType for f32 {
fn into_le(self, buffer: &mut [u8]) {
self.to_bits().into_le(buffer);
}
fn from_le(buffer: &[u8]) -> Result<Self, ValueError> {
Ok(f32::from_bits(<u32 as ValueType>::from_le(buffer)?))
}
}

impl ValueType for f64 {
fn into_le(self, buffer: &mut [u8]) {
self.to_bits().into_le(buffer);
}
fn from_le(buffer: &[u8]) -> Result<Self, ValueError> {
Ok(f64::from_bits(<u64 as ValueType>::from_le(buffer)?))
}
}
convert_value_impl!(u8, i8, u16, i16, u32, i32, u64, i64, f32, f64);

#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
pub enum ElementType {
Expand Down
6 changes: 3 additions & 3 deletions lib/runtime-core/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub struct Ctx {
module: *const ModuleInner,

pub data: *mut c_void,
pub data_finalizer: Option<extern "C" fn(data: *mut c_void)>,
pub data_finalizer: Option<fn(data: *mut c_void)>,
}

/// The internal context of the currently running WebAssembly instance.
Expand Down Expand Up @@ -100,7 +100,7 @@ impl Ctx {
import_backing: &mut ImportBacking,
module: &ModuleInner,
data: *mut c_void,
data_finalizer: extern "C" fn(*mut c_void),
data_finalizer: fn(*mut c_void),
) -> Self {
Self {
internal: InternalCtx {
Expand Down Expand Up @@ -481,7 +481,7 @@ mod vm_ctx_tests {
str: String,
}

extern "C" fn test_data_finalizer(data: *mut c_void) {
fn test_data_finalizer(data: *mut c_void) {
let test_data: &mut TestData = unsafe { &mut *(data as *mut TestData) };
assert_eq!(test_data.x, 10);
assert_eq!(test_data.y, true);
Expand Down
22 changes: 22 additions & 0 deletions lib/wasi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "wasmer-wasi"
version = "0.2.1"
license = "MIT"
authors = ["The Wasmer Engineering Team <[email protected]>"]
repository = "https://github.com/wasmerio/wasmer"
edition = "2018"

[dependencies]
wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" }
libc = "0.2.50"
rand = "0.6.5"
# wasmer-runtime-abi = { path = "../runtime-abi" }
hashbrown = "0.1.8"
generational-arena = "0.2.2"
log = "0.4.6"
byteorder = "1.3.1"

[dependencies.zbox]
git = "https://github.com/wasmerio/zbox"
branch = "bundle-libsodium"
features = ["libsodium-bundled"]
Loading

0 comments on commit b06b9ec

Please sign in to comment.