Skip to content

Commit

Permalink
Merge #1953
Browse files Browse the repository at this point in the history
1953: Get `multi.c` working in the Wasm C API r=MarkMcCaskey a=MarkMcCaskey

Gets the `multi.c` example working.

This PR has significant overlap with #1949 due to changes in vec / boxed vec.

Changes in this PR:
- impl `Clone` more often, implement `*_copy` functions in terms of `Clone`
- clean up boxed vec behavior
- add `*_vec_copy` functions for boxed and unboxed versions
- fix a typo in `wasm-c-api/examples/multi.c`; fixed in the upstream Wasm C API here: WebAssembly/wasm-c-api#163
- additional misc improvements

# Review

- [ ] Add a short description of the the change to the CHANGELOG.md file


Co-authored-by: Mark McCaskey <[email protected]>
Co-authored-by: Mark McCaskey <[email protected]>
  • Loading branch information
3 people authored Dec 21, 2020
2 parents 6f06fc2 + 8724ed9 commit 0a4a2c7
Show file tree
Hide file tree
Showing 11 changed files with 121 additions and 14 deletions.
1 change: 1 addition & 0 deletions lib/c-api/src/wasm_c_api/externals/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub use table::*;
use wasmer::{Extern, Instance};

#[allow(non_camel_case_types)]
#[derive(Clone)]
pub struct wasm_extern_t {
// this is how we ensure the instance stays alive
pub(crate) instance: Option<Arc<Instance>>,
Expand Down
81 changes: 77 additions & 4 deletions lib/c-api/src/wasm_c_api/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,33 @@ int main() {
pub data: *mut [<wasm_ $name _t>],
}

impl Clone for [<wasm_ $name _vec_t>] {
fn clone(&self) -> Self {
if self.data.is_null() {
return Self {
size: self.size,
data: ::std::ptr::null_mut(),
};
}
let data =
unsafe {
let vec = Vec::from_raw_parts(self.data, self.size, self.size);
let mut vec_copy = vec.clone().into_boxed_slice();
let new_ptr = vec_copy.as_mut_ptr();

::std::mem::forget(vec);
::std::mem::forget(vec_copy);

new_ptr
};

Self {
size: self.size,
data,
}
}
}

impl<'a> From<Vec<[<wasm_ $name _t>]>> for [<wasm_ $name _vec_t>] {
fn from(mut vec: Vec<[<wasm_ $name _t>]>) -> Self {
vec.shrink_to_fit();
Expand Down Expand Up @@ -195,6 +222,15 @@ int main() {
::std::mem::forget(bytes);
}

#[doc = "Performs a deep copy of a vector of [`wasm_" $name "_t`]."]
#[no_mangle]
pub unsafe extern "C" fn [<wasm_ $name _vec_copy>](
out_ptr: &mut [<wasm_ $name _vec_t>],
in_ptr: & [<wasm _$name _vec_t>])
{
*out_ptr = in_ptr.clone();
}

#[doc = "Deletes a vector of [`wasm_" $name "_t`].
# Example
Expand Down Expand Up @@ -231,6 +267,34 @@ Read the documentation of [`wasm_" $name "_t`] to see more concrete examples."]
pub data: *mut *mut [<wasm_ $name _t>],
}

impl Clone for [<wasm_ $name _vec_t>] {
fn clone(&self) -> Self {
if self.data.is_null() {
return Self {
size: self.size,
data: ::std::ptr::null_mut(),
};
}
let data =
unsafe {
let data: *mut Option<Box<[<wasm_ $name _t>]>> = self.data as _;
let vec = Vec::from_raw_parts(data, self.size, self.size);
let mut vec_copy = vec.clone().into_boxed_slice();
let new_ptr = vec_copy.as_mut_ptr() as *mut *mut [<wasm_ $name _t>];

::std::mem::forget(vec);
::std::mem::forget(vec_copy);

new_ptr
};

Self {
size: self.size,
data,
}
}
}

impl<'a> From<Vec<Box<[<wasm_ $name _t>]>>> for [<wasm_ $name _vec_t>] {
fn from(other: Vec<Box<[<wasm_ $name _t>]>>) -> Self {
let boxed_slice: Box<[Box<[<wasm_ $name _t>]>]> = other.into_boxed_slice();
Expand Down Expand Up @@ -290,13 +354,13 @@ Read the documentation of [`wasm_" $name "_t`] to see more concrete examples."]
bytes.push(*init.add(i));
}

let pointer = bytes.as_mut_ptr();
debug_assert!(bytes.len() == bytes.capacity());
let mut boxed_vec = bytes.into_boxed_slice();
let pointer = boxed_vec.as_mut_ptr();

(*out).data = pointer;
(*out).size = length;

::std::mem::forget(bytes);
::std::mem::forget(boxed_vec);
}

#[doc = "Creates a new uninitialized vector of [`wasm_" $name "_t`].
Expand Down Expand Up @@ -335,14 +399,23 @@ int main() {
::std::mem::forget(bytes);
}

#[doc = "Performs a deep copy of a vector of [`wasm_" $name "_t`]."]
#[no_mangle]
pub unsafe extern "C" fn [<wasm_ $name _vec_copy>](
out_ptr: &mut [<wasm_ $name _vec_t>],
in_ptr: & [<wasm _$name _vec_t>])
{
*out_ptr = in_ptr.clone();
}

