Merge branch 'master' into fix/create-exe-genearted-code-bugs

This commit is contained in:
Mark McCaskey
2020-10-19 10:03:05 -07:00
committed by GitHub
57 changed files with 672 additions and 591 deletions

View File

@ -9,6 +9,10 @@
### Added ### Added
- [#1736](https://github.com/wasmerio/wasmer/pull/1736) Implement `wasm_global_type` in the Wasm C API.
- [#1699](https://github.com/wasmerio/wasmer/pull/1699) Update `wasm.h` to its latest version.
- [#1685](https://github.com/wasmerio/wasmer/pull/1685) Implement `wasm_exporttype_delete` in the Wasm C API.
- [#1725](https://github.com/wasmerio/wasmer/pull/1725) Implement `wasm_func_type` in the Wasm C API.
- [#1715](https://github.com/wasmerio/wasmer/pull/1715) Register errors from `wasm_module_serialize` in the Wasm C API. - [#1715](https://github.com/wasmerio/wasmer/pull/1715) Register errors from `wasm_module_serialize` in the Wasm C API.
- [#1709](https://github.com/wasmerio/wasmer/pull/1709) Implement `wasm_module_name` and `wasm_module_set_name` in the Wasm(er) C API. - [#1709](https://github.com/wasmerio/wasmer/pull/1709) Implement `wasm_module_name` and `wasm_module_set_name` in the Wasm(er) C API.
- [#1700](https://github.com/wasmerio/wasmer/pull/1700) Implement `wasm_externtype_copy` in the Wasm C API. - [#1700](https://github.com/wasmerio/wasmer/pull/1700) Implement `wasm_externtype_copy` in the Wasm C API.

View File

@ -35,7 +35,7 @@
* **Pluggable**. Wasmer supports different compilation frameworks to best suit your needs (LLVM, Cranelift...). * **Pluggable**. Wasmer supports different compilation frameworks to best suit your needs (LLVM, Cranelift...).
* **Universal**. You can run Wasmer in almost any *platform* (macOS, Linux and Windows) and *chipset*. * **Universal**. You can run Wasmer in any *platform* (macOS, Linux and Windows) and *chipset*.
* **Standards compliant**. The runtime passes [official WebAssembly test * **Standards compliant**. The runtime passes [official WebAssembly test
suite](https://github.com/WebAssembly/testsuite) supporting [WASI](https://github.com/WebAssembly/WASI) and [Emscripten](https://emscripten.org/). suite](https://github.com/WebAssembly/testsuite) supporting [WASI](https://github.com/WebAssembly/WASI) and [Emscripten](https://emscripten.org/).

View File

@ -198,7 +198,7 @@ impl Module {
self.artifact.serialize_to_file(path.as_ref()) self.artifact.serialize_to_file(path.as_ref())
} }
/// Deserializes a a serialized Module binary into a `Module`. /// Deserializes a serialized Module binary into a `Module`.
/// > Note: the module has to be serialized before with the `serialize` method. /// > Note: the module has to be serialized before with the `serialize` method.
/// ///
/// # Safety /// # Safety

View File

@ -90,12 +90,6 @@ pub mod instance;
pub mod memory; pub mod memory;
pub mod module; pub mod module;
pub mod table; pub mod table;
// `not(target_family = "windows")` is simpler than `unix`. See build.rs
// if you want to change the meaning of these `cfg`s in the header file.
/*
TODO: reenable `trampoline` module when the refactor gains feature parity with Wasmer master
#[cfg(all(not(target_family = "windows"), target_arch = "x86_64"))]
pub mod trampoline;*/
pub mod value; pub mod value;
/// The `wasmer_result_t` enum is a type that represents either a /// The `wasmer_result_t` enum is a type that represents either a

View File

@ -1,92 +0,0 @@
//! Trampoline emitter for transforming function calls.
use std::ffi::c_void;
use std::mem;
use wasmer_vm_core::trampoline::*;
#[repr(C)]
pub struct wasmer_trampoline_buffer_builder_t;
#[repr(C)]
pub struct wasmer_trampoline_buffer_t;
#[repr(C)]
pub struct wasmer_trampoline_callable_t;
/// Creates a new trampoline builder.
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn wasmer_trampoline_buffer_builder_new() -> *mut wasmer_trampoline_buffer_builder_t
{
Box::into_raw(Box::new(TrampolineBufferBuilder::new())) as *mut _
}
/// Adds a context trampoline to the builder.
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn wasmer_trampoline_buffer_builder_add_context_trampoline(
builder: *mut wasmer_trampoline_buffer_builder_t,
func: *const wasmer_trampoline_callable_t,
ctx: *const c_void,
) -> usize {
let builder = &mut *(builder as *mut TrampolineBufferBuilder);
builder.add_context_trampoline(func as *const CallTarget, ctx as *const CallContext)
}
/// Adds a callinfo trampoline to the builder.
///
/// Deprecated. In a future version `DynamicFunc::new` will be exposed to the C API and should be used instead of this function.
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn wasmer_trampoline_buffer_builder_add_callinfo_trampoline(
builder: *mut wasmer_trampoline_buffer_builder_t,
func: *const wasmer_trampoline_callable_t,
ctx: *const c_void,
num_params: u32,
) -> usize {
use wasmer::ValType;
let builder = &mut *(builder as *mut TrampolineBufferBuilder);
builder.add_callinfo_trampoline(
mem::transmute(func),
ctx as *const CallContext,
&vec![ValType::I64; num_params as usize],
&[ValType::I64],
)
}
/// Finalizes the trampoline builder into an executable buffer.
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn wasmer_trampoline_buffer_builder_build(
builder: *mut wasmer_trampoline_buffer_builder_t,
) -> *mut wasmer_trampoline_buffer_t {
let builder = Box::from_raw(builder as *mut TrampolineBufferBuilder);
Box::into_raw(Box::new(builder.build())) as *mut _
}
/// Destroys the trampoline buffer if not null.
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn wasmer_trampoline_buffer_destroy(buffer: *mut wasmer_trampoline_buffer_t) {
if !buffer.is_null() {
Box::from_raw(buffer as *mut TrampolineBuffer);
}
}
/// Returns the callable pointer for the trampoline with index `idx`.
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn wasmer_trampoline_buffer_get_trampoline(
buffer: *const wasmer_trampoline_buffer_t,
idx: usize,
) -> *const wasmer_trampoline_callable_t {
let buffer = &*(buffer as *const TrampolineBuffer);
buffer.get_trampoline(idx) as _
}
/// Returns the context added by `add_context_trampoline`, from within the callee function.
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn wasmer_trampoline_get_context() -> *mut c_void {
get_context() as *const c_void as *mut c_void
}

View File

@ -87,6 +87,7 @@ pub extern "C" fn wasm_config_set_engine(config: &mut wasm_config_t, engine: was
} }
/// cbindgen:ignore /// cbindgen:ignore
#[allow(non_camel_case_types)]
pub struct wasm_engine_t { pub struct wasm_engine_t {
pub(crate) inner: Arc<dyn Engine + Send + Sync>, pub(crate) inner: Arc<dyn Engine + Send + Sync>,
} }
@ -170,6 +171,7 @@ pub extern "C" fn wasm_engine_new_with_config(
// TODO: return useful error messages in failure branches // TODO: return useful error messages in failure branches
cfg_if! { cfg_if! {
if #[cfg(feature = "compiler")] { if #[cfg(feature = "compiler")] {
#[allow(unused_mut)]
let mut compiler_config: Box<dyn CompilerConfig> = match config.compiler { let mut compiler_config: Box<dyn CompilerConfig> = match config.compiler {
wasmer_compiler_t::CRANELIFT => { wasmer_compiler_t::CRANELIFT => {
cfg_if! { cfg_if! {

View File

@ -1,7 +1,7 @@
use super::super::store::wasm_store_t; use super::super::store::wasm_store_t;
use super::super::trap::wasm_trap_t; use super::super::trap::wasm_trap_t;
use super::super::types::{wasm_functype_t, wasm_valkind_enum}; use super::super::types::{wasm_functype_t, wasm_valkind_enum};
use super::super::value::{wasm_val_inner, wasm_val_t}; use super::super::value::{wasm_val_inner, wasm_val_t, wasm_val_vec_t};
use std::convert::TryInto; use std::convert::TryInto;
use std::ffi::c_void; use std::ffi::c_void;
use std::sync::Arc; use std::sync::Arc;
@ -15,14 +15,16 @@ pub struct wasm_func_t {
} }
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub type wasm_func_callback_t = pub type wasm_func_callback_t = unsafe extern "C" fn(
unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t; args: *const wasm_val_vec_t,
results: *mut wasm_val_vec_t,
) -> *mut wasm_trap_t;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub type wasm_func_callback_with_env_t = unsafe extern "C" fn( pub type wasm_func_callback_with_env_t = unsafe extern "C" fn(
*mut c_void, *mut c_void,
args: *const wasm_val_t, args: *const wasm_val_vec_t,
results: *mut wasm_val_t, results: *mut wasm_val_vec_t,
) -> *mut wasm_trap_t; ) -> *mut wasm_trap_t;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
@ -38,31 +40,37 @@ pub unsafe extern "C" fn wasm_func_new(
let func_sig = ft.sig(); let func_sig = ft.sig();
let num_rets = func_sig.results().len(); let num_rets = func_sig.results().len();
let inner_callback = move |args: &[Val]| -> Result<Vec<Val>, RuntimeError> { let inner_callback = move |args: &[Val]| -> Result<Vec<Val>, RuntimeError> {
let processed_args = args let processed_args: wasm_val_vec_t = args
.into_iter() .into_iter()
.map(TryInto::try_into) .map(TryInto::try_into)
.collect::<Result<Vec<wasm_val_t>, _>>() .collect::<Result<Vec<wasm_val_t>, _>>()
.expect("Argument conversion failed"); .expect("Argument conversion failed")
.into();
let mut results = vec![ let mut results: wasm_val_vec_t = vec![
wasm_val_t { wasm_val_t {
kind: wasm_valkind_enum::WASM_I64 as _, kind: wasm_valkind_enum::WASM_I64 as _,
of: wasm_val_inner { int64_t: 0 }, of: wasm_val_inner { int64_t: 0 },
}; };
num_rets num_rets
]; ]
.into();
let trap = callback(&processed_args, &mut results);
let trap = callback(processed_args.as_ptr(), results.as_mut_ptr());
if !trap.is_null() { if !trap.is_null() {
let trap: Box<wasm_trap_t> = Box::from_raw(trap); let trap: Box<wasm_trap_t> = Box::from_raw(trap);
RuntimeError::raise(Box::new(trap.inner)); RuntimeError::raise(Box::new(trap.inner));
} }
let processed_results = results let processed_results = results
.into_slice()
.expect("Failed to convert `results` into a slice")
.into_iter() .into_iter()
.map(TryInto::try_into) .map(TryInto::try_into)
.collect::<Result<Vec<Val>, _>>() .collect::<Result<Vec<Val>, _>>()
.expect("Result conversion failed"); .expect("Result conversion failed");
Ok(processed_results) Ok(processed_results)
}; };
let function = Function::new(&store.inner, &func_sig, inner_callback); let function = Function::new(&store.inner, &func_sig, inner_callback);
@ -86,30 +94,36 @@ pub unsafe extern "C" fn wasm_func_new_with_env(
let num_rets = func_sig.results().len(); let num_rets = func_sig.results().len();
let inner_callback = let inner_callback =
move |env: &mut *mut c_void, args: &[Val]| -> Result<Vec<Val>, RuntimeError> { move |env: &mut *mut c_void, args: &[Val]| -> Result<Vec<Val>, RuntimeError> {
let processed_args = args let processed_args: wasm_val_vec_t = args
.into_iter() .into_iter()
.map(TryInto::try_into) .map(TryInto::try_into)
.collect::<Result<Vec<wasm_val_t>, _>>() .collect::<Result<Vec<wasm_val_t>, _>>()
.expect("Argument conversion failed"); .expect("Argument conversion failed")
.into();
let mut results = vec![ let mut results: wasm_val_vec_t = vec![
wasm_val_t { wasm_val_t {
kind: wasm_valkind_enum::WASM_I64 as _, kind: wasm_valkind_enum::WASM_I64 as _,
of: wasm_val_inner { int64_t: 0 }, of: wasm_val_inner { int64_t: 0 },
}; };
num_rets num_rets
]; ]
.into();
let _traps = callback(*env, processed_args.as_ptr(), results.as_mut_ptr()); let _traps = callback(*env, &processed_args, &mut results);
// TODO: do something with `traps` // TODO: do something with `traps`
let processed_results = results let processed_results = results
.into_slice()
.expect("Failed to convert `results` into a slice")
.into_iter() .into_iter()
.map(TryInto::try_into) .map(TryInto::try_into)
.collect::<Result<Vec<Val>, _>>() .collect::<Result<Vec<Val>, _>>()
.expect("Result conversion failed"); .expect("Result conversion failed");
Ok(processed_results) Ok(processed_results)
}; };
let function = Function::new_with_env(&store.inner, &func_sig, env, inner_callback); let function = Function::new_with_env(&store.inner, &func_sig, env, inner_callback);
Some(Box::new(wasm_func_t { Some(Box::new(wasm_func_t {
@ -124,21 +138,29 @@ pub unsafe extern "C" fn wasm_func_delete(_func: Option<Box<wasm_func_t>>) {}
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_func_call( pub unsafe extern "C" fn wasm_func_call(
func: &wasm_func_t, func: &wasm_func_t,
args: *const wasm_val_t, args: &wasm_val_vec_t,
results: *mut wasm_val_t, results: &mut wasm_val_vec_t,
) -> Option<Box<wasm_trap_t>> { ) -> Option<Box<wasm_trap_t>> {
let num_params = func.inner.ty().params().len(); let params = args
let params: Vec<Val> = (0..num_params) .into_slice()
.map(|i| (&(*args.add(i))).try_into()) .map(|slice| {
.collect::<Result<_, _>>() slice
.ok()?; .into_iter()
.map(TryInto::try_into)
.collect::<Result<Vec<Val>, _>>()
.expect("Argument conversion failed")
})
.unwrap_or_default();
match func.inner.call(&params) { match func.inner.call(&params) {
Ok(wasm_results) => { Ok(wasm_results) => {
for (i, actual_result) in wasm_results.iter().enumerate() { *results = wasm_results
let result_loc = &mut (*results.add(i)); .into_iter()
*result_loc = (&*actual_result).try_into().ok()?; .map(TryInto::try_into)
} .collect::<Result<Vec<wasm_val_t>, _>>()
.expect("Argument conversion failed")
.into();
None None
} }
Err(e) => Some(Box::new(e.into())), Err(e) => Some(Box::new(e.into())),
@ -154,3 +176,8 @@ pub unsafe extern "C" fn wasm_func_param_arity(func: &wasm_func_t) -> usize {
pub unsafe extern "C" fn wasm_func_result_arity(func: &wasm_func_t) -> usize { pub unsafe extern "C" fn wasm_func_result_arity(func: &wasm_func_t) -> usize {
func.inner.ty().results().len() func.inner.ty().results().len()
} }
#[no_mangle]
pub extern "C" fn wasm_func_type(func: &wasm_func_t) -> Box<wasm_functype_t> {
Box::new(wasm_functype_t::new(func.inner.ty().clone()))
}

View File

@ -59,3 +59,8 @@ pub unsafe extern "C" fn wasm_global_same(
) -> bool { ) -> bool {
wasm_global1.inner.same(&wasm_global2.inner) wasm_global1.inner.same(&wasm_global2.inner)
} }
#[no_mangle]
pub extern "C" fn wasm_global_type(wasm_global: &wasm_global_t) -> Box<wasm_globaltype_t> {
Box::new(wasm_globaltype_t::new(wasm_global.inner.ty().clone()))
}

View File

@ -12,56 +12,21 @@ pub struct wasm_instance_t {
pub(crate) inner: Arc<Instance>, pub(crate) inner: Arc<Instance>,
} }
struct CArrayIter<T: Sized + 'static> {
cur_entry: *const *const T,
}
impl<T: Sized + 'static> CArrayIter<T> {
fn new(array: *const *const T) -> Option<Self> {
if array.is_null() {
None
} else {
Some(CArrayIter { cur_entry: array })
}
}
}
impl<T: Sized + 'static> Iterator for CArrayIter<T> {
type Item = &'static T;
fn next(&mut self) -> Option<Self::Item> {
let next_entry_candidate = unsafe { *self.cur_entry };
if next_entry_candidate.is_null() {
None
} else {
self.cur_entry = unsafe { self.cur_entry.add(1) };
Some(unsafe { &*next_entry_candidate })
}
}
}
// reads from null-terminated array of `wasm_extern_t`s
unsafe fn argument_import_iter(
imports: *const *const wasm_extern_t,
) -> Box<dyn Iterator<Item = &'static wasm_extern_t>> {
CArrayIter::new(imports)
.map(|it| Box::new(it) as _)
.unwrap_or_else(|| Box::new(std::iter::empty()) as _)
}
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_instance_new( pub unsafe extern "C" fn wasm_instance_new(
_store: &wasm_store_t, _store: &wasm_store_t,
module: &wasm_module_t, module: &wasm_module_t,
imports: *const *const wasm_extern_t, imports: &wasm_extern_vec_t,
// own // own
_traps: *mut *mut wasm_trap_t, _traps: *mut *mut wasm_trap_t,
) -> Option<Box<wasm_instance_t>> { ) -> Option<Box<wasm_instance_t>> {
let wasm_module = &module.inner; let wasm_module = &module.inner;
let module_imports = wasm_module.imports(); let module_imports = wasm_module.imports();
let module_import_count = module_imports.len(); let module_import_count = module_imports.len();
let imports = argument_import_iter(imports);
let resolver: OrderedResolver = imports let resolver: OrderedResolver = imports
.into_slice()
.map(|imports| imports.iter())
.unwrap_or_else(|| [].iter())
.map(|imp| &imp.inner) .map(|imp| &imp.inner)
.take(module_import_count) .take(module_import_count)
.cloned() .cloned()

View File

@ -17,6 +17,14 @@ impl wasm_functype_t {
unreachable!("data corruption: `wasm_functype_t` does not contain a function") unreachable!("data corruption: `wasm_functype_t` does not contain a function")
} }
} }
pub(crate) fn new(function_type: FunctionType) -> Self {
Self {
extern_: wasm_externtype_t {
inner: ExternType::Function(function_type),
},
}
}
} }
wasm_declare_vec!(functype); wasm_declare_vec!(functype);
@ -52,10 +60,9 @@ unsafe fn wasm_functype_new_inner(
.map(Into::into) .map(Into::into)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let extern_ = wasm_externtype_t { Some(Box::new(wasm_functype_t::new(FunctionType::new(
inner: ExternType::Function(FunctionType::new(params, results)), params, results,
}; ))))
Some(Box::new(wasm_functype_t { extern_ }))
} }
#[no_mangle] #[no_mangle]

View File

@ -20,6 +20,14 @@ impl wasm_globaltype_t {
); );
} }
} }
pub(crate) fn new(global_type: GlobalType) -> Self {
Self {
extern_: wasm_externtype_t {
inner: ExternType::Global(global_type),
},
}
}
} }
wasm_declare_vec!(globaltype); wasm_declare_vec!(globaltype);
@ -42,11 +50,10 @@ unsafe fn wasm_globaltype_new_inner(
mutability: wasm_mutability_t, mutability: wasm_mutability_t,
) -> Option<Box<wasm_globaltype_t>> { ) -> Option<Box<wasm_globaltype_t>> {
let me: wasm_mutability_enum = mutability.try_into().ok()?; let me: wasm_mutability_enum = mutability.try_into().ok()?;
let gd = Box::new(wasm_globaltype_t { let gd = Box::new(wasm_globaltype_t::new(GlobalType::new(
extern_: wasm_externtype_t { (*valtype).into(),
inner: ExternType::Global(GlobalType::new((*valtype).into(), me.into())), me.into(),
}, )));
});
wasm_valtype_delete(Some(valtype)); wasm_valtype_delete(Some(valtype));
Some(gd) Some(gd)

View File

@ -23,6 +23,8 @@ pub struct wasm_val_t {
pub of: wasm_val_inner, pub of: wasm_val_inner,
} }
wasm_declare_vec!(val);
impl Clone for wasm_val_t { impl Clone for wasm_val_t {
fn clone(&self) -> Self { fn clone(&self) -> Self {
wasm_val_t { wasm_val_t {

View File

@ -5,7 +5,7 @@
mod capture_files; mod capture_files;
use super::{ use super::{
externals::{wasm_extern_t, wasm_func_t, wasm_memory_t}, externals::{wasm_extern_t, wasm_extern_vec_t, wasm_func_t, wasm_memory_t},
instance::wasm_instance_t, instance::wasm_instance_t,
module::wasm_module_t, module::wasm_module_t,
store::wasm_store_t, store::wasm_store_t,
@ -300,7 +300,7 @@ pub unsafe extern "C" fn wasi_get_imports(
store: &wasm_store_t, store: &wasm_store_t,
module: &wasm_module_t, module: &wasm_module_t,
wasi_env: &wasi_env_t, wasi_env: &wasi_env_t,
imports: *mut *mut wasm_extern_t, imports: &mut wasm_extern_vec_t,
) -> bool { ) -> bool {
wasi_get_imports_inner(store, module, wasi_env, imports).is_some() wasi_get_imports_inner(store, module, wasi_env, imports).is_some()
} }
@ -310,7 +310,7 @@ unsafe fn wasi_get_imports_inner(
store: &wasm_store_t, store: &wasm_store_t,
module: &wasm_module_t, module: &wasm_module_t,
wasi_env: &wasi_env_t, wasi_env: &wasi_env_t,
imports: *mut *mut wasm_extern_t, imports: &mut wasm_extern_vec_t,
) -> Option<()> { ) -> Option<()> {
let store = &store.inner; let store = &store.inner;
@ -322,22 +322,28 @@ unsafe fn wasi_get_imports_inner(
let import_object = generate_import_object_from_env(store, wasi_env.inner.clone(), version); let import_object = generate_import_object_from_env(store, wasi_env.inner.clone(), version);
for (i, it) in module.inner.imports().enumerate() { *imports = module
.inner
.imports()
.map(|import_type| {
let export = c_try!(import_object let export = c_try!(import_object
.resolve_by_name(it.module(), it.name()) .resolve_by_name(import_type.module(), import_type.name())
.ok_or_else(|| CApiError { .ok_or_else(|| CApiError {
msg: format!( msg: format!(
"Failed to resolve import \"{}\" \"{}\"", "Failed to resolve import \"{}\" \"{}\"",
it.module(), import_type.module(),
it.name() import_type.name()
), ),
})); }));
let inner = Extern::from_export(store, export); let inner = Extern::from_export(store, export);
*imports.add(i) = Box::into_raw(Box::new(wasm_extern_t {
Some(Box::new(wasm_extern_t {
instance: None, instance: None,
inner, inner,
})); }))
} })
.collect::<Option<Vec<_>>>()?
.into();
Some(()) Some(())
} }

View File

@ -27,9 +27,9 @@ void print_frame(wasm_frame_t* frame) {
wasm_store_t *store = NULL; wasm_store_t *store = NULL;
own wasm_trap_t *early_exit(const wasm_val_t args[], wasm_val_t results[]) { own wasm_trap_t* early_exit(const wasm_val_vec_t* args, wasm_val_vec_t* results) {
own wasm_message_t trap_message; own wasm_message_t trap_message;
wasm_name_new_from_string(&trap_message, "trapping from a host import"); wasm_name_new_from_string_nt(&trap_message, "trapping from a host import");
own wasm_trap_t *trap = wasm_trap_new(store, &trap_message); own wasm_trap_t *trap = wasm_trap_new(store, &trap_message);
wasm_name_delete(&trap_message); wasm_name_delete(&trap_message);
return trap; return trap;
@ -77,9 +77,13 @@ int main(int argc, const char *argv[]) {
wasm_functype_delete(host_func_type); wasm_functype_delete(host_func_type);
const wasm_extern_t *imports[] = {wasm_func_as_extern(host_func)}; wasm_extern_vec_t imports;
wasm_extern_vec_new_uninitialized(&imports, 1);
imports.data[0] = wasm_func_as_extern(host_func);
own wasm_instance_t *instance = own wasm_instance_t *instance =
wasm_instance_new(store, module, imports, NULL); wasm_instance_new(store, module, &imports, NULL);
if (!instance) { if (!instance) {
printf("> Error instantiating module!\n"); printf("> Error instantiating module!\n");
print_wasmer_error(); print_wasmer_error();
@ -110,12 +114,12 @@ int main(int argc, const char *argv[]) {
// Call. // Call.
printf("Calling export...\n"); printf("Calling export...\n");
own const wasm_val_t args[] = { wasm_val_t values[2] = { WASM_I32_VAL(1), WASM_I32_VAL(7) };
{.kind = WASM_I32, .of = {.i32 = 1}}, own wasm_val_vec_t args = WASM_ARRAY_VEC(values);
{.kind = WASM_I32, .of = {.i32 = 7}}, wasm_val_t result = WASM_INIT_VAL;
}; own wasm_val_vec_t rets = { 1, &result };
own wasm_val_t rets[1] = {}; own wasm_trap_t *trap = wasm_func_call(run_func, &args, &rets);
own wasm_trap_t *trap = wasm_func_call(run_func, args, rets);
if (!trap) { if (!trap) {
printf("> Error calling function: expected trap!\n"); printf("> Error calling function: expected trap!\n");
return 1; return 1;
@ -151,6 +155,7 @@ int main(int argc, const char *argv[]) {
wasm_name_delete(&message); wasm_name_delete(&message);
wasm_extern_vec_delete(&exports); wasm_extern_vec_delete(&exports);
wasm_extern_vec_delete(&imports);
// Shut down. // Shut down.
printf("Shutting down...\n"); printf("Shutting down...\n");

View File

@ -18,7 +18,6 @@ void print_wasmer_error()
printf("Error str: `%s`\n", error_str); printf("Error str: `%s`\n", error_str);
} }
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
// Initialize. // Initialize.
printf("Initializing...\n"); printf("Initializing...\n");
@ -71,18 +70,22 @@ int main(int argc, const char* argv[]) {
printf("Instantiating module...\n"); printf("Instantiating module...\n");
wasm_importtype_vec_t import_types; wasm_importtype_vec_t import_types;
wasm_module_imports(module, &import_types); wasm_module_imports(module, &import_types);
int num_imports = import_types.size;
wasm_extern_t** imports = malloc(num_imports * sizeof(wasm_extern_t*)); wasm_extern_vec_t imports;
wasm_extern_vec_new_uninitialized(&imports, import_types.size);
wasm_importtype_vec_delete(&import_types); wasm_importtype_vec_delete(&import_types);
bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports); bool get_imports_result = wasi_get_imports(store, module, wasi_env, &imports);
if (!get_imports_result) { if (!get_imports_result) {
printf("> Error getting WASI imports!\n"); printf("> Error getting WASI imports!\n");
print_wasmer_error(); print_wasmer_error();
return 1; return 1;
} }
own wasm_instance_t* instance = own wasm_instance_t* instance =
wasm_instance_new(store, module, (const wasm_extern_t *const *) imports, NULL); wasm_instance_new(store, module, &imports, NULL);
if (!instance) { if (!instance) {
printf("> Error instantiating module!\n"); printf("> Error instantiating module!\n");
print_wasmer_error(); print_wasmer_error();
@ -114,7 +117,11 @@ int main(int argc, const char* argv[]) {
// Call. // Call.
printf("Calling export...\n"); printf("Calling export...\n");
printf("Evaluating \"%s\"\n", js_string); printf("Evaluating \"%s\"\n", js_string);
if (wasm_func_call(run_func, NULL, NULL)) {
wasm_val_vec_t args = WASM_EMPTY_VEC;
wasm_val_vec_t res = WASM_EMPTY_VEC;
if (wasm_func_call(run_func, &args, &res)) {
printf("> Error calling function!\n"); printf("> Error calling function!\n");
return 1; return 1;
} }
@ -131,12 +138,7 @@ int main(int argc, const char* argv[]) {
printf("\n"); printf("\n");
wasm_extern_vec_delete(&exports); wasm_extern_vec_delete(&exports);
wasm_extern_vec_delete(&imports);
// NEEDS REVIEW:
for(int i = 0; i < num_imports; ++i) {
wasm_extern_delete(imports[i]);
}
free(imports);
// Shut down. // Shut down.
printf("Shutting down...\n"); printf("Shutting down...\n");

View File

@ -94,6 +94,7 @@ Currently, known implementations of this API are included in
* V8 natively (both C and C++) * V8 natively (both C and C++)
* Wabt (only C?) * Wabt (only C?)
* Wasmtime (only C?) * Wasmtime (only C?)
* [Wasmer](https://github.com/wasmerio/wasmer/tree/master/lib/c-api) (only C, C++ coming soon)
### TODO ### TODO

View File

@ -35,27 +35,27 @@ void wasm_val_print(wasm_val_t val) {
// A function to be called from Wasm code. // A function to be called from Wasm code.
own wasm_trap_t* print_callback( own wasm_trap_t* print_callback(
const wasm_val_t args[], wasm_val_t results[] const wasm_val_vec_t* args, wasm_val_vec_t* results
) { ) {
printf("Calling back...\n> "); printf("Calling back...\n> ");
wasm_val_print(args[0]); wasm_val_print(args->data[0]);
printf("\n"); printf("\n");
wasm_val_copy(&results[0], &args[0]); wasm_val_copy(&results->data[0], &args->data[0]);
return NULL; return NULL;
} }
// A function closure. // A function closure.
own wasm_trap_t* closure_callback( own wasm_trap_t* closure_callback(
void* env, const wasm_val_t args[], wasm_val_t results[] void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results
) { ) {
int i = *(int*)env; int i = *(int*)env;
printf("Calling back closure...\n"); printf("Calling back closure...\n");
printf("> %d\n", i); printf("> %d\n", i);
results[0].kind = WASM_I32; results->data[0].kind = WASM_I32;
results[0].of.i32 = (int32_t)i; results->data[0].of.i32 = (int32_t)i;
return NULL; return NULL;
} }
@ -68,7 +68,7 @@ int main(int argc, const char* argv[]) {
// Load binary. // Load binary.
printf("Loading binary...\n"); printf("Loading binary...\n");
FILE* file = fopen("callback.wasm", "r"); FILE* file = fopen("callback.wasm", "rb");
if (!file) { if (!file) {
printf("> Error loading module!\n"); printf("> Error loading module!\n");
return 1; return 1;
@ -108,11 +108,12 @@ int main(int argc, const char* argv[]) {
// Instantiate. // Instantiate.
printf("Instantiating module...\n"); printf("Instantiating module...\n");
const wasm_extern_t* imports[] = { wasm_extern_t* externs[] = {
wasm_func_as_extern(print_func), wasm_func_as_extern(closure_func) wasm_func_as_extern(print_func), wasm_func_as_extern(closure_func)
}; };
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
own wasm_instance_t* instance = own wasm_instance_t* instance =
wasm_instance_new(store, module, imports, NULL); wasm_instance_new(store, module, &imports, NULL);
if (!instance) { if (!instance) {
printf("> Error instantiating module!\n"); printf("> Error instantiating module!\n");
return 1; return 1;
@ -140,13 +141,11 @@ int main(int argc, const char* argv[]) {
// Call. // Call.
printf("Calling export...\n"); printf("Calling export...\n");
wasm_val_t args[2]; wasm_val_t as[2] = { WASM_I32_VAL(3), WASM_I32_VAL(4) };
args[0].kind = WASM_I32; wasm_val_t rs[1] = { WASM_INIT_VAL };
args[0].of.i32 = 3; wasm_val_vec_t args = WASM_ARRAY_VEC(as);
args[1].kind = WASM_I32; wasm_val_vec_t results = WASM_ARRAY_VEC(rs);
args[1].of.i32 = 4; if (wasm_func_call(run_func, &args, &results)) {
wasm_val_t results[1];
if (wasm_func_call(run_func, args, results)) {
printf("> Error calling function!\n"); printf("> Error calling function!\n");
return 1; return 1;
} }
@ -155,7 +154,7 @@ int main(int argc, const char* argv[]) {
// Print result. // Print result.
printf("Printing result...\n"); printf("Printing result...\n");
printf("> %u\n", results[0].of.i32); printf("> %u\n", rs[0].of.i32);
// Shut down. // Shut down.
printf("Shutting down...\n"); printf("Shutting down...\n");

View File

@ -35,7 +35,7 @@ auto operator<<(std::ostream& out, const wasm::Val& val) -> std::ostream& {
// A function to be called from Wasm code. // A function to be called from Wasm code.
auto print_callback( auto print_callback(
const wasm::Val args[], wasm::Val results[] const wasm::vec<wasm::Val>& args, wasm::vec<wasm::Val>& results
) -> wasm::own<wasm::Trap> { ) -> wasm::own<wasm::Trap> {
std::cout << "Calling back..." << std::endl << "> " << args[0] << std::endl; std::cout << "Calling back..." << std::endl << "> " << args[0] << std::endl;
results[0] = args[0].copy(); results[0] = args[0].copy();
@ -45,7 +45,7 @@ auto print_callback(
// A function closure. // A function closure.
auto closure_callback( auto closure_callback(
void* env, const wasm::Val args[], wasm::Val results[] void* env, const wasm::vec<wasm::Val>& args, wasm::vec<wasm::Val>& results
) -> wasm::own<wasm::Trap> { ) -> wasm::own<wasm::Trap> {
auto i = *reinterpret_cast<int*>(env); auto i = *reinterpret_cast<int*>(env);
std::cout << "Calling back closure..." << std::endl; std::cout << "Calling back closure..." << std::endl;
@ -103,7 +103,8 @@ void run() {
// Instantiate. // Instantiate.
std::cout << "Instantiating module..." << std::endl; std::cout << "Instantiating module..." << std::endl;
wasm::Extern* imports[] = {print_func.get(), closure_func.get()}; auto imports = wasm::vec<wasm::Extern*>::make(
print_func.get(), closure_func.get());
auto instance = wasm::Instance::make(store, module.get(), imports); auto instance = wasm::Instance::make(store, module.get(), imports);
if (!instance) { if (!instance) {
std::cout << "> Error instantiating module!" << std::endl; std::cout << "> Error instantiating module!" << std::endl;
@ -121,8 +122,8 @@ void run() {
// Call. // Call.
std::cout << "Calling export..." << std::endl; std::cout << "Calling export..." << std::endl;
wasm::Val args[] = {wasm::Val::i32(3), wasm::Val::i32(4)}; auto args = wasm::vec<wasm::Val>::make(wasm::Val::i32(3), wasm::Val::i32(4));
wasm::Val results[1]; auto results = wasm::vec<wasm::Val>::make_uninitialized(1);
if (run_func->call(args, results)) { if (run_func->call(args, results)) {
std::cout << "> Error calling function!" << std::endl; std::cout << "> Error calling function!" << std::endl;
exit(1); exit(1);

View File

@ -20,7 +20,7 @@ void finalize(void* data) {
void run_in_store(wasm_store_t* store) { void run_in_store(wasm_store_t* store) {
// Load binary. // Load binary.
printf("Loading binary...\n"); printf("Loading binary...\n");
FILE* file = fopen("finalize.wasm", "r"); FILE* file = fopen("finalize.wasm", "rb");
if (!file) { if (!file) {
printf("> Error loading module!\n"); printf("> Error loading module!\n");
exit(1); exit(1);
@ -50,8 +50,9 @@ void run_in_store(wasm_store_t* store) {
printf("Instantiating modules...\n"); printf("Instantiating modules...\n");
for (int i = 0; i <= iterations; ++i) { for (int i = 0; i <= iterations; ++i) {
if (i % (iterations / 10) == 0) printf("%d\n", i); if (i % (iterations / 10) == 0) printf("%d\n", i);
wasm_extern_vec_t imports = WASM_EMPTY_VEC;
own wasm_instance_t* instance = own wasm_instance_t* instance =
wasm_instance_new(store, module, NULL, NULL); wasm_instance_new(store, module, &imports, NULL);
if (!instance) { if (!instance) {
printf("> Error instantiating module %d!\n", i); printf("> Error instantiating module %d!\n", i);
exit(1); exit(1);

View File

@ -46,7 +46,8 @@ void run_in_store(wasm::Store* store) {
std::cout << "Instantiating modules..." << std::endl; std::cout << "Instantiating modules..." << std::endl;
for (int i = 0; i <= iterations; ++i) { for (int i = 0; i <= iterations; ++i) {
if (i % (iterations / 10) == 0) std::cout << i << std::endl; if (i % (iterations / 10) == 0) std::cout << i << std::endl;
auto instance = wasm::Instance::make(store, module.get(), nullptr); auto imports = wasm::vec<wasm::Extern*>::make();
auto instance = wasm::Instance::make(store, module.get(), imports);
if (!instance) { if (!instance) {
std::cout << "> Error instantiating module " << i << "!" << std::endl; std::cout << "> Error instantiating module " << i << "!" << std::endl;
exit(1); exit(1);

View File

@ -39,9 +39,11 @@ wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) {
#define check_call(func, type, expected) \ #define check_call(func, type, expected) \
{ \ { \
wasm_val_t results[1]; \ wasm_val_t vs[1]; \
wasm_func_call(func, NULL, results); \ wasm_val_vec_t args = WASM_EMPTY_VEC; \
check(results[0], type, expected); \ wasm_val_vec_t results = WASM_ARRAY_VEC(vs); \
wasm_func_call(func, &args, &results); \
check(vs[0], type, expected); \
} }
@ -53,7 +55,7 @@ int main(int argc, const char* argv[]) {
// Load binary. // Load binary.
printf("Loading binary...\n"); printf("Loading binary...\n");
FILE* file = fopen("global.wasm", "r"); FILE* file = fopen("global.wasm", "rb");
if (!file) { if (!file) {
printf("> Error loading module!\n"); printf("> Error loading module!\n");
return 1; return 1;
@ -90,16 +92,16 @@ int main(int argc, const char* argv[]) {
own wasm_globaltype_t* var_i64_type = wasm_globaltype_new( own wasm_globaltype_t* var_i64_type = wasm_globaltype_new(
wasm_valtype_new(WASM_I64), WASM_VAR); wasm_valtype_new(WASM_I64), WASM_VAR);
wasm_val_t val_f32_1 = {.kind = WASM_F32, .of = {.f32 = 1}}; wasm_val_t val_f32_1 = WASM_F32_VAL(1);
own wasm_global_t* const_f32_import = own wasm_global_t* const_f32_import =
wasm_global_new(store, const_f32_type, &val_f32_1); wasm_global_new(store, const_f32_type, &val_f32_1);
wasm_val_t val_i64_2 = {.kind = WASM_I64, .of = {.i64 = 2}}; wasm_val_t val_i64_2 = WASM_I64_VAL(2);
own wasm_global_t* const_i64_import = own wasm_global_t* const_i64_import =
wasm_global_new(store, const_i64_type, &val_i64_2); wasm_global_new(store, const_i64_type, &val_i64_2);
wasm_val_t val_f32_3 = {.kind = WASM_F32, .of = {.f32 = 3}}; wasm_val_t val_f32_3 = WASM_F32_VAL(3);
own wasm_global_t* var_f32_import = own wasm_global_t* var_f32_import =
wasm_global_new(store, var_f32_type, &val_f32_3); wasm_global_new(store, var_f32_type, &val_f32_3);
wasm_val_t val_i64_4 = {.kind = WASM_I64, .of = {.i64 = 4}}; wasm_val_t val_i64_4 = WASM_I64_VAL(4);
own wasm_global_t* var_i64_import = own wasm_global_t* var_i64_import =
wasm_global_new(store, var_i64_type, &val_i64_4); wasm_global_new(store, var_i64_type, &val_i64_4);
@ -110,14 +112,15 @@ int main(int argc, const char* argv[]) {
// Instantiate. // Instantiate.
printf("Instantiating module...\n"); printf("Instantiating module...\n");
const wasm_extern_t* imports[] = { wasm_extern_t* externs[] = {
wasm_global_as_extern(const_f32_import), wasm_global_as_extern(const_f32_import),
wasm_global_as_extern(const_i64_import), wasm_global_as_extern(const_i64_import),
wasm_global_as_extern(var_f32_import), wasm_global_as_extern(var_f32_import),
wasm_global_as_extern(var_i64_import) wasm_global_as_extern(var_i64_import)
}; };
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
own wasm_instance_t* instance = own wasm_instance_t* instance =
wasm_instance_new(store, module, imports, NULL); wasm_instance_new(store, module, &imports, NULL);
if (!instance) { if (!instance) {
printf("> Error instantiating module!\n"); printf("> Error instantiating module!\n");
return 1; return 1;
@ -175,13 +178,13 @@ int main(int argc, const char* argv[]) {
check_call(get_var_i64_export, i64, 8); check_call(get_var_i64_export, i64, 8);
// Modify variables through API and check again. // Modify variables through API and check again.
wasm_val_t val33 = {.kind = WASM_F32, .of = {.f32 = 33}}; wasm_val_t val33 = WASM_F32_VAL(33);
wasm_global_set(var_f32_import, &val33); wasm_global_set(var_f32_import, &val33);
wasm_val_t val34 = {.kind = WASM_I64, .of = {.i64 = 34}}; wasm_val_t val34 = WASM_I64_VAL(34);
wasm_global_set(var_i64_import, &val34); wasm_global_set(var_i64_import, &val34);
wasm_val_t val37 = {.kind = WASM_F32, .of = {.f32 = 37}}; wasm_val_t val37 = WASM_F32_VAL(37);
wasm_global_set(var_f32_export, &val37); wasm_global_set(var_f32_export, &val37);
wasm_val_t val38 = {.kind = WASM_I64, .of = {.i64 = 38}}; wasm_val_t val38 = WASM_I64_VAL(38);
wasm_global_set(var_i64_export, &val38); wasm_global_set(var_i64_export, &val38);
check_global(var_f32_import, f32, 33); check_global(var_f32_import, f32, 33);
@ -195,14 +198,19 @@ int main(int argc, const char* argv[]) {
check_call(get_var_i64_export, i64, 38); check_call(get_var_i64_export, i64, 38);
// Modify variables through calls and check again. // Modify variables through calls and check again.
wasm_val_t args73[] = { {.kind = WASM_F32, .of = {.f32 = 73}} }; wasm_val_vec_t res = WASM_EMPTY_VEC;
wasm_func_call(set_var_f32_import, args73, NULL); wasm_val_t vs73[] = { WASM_F32_VAL(73) };
wasm_val_t args74[] = { {.kind = WASM_I64, .of = {.i64 = 74}} }; wasm_val_vec_t args73 = WASM_ARRAY_VEC(vs73);
wasm_func_call(set_var_i64_import, args74, NULL); wasm_func_call(set_var_f32_import, &args73, &res);
wasm_val_t args77[] = { {.kind = WASM_F32, .of = {.f32 = 77}} }; wasm_val_t vs74[] = { WASM_I64_VAL(74) };
wasm_func_call(set_var_f32_export, args77, NULL); wasm_val_vec_t args74 = WASM_ARRAY_VEC(vs74);
wasm_val_t args78[] = { {.kind = WASM_I64, .of = {.i64 = 78}} }; wasm_func_call(set_var_i64_import, &args74, &res);
wasm_func_call(set_var_i64_export, args78, NULL); wasm_val_t vs77[] = { WASM_F32_VAL(77) };
wasm_val_vec_t args77 = WASM_ARRAY_VEC(vs77);
wasm_func_call(set_var_f32_export, &args77, &res);
wasm_val_t vs78[] = { WASM_I64_VAL(78) };
wasm_val_vec_t args78 = WASM_ARRAY_VEC(vs78);
wasm_func_call(set_var_i64_export, &args78, &res);
check_global(var_f32_import, f32, 73); check_global(var_f32_import, f32, 73);
check_global(var_i64_import, i64, 74); check_global(var_i64_import, i64, 74);

View File

@ -32,8 +32,9 @@ void check(T actual, U expected) {
} }
auto call(const wasm::Func* func) -> wasm::Val { auto call(const wasm::Func* func) -> wasm::Val {
wasm::Val results[1]; auto args = wasm::vec<wasm::Val>::make();
if (func->call(nullptr, results)) { auto results = wasm::vec<wasm::Val>::make_uninitialized(1);
if (func->call(args, results)) {
std::cout << "> Error calling function!" << std::endl; std::cout << "> Error calling function!" << std::endl;
exit(1); exit(1);
} }
@ -41,8 +42,9 @@ auto call(const wasm::Func* func) -> wasm::Val {
} }
void call(const wasm::Func* func, wasm::Val&& arg) { void call(const wasm::Func* func, wasm::Val&& arg) {
wasm::Val args[1] = {std::move(arg)}; auto args = wasm::vec<wasm::Val>::make(std::move(arg));
if (func->call(args)) { auto results = wasm::vec<wasm::Val>::make();
if (func->call(args, results)) {
std::cout << "> Error calling function!" << std::endl; std::cout << "> Error calling function!" << std::endl;
exit(1); exit(1);
} }
@ -95,10 +97,10 @@ void run() {
// Instantiate. // Instantiate.
std::cout << "Instantiating module..." << std::endl; std::cout << "Instantiating module..." << std::endl;
wasm::Extern* imports[] = { auto imports = wasm::vec<wasm::Extern*>::make(
const_f32_import.get(), const_i64_import.get(), const_f32_import.get(), const_i64_import.get(),
var_f32_import.get(), var_i64_import.get() var_f32_import.get(), var_i64_import.get()
}; );
auto instance = wasm::Instance::make(store, module.get(), imports); auto instance = wasm::Instance::make(store, module.get(), imports);
if (!instance) { if (!instance) {
std::cout << "> Error instantiating module!" << std::endl; std::cout << "> Error instantiating module!" << std::endl;

View File

@ -9,7 +9,7 @@
// A function to be called from Wasm code. // A function to be called from Wasm code.
own wasm_trap_t* hello_callback( own wasm_trap_t* hello_callback(
const wasm_val_t args[], wasm_val_t results[] const wasm_val_vec_t* args, wasm_val_vec_t* results
) { ) {
printf("Calling back...\n"); printf("Calling back...\n");
printf("> Hello World!\n"); printf("> Hello World!\n");
@ -25,7 +25,7 @@ int main(int argc, const char* argv[]) {
// Load binary. // Load binary.
printf("Loading binary...\n"); printf("Loading binary...\n");
FILE* file = fopen("hello.wasm", "r"); FILE* file = fopen("hello.wasm", "rb");
if (!file) { if (!file) {
printf("> Error loading module!\n"); printf("> Error loading module!\n");
return 1; return 1;
@ -61,9 +61,10 @@ int main(int argc, const char* argv[]) {
// Instantiate. // Instantiate.
printf("Instantiating module...\n"); printf("Instantiating module...\n");
const wasm_extern_t* imports[] = { wasm_func_as_extern(hello_func) }; wasm_extern_t* externs[] = { wasm_func_as_extern(hello_func) };
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
own wasm_instance_t* instance = own wasm_instance_t* instance =
wasm_instance_new(store, module, imports, NULL); wasm_instance_new(store, module, &imports, NULL);
if (!instance) { if (!instance) {
printf("> Error instantiating module!\n"); printf("> Error instantiating module!\n");
return 1; return 1;
@ -90,7 +91,9 @@ int main(int argc, const char* argv[]) {
// Call. // Call.
printf("Calling export...\n"); printf("Calling export...\n");
if (wasm_func_call(run_func, NULL, NULL)) { wasm_val_vec_t args = WASM_EMPTY_VEC;
wasm_val_vec_t results = WASM_EMPTY_VEC;
if (wasm_func_call(run_func, &args, &results)) {
printf("> Error calling function!\n"); printf("> Error calling function!\n");
return 1; return 1;
} }

View File

@ -9,7 +9,7 @@
// A function to be called from Wasm code. // A function to be called from Wasm code.
auto hello_callback( auto hello_callback(
const wasm::Val args[], wasm::Val results[] const wasm::vec<wasm::Val>& args, wasm::vec<wasm::Val>& results
) -> wasm::own<wasm::Trap> { ) -> wasm::own<wasm::Trap> {
std::cout << "Calling back..." << std::endl; std::cout << "Calling back..." << std::endl;
std::cout << "> Hello world!" << std::endl; std::cout << "> Hello world!" << std::endl;
@ -55,7 +55,7 @@ void run() {
// Instantiate. // Instantiate.
std::cout << "Instantiating module..." << std::endl; std::cout << "Instantiating module..." << std::endl;
wasm::Extern* imports[] = {hello_func.get()}; auto imports = wasm::vec<wasm::Extern*>::make(hello_func.get());
auto instance = wasm::Instance::make(store, module.get(), imports); auto instance = wasm::Instance::make(store, module.get(), imports);
if (!instance) { if (!instance) {
std::cout << "> Error instantiating module!" << std::endl; std::cout << "> Error instantiating module!" << std::endl;
@ -73,7 +73,9 @@ void run() {
// Call. // Call.
std::cout << "Calling export..." << std::endl; std::cout << "Calling export..." << std::endl;
if (run_func->call()) { auto args = wasm::vec<wasm::Val>::make();
auto results = wasm::vec<wasm::Val>::make();
if (run_func->call(args, results)) {
std::cout << "> Error calling function!" << std::endl; std::cout << "> Error calling function!" << std::endl;
exit(1); exit(1);
} }

View File

@ -10,12 +10,12 @@
// A function to be called from Wasm code. // A function to be called from Wasm code.
own wasm_trap_t* callback( own wasm_trap_t* callback(
const wasm_val_t args[], wasm_val_t results[] const wasm_val_vec_t* args, wasm_val_vec_t* results
) { ) {
printf("Calling back...\n> "); printf("Calling back...\n> ");
printf("> %p\n", printf("> %p\n",
args[0].of.ref ? wasm_ref_get_host_info(args[0].of.ref) : NULL); args->data[0].of.ref ? wasm_ref_get_host_info(args->data[0].of.ref) : NULL);
wasm_val_copy(&results[0], &args[0]); wasm_val_copy(&results->data[0], &args->data[0]);
return NULL; return NULL;
} }
@ -47,21 +47,23 @@ wasm_table_t* get_export_table(const wasm_extern_vec_t* exports, size_t i) {
own wasm_ref_t* call_v_r(const wasm_func_t* func) { own wasm_ref_t* call_v_r(const wasm_func_t* func) {
printf("call_v_r... "); fflush(stdout); printf("call_v_r... "); fflush(stdout);
wasm_val_t results[1]; wasm_val_t rs[] = { WASM_INIT_VAL };
if (wasm_func_call(func, NULL, results)) { wasm_val_vec_t args = WASM_EMPTY_VEC;
wasm_val_vec_t results = WASM_ARRAY_VEC(rs);
if (wasm_func_call(func, &args, &results)) {
printf("> Error calling function!\n"); printf("> Error calling function!\n");
exit(1); exit(1);
} }
printf("okay\n"); printf("okay\n");
return results[0].of.ref; return rs[0].of.ref;
} }
void call_r_v(const wasm_func_t* func, wasm_ref_t* ref) { void call_r_v(const wasm_func_t* func, wasm_ref_t* ref) {
printf("call_r_v... "); fflush(stdout); printf("call_r_v... "); fflush(stdout);
wasm_val_t args[1]; wasm_val_t vs[1] = { WASM_REF_VAL(ref) };
args[0].kind = WASM_ANYREF; wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
args[0].of.ref = ref; wasm_val_vec_t results = WASM_EMPTY_VEC;
if (wasm_func_call(func, args, NULL)) { if (wasm_func_call(func, &args, &results)) {
printf("> Error calling function!\n"); printf("> Error calling function!\n");
exit(1); exit(1);
} }
@ -70,26 +72,24 @@ void call_r_v(const wasm_func_t* func, wasm_ref_t* ref) {
own wasm_ref_t* call_r_r(const wasm_func_t* func, wasm_ref_t* ref) { own wasm_ref_t* call_r_r(const wasm_func_t* func, wasm_ref_t* ref) {
printf("call_r_r... "); fflush(stdout); printf("call_r_r... "); fflush(stdout);
wasm_val_t args[1]; wasm_val_t vs[1] = { WASM_REF_VAL(ref) };
args[0].kind = WASM_ANYREF; wasm_val_t rs[1] = { WASM_INIT_VAL };
args[0].of.ref = ref; wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
wasm_val_t results[1]; wasm_val_vec_t results = WASM_ARRAY_VEC(rs);
if (wasm_func_call(func, args, results)) { if (wasm_func_call(func, &args, &results)) {
printf("> Error calling function!\n"); printf("> Error calling function!\n");
exit(1); exit(1);
} }
printf("okay\n"); printf("okay\n");
return results[0].of.ref; return rs[0].of.ref;
} }
void call_ir_v(const wasm_func_t* func, int32_t i, wasm_ref_t* ref) { void call_ir_v(const wasm_func_t* func, int32_t i, wasm_ref_t* ref) {
printf("call_ir_v... "); fflush(stdout); printf("call_ir_v... "); fflush(stdout);
wasm_val_t args[2]; wasm_val_t vs[2] = { WASM_I32_VAL(i), WASM_REF_VAL(ref) };
args[0].kind = WASM_I32; wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
args[0].of.i32 = i; wasm_val_vec_t results = WASM_EMPTY_VEC;
args[1].kind = WASM_ANYREF; if (wasm_func_call(func, &args, &results)) {
args[1].of.ref = ref;
if (wasm_func_call(func, args, NULL)) {
printf("> Error calling function!\n"); printf("> Error calling function!\n");
exit(1); exit(1);
} }
@ -98,16 +98,16 @@ void call_ir_v(const wasm_func_t* func, int32_t i, wasm_ref_t* ref) {
own wasm_ref_t* call_i_r(const wasm_func_t* func, int32_t i) { own wasm_ref_t* call_i_r(const wasm_func_t* func, int32_t i) {
printf("call_i_r... "); fflush(stdout); printf("call_i_r... "); fflush(stdout);
wasm_val_t args[1]; wasm_val_t vs[1] = { WASM_I32_VAL(i) };
args[0].kind = WASM_I32; wasm_val_t rs[1] = { WASM_INIT_VAL };
args[0].of.i32 = i; wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
wasm_val_t results[1]; wasm_val_vec_t results = WASM_ARRAY_VEC(rs);
if (wasm_func_call(func, args, results)) { if (wasm_func_call(func, &args, &results)) {
printf("> Error calling function!\n"); printf("> Error calling function!\n");
exit(1); exit(1);
} }
printf("okay\n"); printf("okay\n");
return results[0].of.ref; return rs[0].of.ref;
} }
void check(own wasm_ref_t* actual, const wasm_ref_t* expected) { void check(own wasm_ref_t* actual, const wasm_ref_t* expected) {
@ -130,7 +130,7 @@ int main(int argc, const char* argv[]) {
// Load binary. // Load binary.
printf("Loading binary...\n"); printf("Loading binary...\n");
FILE* file = fopen("hostref.wasm", "r"); FILE* file = fopen("hostref.wasm", "rb");
if (!file) { if (!file) {
printf("> Error loading module!\n"); printf("> Error loading module!\n");
return 1; return 1;
@ -167,9 +167,10 @@ int main(int argc, const char* argv[]) {
// Instantiate. // Instantiate.
printf("Instantiating module...\n"); printf("Instantiating module...\n");
const wasm_extern_t* imports[] = { wasm_func_as_extern(callback_func) }; wasm_extern_t* externs[] = { wasm_func_as_extern(callback_func) };
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
own wasm_instance_t* instance = own wasm_instance_t* instance =
wasm_instance_new(store, module, imports, NULL); wasm_instance_new(store, module, &imports, NULL);
if (!instance) { if (!instance) {
printf("> Error instantiating module!\n"); printf("> Error instantiating module!\n");
return 1; return 1;

View File

@ -9,7 +9,7 @@
// A function to be called from Wasm code. // A function to be called from Wasm code.
auto callback( auto callback(
const wasm::Val args[], wasm::Val results[] const wasm::vec<wasm::Val>& args, wasm::vec<wasm::Val>& results
) -> wasm::own<wasm::Trap> { ) -> wasm::own<wasm::Trap> {
std::cout << "Calling back..." << std::endl; std::cout << "Calling back..." << std::endl;
std::cout << "> " << (args[0].ref() ? args[0].ref()->get_host_info() : nullptr) << std::endl; std::cout << "> " << (args[0].ref() ? args[0].ref()->get_host_info() : nullptr) << std::endl;
@ -45,8 +45,9 @@ auto get_export_table(wasm::ownvec<wasm::Extern>& exports, size_t i) -> wasm::Ta
void call_r_v(const wasm::Func* func, const wasm::Ref* ref) { void call_r_v(const wasm::Func* func, const wasm::Ref* ref) {
std::cout << "call_r_v... " << std::flush; std::cout << "call_r_v... " << std::flush;
wasm::Val args[1] = {wasm::Val::ref(ref ? ref->copy() : wasm::own<wasm::Ref>())}; auto args = wasm::vec<wasm::Val>::make(wasm::Val::ref(ref ? ref->copy() : wasm::own<wasm::Ref>()));
if (func->call(args, nullptr)) { auto results = wasm::vec<wasm::Val>::make();
if (func->call(args, results)) {
std::cout << "> Error calling function!" << std::endl; std::cout << "> Error calling function!" << std::endl;
exit(1); exit(1);
} }
@ -55,8 +56,9 @@ void call_r_v(const wasm::Func* func, const wasm::Ref* ref) {
auto call_v_r(const wasm::Func* func) -> wasm::own<wasm::Ref> { auto call_v_r(const wasm::Func* func) -> wasm::own<wasm::Ref> {
std::cout << "call_v_r... " << std::flush; std::cout << "call_v_r... " << std::flush;
wasm::Val results[1]; auto args = wasm::vec<wasm::Val>::make();
if (func->call(nullptr, results)) { auto results = wasm::vec<wasm::Val>::make_uninitialized(1);
if (func->call(args, results)) {
std::cout << "> Error calling function!" << std::endl; std::cout << "> Error calling function!" << std::endl;
exit(1); exit(1);
} }
@ -66,8 +68,8 @@ auto call_v_r(const wasm::Func* func) -> wasm::own<wasm::Ref> {
auto call_r_r(const wasm::Func* func, const wasm::Ref* ref) -> wasm::own<wasm::Ref> { auto call_r_r(const wasm::Func* func, const wasm::Ref* ref) -> wasm::own<wasm::Ref> {
std::cout << "call_r_r... " << std::flush; std::cout << "call_r_r... " << std::flush;
wasm::Val args[1] = {wasm::Val::ref(ref ? ref->copy() : wasm::own<wasm::Ref>())}; auto args = wasm::vec<wasm::Val>::make(wasm::Val::ref(ref ? ref->copy() : wasm::own<wasm::Ref>()));
wasm::Val results[1]; auto results = wasm::vec<wasm::Val>::make_uninitialized(1);
if (func->call(args, results)) { if (func->call(args, results)) {
std::cout << "> Error calling function!" << std::endl; std::cout << "> Error calling function!" << std::endl;
exit(1); exit(1);
@ -78,8 +80,10 @@ auto call_r_r(const wasm::Func* func, const wasm::Ref* ref) -> wasm::own<wasm::R
void call_ir_v(const wasm::Func* func, int32_t i, const wasm::Ref* ref) { void call_ir_v(const wasm::Func* func, int32_t i, const wasm::Ref* ref) {
std::cout << "call_ir_v... " << std::flush; std::cout << "call_ir_v... " << std::flush;
wasm::Val args[2] = {wasm::Val::i32(i), wasm::Val::ref(ref ? ref->copy() : wasm::own<wasm::Ref>())}; auto args = wasm::vec<wasm::Val>::make(
if (func->call(args, nullptr)) { wasm::Val::i32(i), wasm::Val::ref(ref ? ref->copy() : wasm::own<wasm::Ref>()));
auto results = wasm::vec<wasm::Val>::make();
if (func->call(args, results)) {
std::cout << "> Error calling function!" << std::endl; std::cout << "> Error calling function!" << std::endl;
exit(1); exit(1);
} }
@ -88,8 +92,8 @@ void call_ir_v(const wasm::Func* func, int32_t i, const wasm::Ref* ref) {
auto call_i_r(const wasm::Func* func, int32_t i) -> wasm::own<wasm::Ref> { auto call_i_r(const wasm::Func* func, int32_t i) -> wasm::own<wasm::Ref> {
std::cout << "call_i_r... " << std::flush; std::cout << "call_i_r... " << std::flush;
wasm::Val args[1] = {wasm::Val::i32(i)}; auto args = wasm::vec<wasm::Val>::make(wasm::Val::i32(i));
wasm::Val results[1]; auto results = wasm::vec<wasm::Val>::make_uninitialized(1);
if (func->call(args, results)) { if (func->call(args, results)) {
std::cout << "> Error calling function!" << std::endl; std::cout << "> Error calling function!" << std::endl;
exit(1); exit(1);
@ -147,7 +151,7 @@ void run() {
// Instantiate. // Instantiate.
std::cout << "Instantiating module..." << std::endl; std::cout << "Instantiating module..." << std::endl;
wasm::Extern* imports[] = {callback_func.get()}; auto imports = wasm::vec<wasm::Extern*>::make(callback_func.get());
auto instance = wasm::Instance::make(store, module.get(), imports); auto instance = wasm::Instance::make(store, module.get(), imports);
if (!instance) { if (!instance) {
std::cout << "> Error instantiating module!" << std::endl; std::cout << "> Error instantiating module!" << std::endl;

View File

@ -32,49 +32,49 @@ void check(bool success) {
} }
} }
void check_call(wasm_func_t* func, wasm_val_t args[], int32_t expected) { void check_call(wasm_func_t* func, int i, wasm_val_t args[], int32_t expected) {
wasm_val_t results[1]; wasm_val_t r = WASM_INIT_VAL;
if (wasm_func_call(func, args, results) || results[0].of.i32 != expected) { wasm_val_vec_t args_ = {i, args};
wasm_val_vec_t results = {1, &r};
if (wasm_func_call(func, &args_, &results) || r.of.i32 != expected) {
printf("> Error on result\n"); printf("> Error on result\n");
exit(1); exit(1);
} }
} }
void check_call0(wasm_func_t* func, int32_t expected) { void check_call0(wasm_func_t* func, int32_t expected) {
check_call(func, NULL, expected); check_call(func, 0, NULL, expected);
} }
void check_call1(wasm_func_t* func, int32_t arg, int32_t expected) { void check_call1(wasm_func_t* func, int32_t arg, int32_t expected) {
wasm_val_t args[] = { {.kind = WASM_I32, .of = {.i32 = arg}} }; wasm_val_t args[] = { WASM_I32_VAL(arg) };
check_call(func, args, expected); check_call(func, 1, args, expected);
} }
void check_call2(wasm_func_t* func, int32_t arg1, int32_t arg2, int32_t expected) { void check_call2(wasm_func_t* func, int32_t arg1, int32_t arg2, int32_t expected) {
wasm_val_t args[2] = { wasm_val_t args[] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) };
{.kind = WASM_I32, .of = {.i32 = arg1}}, check_call(func, 2, args, expected);
{.kind = WASM_I32, .of = {.i32 = arg2}}
};
check_call(func, args, expected);
} }
void check_ok(wasm_func_t* func, wasm_val_t args[]) { void check_ok(wasm_func_t* func, int i, wasm_val_t args[]) {
if (wasm_func_call(func, args, NULL)) { wasm_val_vec_t args_ = {i, args};
wasm_val_vec_t results = {0, NULL};
if (wasm_func_call(func, &args_, &results)) {
printf("> Error on result, expected empty\n"); printf("> Error on result, expected empty\n");
exit(1); exit(1);
} }
} }
void check_ok2(wasm_func_t* func, int32_t arg1, int32_t arg2) { void check_ok2(wasm_func_t* func, int32_t arg1, int32_t arg2) {
wasm_val_t args[2] = { wasm_val_t args[] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) };
{.kind = WASM_I32, .of = {.i32 = arg1}}, check_ok(func, 2, args);
{.kind = WASM_I32, .of = {.i32 = arg2}}
};
check_ok(func, args);
} }
void check_trap(wasm_func_t* func, wasm_val_t args[]) { void check_trap(wasm_func_t* func, int i, wasm_val_t args[]) {
wasm_val_t results[1]; wasm_val_t r = WASM_INIT_VAL;
own wasm_trap_t* trap = wasm_func_call(func, args, results); wasm_val_vec_t args_ = {i, args};
wasm_val_vec_t results = {1, &r};
own wasm_trap_t* trap = wasm_func_call(func, &args_, &results);
if (! trap) { if (! trap) {
printf("> Error on result, expected trap\n"); printf("> Error on result, expected trap\n");
exit(1); exit(1);
@ -83,16 +83,13 @@ void check_trap(wasm_func_t* func, wasm_val_t args[]) {
} }
void check_trap1(wasm_func_t* func, int32_t arg) { void check_trap1(wasm_func_t* func, int32_t arg) {
wasm_val_t args[1] = { {.kind = WASM_I32, .of = {.i32 = arg}} }; wasm_val_t args[] = { WASM_I32_VAL(arg) };
check_trap(func, args); check_trap(func, 1, args);
} }
void check_trap2(wasm_func_t* func, int32_t arg1, int32_t arg2) { void check_trap2(wasm_func_t* func, int32_t arg1, int32_t arg2) {
wasm_val_t args[2] = { wasm_val_t args[] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) };
{.kind = WASM_I32, .of = {.i32 = arg1}}, check_trap(func, 2, args);
{.kind = WASM_I32, .of = {.i32 = arg2}}
};
check_trap(func, args);
} }
@ -104,7 +101,7 @@ int main(int argc, const char* argv[]) {
// Load binary. // Load binary.
printf("Loading binary...\n"); printf("Loading binary...\n");
FILE* file = fopen("memory.wasm", "r"); FILE* file = fopen("memory.wasm", "rb");
if (!file) { if (!file) {
printf("> Error loading module!\n"); printf("> Error loading module!\n");
return 1; return 1;
@ -132,7 +129,9 @@ int main(int argc, const char* argv[]) {
// Instantiate. // Instantiate.
printf("Instantiating module...\n"); printf("Instantiating module...\n");
own wasm_instance_t* instance = wasm_instance_new(store, module, NULL, NULL); wasm_extern_vec_t imports = WASM_EMPTY_VEC;
own wasm_instance_t* instance =
wasm_instance_new(store, module, &imports, NULL);
if (!instance) { if (!instance) {
printf("> Error instantiating module!\n"); printf("> Error instantiating module!\n");
return 1; return 1;

View File

@ -33,8 +33,9 @@ void check(T actual, U expected) {
template<class... Args> template<class... Args>
void check_ok(const wasm::Func* func, Args... xs) { void check_ok(const wasm::Func* func, Args... xs) {
wasm::Val args[] = {wasm::Val::i32(xs)...}; auto args = wasm::vec<wasm::Val>::make(wasm::Val::i32(xs)...);
if (func->call(args)) { auto results = wasm::vec<wasm::Val>::make();
if (func->call(args, results)) {
std::cout << "> Error on result, expected return" << std::endl; std::cout << "> Error on result, expected return" << std::endl;
exit(1); exit(1);
} }
@ -42,8 +43,9 @@ void check_ok(const wasm::Func* func, Args... xs) {
template<class... Args> template<class... Args>
void check_trap(const wasm::Func* func, Args... xs) { void check_trap(const wasm::Func* func, Args... xs) {
wasm::Val args[] = {wasm::Val::i32(xs)...}; auto args = wasm::vec<wasm::Val>::make(wasm::Val::i32(xs)...);
if (! func->call(args)) { auto results = wasm::vec<wasm::Val>::make();
if (! func->call(args, results)) {
std::cout << "> Error on result, expected trap" << std::endl; std::cout << "> Error on result, expected trap" << std::endl;
exit(1); exit(1);
} }
@ -51,8 +53,8 @@ void check_trap(const wasm::Func* func, Args... xs) {
template<class... Args> template<class... Args>
auto call(const wasm::Func* func, Args... xs) -> int32_t { auto call(const wasm::Func* func, Args... xs) -> int32_t {
wasm::Val args[] = {wasm::Val::i32(xs)...}; auto args = wasm::vec<wasm::Val>::make(wasm::Val::i32(xs)...);
wasm::Val results[1]; auto results = wasm::vec<wasm::Val>::make_uninitialized(1);
if (func->call(args, results)) { if (func->call(args, results)) {
std::cout << "> Error on result, expected return" << std::endl; std::cout << "> Error on result, expected return" << std::endl;
exit(1); exit(1);
@ -92,7 +94,8 @@ void run() {
// Instantiate. // Instantiate.
std::cout << "Instantiating module..." << std::endl; std::cout << "Instantiating module..." << std::endl;
auto instance = wasm::Instance::make(store, module.get(), nullptr); auto imports = wasm::vec<wasm::Extern*>::make();
auto instance = wasm::Instance::make(store, module.get(), imports);
if (!instance) { if (!instance) {
std::cout << "> Error instantiating module!" << std::endl; std::cout << "> Error instantiating module!" << std::endl;
exit(1); exit(1);

View File

@ -9,31 +9,32 @@
// A function to be called from Wasm code. // A function to be called from Wasm code.
own wasm_trap_t* callback( own wasm_trap_t* callback(
const wasm_val_t args[], wasm_val_t results[] const wasm_val_vec_t* args, wasm_val_vec_t* results
) { ) {
printf("Calling back...\n> "); printf("Calling back...\n> ");
printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n", printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n",
args[0].of.i32, args[1].of.i64, args[2].of.i64, args[3].of.i32); args->data[0].of.i32, args->data[1].of.i64,
args->data[2].of.i64, args->data[3].of.i32);
printf("\n"); printf("\n");
wasm_val_copy(&results[0], &args[3]); wasm_val_copy(&results->data[0], &args->data[3]);
wasm_val_copy(&results[1], &args[1]); wasm_val_copy(&results->data[1], &args->data[1]);
wasm_val_copy(&results[2], &args[2]); wasm_val_copy(&results->data[2], &args->data[2]);
wasm_val_copy(&results[3], &args[0]); wasm_val_copy(&results->data[3], &args->data[0]);
return NULL; return NULL;
} }
// A function closure. // A function closure.
own wasm_trap_t* closure_callback( own wasm_trap_t* closure_callback(
void* env, const wasm_val_t args[], wasm_val_t results[] void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results
) { ) {
int i = *(int*)env; int i = *(int*)env;
printf("Calling back closure...\n"); printf("Calling back closure...\n");
printf("> %d\n", i); printf("> %d\n", i);
results[0].kind = WASM_I32; results->data[0].kind = WASM_I32;
results[0].of.i32 = (int32_t)i; results->data[0].of.i32 = (int32_t)i;
return NULL; return NULL;
} }
@ -46,7 +47,7 @@ int main(int argc, const char* argv[]) {
// Load binary. // Load binary.
printf("Loading binary...\n"); printf("Loading binary...\n");
FILE* file = fopen("multi.wasm", "r"); FILE* file = fopen("multi.wasm", "rb");
if (!file) { if (!file) {
printf("> Error loading module!\n"); printf("> Error loading module!\n");
return 1; return 1;
@ -89,9 +90,10 @@ int main(int argc, const char* argv[]) {
// Instantiate. // Instantiate.
printf("Instantiating module...\n"); printf("Instantiating module...\n");
const wasm_extern_t* imports[] = {wasm_func_as_extern(callback_func)}; wasm_extern_t* externs[] = { wasm_func_as_extern(callback_func) };
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
own wasm_instance_t* instance = own wasm_instance_t* instance =
wasm_instance_new(store, module, imports, NULL); wasm_instance_new(store, module, &imports, NULL);
if (!instance) { if (!instance) {
printf("> Error instantiating module!\n"); printf("> Error instantiating module!\n");
return 1; return 1;
@ -118,17 +120,15 @@ int main(int argc, const char* argv[]) {
// Call. // Call.
printf("Calling export...\n"); printf("Calling export...\n");
wasm_val_t args[4]; wasm_val_t vals[4] = {
args[0].kind = WASM_I32; WASM_I32_VAL(1), WASM_I32_VAL(2), WASM_I32_VAL(3), WASM_I32_VAL(4)
args[0].of.i32 = 1; };
args[1].kind = WASM_I64; wasm_val_t res[4] = {
args[1].of.i64 = 2; WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL
args[2].kind = WASM_I64; };
args[2].of.i64 = 3; wasm_val_vec_t args = WASM_ARRAY_VEC(vals);
args[3].kind = WASM_I32; wasm_val_vec_t results = WASM_ARRAY_VEC(res);
args[3].of.i32 = 4; if (wasm_func_call(run_func, &args, &results)) {
wasm_val_t results[4];
if (wasm_func_call(run_func, args, results)) {
printf("> Error calling function!\n"); printf("> Error calling function!\n");
return 1; return 1;
} }
@ -138,13 +138,12 @@ int main(int argc, const char* argv[]) {
// Print result. // Print result.
printf("Printing result...\n"); printf("Printing result...\n");
printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n", printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n",
results[0].of.i32, results[1].of.i64, res[0].of.i32, res[1].of.i64, res[2].of.i64, res[3].of.i32);
results[2].of.i64, results[3].of.i32);
assert(results[0].of.i32 == 4); assert(res[0].of.i32 == 4);
assert(results[1].of.i64 == 3); assert(res[1].of.i64 == 3);
assert(results[2].of.i64 == 2); assert(res[2].of.i64 == 2);
assert(results[3].of.i32 == 1); assert(res[3].of.i32 == 1);
// Shut down. // Shut down.
printf("Shutting down...\n"); printf("Shutting down...\n");

View File

@ -8,7 +8,7 @@
// A function to be called from Wasm code. // A function to be called from Wasm code.
auto callback( auto callback(
const wasm::Val args[], wasm::Val results[] const wasm::vec<wasm::Val>& args, wasm::vec<wasm::Val>& results
) -> wasm::own<wasm::Trap> { ) -> wasm::own<wasm::Trap> {
std::cout << "Calling back..." << std::endl; std::cout << "Calling back..." << std::endl;
std::cout << "> " << args[0].i32(); std::cout << "> " << args[0].i32();
@ -66,7 +66,7 @@ void run() {
// Instantiate. // Instantiate.
std::cout << "Instantiating module..." << std::endl; std::cout << "Instantiating module..." << std::endl;
wasm::Extern* imports[] = {callback_func.get()}; auto imports = wasm::vec<wasm::Extern*>::make(callback_func.get());
auto instance = wasm::Instance::make(store, module.get(), imports); auto instance = wasm::Instance::make(store, module.get(), imports);
if (!instance) { if (!instance) {
std::cout << "> Error instantiating module!" << std::endl; std::cout << "> Error instantiating module!" << std::endl;
@ -84,10 +84,10 @@ void run() {
// Call. // Call.
std::cout << "Calling export..." << std::endl; std::cout << "Calling export..." << std::endl;
wasm::Val args[] = { auto args = wasm::vec<wasm::Val>::make(
wasm::Val::i32(1), wasm::Val::i64(2), wasm::Val::i64(3), wasm::Val::i32(4) wasm::Val::i32(1), wasm::Val::i64(2), wasm::Val::i64(3), wasm::Val::i32(4)
}; );
wasm::Val results[4]; auto results = wasm::vec<wasm::Val>::make_uninitialized(4);
if (wasm::own<wasm::Trap> trap = run_func->call(args, results)) { if (wasm::own<wasm::Trap> trap = run_func->call(args, results)) {
std::cout << "> Error calling function! " << trap->message().get() << std::endl; std::cout << "> Error calling function! " << trap->message().get() << std::endl;
exit(1); exit(1);

View File

@ -90,7 +90,7 @@ int main(int argc, const char* argv[]) {
// Load binary. // Load binary.
printf("Loading binary...\n"); printf("Loading binary...\n");
FILE* file = fopen("reflect.wasm", "r"); FILE* file = fopen("reflect.wasm", "rb");
if (!file) { if (!file) {
printf("> Error loading module!\n"); printf("> Error loading module!\n");
return 1; return 1;
@ -118,7 +118,9 @@ int main(int argc, const char* argv[]) {
// Instantiate. // Instantiate.
printf("Instantiating module...\n"); printf("Instantiating module...\n");
own wasm_instance_t* instance = wasm_instance_new(store, module, NULL, NULL); wasm_extern_vec_t imports = WASM_EMPTY_VEC;
own wasm_instance_t* instance =
wasm_instance_new(store, module, &imports, NULL);
if (!instance) { if (!instance) {
printf("> Error instantiating module!\n"); printf("> Error instantiating module!\n");
return 1; return 1;

View File

@ -101,7 +101,8 @@ void run() {
// Instantiate. // Instantiate.
std::cout << "Instantiating module..." << std::endl; std::cout << "Instantiating module..." << std::endl;
auto instance = wasm::Instance::make(store, module.get(), nullptr); auto imports = wasm::vec<wasm::Extern*>::make();
auto instance = wasm::Instance::make(store, module.get(), imports);
if (!instance) { if (!instance) {
std::cout << "> Error instantiating module!" << std::endl; std::cout << "> Error instantiating module!" << std::endl;
exit(1); exit(1);

View File

@ -8,7 +8,9 @@
#define own #define own
// A function to be called from Wasm code. // A function to be called from Wasm code.
own wasm_trap_t* hello_callback(const wasm_val_t args[], wasm_val_t results[]) { own wasm_trap_t* hello_callback(
const wasm_val_vec_t* args, wasm_val_vec_t* results
) {
printf("Calling back...\n"); printf("Calling back...\n");
printf("> Hello World!\n"); printf("> Hello World!\n");
return NULL; return NULL;
@ -23,7 +25,7 @@ int main(int argc, const char* argv[]) {
// Load binary. // Load binary.
printf("Loading binary...\n"); printf("Loading binary...\n");
FILE* file = fopen("serialize.wasm", "r"); FILE* file = fopen("serialize.wasm", "rb");
if (!file) { if (!file) {
printf("> Error loading module!\n"); printf("> Error loading module!\n");
return 1; return 1;
@ -76,9 +78,10 @@ int main(int argc, const char* argv[]) {
// Instantiate. // Instantiate.
printf("Instantiating deserialized module...\n"); printf("Instantiating deserialized module...\n");
const wasm_extern_t* imports[] = { wasm_func_as_extern(hello_func) }; wasm_extern_t* externs[] = { wasm_func_as_extern(hello_func) };
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
own wasm_instance_t* instance = own wasm_instance_t* instance =
wasm_instance_new(store, deserialized, imports, NULL); wasm_instance_new(store, deserialized, &imports, NULL);
if (!instance) { if (!instance) {
printf("> Error instantiating module!\n"); printf("> Error instantiating module!\n");
return 1; return 1;
@ -105,7 +108,8 @@ int main(int argc, const char* argv[]) {
// Call. // Call.
printf("Calling export...\n"); printf("Calling export...\n");
if (wasm_func_call(run_func, NULL, NULL)) { wasm_val_vec_t empty = WASM_EMPTY_VEC;
if (wasm_func_call(run_func, &empty, &empty)) {
printf("> Error calling function!\n"); printf("> Error calling function!\n");
return 1; return 1;
} }

View File

@ -9,7 +9,7 @@
// A function to be called from Wasm code. // A function to be called from Wasm code.
auto hello_callback( auto hello_callback(
const wasm::Val args[], wasm::Val results[] const wasm::vec<wasm::Val>& args, wasm::vec<wasm::Val>& results
) -> wasm::own<wasm::Trap> { ) -> wasm::own<wasm::Trap> {
std::cout << "Calling back..." << std::endl; std::cout << "Calling back..." << std::endl;
std::cout << "> Hello world!" << std::endl; std::cout << "> Hello world!" << std::endl;
@ -67,7 +67,7 @@ void run() {
// Instantiate. // Instantiate.
std::cout << "Instantiating deserialized module..." << std::endl; std::cout << "Instantiating deserialized module..." << std::endl;
wasm::Extern* imports[] = {hello_func.get()}; auto imports = wasm::vec<wasm::Extern*>::make(hello_func.get());
auto instance = wasm::Instance::make(store, deserialized.get(), imports); auto instance = wasm::Instance::make(store, deserialized.get(), imports);
if (!instance) { if (!instance) {
std::cout << "> Error instantiating module!" << std::endl; std::cout << "> Error instantiating module!" << std::endl;
@ -85,7 +85,9 @@ void run() {
// Call. // Call.
std::cout << "Calling export..." << std::endl; std::cout << "Calling export..." << std::endl;
if (run_func->call()) { auto args = wasm::vec<wasm::Val>::make();
auto results = wasm::vec<wasm::Val>::make();
if (run_func->call(args, results)) {
std::cout << "> Error calling function!" << std::endl; std::cout << "> Error calling function!" << std::endl;
exit(1); exit(1);
} }

View File

@ -26,7 +26,7 @@ int main(int argc, const char* argv[]) {
// Load binary. // Load binary.
printf("Loading binary...\n"); printf("Loading binary...\n");
FILE* file = fopen("start.wasm", "r"); FILE* file = fopen("start.wasm", "rb");
if (!file) { if (!file) {
printf("> Error loading module!\n"); printf("> Error loading module!\n");
return 1; return 1;
@ -54,9 +54,10 @@ int main(int argc, const char* argv[]) {
// Instantiate. // Instantiate.
printf("Instantiating module...\n"); printf("Instantiating module...\n");
wasm_extern_vec_t imports = WASM_EMPTY_VEC;
own wasm_trap_t* trap = NULL; own wasm_trap_t* trap = NULL;
own wasm_instance_t* instance = own wasm_instance_t* instance =
wasm_instance_new(store, module, NULL, &trap); wasm_instance_new(store, module, &imports, &trap);
if (instance || !trap) { if (instance || !trap) {
printf("> Error instantiating module, expected trap!\n"); printf("> Error instantiating module, expected trap!\n");
return 1; return 1;

View File

@ -47,7 +47,8 @@ void run() {
// Instantiate. // Instantiate.
std::cout << "Instantiating module..." << std::endl; std::cout << "Instantiating module..." << std::endl;
wasm::own<wasm::Trap> trap; wasm::own<wasm::Trap> trap;
auto instance = wasm::Instance::make(store, module.get(), nullptr, &trap); auto imports = wasm::vec<wasm::Extern*>::make();
auto instance = wasm::Instance::make(store, module.get(), imports, &trap);
if (instance || !trap) { if (instance || !trap) {
std::cout << "> Error instantiating module, expected trap!" << std::endl; std::cout << "> Error instantiating module, expected trap!" << std::endl;
exit(1); exit(1);

View File

@ -9,11 +9,11 @@
// A function to be called from Wasm code. // A function to be called from Wasm code.
own wasm_trap_t* neg_callback( own wasm_trap_t* neg_callback(
const wasm_val_t args[], wasm_val_t results[] const wasm_val_vec_t* args, wasm_val_vec_t* results
) { ) {
printf("Calling back...\n"); printf("Calling back...\n");
results[0].kind = WASM_I32; results->data[0].kind = WASM_I32;
results[0].of.i32 = -args[0].of.i32; results->data[0].of.i32 = -args->data[0].of.i32;
return NULL; return NULL;
} }
@ -49,23 +49,22 @@ void check_table(wasm_table_t* table, int32_t i, bool expect_set) {
} }
void check_call(wasm_func_t* func, int32_t arg1, int32_t arg2, int32_t expected) { void check_call(wasm_func_t* func, int32_t arg1, int32_t arg2, int32_t expected) {
wasm_val_t args[2] = { wasm_val_t vs[2] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) };
{.kind = WASM_I32, .of = {.i32 = arg1}}, wasm_val_t r[1] = { WASM_INIT_VAL };
{.kind = WASM_I32, .of = {.i32 = arg2}} wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
}; wasm_val_vec_t results = WASM_ARRAY_VEC(r);
wasm_val_t results[1]; if (wasm_func_call(func, &args, &results) || r[0].of.i32 != expected) {
if (wasm_func_call(func, args, results) || results[0].of.i32 != expected) {
printf("> Error on result\n"); printf("> Error on result\n");
exit(1); exit(1);
} }
} }
void check_trap(wasm_func_t* func, int32_t arg1, int32_t arg2) { void check_trap(wasm_func_t* func, int32_t arg1, int32_t arg2) {
wasm_val_t args[2] = { wasm_val_t vs[2] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) };
{.kind = WASM_I32, .of = {.i32 = arg1}}, wasm_val_t r[1] = { WASM_INIT_VAL };
{.kind = WASM_I32, .of = {.i32 = arg2}} wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
}; wasm_val_vec_t results = WASM_ARRAY_VEC(r);
own wasm_trap_t* trap = wasm_func_call(func, args, NULL); own wasm_trap_t* trap = wasm_func_call(func, &args, &results);
if (! trap) { if (! trap) {
printf("> Error on result, expected trap\n"); printf("> Error on result, expected trap\n");
exit(1); exit(1);
@ -82,7 +81,7 @@ int main(int argc, const char* argv[]) {
// Load binary. // Load binary.
printf("Loading binary...\n"); printf("Loading binary...\n");
FILE* file = fopen("table.wasm", "r"); FILE* file = fopen("table.wasm", "rb");
if (!file) { if (!file) {
printf("> Error loading module!\n"); printf("> Error loading module!\n");
return 1; return 1;
@ -110,7 +109,9 @@ int main(int argc, const char* argv[]) {
// Instantiate. // Instantiate.
printf("Instantiating module...\n"); printf("Instantiating module...\n");
own wasm_instance_t* instance = wasm_instance_new(store, module, NULL, NULL); wasm_extern_vec_t imports = WASM_EMPTY_VEC;
own wasm_instance_t* instance =
wasm_instance_new(store, module, &imports, NULL);
if (!instance) { if (!instance) {
printf("> Error instantiating module!\n"); printf("> Error instantiating module!\n");
return 1; return 1;

View File

@ -9,7 +9,7 @@
// A function to be called from Wasm code. // A function to be called from Wasm code.
auto neg_callback( auto neg_callback(
const wasm::Val args[], wasm::Val results[] const wasm::vec<wasm::Val>& args, wasm::vec<wasm::Val>& results
) -> wasm::own<wasm::Trap> { ) -> wasm::own<wasm::Trap> {
std::cout << "Calling back..." << std::endl; std::cout << "Calling back..." << std::endl;
results[0] = wasm::Val(-args[0].i32()); results[0] = wasm::Val(-args[0].i32());
@ -51,8 +51,8 @@ void check(bool success) {
auto call( auto call(
const wasm::Func* func, wasm::Val&& arg1, wasm::Val&& arg2 const wasm::Func* func, wasm::Val&& arg1, wasm::Val&& arg2
) -> wasm::Val { ) -> wasm::Val {
wasm::Val args[2] = {std::move(arg1), std::move(arg2)}; auto args = wasm::vec<wasm::Val>::make(std::move(arg1), std::move(arg2));
wasm::Val results[1]; auto results = wasm::vec<wasm::Val>::make_uninitialized(1);
if (func->call(args, results)) { if (func->call(args, results)) {
std::cout << "> Error on result, expected return" << std::endl; std::cout << "> Error on result, expected return" << std::endl;
exit(1); exit(1);
@ -61,8 +61,8 @@ auto call(
} }
void check_trap(const wasm::Func* func, wasm::Val&& arg1, wasm::Val&& arg2) { void check_trap(const wasm::Func* func, wasm::Val&& arg1, wasm::Val&& arg2) {
wasm::Val args[2] = {std::move(arg1), std::move(arg2)}; auto args = wasm::vec<wasm::Val>::make(std::move(arg1), std::move(arg2));
wasm::Val results[1]; auto results = wasm::vec<wasm::Val>::make_uninitialized(1);
if (! func->call(args, results)) { if (! func->call(args, results)) {
std::cout << "> Error on result, expected trap" << std::endl; std::cout << "> Error on result, expected trap" << std::endl;
exit(1); exit(1);
@ -100,7 +100,8 @@ void run() {
// Instantiate. // Instantiate.
std::cout << "Instantiating module..." << std::endl; std::cout << "Instantiating module..." << std::endl;
auto instance = wasm::Instance::make(store, module.get(), nullptr); auto imports = wasm::vec<wasm::Extern*>::make();
auto instance = wasm::Instance::make(store, module.get(), imports);
if (!instance) { if (!instance) {
std::cout << "> Error instantiating module!" << std::endl; std::cout << "> Error instantiating module!" << std::endl;
exit(1); exit(1);

View File

@ -13,9 +13,9 @@ const int N_THREADS = 10;
const int N_REPS = 3; const int N_REPS = 3;
// A function to be called from Wasm code. // A function to be called from Wasm code.
own wasm_trap_t* callback(const wasm_val_t args[], wasm_val_t results[]) { own wasm_trap_t* callback(const wasm_val_vec_t* args, wasm_val_vec_t* results) {
assert(args[0].kind == WASM_I32); assert(args->data[0].kind == WASM_I32);
printf("> Thread %d running\n", args[0].of.i32); printf("> Thread %d running\n", args->data[0].of.i32);
return NULL; return NULL;
} }
@ -42,18 +42,19 @@ void* run(void* args_abs) {
own wasm_func_t* func = wasm_func_new(store, func_type, callback); own wasm_func_t* func = wasm_func_new(store, func_type, callback);
wasm_functype_delete(func_type); wasm_functype_delete(func_type);
wasm_val_t val = {.kind = WASM_I32, .of = {.i32 = (int32_t)args->id}}; wasm_val_t val = WASM_I32_VAL((int32_t)args->id);
own wasm_globaltype_t* global_type = own wasm_globaltype_t* global_type =
wasm_globaltype_new(wasm_valtype_new_i32(), WASM_CONST); wasm_globaltype_new(wasm_valtype_new_i32(), WASM_CONST);
own wasm_global_t* global = wasm_global_new(store, global_type, &val); own wasm_global_t* global = wasm_global_new(store, global_type, &val);
wasm_globaltype_delete(global_type); wasm_globaltype_delete(global_type);
// Instantiate. // Instantiate.
const wasm_extern_t* imports[] = { wasm_extern_t* externs[] = {
wasm_func_as_extern(func), wasm_global_as_extern(global), wasm_func_as_extern(func), wasm_global_as_extern(global),
}; };
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
own wasm_instance_t* instance = own wasm_instance_t* instance =
wasm_instance_new(store, module, imports, NULL); wasm_instance_new(store, module, &imports, NULL);
if (!instance) { if (!instance) {
printf("> Error instantiating module!\n"); printf("> Error instantiating module!\n");
return NULL; return NULL;
@ -78,7 +79,8 @@ void* run(void* args_abs) {
wasm_instance_delete(instance); wasm_instance_delete(instance);
// Call. // Call.
if (wasm_func_call(run_func, NULL, NULL)) { wasm_val_vec_t empty = WASM_EMPTY_VEC;
if (wasm_func_call(run_func, &empty, &empty)) {
printf("> Error calling function!\n"); printf("> Error calling function!\n");
return NULL; return NULL;
} }
@ -99,7 +101,7 @@ int main(int argc, const char *argv[]) {
wasm_engine_t* engine = wasm_engine_new(); wasm_engine_t* engine = wasm_engine_new();
// Load binary. // Load binary.
FILE* file = fopen("threads.wasm", "r"); FILE* file = fopen("threads.wasm", "rb");
if (!file) { if (!file) {
printf("> Error loading module!\n"); printf("> Error loading module!\n");
return 1; return 1;

View File

@ -10,7 +10,7 @@ const int N_REPS = 3;
// A function to be called from Wasm code. // A function to be called from Wasm code.
auto callback( auto callback(
void* env, const wasm::Val args[], wasm::Val results[] void* env, const wasm::vec<wasm::Val>& args, wasm::vec<wasm::Val>& results
) -> wasm::own<wasm::Trap> { ) -> wasm::own<wasm::Trap> {
assert(args[0].kind() == wasm::ValKind::I32); assert(args[0].kind() == wasm::ValKind::I32);
std::lock_guard<std::mutex> lock(*reinterpret_cast<std::mutex*>(env)); std::lock_guard<std::mutex> lock(*reinterpret_cast<std::mutex*>(env));
@ -53,7 +53,7 @@ void run(
store, global_type.get(), wasm::Val::i32(i)); store, global_type.get(), wasm::Val::i32(i));
// Instantiate. // Instantiate.
wasm::Extern* imports[] = {func.get(), global.get()}; auto imports = wasm::vec<wasm::Extern*>::make(func.get(), global.get());
auto instance = wasm::Instance::make(store, module.get(), imports); auto instance = wasm::Instance::make(store, module.get(), imports);
if (!instance) { if (!instance) {
std::lock_guard<std::mutex> lock(*mutex); std::lock_guard<std::mutex> lock(*mutex);
@ -71,7 +71,8 @@ void run(
auto run_func = exports[0]->func(); auto run_func = exports[0]->func();
// Call. // Call.
run_func->call(); auto empty = wasm::vec<wasm::Val>::make();
run_func->call(empty, empty);
} }
} }

View File

@ -9,11 +9,11 @@
// A function to be called from Wasm code. // A function to be called from Wasm code.
own wasm_trap_t* fail_callback( own wasm_trap_t* fail_callback(
void* env, const wasm_val_t args[], wasm_val_t results[] void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results
) { ) {
printf("Calling back...\n"); printf("Calling back...\n");
own wasm_name_t message; own wasm_name_t message;
wasm_name_new_from_string(&message, "callback abort"); wasm_name_new_from_string_nt(&message, "callback abort");
own wasm_trap_t* trap = wasm_trap_new((wasm_store_t*)env, &message); own wasm_trap_t* trap = wasm_trap_new((wasm_store_t*)env, &message);
wasm_name_delete(&message); wasm_name_delete(&message);
return trap; return trap;
@ -38,7 +38,7 @@ int main(int argc, const char* argv[]) {
// Load binary. // Load binary.
printf("Loading binary...\n"); printf("Loading binary...\n");
FILE* file = fopen("trap.wasm", "r"); FILE* file = fopen("trap.wasm", "rb");
if (!file) { if (!file) {
printf("> Error loading module!\n"); printf("> Error loading module!\n");
return 1; return 1;
@ -75,9 +75,10 @@ int main(int argc, const char* argv[]) {
// Instantiate. // Instantiate.
printf("Instantiating module...\n"); printf("Instantiating module...\n");
const wasm_extern_t* imports[] = { wasm_func_as_extern(fail_func) }; wasm_extern_t* externs[] = { wasm_func_as_extern(fail_func) };
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
own wasm_instance_t* instance = own wasm_instance_t* instance =
wasm_instance_new(store, module, imports, NULL); wasm_instance_new(store, module, &imports, NULL);
if (!instance) { if (!instance) {
printf("> Error instantiating module!\n"); printf("> Error instantiating module!\n");
return 1; return 1;
@ -106,7 +107,9 @@ int main(int argc, const char* argv[]) {
} }
printf("Calling export %d...\n", i); printf("Calling export %d...\n", i);
own wasm_trap_t* trap = wasm_func_call(func, NULL, NULL); wasm_val_vec_t args = WASM_EMPTY_VEC;
wasm_val_vec_t results = WASM_EMPTY_VEC;
own wasm_trap_t* trap = wasm_func_call(func, &args, &results);
if (!trap) { if (!trap) {
printf("> Error calling function, expected trap!\n"); printf("> Error calling function, expected trap!\n");
return 1; return 1;

View File

@ -8,11 +8,11 @@
// A function to be called from Wasm code. // A function to be called from Wasm code.
auto fail_callback( auto fail_callback(
void* env, const wasm::Val args[], wasm::Val results[] void* env, const wasm::vec<wasm::Val>& args, wasm::vec<wasm::Val>& results
) -> wasm::own<wasm::Trap> { ) -> wasm::own<wasm::Trap> {
std::cout << "Calling back..." << std::endl; std::cout << "Calling back..." << std::endl;
auto store = reinterpret_cast<wasm::Store*>(env); auto store = reinterpret_cast<wasm::Store*>(env);
auto message = wasm::Name::make(std::string("callback abort")); auto message = wasm::Name::make_nt(std::string("callback abort"));
return wasm::Trap::make(store, message); return wasm::Trap::make(store, message);
} }
@ -65,7 +65,7 @@ void run() {
// Instantiate. // Instantiate.
std::cout << "Instantiating module..." << std::endl; std::cout << "Instantiating module..." << std::endl;
wasm::Extern* imports[] = {fail_func.get()}; auto imports = wasm::vec<wasm::Extern*>::make(fail_func.get());
auto instance = wasm::Instance::make(store, module.get(), imports); auto instance = wasm::Instance::make(store, module.get(), imports);
if (!instance) { if (!instance) {
std::cout << "> Error instantiating module!" << std::endl; std::cout << "> Error instantiating module!" << std::endl;
@ -85,7 +85,9 @@ void run() {
// Call. // Call.
for (size_t i = 0; i < 2; ++i) { for (size_t i = 0; i < 2; ++i) {
std::cout << "Calling export " << i << "..." << std::endl; std::cout << "Calling export " << i << "..." << std::endl;
auto trap = exports[i]->func()->call(); auto args = wasm::vec<wasm::Val>::make();
auto results = wasm::vec<wasm::Val>::make();
auto trap = exports[i]->func()->call(args, results);
if (!trap) { if (!trap) {
std::cout << "> Error calling function, expected trap!" << std::endl; std::cout << "> Error calling function, expected trap!" << std::endl;
exit(1); exit(1);

View File

@ -105,7 +105,13 @@ typedef wasm_byte_vec_t wasm_name_t;
#define wasm_name_delete wasm_byte_vec_delete #define wasm_name_delete wasm_byte_vec_delete
static inline void wasm_name_new_from_string( static inline void wasm_name_new_from_string(
own wasm_name_t* out, const char* s own wasm_name_t* out, own const char* s
) {
wasm_name_new(out, strlen(s), s);
}
static inline void wasm_name_new_from_string_nt(
own wasm_name_t* out, own const char* s
) { ) {
wasm_name_new(out, strlen(s) + 1, s); wasm_name_new(out, strlen(s) + 1, s);
} }
@ -408,9 +414,9 @@ WASM_API_EXTERN own wasm_module_t* wasm_module_deserialize(wasm_store_t*, const
WASM_DECLARE_REF(func) WASM_DECLARE_REF(func)
typedef own wasm_trap_t* (*wasm_func_callback_t)( typedef own wasm_trap_t* (*wasm_func_callback_t)(
const wasm_val_t args[], wasm_val_t results[]); const wasm_val_vec_t* args, own wasm_val_vec_t* results);
typedef own wasm_trap_t* (*wasm_func_callback_with_env_t)( typedef own wasm_trap_t* (*wasm_func_callback_with_env_t)(
void* env, const wasm_val_t args[], wasm_val_t results[]); void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results);
WASM_API_EXTERN own wasm_func_t* wasm_func_new( WASM_API_EXTERN own wasm_func_t* wasm_func_new(
wasm_store_t*, const wasm_functype_t*, wasm_func_callback_t); wasm_store_t*, const wasm_functype_t*, wasm_func_callback_t);
@ -423,7 +429,7 @@ WASM_API_EXTERN size_t wasm_func_param_arity(const wasm_func_t*);
WASM_API_EXTERN size_t wasm_func_result_arity(const wasm_func_t*); WASM_API_EXTERN size_t wasm_func_result_arity(const wasm_func_t*);
WASM_API_EXTERN own wasm_trap_t* wasm_func_call( WASM_API_EXTERN own wasm_trap_t* wasm_func_call(
const wasm_func_t*, const wasm_val_t args[], wasm_val_t results[]); const wasm_func_t*, const wasm_val_vec_t* args, wasm_val_vec_t* results);
// Global Instances // Global Instances
@ -510,7 +516,7 @@ WASM_API_EXTERN const wasm_memory_t* wasm_extern_as_memory_const(const wasm_exte
WASM_DECLARE_REF(instance) WASM_DECLARE_REF(instance)
WASM_API_EXTERN own wasm_instance_t* wasm_instance_new( WASM_API_EXTERN own wasm_instance_t* wasm_instance_new(
wasm_store_t*, const wasm_module_t*, const wasm_extern_t* const imports[], wasm_store_t*, const wasm_module_t*, const wasm_extern_vec_t* imports,
own wasm_trap_t** own wasm_trap_t**
); );
@ -520,6 +526,12 @@ WASM_API_EXTERN void wasm_instance_exports(const wasm_instance_t*, own wasm_exte
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Convenience // Convenience
// Vectors
#define WASM_EMPTY_VEC {0, NULL}
#define WASM_ARRAY_VEC(array) {sizeof(array)/sizeof(*(array)), array}
// Value Type construction short-hands // Value Type construction short-hands
static inline own wasm_valtype_t* wasm_valtype_new_i32() { static inline own wasm_valtype_t* wasm_valtype_new_i32() {
@ -692,6 +704,13 @@ static inline void* wasm_val_ptr(const wasm_val_t* val) {
#endif #endif
} }
#define WASM_I32_VAL(i) {.kind = WASM_I32, .of = {.i32 = i}}
#define WASM_I64_VAL(i) {.kind = WASM_I64, .of = {.i64 = i}}
#define WASM_F32_VAL(z) {.kind = WASM_F32, .of = {.f32 = z}}
#define WASM_F64_VAL(z) {.kind = WASM_F64, .of = {.f64 = z}}
#define WASM_REF_VAL(r) {.kind = WASM_ANYREF, .of = {.ref = r}}
#define WASM_INIT_VAL {.kind = WASM_ANYREF, .of = {.ref = NULL}}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -146,6 +146,12 @@ public:
} }
static auto make(std::string s) -> vec<char> { static auto make(std::string s) -> vec<char> {
auto v = vec(s.length());
if (v) std::strncpy(v.get(), s.data(), s.length());
return v;
}
static auto make_nt(std::string s) -> vec<char> {
auto v = vec(s.length() + 1); auto v = vec(s.length() + 1);
if (v) std::strcpy(v.get(), s.data()); if (v) std::strcpy(v.get(), s.data());
return v; return v;
@ -431,11 +437,11 @@ class Val {
public: public:
Val() : kind_(ValKind::ANYREF) { impl_.ref = nullptr; } Val() : kind_(ValKind::ANYREF) { impl_.ref = nullptr; }
Val(int32_t i) : kind_(ValKind::I32) { impl_.i32 = i; } explicit Val(int32_t i) : kind_(ValKind::I32) { impl_.i32 = i; }
Val(int64_t i) : kind_(ValKind::I64) { impl_.i64 = i; } explicit Val(int64_t i) : kind_(ValKind::I64) { impl_.i64 = i; }
Val(float32_t z) : kind_(ValKind::F32) { impl_.f32 = z; } explicit Val(float32_t z) : kind_(ValKind::F32) { impl_.f32 = z; }
Val(float64_t z) : kind_(ValKind::F64) { impl_.f64 = z; } explicit Val(float64_t z) : kind_(ValKind::F64) { impl_.f64 = z; }
Val(own<Ref>&& r) : kind_(ValKind::ANYREF) { impl_.ref = r.release(); } explicit Val(own<Ref>&& r) : kind_(ValKind::ANYREF) { impl_.ref = r.release(); }
Val(Val&& that) : kind_(that.kind_), impl_(that.impl_) { Val(Val&& that) : kind_(that.kind_), impl_(that.impl_) {
if (is_ref()) that.impl_.ref = nullptr; if (is_ref()) that.impl_.ref = nullptr;
@ -648,8 +654,8 @@ public:
Func() = delete; Func() = delete;
~Func(); ~Func();
using callback = auto (*)(const Val[], Val[]) -> own<Trap>; using callback = auto (*)(const vec<Val>&, vec<Val>&) -> own<Trap>;
using callback_with_env = auto (*)(void*, const Val[], Val[]) -> own<Trap>; using callback_with_env = auto (*)(void*, const vec<Val>&, vec<Val>&) -> own<Trap>;
static auto make(Store*, const FuncType*, callback) -> own<Func>; static auto make(Store*, const FuncType*, callback) -> own<Func>;
static auto make(Store*, const FuncType*, callback_with_env, static auto make(Store*, const FuncType*, callback_with_env,
@ -660,7 +666,7 @@ public:
auto param_arity() const -> size_t; auto param_arity() const -> size_t;
auto result_arity() const -> size_t; auto result_arity() const -> size_t;
auto call(const Val[] = nullptr, Val[] = nullptr) const -> own<Trap>; auto call(const vec<Val>&, vec<Val>&) const -> own<Trap>;
}; };
@ -731,7 +737,7 @@ public:
~Instance(); ~Instance();
static auto make( static auto make(
Store*, const Module*, const Extern* const[], own<Trap>* = nullptr Store*, const Module*, const vec<Extern*>&, own<Trap>* = nullptr
) -> own<Instance>; ) -> own<Instance>;
auto copy() const -> own<Instance>; auto copy() const -> own<Instance>;

View File

@ -60,7 +60,7 @@ struct borrowed_vec {
// Vectors // Vectors
#define WASM_DEFINE_VEC_BASE(name, Name, vec, ptr_or_none) \ #define WASM_DEFINE_VEC_BASE(name, Name, vec, plainvec, ptr_or_none) \
static_assert( \ static_assert( \
sizeof(wasm_##name##_vec_t) == sizeof(vec<Name>), \ sizeof(wasm_##name##_vec_t) == sizeof(vec<Name>), \
"C/C++ incompatibility" \ "C/C++ incompatibility" \
@ -86,6 +86,14 @@ struct borrowed_vec {
-> wasm_##name##_t ptr_or_none const* { \ -> wasm_##name##_t ptr_or_none const* { \
return reinterpret_cast<wasm_##name##_t ptr_or_none const*>(v); \ return reinterpret_cast<wasm_##name##_t ptr_or_none const*>(v); \
} \ } \
extern "C++" inline auto reveal_##name##_vec(wasm_##name##_vec_t* v) \
-> plainvec<Name*>* { \
return reinterpret_cast<plainvec<Name*>*>(v); \
} \
extern "C++" inline auto reveal_##name##_vec(const wasm_##name##_vec_t* v) \
-> const plainvec<Name*>* { \
return reinterpret_cast<const plainvec<Name*>*>(v); \
} \
extern "C++" inline auto reveal_##name##_vec(wasm_##name##_t ptr_or_none* v) \ extern "C++" inline auto reveal_##name##_vec(wasm_##name##_t ptr_or_none* v) \
-> vec<Name>::elem_type* { \ -> vec<Name>::elem_type* { \
return reinterpret_cast<vec<Name>::elem_type*>(v); \ return reinterpret_cast<vec<Name>::elem_type*>(v); \
@ -134,7 +142,7 @@ struct borrowed_vec {
// Vectors with no ownership management of elements // Vectors with no ownership management of elements
#define WASM_DEFINE_VEC_PLAIN(name, Name) \ #define WASM_DEFINE_VEC_PLAIN(name, Name) \
WASM_DEFINE_VEC_BASE(name, Name, vec, ) \ WASM_DEFINE_VEC_BASE(name, Name, vec, vec, ) \
\ \
void wasm_##name##_vec_new( \ void wasm_##name##_vec_new( \
wasm_##name##_vec_t* out, \ wasm_##name##_vec_t* out, \
@ -156,7 +164,7 @@ struct borrowed_vec {
// Vectors that own their elements // Vectors that own their elements
#define WASM_DEFINE_VEC_OWN(name, Name) \ #define WASM_DEFINE_VEC_OWN(name, Name) \
WASM_DEFINE_VEC_BASE(name, Name, ownvec, *) \ WASM_DEFINE_VEC_BASE(name, Name, ownvec, vec, *) \
\ \
void wasm_##name##_vec_new( \ void wasm_##name##_vec_new( \
wasm_##name##_vec_t* out, \ wasm_##name##_vec_t* out, \
@ -620,7 +628,7 @@ inline auto borrow_val(const wasm_val_t* v) -> borrowed_val {
} // extern "C++" } // extern "C++"
WASM_DEFINE_VEC_BASE(val, Val, vec, ) WASM_DEFINE_VEC_BASE(val, Val, vec, vec, )
void wasm_val_vec_new( void wasm_val_vec_new(
wasm_val_vec_t* out, size_t size, wasm_val_t const data[] wasm_val_vec_t* out, size_t size, wasm_val_t const data[]
@ -771,7 +779,9 @@ WASM_DEFINE_REF(func, Func)
extern "C++" { extern "C++" {
auto wasm_callback(void* env, const Val args[], Val results[]) -> own<Trap> { auto wasm_callback(
void* env, const vec<Val>& args, vec<Val>& results
) -> own<Trap> {
auto f = reinterpret_cast<wasm_func_callback_t>(env); auto f = reinterpret_cast<wasm_func_callback_t>(env);
return adopt_trap(f(hide_val_vec(args), hide_val_vec(results))); return adopt_trap(f(hide_val_vec(args), hide_val_vec(results)));
} }
@ -783,7 +793,7 @@ struct wasm_callback_env_t {
}; };
auto wasm_callback_with_env( auto wasm_callback_with_env(
void* env, const Val args[], Val results[] void* env, const vec<Val>& args, vec<Val>& results
) -> own<Trap> { ) -> own<Trap> {
auto t = static_cast<wasm_callback_env_t*>(env); auto t = static_cast<wasm_callback_env_t*>(env);
return adopt_trap(t->callback(t->env, hide_val_vec(args), hide_val_vec(results))); return adopt_trap(t->callback(t->env, hide_val_vec(args), hide_val_vec(results)));
@ -826,9 +836,11 @@ size_t wasm_func_result_arity(const wasm_func_t* func) {
} }
wasm_trap_t* wasm_func_call( wasm_trap_t* wasm_func_call(
const wasm_func_t* func, const wasm_val_t args[], wasm_val_t results[] const wasm_func_t* func, const wasm_val_vec_t* args, wasm_val_vec_t* results
) { ) {
return release_trap(func->call(reveal_val_vec(args), reveal_val_vec(results))); auto args_ = borrow_val_vec(args);
auto results_ = borrow_val_vec(results);
return release_trap(func->call(args_.it, results_.it));
} }
@ -995,12 +1007,13 @@ WASM_DEFINE_REF(instance, Instance)
wasm_instance_t* wasm_instance_new( wasm_instance_t* wasm_instance_new(
wasm_store_t* store, wasm_store_t* store,
const wasm_module_t* module, const wasm_module_t* module,
const wasm_extern_t* const imports[], const wasm_extern_vec_t* imports,
wasm_trap_t** trap wasm_trap_t** trap
) { ) {
own<Trap> error; own<Trap> error;
auto instance = release_instance(Instance::make(store, module, auto imports_ = reveal_extern_vec(imports);
reinterpret_cast<const Extern* const*>(imports), &error)); auto instance =
release_instance(Instance::make(store, module, *imports_, &error));
if (trap) *trap = hide_trap(error.release()); if (trap) *trap = hide_trap(error.release());
return instance; return instance;
} }

View File

@ -229,6 +229,7 @@ DEFINE_VEC(Global, ownvec, GLOBAL)
DEFINE_VEC(Table, ownvec, TABLE) DEFINE_VEC(Table, ownvec, TABLE)
DEFINE_VEC(Memory, ownvec, MEMORY) DEFINE_VEC(Memory, ownvec, MEMORY)
DEFINE_VEC(Extern, ownvec, EXTERN) DEFINE_VEC(Extern, ownvec, EXTERN)
DEFINE_VEC(Extern*, vec, EXTERN)
DEFINE_VEC(Val, vec, VAL) DEFINE_VEC(Val, vec, VAL)
#endif // #ifdef WASM_API_DEBUG #endif // #ifdef WASM_API_DEBUG
@ -1257,7 +1258,7 @@ auto Trap::message() const -> Message {
auto message = v8::Exception::CreateMessage(isolate, impl(this)->v8_object()); auto message = v8::Exception::CreateMessage(isolate, impl(this)->v8_object());
v8::String::Utf8Value string(isolate, message->Get()); v8::String::Utf8Value string(isolate, message->Get());
return vec<byte_t>::make(std::string(*string)); return vec<byte_t>::make_nt(std::string(*string));
} }
auto Trap::origin() const -> own<Frame> { auto Trap::origin() const -> own<Frame> {
@ -1687,7 +1688,7 @@ auto Func::result_arity() const -> size_t {
return wasm_v8::func_type_result_arity(impl(this)->v8_object()); return wasm_v8::func_type_result_arity(impl(this)->v8_object());
} }
auto Func::call(const Val args[], Val results[]) const -> own<Trap> { auto Func::call(const vec<Val>& args, vec<Val>& results) const -> own<Trap> {
auto func = impl(this); auto func = impl(this);
auto store = func->store(); auto store = func->store();
auto isolate = store->isolate(); auto isolate = store->isolate();
@ -1754,17 +1755,17 @@ void FuncData::v8_callback(const v8::FunctionCallbackInfo<v8::Value>& info) {
assert(param_types.size() == info.Length()); assert(param_types.size() == info.Length());
// TODO: cache params and result arrays per thread. // TODO: cache params and result arrays per thread.
auto args = std::unique_ptr<Val[]>(new Val[param_types.size()]); auto args = vec<Val>::make_uninitialized(param_types.size());
auto results = std::unique_ptr<Val[]>(new Val[result_types.size()]); auto results = vec<Val>::make_uninitialized(result_types.size());
for (size_t i = 0; i < param_types.size(); ++i) { for (size_t i = 0; i < param_types.size(); ++i) {
args[i] = v8_to_val(store, info[i], param_types[i].get()); args[i] = v8_to_val(store, info[i], param_types[i].get());
} }
own<Trap> trap; own<Trap> trap;
if (self->kind == CALLBACK_WITH_ENV) { if (self->kind == CALLBACK_WITH_ENV) {
trap = self->callback_with_env(self->env, args.get(), results.get()); trap = self->callback_with_env(self->env, args, results);
} else { } else {
trap = self->callback(args.get(), results.get()); trap = self->callback(args, results);
} }
if (trap) { if (trap) {
@ -2019,7 +2020,7 @@ auto Instance::copy() const -> own<Instance> {
} }
auto Instance::make( auto Instance::make(
Store* store_abs, const Module* module_abs, const Extern* const imports[], Store* store_abs, const Module* module_abs, const vec<Extern*>& imports,
own<Trap>* trap own<Trap>* trap
) -> own<Instance> { ) -> own<Instance> {
auto store = impl(store_abs); auto store = impl(store_abs);

View File

@ -147,7 +147,7 @@ void wasi_env_set_memory(wasi_env_t *env, const wasm_memory_t *memory);
bool wasi_get_imports(const wasm_store_t *store, bool wasi_get_imports(const wasm_store_t *store,
const wasm_module_t *module, const wasm_module_t *module,
const wasi_env_t *wasi_env, const wasi_env_t *wasi_env,
wasm_extern_t **imports); wasm_extern_vec_t *imports);
#endif #endif
#if defined(WASMER_WASI_ENABLED) #if defined(WASMER_WASI_ENABLED)

View File

@ -136,20 +136,24 @@ int main(int argc, char* argv[]) {
wasm_importtype_vec_t import_types; wasm_importtype_vec_t import_types;
wasm_module_imports(module, &import_types); wasm_module_imports(module, &import_types);
int num_imports = import_types.size;
wasm_extern_t** imports = (wasm_extern_t**) malloc(num_imports * sizeof(wasm_extern_t*)); wasm_extern_vec_t imports;
wasm_extern_vec_new_uninitialized(&imports, import_types.size);
wasm_importtype_vec_delete(&import_types); wasm_importtype_vec_delete(&import_types);
#ifdef WASI #ifdef WASI
bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports); bool get_imports_result = wasi_get_imports(store, module, wasi_env, &imports);
if (!get_imports_result) { if (!get_imports_result) {
fprintf(stderr, "Error getting WASI imports!\n"); fprintf(stderr, "Error getting WASI imports!\n");
print_wasmer_error(); print_wasmer_error();
return 1; return 1;
} }
#endif #endif
wasm_instance_t* instance = wasm_instance_new(store, module, (const wasm_extern_t* const*) imports, NULL); wasm_instance_t* instance = wasm_instance_new(store, module, &imports, NULL);
if (!instance) { if (!instance) {
fprintf(stderr, "Failed to create instance\n"); fprintf(stderr, "Failed to create instance\n");
print_wasmer_error(); print_wasmer_error();

View File

@ -6286,6 +6286,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
offset, offset,
4, 4,
)?; )?;
let dead_load = self.builder.build_load(effective_address, "");
self.annotate_user_memaccess(
memory_index,
memarg,
1,
dead_load.as_instruction_value().unwrap(),
)?;
let store = self.builder.build_store(effective_address, value); let store = self.builder.build_store(effective_address, value);
self.annotate_user_memaccess(memory_index, memarg, 1, store)?; self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
} }
@ -6300,6 +6307,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
offset, offset,
8, 8,
)?; )?;
let dead_load = self.builder.build_load(effective_address, "");
self.annotate_user_memaccess(
memory_index,
memarg,
1,
dead_load.as_instruction_value().unwrap(),
)?;
let store = self.builder.build_store(effective_address, value); let store = self.builder.build_store(effective_address, value);
self.annotate_user_memaccess(memory_index, memarg, 1, store)?; self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
} }
@ -6315,6 +6329,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
offset, offset,
4, 4,
)?; )?;
let dead_load = self.builder.build_load(effective_address, "");
self.annotate_user_memaccess(
memory_index,
memarg,
1,
dead_load.as_instruction_value().unwrap(),
)?;
let store = self.builder.build_store(effective_address, v); let store = self.builder.build_store(effective_address, v);
self.annotate_user_memaccess(memory_index, memarg, 1, store)?; self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
} }
@ -6330,6 +6351,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
offset, offset,
8, 8,
)?; )?;
let dead_load = self.builder.build_load(effective_address, "");
self.annotate_user_memaccess(
memory_index,
memarg,
1,
dead_load.as_instruction_value().unwrap(),
)?;
let store = self.builder.build_store(effective_address, v); let store = self.builder.build_store(effective_address, v);
self.annotate_user_memaccess(memory_index, memarg, 1, store)?; self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
} }
@ -6345,6 +6373,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
offset, offset,
16, 16,
)?; )?;
let dead_load = self.builder.build_load(effective_address, "");
self.annotate_user_memaccess(
memory_index,
memarg,
1,
dead_load.as_instruction_value().unwrap(),
)?;
let store = self.builder.build_store(effective_address, v); let store = self.builder.build_store(effective_address, v);
self.annotate_user_memaccess(memory_index, memarg, 1, store)?; self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
} }
@ -6603,6 +6638,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
offset, offset,
1, 1,
)?; )?;
let dead_load = self.builder.build_load(effective_address, "");
self.annotate_user_memaccess(
memory_index,
memarg,
1,
dead_load.as_instruction_value().unwrap(),
)?;
let narrow_value = let narrow_value =
self.builder self.builder
.build_int_truncate(value, self.intrinsics.i8_ty, ""); .build_int_truncate(value, self.intrinsics.i8_ty, "");
@ -6620,6 +6662,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
offset, offset,
2, 2,
)?; )?;
let dead_load = self.builder.build_load(effective_address, "");
self.annotate_user_memaccess(
memory_index,
memarg,
1,
dead_load.as_instruction_value().unwrap(),
)?;
let narrow_value = let narrow_value =
self.builder self.builder
.build_int_truncate(value, self.intrinsics.i16_ty, ""); .build_int_truncate(value, self.intrinsics.i16_ty, "");
@ -6637,6 +6686,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
offset, offset,
4, 4,
)?; )?;
let dead_load = self.builder.build_load(effective_address, "");
self.annotate_user_memaccess(
memory_index,
memarg,
1,
dead_load.as_instruction_value().unwrap(),
)?;
let narrow_value = let narrow_value =
self.builder self.builder
.build_int_truncate(value, self.intrinsics.i32_ty, ""); .build_int_truncate(value, self.intrinsics.i32_ty, "");

View File

@ -43,7 +43,7 @@ fn get_module(store: &Store) -> Result<Module> {
#[test] #[test]
fn dynamic_function() -> Result<()> { fn dynamic_function() -> Result<()> {
let store = get_store(); let store = get_store(false);
let module = get_module(&store)?; let module = get_module(&store)?;
static HITS: AtomicUsize = AtomicUsize::new(0); static HITS: AtomicUsize = AtomicUsize::new(0);
Instance::new( Instance::new(
@ -83,7 +83,7 @@ fn dynamic_function() -> Result<()> {
#[test] #[test]
fn dynamic_function_with_env() -> Result<()> { fn dynamic_function_with_env() -> Result<()> {
let store = get_store(); let store = get_store(false);
let module = get_module(&store)?; let module = get_module(&store)?;
let env: Arc<AtomicUsize> = Arc::new(AtomicUsize::new(0)); let env: Arc<AtomicUsize> = Arc::new(AtomicUsize::new(0));
@ -124,7 +124,7 @@ fn dynamic_function_with_env() -> Result<()> {
#[test] #[test]
fn static_function() -> Result<()> { fn static_function() -> Result<()> {
let store = get_store(); let store = get_store(false);
let module = get_module(&store)?; let module = get_module(&store)?;
static HITS: AtomicUsize = AtomicUsize::new(0); static HITS: AtomicUsize = AtomicUsize::new(0);
@ -162,7 +162,7 @@ fn static_function() -> Result<()> {
#[test] #[test]
fn static_function_with_results() -> Result<()> { fn static_function_with_results() -> Result<()> {
let store = get_store(); let store = get_store(false);
let module = get_module(&store)?; let module = get_module(&store)?;
static HITS: AtomicUsize = AtomicUsize::new(0); static HITS: AtomicUsize = AtomicUsize::new(0);
@ -200,7 +200,7 @@ fn static_function_with_results() -> Result<()> {
#[test] #[test]
fn static_function_with_env() -> Result<()> { fn static_function_with_env() -> Result<()> {
let store = get_store(); let store = get_store(false);
let module = get_module(&store)?; let module = get_module(&store)?;
let env: Arc<AtomicUsize> = Arc::new(AtomicUsize::new(0)); let env: Arc<AtomicUsize> = Arc::new(AtomicUsize::new(0));
@ -238,7 +238,7 @@ fn static_function_with_env() -> Result<()> {
#[test] #[test]
fn static_function_that_fails() -> Result<()> { fn static_function_that_fails() -> Result<()> {
let store = get_store(); let store = get_store(false);
let wat = r#" let wat = r#"
(import "host" "0" (func)) (import "host" "0" (func))

View File

@ -39,7 +39,7 @@ macro_rules! mvr_test {
#[test] #[test]
#[cfg_attr(any(feature = "test-cranelift", feature="test-singlepass"), ignore)] #[cfg_attr(any(feature = "test-cranelift", feature="test-singlepass"), ignore)]
fn native() -> anyhow::Result<()> { fn native() -> anyhow::Result<()> {
let store = get_store(); let store = get_store(false);
let module = get_module(&store)?; let module = get_module(&store)?;
let instance = wasmer::Instance::new( let instance = wasmer::Instance::new(
&module, &module,
@ -65,7 +65,7 @@ macro_rules! mvr_test {
#[test] #[test]
#[cfg_attr(feature="test-singlepass", ignore)] #[cfg_attr(feature="test-singlepass", ignore)]
fn dynamic() -> anyhow::Result<()> { fn dynamic() -> anyhow::Result<()> {
let store = get_store(); let store = get_store(false);
let module = get_module(&store)?; let module = get_module(&store)?;
let callback_fn = wasmer::Function::new(&store, &wasmer::FunctionType::new(vec![wasmer::ValType::I32], vec![ $( <$result_type>::expected_valtype() ),* ]), dynamic_callback_fn); let callback_fn = wasmer::Function::new(&store, &wasmer::FunctionType::new(vec![wasmer::ValType::I32], vec![ $( <$result_type>::expected_valtype() ),* ]), dynamic_callback_fn);
let instance = wasmer::Instance::new( let instance = wasmer::Instance::new(

View File

@ -8,7 +8,7 @@ use wasmer::*;
#[test] #[test]
fn native_function_works_for_wasm() -> Result<()> { fn native_function_works_for_wasm() -> Result<()> {
let store = get_store(); let store = get_store(false);
let wat = r#"(module let wat = r#"(module
(func $multiply (import "env" "multiply") (param i32 i32) (result i32)) (func $multiply (import "env" "multiply") (param i32 i32) (result i32))
(func (export "add") (param i32 i32) (result i32) (func (export "add") (param i32 i32) (result i32)
@ -52,7 +52,7 @@ fn native_function_works_for_wasm() -> Result<()> {
#[test] #[test]
fn static_host_function_without_env() -> anyhow::Result<()> { fn static_host_function_without_env() -> anyhow::Result<()> {
let store = get_store(); let store = get_store(false);
fn f(a: i32, b: i64, c: f32, d: f64) -> (f64, f32, i64, i32) { fn f(a: i32, b: i64, c: f32, d: f64) -> (f64, f32, i64, i32) {
(d * 4.0, c * 3.0, b * 2, a * 1) (d * 4.0, c * 3.0, b * 2, a * 1)
@ -83,7 +83,7 @@ fn static_host_function_without_env() -> anyhow::Result<()> {
#[test] #[test]
fn static_host_function_with_env() -> anyhow::Result<()> { fn static_host_function_with_env() -> anyhow::Result<()> {
let store = get_store(); let store = get_store(false);
fn f(env: &mut Env, a: i32, b: i64, c: f32, d: f64) -> (f64, f32, i64, i32) { fn f(env: &mut Env, a: i32, b: i64, c: f32, d: f64) -> (f64, f32, i64, i32) {
assert_eq!(*env.0.borrow(), 100); assert_eq!(*env.0.borrow(), 100);
@ -143,7 +143,7 @@ fn static_host_function_with_env() -> anyhow::Result<()> {
#[test] #[test]
fn dynamic_host_function_without_env() -> anyhow::Result<()> { fn dynamic_host_function_without_env() -> anyhow::Result<()> {
let store = get_store(); let store = get_store(false);
let f = Function::new( let f = Function::new(
&store, &store,
@ -170,7 +170,7 @@ fn dynamic_host_function_without_env() -> anyhow::Result<()> {
#[test] #[test]
fn dynamic_host_function_with_env() -> anyhow::Result<()> { fn dynamic_host_function_with_env() -> anyhow::Result<()> {
let store = get_store(); let store = get_store(false);
#[derive(Clone)] #[derive(Clone)]
struct Env(Rc<RefCell<i32>>); struct Env(Rc<RefCell<i32>>);

View File

@ -4,7 +4,7 @@ use wasmer::*;
#[test] #[test]
fn test_serialize() -> Result<()> { fn test_serialize() -> Result<()> {
let store = get_store(); let store = get_store(false);
let wat = r#" let wat = r#"
(module (module
(func $hello (import "" "hello")) (func $hello (import "" "hello"))
@ -20,7 +20,7 @@ fn test_serialize() -> Result<()> {
#[test] #[test]
fn test_deserialize() -> Result<()> { fn test_deserialize() -> Result<()> {
let store = get_store(); let store = get_store(false);
let wat = r#" let wat = r#"
(module $name (module $name
(import "host" "sum_part" (func (param i32 i64 i32 f32 f64) (result i64))) (import "host" "sum_part" (func (param i32 i64 i32 f32 f64) (result i64)))

View File

@ -5,7 +5,7 @@ use wasmer::*;
#[test] #[test]
fn test_trap_return() -> Result<()> { fn test_trap_return() -> Result<()> {
let store = get_store(); let store = get_store(false);
let wat = r#" let wat = r#"
(module (module
(func $hello (import "" "hello")) (func $hello (import "" "hello"))
@ -47,7 +47,7 @@ fn test_trap_return() -> Result<()> {
ignore ignore
)] )]
fn test_trap_trace() -> Result<()> { fn test_trap_trace() -> Result<()> {
let store = get_store(); let store = get_store(false);
let wat = r#" let wat = r#"
(module $hello_mod (module $hello_mod
(func (export "run") (call $hello)) (func (export "run") (call $hello))
@ -83,7 +83,7 @@ fn test_trap_trace() -> Result<()> {
#[test] #[test]
fn test_trap_trace_cb() -> Result<()> { fn test_trap_trace_cb() -> Result<()> {
let store = get_store(); let store = get_store(false);
let wat = r#" let wat = r#"
(module $hello_mod (module $hello_mod
(import "" "throw" (func $throw)) (import "" "throw" (func $throw))
@ -134,7 +134,7 @@ fn test_trap_trace_cb() -> Result<()> {
ignore ignore
)] )]
fn test_trap_stack_overflow() -> Result<()> { fn test_trap_stack_overflow() -> Result<()> {
let store = get_store(); let store = get_store(false);
let wat = r#" let wat = r#"
(module $rec_mod (module $rec_mod
(func $run (export "run") (call $run)) (func $run (export "run") (call $run))
@ -173,7 +173,7 @@ fn test_trap_stack_overflow() -> Result<()> {
ignore ignore
)] )]
fn trap_display_pretty() -> Result<()> { fn trap_display_pretty() -> Result<()> {
let store = get_store(); let store = get_store(false);
let wat = r#" let wat = r#"
(module $m (module $m
(func $die unreachable) (func $die unreachable)
@ -214,7 +214,7 @@ RuntimeError: unreachable
ignore ignore
)] )]
fn trap_display_multi_module() -> Result<()> { fn trap_display_multi_module() -> Result<()> {
let store = get_store(); let store = get_store(false);
let wat = r#" let wat = r#"
(module $a (module $a
(func $die unreachable) (func $die unreachable)
@ -266,7 +266,7 @@ RuntimeError: unreachable
#[test] #[test]
fn trap_start_function_import() -> Result<()> { fn trap_start_function_import() -> Result<()> {
let store = get_store(); let store = get_store(false);
let binary = r#" let binary = r#"
(module $a (module $a
(import "" "" (func $foo)) (import "" "" (func $foo))
@ -299,7 +299,7 @@ fn trap_start_function_import() -> Result<()> {
#[test] #[test]
fn rust_panic_import() -> Result<()> { fn rust_panic_import() -> Result<()> {
let store = get_store(); let store = get_store(false);
let binary = r#" let binary = r#"
(module $a (module $a
(import "" "foo" (func $foo)) (import "" "foo" (func $foo))
@ -344,7 +344,7 @@ fn rust_panic_import() -> Result<()> {
#[test] #[test]
fn rust_panic_start_function() -> Result<()> { fn rust_panic_start_function() -> Result<()> {
let store = get_store(); let store = get_store(false);
let binary = r#" let binary = r#"
(module $a (module $a
(import "" "" (func $foo)) (import "" "" (func $foo))
@ -389,7 +389,7 @@ fn rust_panic_start_function() -> Result<()> {
#[test] #[test]
fn mismatched_arguments() -> Result<()> { fn mismatched_arguments() -> Result<()> {
let store = get_store(); let store = get_store(false);
let binary = r#" let binary = r#"
(module $a (module $a
(func (export "foo") (param i32)) (func (export "foo") (param i32))
@ -426,7 +426,7 @@ fn mismatched_arguments() -> Result<()> {
ignore ignore
)] )]
fn call_signature_mismatch() -> Result<()> { fn call_signature_mismatch() -> Result<()> {
let store = get_store(); let store = get_store(false);
let binary = r#" let binary = r#"
(module $a (module $a
(func $foo (func $foo
@ -465,7 +465,7 @@ RuntimeError: indirect call type mismatch
ignore ignore
)] )]
fn start_trap_pretty() -> Result<()> { fn start_trap_pretty() -> Result<()> {
let store = get_store(); let store = get_store(false);
let wat = r#" let wat = r#"
(module $m (module $m
(func $die unreachable) (func $die unreachable)
@ -497,7 +497,7 @@ RuntimeError: unreachable
#[test] #[test]
#[cfg_attr(feature = "test-native", ignore)] #[cfg_attr(feature = "test-native", ignore)]
fn present_after_module_drop() -> Result<()> { fn present_after_module_drop() -> Result<()> {
let store = get_store(); let store = get_store(false);
let module = Module::new(&store, r#"(func (export "foo") unreachable)"#)?; let module = Module::new(&store, r#"(func (export "foo") unreachable)"#)?;
let instance = Instance::new(&module, &imports! {})?; let instance = Instance::new(&module, &imports! {})?;
let func: Function = instance.exports.get_function("foo")?.clone(); let func: Function = instance.exports.get_function("foo")?.clone();

View File

@ -36,18 +36,18 @@ pub fn get_compiler(canonicalize_nans: bool) -> impl CompilerConfig {
} }
#[cfg(feature = "test-jit")] #[cfg(feature = "test-jit")]
pub fn get_engine() -> impl Engine { pub fn get_engine(canonicalize_nans: bool) -> impl Engine {
let compiler_config = get_compiler(false); let compiler_config = get_compiler(canonicalize_nans);
JIT::new(&compiler_config).engine() JIT::new(&compiler_config).engine()
} }
#[cfg(feature = "test-native")] #[cfg(feature = "test-native")]
pub fn get_engine() -> impl Engine { pub fn get_engine(canonicalize_nans: bool) -> impl Engine {
let mut compiler_config = get_compiler(false); let mut compiler_config = get_compiler(canonicalize_nans);
Native::new(&mut compiler_config).engine() Native::new(&mut compiler_config).engine()
} }
pub fn get_store() -> Store { pub fn get_store(canonicalize_nans: bool) -> Store {
Store::new(&get_engine()) Store::new(&get_engine(canonicalize_nans))
} }
pub fn get_store_with_middlewares<I: Iterator<Item = Arc<dyn FunctionMiddlewareGenerator>>>( pub fn get_store_with_middlewares<I: Iterator<Item = Arc<dyn FunctionMiddlewareGenerator>>>(
@ -67,7 +67,6 @@ pub fn get_store_with_middlewares<I: Iterator<Item = Arc<dyn FunctionMiddlewareG
#[cfg(feature = "test-jit")] #[cfg(feature = "test-jit")]
pub fn get_headless_store() -> Store { pub fn get_headless_store() -> Store {
Store::new(&JIT::headless().engine()) Store::new(&JIT::headless().engine())
// Store::new(&Native::headless().engine())
} }
#[cfg(feature = "test-native")] #[cfg(feature = "test-native")]

View File

@ -1,11 +1,8 @@
#![cfg(all(feature = "compiler", feature = "engine"))] #![cfg(all(feature = "compiler", feature = "engine"))]
use crate::utils::get_compiler; use crate::utils::get_store;
use std::fs::File; use std::fs::File;
use std::io::Read; use std::io::Read;
use wasmer::Store;
#[cfg(feature = "jit")]
use wasmer_engine_jit::JIT;
use wasmer_wast::WasiTest; use wasmer_wast::WasiTest;
// The generated tests (from build.rs) look like: // The generated tests (from build.rs) look like:
@ -25,8 +22,7 @@ pub fn run_wasi(wast_path: &str, base_dir: &str, compiler: &str) -> anyhow::Resu
"Running wasi wast `{}` with the {} compiler", "Running wasi wast `{}` with the {} compiler",
wast_path, compiler wast_path, compiler
); );
let compiler_config = get_compiler(true); let store = get_store(true);
let store = Store::new(&JIT::new(&compiler_config).engine());
let source = { let source = {
let mut out = String::new(); let mut out = String::new();

View File

@ -32,6 +32,7 @@ int main() {
wasm_store_t* store = wasm_store_new(engine); wasm_store_t* store = wasm_store_new(engine);
wasm_module_t* module = wasmer_object_file_engine_new(store, "qjs.wasm"); wasm_module_t* module = wasmer_object_file_engine_new(store, "qjs.wasm");
if (!module) { if (!module) {
printf("Failed to create module\n"); printf("Failed to create module\n");
print_wasmer_error(); print_wasmer_error();
@ -47,6 +48,7 @@ int main() {
wasi_config_arg(wasi_config, "--eval"); wasi_config_arg(wasi_config, "--eval");
wasi_config_arg(wasi_config, js_string); wasi_config_arg(wasi_config, js_string);
wasi_env_t* wasi_env = wasi_env_new(wasi_config); wasi_env_t* wasi_env = wasi_env_new(wasi_config);
if (!wasi_env) { if (!wasi_env) {
printf("> Error building WASI env!\n"); printf("> Error building WASI env!\n");
print_wasmer_error(); print_wasmer_error();
@ -55,18 +57,22 @@ int main() {
wasm_importtype_vec_t import_types; wasm_importtype_vec_t import_types;
wasm_module_imports(module, &import_types); wasm_module_imports(module, &import_types);
int num_imports = import_types.size;
wasm_extern_t** imports = (wasm_extern_t**) malloc(num_imports * sizeof(wasm_extern_t*)); wasm_extern_vec_t imports;
wasm_extern_vec_new_uninitialized(&imports, import_types.size);
wasm_importtype_vec_delete(&import_types); wasm_importtype_vec_delete(&import_types);
bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports); bool get_imports_result = wasi_get_imports(store, module, wasi_env, &imports);
if (!get_imports_result) { if (!get_imports_result) {
printf("> Error getting WASI imports!\n"); printf("> Error getting WASI imports!\n");
print_wasmer_error(); print_wasmer_error();
return 1; return 1;
} }
wasm_instance_t* instance = wasm_instance_new(store, module, (const wasm_extern_t* const*) imports, NULL); wasm_instance_t* instance = wasm_instance_new(store, module, &imports, NULL);
if (!instance) { if (!instance) {
printf("Failed to create instance\n"); printf("Failed to create instance\n");
print_wasmer_error(); print_wasmer_error();
@ -89,9 +95,11 @@ int main() {
return -1; return -1;
} }
wasm_extern_vec_delete(&imports);
wasm_instance_delete(instance); wasm_instance_delete(instance);
wasm_module_delete(module); wasm_module_delete(module);
wasm_store_delete(store); wasm_store_delete(store);
wasm_engine_delete(engine); wasm_engine_delete(engine);
return 0; return 0;
} }