Skip to content

Commit

Permalink
Update WebAssembly C API submodule to latest commit.
Browse files Browse the repository at this point in the history
This commit updates the WebAssembly C API submodule (for `wasm.h`) to the
latest commit out of master.

This fixes the behavior of `wasm_name_new_from_string` such that it no longer
copies the null character into the name, which caused unexpected failures when
using the Wasmtime linker as imports wouldn't resolve when the null was
present.

Along with this change were breaking changes to `wasm_func_call`, the host
callback signatures, and `wasm_instance_new` to take a vector type instead of a
pointer to an unsized array.

As a result, Wasmtime language bindings based on the C API will need to be
updated once this change is pulled in.

Fixes #2211.
Fixes #2131.
  • Loading branch information
peterhuene committed Jan 13, 2021
1 parent 2b2f369 commit b9a0055
Show file tree
Hide file tree
Showing 19 changed files with 171 additions and 134 deletions.
12 changes: 8 additions & 4 deletions crates/c-api/include/doc-wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,12 @@
*
* \fn wasm_name_new_new_uninitialized
* \brief Convenience alias
*
* \fn wasm_name_new_from_string
* \brief Create a new name from a C string.
*
* \fn wasm_name_new_from_string_nt
* \brief Create a new name from a C string with null terminator.
*
* \fn wasm_name_copy
* \brief Convenience alias
Expand Down Expand Up @@ -1520,8 +1526,6 @@
* and types of results as the original type signature. It is undefined behavior
* to return other types or different numbers of values.
*
* This function takes ownership of all of the parameters given. It's expected
* that the caller will invoke `wasm_val_delete` for each one provided.
* Ownership of the results and the trap returned, if any, is passed to the
* caller of this function.
*
Expand Down Expand Up @@ -1608,7 +1612,7 @@
* \fn size_t wasm_func_result_arity(const wasm_func_t *);
* \brief Returns the number of results returned by this function.
*
* \fn own wasm_trap_t *wasm_func_call(const wasm_func_t *, const wasm_val_t args[], const wasm_val_t results[]);
* \fn own wasm_trap_t *wasm_func_call(const wasm_func_t *, const wasm_val_vec_t *args, wasm_val_vec_t *results);
* \brief Calls the provided function with the arguments given.
*
* This function is used to call WebAssembly from the host. The parameter array
Expand Down Expand Up @@ -2164,7 +2168,7 @@
* \fn wasm_ref_as_instance_const(const wasm_ref_t *);
* \brief Unimplemented in Wasmtime, aborts the process if called.
*
* \fn own wasm_instance_t *wasm_instance_new(wasm_store_t *, const wasm_module_t *, const wasm_extern_t *const[], wasm_trap_t **);
* \fn own wasm_instance_t *wasm_instance_new(wasm_store_t *, const wasm_module_t *, const wasm_extern_vec_t *, wasm_trap_t **);
* \brief Instantiates a module with the provided imports.
*
* This function will instantiate the provided #wasm_module_t into the provided
Expand Down
11 changes: 3 additions & 8 deletions crates/c-api/include/wasmtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,6 @@ WASM_API_EXTERN const wasm_name_t *wasmtime_frame_module_name(const wasm_frame_t
*
* This function is similar to #wasm_func_call, but with a few tweaks:
*
* * `args` and `results` have a size parameter saying how big the arrays are
* * An error *and* a trap can be returned
* * Errors are returned if `args` have the wrong types, if the args/results
* arrays have the wrong lengths, or if values come from the wrong store.
Expand All @@ -697,10 +696,8 @@ WASM_API_EXTERN const wasm_name_t *wasmtime_frame_module_name(const wasm_frame_t
*/
WASM_API_EXTERN own wasmtime_error_t *wasmtime_func_call(
wasm_func_t *func,
const wasm_val_t *args,
size_t num_args,
wasm_val_t *results,
size_t num_results,
const wasm_val_vec_t *args,
wasm_val_vec_t *results,
own wasm_trap_t **trap
);

Expand Down Expand Up @@ -741,7 +738,6 @@ WASM_API_EXTERN own wasmtime_error_t *wasmtime_global_set(
* This function is similar to #wasm_instance_new, but with a few tweaks:
*
* * An error message can be returned from this function.
* * The number of imports specified is passed as an argument
* * The `trap` pointer is required to not be NULL.
*
* The states of return values from this function are similar to
Expand All @@ -759,8 +755,7 @@ WASM_API_EXTERN own wasmtime_error_t *wasmtime_global_set(
WASM_API_EXTERN own wasmtime_error_t *wasmtime_instance_new(
wasm_store_t *store,
const wasm_module_t *module,
const wasm_extern_t* const imports[],
size_t num_imports,
const wasm_extern_vec_t* imports,
own wasm_instance_t **instance,
own wasm_trap_t **trap
);
Expand Down
57 changes: 29 additions & 28 deletions crates/c-api/src/func.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{wasm_extern_t, wasm_functype_t, wasm_store_t, wasm_val_t};
use crate::{wasm_extern_t, wasm_functype_t, wasm_store_t, wasm_val_t, wasm_val_vec_t};
use crate::{wasm_name_t, wasm_trap_t, wasmtime_error_t};
use anyhow::anyhow;
use std::ffi::c_void;
Expand All @@ -21,26 +21,28 @@ pub struct wasmtime_caller_t<'a> {
caller: Caller<'a>,
}

pub type wasm_func_callback_t =
extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> Option<Box<wasm_trap_t>>;
pub type wasm_func_callback_t = extern "C" fn(
args: *const wasm_val_vec_t,
results: *mut wasm_val_vec_t,
) -> Option<Box<wasm_trap_t>>;

pub type wasm_func_callback_with_env_t = extern "C" fn(
env: *mut std::ffi::c_void,
args: *const wasm_val_t,
results: *mut wasm_val_t,
args: *const wasm_val_vec_t,
results: *mut wasm_val_vec_t,
) -> Option<Box<wasm_trap_t>>;

pub type wasmtime_func_callback_t = extern "C" fn(
caller: *const wasmtime_caller_t,
args: *const wasm_val_t,
results: *mut wasm_val_t,
args: *const wasm_val_vec_t,
results: *mut wasm_val_vec_t,
) -> Option<Box<wasm_trap_t>>;

pub type wasmtime_func_callback_with_env_t = extern "C" fn(
caller: *const wasmtime_caller_t,
env: *mut std::ffi::c_void,
args: *const wasm_val_t,
results: *mut wasm_val_t,
args: *const wasm_val_vec_t,
results: *mut wasm_val_vec_t,
) -> Option<Box<wasm_trap_t>>;

struct Finalizer {
Expand Down Expand Up @@ -83,21 +85,25 @@ impl From<Func> for wasm_func_t {
fn create_function(
store: &wasm_store_t,
ty: &wasm_functype_t,
func: impl Fn(Caller<'_>, *const wasm_val_t, *mut wasm_val_t) -> Option<Box<wasm_trap_t>> + 'static,
func: impl Fn(Caller<'_>, *const wasm_val_vec_t, *mut wasm_val_vec_t) -> Option<Box<wasm_trap_t>>
+ 'static,
) -> Box<wasm_func_t> {
let store = &store.store;
let ty = ty.ty().ty.clone();
let func = Func::new(store, ty, move |caller, params, results| {
let params = params
let params: wasm_val_vec_t = params
.iter()
.cloned()
.map(|p| wasm_val_t::from_val(p))
.collect::<Vec<_>>();
let mut out_results = vec![wasm_val_t::default(); results.len()];
let out = func(caller, params.as_ptr(), out_results.as_mut_ptr());
.collect::<Vec<_>>()
.into();
let mut out_results: wasm_val_vec_t = vec![wasm_val_t::default(); results.len()].into();
let out = func(caller, &params, &mut out_results);
if let Some(trap) = out {
return Err(trap.trap.clone());
}

let out_results = out_results.as_slice();
for i in 0..results.len() {
results[i] = out_results[i].val();
}
Expand Down Expand Up @@ -164,17 +170,14 @@ pub extern "C" fn wasmtime_func_new_with_env(
#[no_mangle]
pub unsafe extern "C" fn wasm_func_call(
wasm_func: &wasm_func_t,
args: *const wasm_val_t,
results: *mut MaybeUninit<wasm_val_t>,
args: *const wasm_val_vec_t,
results: *mut wasm_val_vec_t,
) -> *mut wasm_trap_t {
let func = wasm_func.func();
let mut trap = ptr::null_mut();
let error = wasmtime_func_call(
let error = _wasmtime_func_call(
wasm_func,
args,
func.param_arity(),
results,
func.result_arity(),
(*args).as_slice(),
(*results).as_uninit_slice(),
&mut trap,
);
match error {
Expand All @@ -186,16 +189,14 @@ pub unsafe extern "C" fn wasm_func_call(
#[no_mangle]
pub unsafe extern "C" fn wasmtime_func_call(
func: &wasm_func_t,
args: *const wasm_val_t,
num_args: usize,
results: *mut MaybeUninit<wasm_val_t>,
num_results: usize,
args: *const wasm_val_vec_t,
results: *mut wasm_val_vec_t,
trap_ptr: &mut *mut wasm_trap_t,
) -> Option<Box<wasmtime_error_t>> {
_wasmtime_func_call(
func,
std::slice::from_raw_parts(args, num_args),
std::slice::from_raw_parts_mut(results, num_results),
(*args).as_slice(),
(*results).as_uninit_slice(),
trap_ptr,
)
}
Expand Down
25 changes: 10 additions & 15 deletions crates/c-api/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,15 @@ impl wasm_instance_t {
pub unsafe extern "C" fn wasm_instance_new(
store: &wasm_store_t,
wasm_module: &wasm_module_t,
imports: *const Box<wasm_extern_t>,
imports: *const wasm_extern_vec_t,
result: Option<&mut *mut wasm_trap_t>,
) -> Option<Box<wasm_instance_t>> {
let mut instance = ptr::null_mut();
let mut trap = ptr::null_mut();
let err = wasmtime_instance_new(
let err = _wasmtime_instance_new(
store,
wasm_module,
imports,
wasm_module.module().imports().len(),
(*imports).as_slice(),
&mut instance,
&mut trap,
);
Expand Down Expand Up @@ -83,31 +82,27 @@ pub unsafe extern "C" fn wasm_instance_new(
pub unsafe extern "C" fn wasmtime_instance_new(
store: &wasm_store_t,
module: &wasm_module_t,
imports: *const Box<wasm_extern_t>,
num_imports: usize,
imports: *const wasm_extern_vec_t,
instance_ptr: &mut *mut wasm_instance_t,
trap_ptr: &mut *mut wasm_trap_t,
) -> Option<Box<wasmtime_error_t>> {
_wasmtime_instance_new(
store,
module,
std::slice::from_raw_parts(imports, num_imports),
instance_ptr,
trap_ptr,
)
_wasmtime_instance_new(store, module, (*imports).as_slice(), instance_ptr, trap_ptr)
}

fn _wasmtime_instance_new(
store: &wasm_store_t,
module: &wasm_module_t,
imports: &[Box<wasm_extern_t>],
imports: &[Option<Box<wasm_extern_t>>],
instance_ptr: &mut *mut wasm_instance_t,
trap_ptr: &mut *mut wasm_trap_t,
) -> Option<Box<wasmtime_error_t>> {
let store = &store.store;
let imports = imports
.iter()
.map(|import| import.which.clone())
.filter_map(|import| match import {
Some(i) => Some(i.which.clone()),
None => None,
})
.collect::<Vec<_>>();
handle_instantiate(
Instance::new(store, module.module(), &imports),
Expand Down
13 changes: 13 additions & 0 deletions crates/c-api/src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
wasm_moduletype_t, wasm_tabletype_t, wasm_val_t, wasm_valtype_t,
};
use std::mem;
use std::mem::MaybeUninit;
use std::ptr;
use std::slice;

Expand Down Expand Up @@ -54,6 +55,18 @@ macro_rules! declare_vecs {
}
}

pub fn as_uninit_slice(&mut self) -> &mut [MaybeUninit<$elem_ty>] {
// Note that we're careful to not create a slice with a null
// pointer as the data pointer, since that isn't defined
// behavior in Rust.
if self.size == 0 {
&mut []
} else {
assert!(!self.data.is_null());
unsafe { slice::from_raw_parts_mut(self.data as _, self.size) }
}
}

pub fn take(&mut self) -> Vec<$elem_ty> {
if self.data.is_null() {
return Vec::new();
Expand Down
11 changes: 6 additions & 5 deletions examples/externref.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ int main() {
printf("Instantiating module...\n");
wasm_trap_t *trap = NULL;
wasm_instance_t *instance = NULL;
error = wasmtime_instance_new(store, module, NULL, 0, &instance, &trap);
wasm_extern_vec_t imports = WASM_EMPTY_VEC;
error = wasmtime_instance_new(store, module, &imports, &instance, &trap);
if (instance == NULL)
exit_with_error("failed to instantiate", error, trap);

Expand Down Expand Up @@ -139,10 +140,11 @@ int main() {
assert(func != NULL);

// And call it!
wasm_val_t args[1];
wasm_val_copy(&args[0], &externref);
wasm_val_t args[1] = { externref };
wasm_val_t results[1];
error = wasmtime_func_call(func, args, 1, results, 1, &trap);
wasm_val_vec_t args_vec = WASM_ARRAY_VEC(args);
wasm_val_vec_t results_vec = WASM_ARRAY_VEC(results);
error = wasmtime_func_call(func, &args_vec, &results_vec, &trap);
if (error != NULL || trap != NULL)
exit_with_error("failed to call function", error, trap);

Expand All @@ -161,7 +163,6 @@ int main() {
ret = 0;

wasm_val_delete(&results[0]);
wasm_val_delete(&args[0]);
wasm_val_delete(&global_val);
wasm_val_delete(&elem);
wasm_extern_vec_delete(&externs);
Expand Down
9 changes: 6 additions & 3 deletions examples/fib-debug/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ int main(int argc, const char* argv[]) {
printf("Instantiating module...\n");
wasm_instance_t* instance = NULL;
wasm_trap_t *trap = NULL;
error = wasmtime_instance_new(store, module, NULL, 0, &instance, &trap);
wasm_extern_vec_t imports = WASM_EMPTY_VEC;
error = wasmtime_instance_new(store, module, &imports, &instance, &trap);
if (error != NULL || trap != NULL)
exit_with_error("failed to instantiate", error, trap);
wasm_module_delete(module);
Expand All @@ -95,9 +96,11 @@ int main(int argc, const char* argv[]) {

// Call.
printf("Calling fib...\n");
wasm_val_t params[1] = { {.kind = WASM_I32, .of = {.i32 = 6}} };
wasm_val_t params[1] = { WASM_I32_VAL(6) };
wasm_val_t results[1];
error = wasmtime_func_call(run_func, params, 1, results, 1, &trap);
wasm_val_vec_t params_vec = WASM_ARRAY_VEC(params);
wasm_val_vec_t results_vec = WASM_ARRAY_VEC(results);
error = wasmtime_func_call(run_func, &params_vec, &results_vec, &trap);
if (error != NULL || trap != NULL)
exit_with_error("failed to call function", error, trap);

Expand Down
13 changes: 6 additions & 7 deletions examples/gcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ int main() {
wasm_byte_vec_delete(&wasm);
wasm_trap_t *trap = NULL;
wasm_instance_t *instance = NULL;
error = wasmtime_instance_new(store, module, NULL, 0, &instance, &trap);
wasm_extern_vec_t imports = WASM_EMPTY_VEC;
error = wasmtime_instance_new(store, module, &imports, &instance, &trap);
if (instance == NULL)
exit_with_error("failed to instantiate", error, trap);

Expand All @@ -79,13 +80,11 @@ int main() {
// And call it!
int a = 6;
int b = 27;
wasm_val_t params[2];
wasm_val_t params[2] = { WASM_I32_VAL(a), WASM_I32_VAL(b) };
wasm_val_t results[1];
params[0].kind = WASM_I32;
params[0].of.i32 = a;
params[1].kind = WASM_I32;
params[1].of.i32 = b;
error = wasmtime_func_call(gcd, params, 2, results, 1, &trap);
wasm_val_vec_t params_vec = WASM_ARRAY_VEC(params);
wasm_val_vec_t results_vec = WASM_ARRAY_VEC(results);
error = wasmtime_func_call(gcd, &params_vec, &results_vec, &trap);
if (error != NULL || trap != NULL)
exit_with_error("failed to call gcd", error, trap);
assert(results[0].kind == WASM_I32);
Expand Down
Loading

0 comments on commit b9a0055

Please sign in to comment.