#[doc = "Deletes a vector of [`wasm_" $name "_t`].
# Example
See the [`wasm_" $name "_vec_t`] type to get an example."]
#[no_mangle]
pub unsafe extern "C" fn [<wasm_ $name _vec_delete>](ptr: Option<&mut [<wasm_ $name _vec_t>]>) {
if let Some(vec) = ptr {
if let Some(vec) = ptr {
if !vec.data.is_null() {
let data = vec.data as *mut Option<Box<[<wasm_ $name _t>]>>;
let _data: Vec<Option<Box<[<wasm_ $name _t>]>>> = Vec::from_raw_parts(data, vec.size, vec.size);
Expand Down
1 change: 1 addition & 0 deletions lib/c-api/src/wasm_c_api/types/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::{wasm_externtype_t, wasm_name_t};
use wasmer::ExportType;

#[allow(non_camel_case_types)]
#[derive(Clone)]
pub struct wasm_exporttype_t {
name: Box<wasm_name_t>,
extern_type: Box<wasm_externtype_t>,
Expand Down
6 changes: 2 additions & 4 deletions lib/c-api/src/wasm_c_api/types/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl Clone for WasmFunctionType {
}

#[allow(non_camel_case_types)]
#[derive(Debug)]
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct wasm_functype_t {
pub(crate) extern_type: wasm_externtype_t,
Expand Down Expand Up @@ -90,9 +90,7 @@ pub unsafe extern "C" fn wasm_functype_copy(
) -> Option<Box<wasm_functype_t>> {
let function_type = function_type?;

Some(Box::new(wasm_functype_t::new(
function_type.inner().function_type.clone(),
)))
Some(Box::new(function_type.clone()))
}

#[no_mangle]
Expand Down
2 changes: 1 addition & 1 deletion lib/c-api/src/wasm_c_api/types/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl WasmGlobalType {
}

#[allow(non_camel_case_types)]
#[derive(Debug)]
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct wasm_globaltype_t {
pub(crate) extern_type: wasm_externtype_t,
Expand Down
1 change: 1 addition & 0 deletions lib/c-api/src/wasm_c_api/types/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::{wasm_externtype_t, wasm_name_t};
use wasmer::ImportType;

#[allow(non_camel_case_types)]
#[derive(Clone)]
pub struct wasm_importtype_t {
module: Box<wasm_name_t>,
name: Box<wasm_name_t>,
Expand Down
2 changes: 1 addition & 1 deletion lib/c-api/src/wasm_c_api/types/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl WasmMemoryType {
}

#[allow(non_camel_case_types)]
#[derive(Debug)]
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct wasm_memorytype_t {
pub(crate) extern_type: wasm_externtype_t,
Expand Down
2 changes: 1 addition & 1 deletion lib/c-api/src/wasm_c_api/types/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl WasmTableType {
}

#[allow(non_camel_case_types)]
#[derive(Debug)]
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct wasm_tabletype_t {
pub(crate) extern_type: wasm_externtype_t,
Expand Down
33 changes: 33 additions & 0 deletions lib/c-api/src/wasm_c_api/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,39 @@ pub struct wasm_val_t {
pub of: wasm_val_inner,
}

impl std::fmt::Debug for wasm_val_t {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let mut ds = f.debug_struct("wasm_val_t");
ds.field("kind", &self.kind);

match self.kind.try_into() {
Ok(wasm_valkind_enum::WASM_I32) => {
ds.field("i32", &unsafe { self.of.int32_t });
}
Ok(wasm_valkind_enum::WASM_I64) => {
ds.field("i64", &unsafe { self.of.int64_t });
}
Ok(wasm_valkind_enum::WASM_F32) => {
ds.field("f32", &unsafe { self.of.float32_t });
}
Ok(wasm_valkind_enum::WASM_F64) => {
ds.field("f64", &unsafe { self.of.float64_t });
}
Ok(wasm_valkind_enum::WASM_ANYREF) => {
ds.field("anyref", &unsafe { self.of.wref });
}

Ok(wasm_valkind_enum::WASM_FUNCREF) => {
ds.field("funcref", &unsafe { self.of.wref });
}
Err(_) => {
ds.field("value", &"Invalid value type");
}
}
ds.finish()
}
}

wasm_declare_vec!(val);

impl Clone for wasm_val_t {
Expand Down
4 changes: 2 additions & 2 deletions lib/c-api/tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ CAPI_WASMER_TESTS = \
CAPI_BASE_TESTS = \
wasm-c-api/example/callback wasm-c-api/example/global wasm-c-api/example/hello \
wasm-c-api/example/memory wasm-c-api/example/reflect wasm-c-api/example/serialize \
wasm-c-api/example/start wasm-c-api/example/trap
wasm-c-api/example/start wasm-c-api/example/trap wasm-c-api/example/multi

CAPI_BASE_TESTS_NOT_WORKING = \
wasm-c-api/example/finalize wasm-c-api/example/hostref wasm-c-api/example/multi \
wasm-c-api/example/finalize wasm-c-api/example/hostref \
wasm-c-api/example/table wasm-c-api/example/threads

DEPRECATED_TESTS = \
Expand Down
2 changes: 1 addition & 1 deletion lib/c-api/tests/wasm-c-api/example/multi.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ int main(int argc, const char* argv[]) {
// Call.
printf("Calling export...\n");
wasm_val_t vals[4] = {
WASM_I32_VAL(1), WASM_I32_VAL(2), WASM_I32_VAL(3), WASM_I32_VAL(4)
WASM_I32_VAL(1), WASM_I64_VAL(2), WASM_I64_VAL(3), WASM_I32_VAL(4)
};
wasm_val_t res[4] = {
WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL
Expand Down

0 comments on commit 0a4a2c7

Please sign in to comment.