From 49c01f609356ce005f46b8723421a98785b1756a Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 29 Mar 2019 14:40:26 +0100 Subject: [PATCH 01/12] feat(runtime-c-api) Extract the `value` module. --- lib/runtime-c-api/src/lib.rs | 30 ++++-------------------------- lib/runtime-c-api/src/value.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 26 deletions(-) create mode 100644 lib/runtime-c-api/src/value.rs diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 80774ce610e..4cd51d13028 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -21,6 +21,10 @@ use wasmer_runtime_core::module::{ExportIndex, ImportName}; use wasmer_runtime_core::types::{ElementType, FuncSig, MemoryDescriptor, TableDescriptor, Type}; use wasmer_runtime_core::units::{Bytes, Pages}; +pub mod value; + +use value::{wasmer_value, wasmer_value_t, wasmer_value_tag}; + #[repr(C)] pub struct wasmer_module_t; @@ -40,32 +44,6 @@ pub enum wasmer_result_t { WASMER_ERROR = 2, } -#[allow(non_camel_case_types)] -#[repr(u32)] -#[derive(Clone)] -pub enum wasmer_value_tag { - WASM_I32, - WASM_I64, - WASM_F32, - WASM_F64, -} - -#[repr(C)] -#[derive(Clone, Copy)] -pub union wasmer_value { - I32: int32_t, - I64: int64_t, - F32: f32, - F64: f64, -} - -#[repr(C)] -#[derive(Clone)] -pub struct wasmer_value_t { - tag: wasmer_value_tag, - value: wasmer_value, -} - #[repr(C)] #[derive(Clone)] pub struct wasmer_global_descriptor_t { diff --git a/lib/runtime-c-api/src/value.rs b/lib/runtime-c-api/src/value.rs new file mode 100644 index 00000000000..fc4e791a064 --- /dev/null +++ b/lib/runtime-c-api/src/value.rs @@ -0,0 +1,29 @@ +//! Wasm values. + +use libc::{int32_t, int64_t}; + +#[allow(non_camel_case_types)] +#[repr(u32)] +#[derive(Clone)] +pub enum wasmer_value_tag { + WASM_I32, + WASM_I64, + WASM_F32, + WASM_F64, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union wasmer_value { + pub I32: int32_t, + pub I64: int64_t, + pub F32: f32, + pub F64: f64, +} + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_value_t { + pub tag: wasmer_value_tag, + pub value: wasmer_value, +} From 96324977b5fb5a6cb6f0c604026b5d76c19708cc Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 29 Mar 2019 14:41:39 +0100 Subject: [PATCH 02/12] feat(runtime-c-api) Extract the `error` module. --- lib/runtime-c-api/src/error.rs | 102 +++++++++++++++++++++++++++++++++ lib/runtime-c-api/src/lib.rs | 98 +------------------------------ 2 files changed, 104 insertions(+), 96 deletions(-) create mode 100644 lib/runtime-c-api/src/error.rs diff --git a/lib/runtime-c-api/src/error.rs b/lib/runtime-c-api/src/error.rs new file mode 100644 index 00000000000..5980c79a9eb --- /dev/null +++ b/lib/runtime-c-api/src/error.rs @@ -0,0 +1,102 @@ +//! Errors. + +use libc::{c_char, c_int}; +use std::cell::RefCell; +use std::error::Error; +use std::fmt::{self, Display, Formatter}; +use std::ptr; +use std::slice; + +thread_local! { + static LAST_ERROR: RefCell>> = RefCell::new(None); +} + +pub(crate) fn update_last_error(err: E) { + LAST_ERROR.with(|prev| { + *prev.borrow_mut() = Some(Box::new(err)); + }); +} + +/// Retrieve the most recent error, clearing it in the process. +pub(crate) fn take_last_error() -> Option> { + LAST_ERROR.with(|prev| prev.borrow_mut().take()) +} + +/// Gets the length in bytes of the last error. +/// This can be used to dynamically allocate a buffer with the correct number of +/// bytes needed to store a message. +/// +/// # Example +/// +/// ```c +/// int error_len = wasmer_last_error_length(); +/// char *error_str = malloc(error_len); +/// ``` +#[no_mangle] +pub extern "C" fn wasmer_last_error_length() -> c_int { + LAST_ERROR.with(|prev| match *prev.borrow() { + Some(ref err) => err.to_string().len() as c_int + 1, + None => 0, + }) +} + +/// Stores the last error message into the provided buffer up to the given `length`. +/// The `length` parameter must be large enough to store the last error message. +/// +/// Returns the length of the string in bytes. +/// Returns `-1` if an error occurs. +/// +/// # Example +/// +/// ```c +/// int error_len = wasmer_last_error_length(); +/// char *error_str = malloc(error_len); +/// wasmer_last_error_message(error_str, error_len); +/// printf("Error str: `%s`\n", error_str); +/// ``` +#[no_mangle] +pub unsafe extern "C" fn wasmer_last_error_message(buffer: *mut c_char, length: c_int) -> c_int { + if buffer.is_null() { + // buffer pointer is null + return -1; + } + + let last_error = match take_last_error() { + Some(err) => err, + None => return 0, + }; + + let error_message = last_error.to_string(); + + let buffer = slice::from_raw_parts_mut(buffer as *mut u8, length as usize); + + if error_message.len() >= buffer.len() { + // buffer to small for err message + return -1; + } + + ptr::copy_nonoverlapping( + error_message.as_ptr(), + buffer.as_mut_ptr(), + error_message.len(), + ); + + // Add a trailing null so people using the string as a `char *` don't + // accidentally read into garbage. + buffer[error_message.len()] = 0; + + error_message.len() as c_int +} + +#[derive(Debug)] +pub(crate) struct CApiError { + pub(crate) msg: String, +} + +impl Display for CApiError { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}", &self.msg) + } +} + +impl Error for CApiError {} diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 4cd51d13028..06334b6210d 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -21,8 +21,10 @@ use wasmer_runtime_core::module::{ExportIndex, ImportName}; use wasmer_runtime_core::types::{ElementType, FuncSig, MemoryDescriptor, TableDescriptor, Type}; use wasmer_runtime_core::units::{Bytes, Pages}; +pub mod error; pub mod value; +use error::{update_last_error, CApiError}; use value::{wasmer_value, wasmer_value_t, wasmer_value_tag}; #[repr(C)] @@ -1644,102 +1646,6 @@ impl From<(&std::string::String, &ExportIndex)> for NamedExportDescriptor { } } -// Error reporting - -thread_local! { - static LAST_ERROR: RefCell>> = RefCell::new(None); -} - -fn update_last_error(err: E) { - LAST_ERROR.with(|prev| { - *prev.borrow_mut() = Some(Box::new(err)); - }); -} - -/// Retrieve the most recent error, clearing it in the process. -fn take_last_error() -> Option> { - LAST_ERROR.with(|prev| prev.borrow_mut().take()) -} - -/// Gets the length in bytes of the last error. -/// This can be used to dynamically allocate a buffer with the correct number of -/// bytes needed to store a message. -/// -/// # Example -/// -/// ```c -/// int error_len = wasmer_last_error_length(); -/// char *error_str = malloc(error_len); -/// ``` -#[no_mangle] -pub extern "C" fn wasmer_last_error_length() -> c_int { - LAST_ERROR.with(|prev| match *prev.borrow() { - Some(ref err) => err.to_string().len() as c_int + 1, - None => 0, - }) -} - -/// Stores the last error message into the provided buffer up to the given `length`. -/// The `length` parameter must be large enough to store the last error message. -/// -/// Returns the length of the string in bytes. -/// Returns `-1` if an error occurs. -/// -/// # Example -/// -/// ```c -/// int error_len = wasmer_last_error_length(); -/// char *error_str = malloc(error_len); -/// wasmer_last_error_message(error_str, error_len); -/// printf("Error str: `%s`\n", error_str); -/// ``` -#[no_mangle] -pub unsafe extern "C" fn wasmer_last_error_message(buffer: *mut c_char, length: c_int) -> c_int { - if buffer.is_null() { - // buffer pointer is null - return -1; - } - - let last_error = match take_last_error() { - Some(err) => err, - None => return 0, - }; - - let error_message = last_error.to_string(); - - let buffer = slice::from_raw_parts_mut(buffer as *mut u8, length as usize); - - if error_message.len() >= buffer.len() { - // buffer to small for err message - return -1; - } - - ptr::copy_nonoverlapping( - error_message.as_ptr(), - buffer.as_mut_ptr(), - error_message.len(), - ); - - // Add a trailing null so people using the string as a `char *` don't - // accidentally read into garbage. - buffer[error_message.len()] = 0; - - error_message.len() as c_int -} - -#[derive(Debug)] -struct CApiError { - msg: String, -} - -impl fmt::Display for CApiError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", &self.msg) - } -} - -impl Error for CApiError {} - struct NamedImportDescriptor { module: String, name: String, From 168aa8031fbaa7f39cc48f9e8e2d8f16e7ba9666 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 29 Mar 2019 14:50:34 +0100 Subject: [PATCH 03/12] feat(runtime-c-api) Extract the `module` module. --- lib/runtime-c-api/src/lib.rs | 275 +------------------------------- lib/runtime-c-api/src/module.rs | 272 +++++++++++++++++++++++++++++++ 2 files changed, 277 insertions(+), 270 deletions(-) create mode 100644 lib/runtime-c-api/src/module.rs diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 06334b6210d..8148073e9e7 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -1,38 +1,28 @@ extern crate wasmer_runtime; extern crate wasmer_runtime_core; -use libc::{c_char, c_int, int32_t, int64_t, uint32_t, uint8_t}; -use std::cell::{Cell, RefCell}; +use libc::{c_char, c_int, uint32_t, uint8_t}; +use std::cell::Cell; use std::collections::HashMap; -use std::error::Error; use std::ffi::CStr; -use std::fmt; use std::slice; use std::sync::Arc; use std::{ffi::c_void, ptr}; -use wasmer_runtime::{ - default_compiler, Ctx, Global, ImportObject, Instance, Memory, Module, Table, Value, -}; -use wasmer_runtime_core::cache::Artifact; +use wasmer_runtime::{Ctx, Global, ImportObject, Instance, Memory, Module, Table, Value}; use wasmer_runtime_core::export::{Context, Export, FuncPointer}; use wasmer_runtime_core::import::Namespace; -use wasmer_runtime_core::load_cache_with; use wasmer_runtime_core::module::{ExportIndex, ImportName}; use wasmer_runtime_core::types::{ElementType, FuncSig, MemoryDescriptor, TableDescriptor, Type}; use wasmer_runtime_core::units::{Bytes, Pages}; pub mod error; +pub mod module; pub mod value; use error::{update_last_error, CApiError}; +use module::wasmer_module_t; use value::{wasmer_value, wasmer_value_t, wasmer_value_tag}; -#[repr(C)] -pub struct wasmer_module_t; - -#[repr(C)] -pub struct wasmer_serialized_module_t; - #[repr(C)] pub struct wasmer_instance_t; @@ -365,114 +355,6 @@ pub extern "C" fn wasmer_memory_destroy(memory: *mut wasmer_memory_t) { } } -/// Creates a new Module from the given wasm bytes. -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_compile( - module: *mut *mut wasmer_module_t, - wasm_bytes: *mut uint8_t, - wasm_bytes_len: uint32_t, -) -> wasmer_result_t { - let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize); - let result = wasmer_runtime::compile(bytes); - let new_module = match result { - Ok(instance) => instance, - Err(error) => { - update_last_error(error); - return wasmer_result_t::WASMER_ERROR; - } - }; - *module = Box::into_raw(Box::new(new_module)) as *mut wasmer_module_t; - wasmer_result_t::WASMER_OK -} - -/// Creates a new Instance from the given module and imports. -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_module_instantiate( - module: *const wasmer_module_t, - instance: *mut *mut wasmer_instance_t, - imports: *mut wasmer_import_t, - imports_len: c_int, -) -> wasmer_result_t { - let imports: &[wasmer_import_t] = slice::from_raw_parts(imports, imports_len as usize); - let mut import_object = ImportObject::new(); - let mut namespaces = HashMap::new(); - for import in imports { - let module_name = slice::from_raw_parts( - import.module_name.bytes, - import.module_name.bytes_len as usize, - ); - let module_name = if let Ok(s) = std::str::from_utf8(module_name) { - s - } else { - update_last_error(CApiError { - msg: "error converting module name to string".to_string(), - }); - return wasmer_result_t::WASMER_ERROR; - }; - let import_name = slice::from_raw_parts( - import.import_name.bytes, - import.import_name.bytes_len as usize, - ); - let import_name = if let Ok(s) = std::str::from_utf8(import_name) { - s - } else { - update_last_error(CApiError { - msg: "error converting import_name to string".to_string(), - }); - return wasmer_result_t::WASMER_ERROR; - }; - - let namespace = namespaces.entry(module_name).or_insert_with(Namespace::new); - - let export = match import.tag { - wasmer_import_export_kind::WASM_MEMORY => { - let mem = import.value.memory as *mut Memory; - Export::Memory((&*mem).clone()) - } - wasmer_import_export_kind::WASM_FUNCTION => { - let func_export = import.value.func as *mut Export; - (&*func_export).clone() - } - wasmer_import_export_kind::WASM_GLOBAL => { - let global = import.value.global as *mut Global; - Export::Global((&*global).clone()) - } - wasmer_import_export_kind::WASM_TABLE => { - let table = import.value.table as *mut Table; - Export::Table((&*table).clone()) - } - }; - namespace.insert(import_name, export); - } - for (module_name, namespace) in namespaces.into_iter() { - import_object.register(module_name, namespace); - } - - let module = &*(module as *const Module); - let new_instance = if let Ok(res) = module.instantiate(&import_object) { - res - } else { - update_last_error(CApiError { - msg: "error instantiating from module".to_string(), - }); - return wasmer_result_t::WASMER_ERROR; - }; - *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t; - wasmer_result_t::WASMER_OK -} - /// Gets export descriptors for the given module /// /// The caller owns the object and should call `wasmer_export_descriptors_destroy` to free it. @@ -554,153 +436,6 @@ pub unsafe extern "C" fn wasmer_export_descriptor_kind( named_export_descriptor.kind.clone() } -/// Serialize the given Module. -/// -/// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it. -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_module_serialize( - serialized_module: *mut *mut wasmer_serialized_module_t, - module: *const wasmer_module_t, -) -> wasmer_result_t { - let module = &*(module as *const Module); - - match module.cache() { - Ok(artifact) => match artifact.serialize() { - Ok(serialized_artifact) => { - *serialized_module = Box::into_raw(Box::new(serialized_artifact)) as _; - - wasmer_result_t::WASMER_OK - } - Err(_) => { - update_last_error(CApiError { - msg: "Failed to serialize the module artifact".to_string(), - }); - wasmer_result_t::WASMER_ERROR - } - }, - Err(_) => { - update_last_error(CApiError { - msg: "Failed to serialize the module".to_string(), - }); - wasmer_result_t::WASMER_ERROR - } - } -} - -/// Get bytes of the serialized module. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_serialized_module_bytes( - serialized_module: *const wasmer_serialized_module_t, -) -> wasmer_byte_array { - let serialized_module = &*(serialized_module as *const &[u8]); - - wasmer_byte_array { - bytes: serialized_module.as_ptr(), - bytes_len: serialized_module.len() as u32, - } -} - -/// Transform a sequence of bytes into a serialized module. -/// -/// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it. -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_serialized_module_from_bytes( - serialized_module: *mut *mut wasmer_serialized_module_t, - serialized_module_bytes: *const uint8_t, - serialized_module_bytes_length: uint32_t, -) -> wasmer_result_t { - if serialized_module.is_null() { - update_last_error(CApiError { - msg: "`serialized_module_bytes` pointer is null".to_string(), - }); - return wasmer_result_t::WASMER_ERROR; - } - - let serialized_module_bytes: &[u8] = slice::from_raw_parts( - serialized_module_bytes, - serialized_module_bytes_length as usize, - ); - - *serialized_module = Box::into_raw(Box::new(serialized_module_bytes)) as _; - wasmer_result_t::WASMER_OK -} - -/// Deserialize the given serialized module. -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_module_deserialize( - module: *mut *mut wasmer_module_t, - serialized_module: *const wasmer_serialized_module_t, -) -> wasmer_result_t { - if serialized_module.is_null() { - update_last_error(CApiError { - msg: "`serialized_module` pointer is null".to_string(), - }); - return wasmer_result_t::WASMER_ERROR; - } - - let serialized_module: &[u8] = &*(serialized_module as *const &[u8]); - - match Artifact::deserialize(serialized_module) { - Ok(artifact) => match load_cache_with(artifact, default_compiler()) { - Ok(deserialized_module) => { - *module = Box::into_raw(Box::new(deserialized_module)) as _; - wasmer_result_t::WASMER_OK - } - Err(_) => { - update_last_error(CApiError { - msg: "Failed to compile the serialized module".to_string(), - }); - wasmer_result_t::WASMER_ERROR - } - }, - Err(_) => { - update_last_error(CApiError { - msg: "Failed to deserialize the module".to_string(), - }); - wasmer_result_t::WASMER_ERROR - } - } -} - -/// Frees memory for the given serialized Module. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_serialized_module_destroy( - serialized_module: *mut wasmer_serialized_module_t, -) { - if !serialized_module.is_null() { - unsafe { Box::from_raw(serialized_module as *mut &[u8]) }; - } -} - -/// Frees memory for the given Module -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_module_destroy(module: *mut wasmer_module_t) { - if !module.is_null() { - unsafe { Box::from_raw(module as *mut Module) }; - } -} - /// Gets import descriptors for the given module /// /// The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it. diff --git a/lib/runtime-c-api/src/module.rs b/lib/runtime-c-api/src/module.rs new file mode 100644 index 00000000000..58585dd25cf --- /dev/null +++ b/lib/runtime-c-api/src/module.rs @@ -0,0 +1,272 @@ +//! Wasm module. + +use crate::{ + error::{update_last_error, CApiError}, + wasmer_byte_array, wasmer_import_export_kind, wasmer_import_t, wasmer_instance_t, + wasmer_result_t, +}; +use libc::{c_int, uint32_t, uint8_t}; +use std::{collections::HashMap, slice}; +use wasmer_runtime::{compile, default_compiler, Global, ImportObject, Memory, Module, Table}; +use wasmer_runtime_core::{cache::Artifact, export::Export, import::Namespace, load_cache_with}; + +#[repr(C)] +pub struct wasmer_module_t; + +#[repr(C)] +pub struct wasmer_serialized_module_t; + +/// Creates a new Module from the given wasm bytes. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_compile( + module: *mut *mut wasmer_module_t, + wasm_bytes: *mut uint8_t, + wasm_bytes_len: uint32_t, +) -> wasmer_result_t { + let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize); + let result = compile(bytes); + let new_module = match result { + Ok(instance) => instance, + Err(error) => { + update_last_error(error); + return wasmer_result_t::WASMER_ERROR; + } + }; + *module = Box::into_raw(Box::new(new_module)) as *mut wasmer_module_t; + wasmer_result_t::WASMER_OK +} + +/// Creates a new Instance from the given module and imports. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_module_instantiate( + module: *const wasmer_module_t, + instance: *mut *mut wasmer_instance_t, + imports: *mut wasmer_import_t, + imports_len: c_int, +) -> wasmer_result_t { + let imports: &[wasmer_import_t] = slice::from_raw_parts(imports, imports_len as usize); + let mut import_object = ImportObject::new(); + let mut namespaces = HashMap::new(); + for import in imports { + let module_name = slice::from_raw_parts( + import.module_name.bytes, + import.module_name.bytes_len as usize, + ); + let module_name = if let Ok(s) = std::str::from_utf8(module_name) { + s + } else { + update_last_error(CApiError { + msg: "error converting module name to string".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + }; + let import_name = slice::from_raw_parts( + import.import_name.bytes, + import.import_name.bytes_len as usize, + ); + let import_name = if let Ok(s) = std::str::from_utf8(import_name) { + s + } else { + update_last_error(CApiError { + msg: "error converting import_name to string".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + }; + + let namespace = namespaces.entry(module_name).or_insert_with(Namespace::new); + + let export = match import.tag { + wasmer_import_export_kind::WASM_MEMORY => { + let mem = import.value.memory as *mut Memory; + Export::Memory((&*mem).clone()) + } + wasmer_import_export_kind::WASM_FUNCTION => { + let func_export = import.value.func as *mut Export; + (&*func_export).clone() + } + wasmer_import_export_kind::WASM_GLOBAL => { + let global = import.value.global as *mut Global; + Export::Global((&*global).clone()) + } + wasmer_import_export_kind::WASM_TABLE => { + let table = import.value.table as *mut Table; + Export::Table((&*table).clone()) + } + }; + namespace.insert(import_name, export); + } + for (module_name, namespace) in namespaces.into_iter() { + import_object.register(module_name, namespace); + } + + let module = &*(module as *const Module); + let new_instance = if let Ok(res) = module.instantiate(&import_object) { + res + } else { + update_last_error(CApiError { + msg: "error instantiating from module".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + }; + *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t; + wasmer_result_t::WASMER_OK +} + +/// Serialize the given Module. +/// +/// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_module_serialize( + serialized_module: *mut *mut wasmer_serialized_module_t, + module: *const wasmer_module_t, +) -> wasmer_result_t { + let module = &*(module as *const Module); + + match module.cache() { + Ok(artifact) => match artifact.serialize() { + Ok(serialized_artifact) => { + *serialized_module = Box::into_raw(Box::new(serialized_artifact)) as _; + + wasmer_result_t::WASMER_OK + } + Err(_) => { + update_last_error(CApiError { + msg: "Failed to serialize the module artifact".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } + }, + Err(_) => { + update_last_error(CApiError { + msg: "Failed to serialize the module".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } + } +} + +/// Get bytes of the serialized module. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_serialized_module_bytes( + serialized_module: *const wasmer_serialized_module_t, +) -> wasmer_byte_array { + let serialized_module = &*(serialized_module as *const &[u8]); + + wasmer_byte_array { + bytes: serialized_module.as_ptr(), + bytes_len: serialized_module.len() as u32, + } +} + +/// Transform a sequence of bytes into a serialized module. +/// +/// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_serialized_module_from_bytes( + serialized_module: *mut *mut wasmer_serialized_module_t, + serialized_module_bytes: *const uint8_t, + serialized_module_bytes_length: uint32_t, +) -> wasmer_result_t { + if serialized_module.is_null() { + update_last_error(CApiError { + msg: "`serialized_module_bytes` pointer is null".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + } + + let serialized_module_bytes: &[u8] = slice::from_raw_parts( + serialized_module_bytes, + serialized_module_bytes_length as usize, + ); + + *serialized_module = Box::into_raw(Box::new(serialized_module_bytes)) as _; + wasmer_result_t::WASMER_OK +} + +/// Deserialize the given serialized module. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_module_deserialize( + module: *mut *mut wasmer_module_t, + serialized_module: *const wasmer_serialized_module_t, +) -> wasmer_result_t { + if serialized_module.is_null() { + update_last_error(CApiError { + msg: "`serialized_module` pointer is null".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + } + + let serialized_module: &[u8] = &*(serialized_module as *const &[u8]); + + match Artifact::deserialize(serialized_module) { + Ok(artifact) => match load_cache_with(artifact, default_compiler()) { + Ok(deserialized_module) => { + *module = Box::into_raw(Box::new(deserialized_module)) as _; + wasmer_result_t::WASMER_OK + } + Err(_) => { + update_last_error(CApiError { + msg: "Failed to compile the serialized module".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } + }, + Err(_) => { + update_last_error(CApiError { + msg: "Failed to deserialize the module".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } + } +} + +/// Frees memory for the given serialized Module. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_serialized_module_destroy( + serialized_module: *mut wasmer_serialized_module_t, +) { + if !serialized_module.is_null() { + unsafe { Box::from_raw(serialized_module as *mut &[u8]) }; + } +} + +/// Frees memory for the given Module +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_module_destroy(module: *mut wasmer_module_t) { + if !module.is_null() { + unsafe { Box::from_raw(module as *mut Module) }; + } +} From 55c010688c999658ba7d979eb76d45aa599fab20 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 29 Mar 2019 14:57:08 +0100 Subject: [PATCH 04/12] feat(runtime-c-api) Extract the `memory` module. --- lib/runtime-c-api/src/lib.rs | 104 +----------------------------- lib/runtime-c-api/src/memory.rs | 108 ++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 101 deletions(-) create mode 100644 lib/runtime-c-api/src/memory.rs diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 8148073e9e7..e0cad3f8619 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -2,7 +2,6 @@ extern crate wasmer_runtime; extern crate wasmer_runtime_core; use libc::{c_char, c_int, uint32_t, uint8_t}; -use std::cell::Cell; use std::collections::HashMap; use std::ffi::CStr; use std::slice; @@ -12,14 +11,15 @@ use wasmer_runtime::{Ctx, Global, ImportObject, Instance, Memory, Module, Table, use wasmer_runtime_core::export::{Context, Export, FuncPointer}; use wasmer_runtime_core::import::Namespace; use wasmer_runtime_core::module::{ExportIndex, ImportName}; -use wasmer_runtime_core::types::{ElementType, FuncSig, MemoryDescriptor, TableDescriptor, Type}; -use wasmer_runtime_core::units::{Bytes, Pages}; +use wasmer_runtime_core::types::{ElementType, FuncSig, TableDescriptor, Type}; pub mod error; +pub mod memory; pub mod module; pub mod value; use error::{update_last_error, CApiError}; +use memory::wasmer_memory_t; use module::wasmer_module_t; use value::{wasmer_value, wasmer_value_t, wasmer_value_tag}; @@ -43,10 +43,6 @@ pub struct wasmer_global_descriptor_t { kind: wasmer_value_tag, } -#[repr(C)] -#[derive(Clone)] -pub struct wasmer_memory_t; - #[repr(C)] #[derive(Clone)] pub struct wasmer_table_t; @@ -147,74 +143,6 @@ pub unsafe extern "C" fn wasmer_validate( wasmer_runtime_core::validate(bytes) } -/// Creates a new Memory for the given descriptor and initializes the given -/// pointer to pointer to a pointer to the new memory. -/// -/// The caller owns the object and should call `wasmer_memory_destroy` to free it. -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[no_mangle] -pub unsafe extern "C" fn wasmer_memory_new( - memory: *mut *mut wasmer_memory_t, - limits: wasmer_limits_t, -) -> wasmer_result_t { - let max = if limits.max.has_some { - Some(Pages(limits.max.some)) - } else { - None - }; - let desc = MemoryDescriptor { - minimum: Pages(limits.min), - maximum: max, - shared: false, - }; - let result = Memory::new(desc); - let new_memory = match result { - Ok(memory) => memory, - Err(error) => { - update_last_error(error); - return wasmer_result_t::WASMER_ERROR; - } - }; - *memory = Box::into_raw(Box::new(new_memory)) as *mut wasmer_memory_t; - wasmer_result_t::WASMER_OK -} - -/// Grows a Memory by the given number of pages. -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_memory_grow( - memory: *mut wasmer_memory_t, - delta: uint32_t, -) -> wasmer_result_t { - let memory = unsafe { &*(memory as *mut Memory) }; - let delta_result = memory.grow(Pages(delta)); - match delta_result { - Ok(_) => wasmer_result_t::WASMER_OK, - Err(grow_error) => { - update_last_error(grow_error); - wasmer_result_t::WASMER_ERROR - } - } -} - -/// Returns the current length in pages of the given memory -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_memory_length(memory: *const wasmer_memory_t) -> uint32_t { - let memory = unsafe { &*(memory as *const Memory) }; - let Pages(len) = memory.size(); - len -} - /// Creates a new Table for the given descriptor and initializes the given /// pointer to pointer to a pointer to the new Table. /// @@ -346,15 +274,6 @@ pub extern "C" fn wasmer_global_destroy(global: *mut wasmer_global_t) { } } -/// Frees memory for the given Memory -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_memory_destroy(memory: *mut wasmer_memory_t) { - if !memory.is_null() { - unsafe { Box::from_raw(memory as *mut Memory) }; - } -} - /// Gets export descriptors for the given module /// /// The caller owns the object and should call `wasmer_export_descriptors_destroy` to free it. @@ -1256,23 +1175,6 @@ pub extern "C" fn wasmer_instance_context_data_get( ctx.data } -/// Gets the start pointer to the bytes within a Memory -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_memory_data(mem: *const wasmer_memory_t) -> *mut uint8_t { - let memory = unsafe { &*(mem as *const Memory) }; - memory.view::()[..].as_ptr() as *mut Cell as *mut u8 -} - -/// Gets the size in bytes of a Memory -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_memory_data_length(mem: *mut wasmer_memory_t) -> uint32_t { - let memory = mem as *mut Memory; - let Bytes(len) = unsafe { (*memory).size().bytes() }; - len as uint32_t -} - /// Frees memory for the given Instance #[allow(clippy::cast_ptr_alignment)] #[no_mangle] diff --git a/lib/runtime-c-api/src/memory.rs b/lib/runtime-c-api/src/memory.rs new file mode 100644 index 00000000000..f9096558646 --- /dev/null +++ b/lib/runtime-c-api/src/memory.rs @@ -0,0 +1,108 @@ +//! Wasm memory.o + +use crate::{error::update_last_error, wasmer_limits_t, wasmer_result_t}; +use libc::{uint32_t, uint8_t}; +use std::cell::Cell; +use wasmer_runtime::Memory; +use wasmer_runtime_core::{ + types::MemoryDescriptor, + units::{Bytes, Pages}, +}; + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_memory_t; + +/// Creates a new Memory for the given descriptor and initializes the given +/// pointer to pointer to a pointer to the new memory. +/// +/// The caller owns the object and should call `wasmer_memory_destroy` to free it. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +pub unsafe extern "C" fn wasmer_memory_new( + memory: *mut *mut wasmer_memory_t, + limits: wasmer_limits_t, +) -> wasmer_result_t { + let max = if limits.max.has_some { + Some(Pages(limits.max.some)) + } else { + None + }; + let desc = MemoryDescriptor { + minimum: Pages(limits.min), + maximum: max, + shared: false, + }; + let result = Memory::new(desc); + let new_memory = match result { + Ok(memory) => memory, + Err(error) => { + update_last_error(error); + return wasmer_result_t::WASMER_ERROR; + } + }; + *memory = Box::into_raw(Box::new(new_memory)) as *mut wasmer_memory_t; + wasmer_result_t::WASMER_OK +} + +/// Grows a Memory by the given number of pages. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_memory_grow( + memory: *mut wasmer_memory_t, + delta: uint32_t, +) -> wasmer_result_t { + let memory = unsafe { &*(memory as *mut Memory) }; + let delta_result = memory.grow(Pages(delta)); + match delta_result { + Ok(_) => wasmer_result_t::WASMER_OK, + Err(grow_error) => { + update_last_error(grow_error); + wasmer_result_t::WASMER_ERROR + } + } +} + +/// Returns the current length in pages of the given memory +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_memory_length(memory: *const wasmer_memory_t) -> uint32_t { + let memory = unsafe { &*(memory as *const Memory) }; + let Pages(len) = memory.size(); + len +} + +/// Gets the start pointer to the bytes within a Memory +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_memory_data(mem: *const wasmer_memory_t) -> *mut uint8_t { + let memory = unsafe { &*(mem as *const Memory) }; + memory.view::()[..].as_ptr() as *mut Cell as *mut u8 +} + +/// Gets the size in bytes of a Memory +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_memory_data_length(mem: *mut wasmer_memory_t) -> uint32_t { + let memory = mem as *mut Memory; + let Bytes(len) = unsafe { (*memory).size().bytes() }; + len as uint32_t +} + +/// Frees memory for the given Memory +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_memory_destroy(memory: *mut wasmer_memory_t) { + if !memory.is_null() { + unsafe { Box::from_raw(memory as *mut Memory) }; + } +} From 423997524018c7acf4c1375fcf3579f4653c2cde Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 29 Mar 2019 14:59:02 +0100 Subject: [PATCH 05/12] feat(runtime-c-api) Move `wasmer_validate` into the `module` module. --- lib/runtime-c-api/src/lib.rs | 15 --------------- lib/runtime-c-api/src/module.rs | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index e0cad3f8619..605e9d7e519 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -128,21 +128,6 @@ pub struct wasmer_byte_array { bytes_len: uint32_t, } -/// Returns true for valid wasm bytes and false for invalid bytes -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_validate( - wasm_bytes: *const uint8_t, - wasm_bytes_len: uint32_t, -) -> bool { - if wasm_bytes.is_null() { - return false; - } - let bytes: &[u8] = slice::from_raw_parts(wasm_bytes, wasm_bytes_len as usize); - - wasmer_runtime_core::validate(bytes) -} - /// Creates a new Table for the given descriptor and initializes the given /// pointer to pointer to a pointer to the new Table. /// diff --git a/lib/runtime-c-api/src/module.rs b/lib/runtime-c-api/src/module.rs index 58585dd25cf..18f1696212d 100644 --- a/lib/runtime-c-api/src/module.rs +++ b/lib/runtime-c-api/src/module.rs @@ -42,6 +42,21 @@ pub unsafe extern "C" fn wasmer_compile( wasmer_result_t::WASMER_OK } +/// Returns true for valid wasm bytes and false for invalid bytes +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_validate( + wasm_bytes: *const uint8_t, + wasm_bytes_len: uint32_t, +) -> bool { + if wasm_bytes.is_null() { + return false; + } + let bytes: &[u8] = slice::from_raw_parts(wasm_bytes, wasm_bytes_len as usize); + + wasmer_runtime_core::validate(bytes) +} + /// Creates a new Instance from the given module and imports. /// /// Returns `wasmer_result_t::WASMER_OK` upon success. From 8bdb458ea7b4a497a74e5fd42651d971a770f9fb Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 29 Mar 2019 15:02:50 +0100 Subject: [PATCH 06/12] feat(runtime-c-api) Extract the `table` module. --- lib/runtime-c-api/src/lib.rs | 84 ++------------------------------- lib/runtime-c-api/src/table.rs | 86 ++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 81 deletions(-) create mode 100644 lib/runtime-c-api/src/table.rs diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 605e9d7e519..759c11a684d 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -11,16 +11,18 @@ use wasmer_runtime::{Ctx, Global, ImportObject, Instance, Memory, Module, Table, use wasmer_runtime_core::export::{Context, Export, FuncPointer}; use wasmer_runtime_core::import::Namespace; use wasmer_runtime_core::module::{ExportIndex, ImportName}; -use wasmer_runtime_core::types::{ElementType, FuncSig, TableDescriptor, Type}; +use wasmer_runtime_core::types::{FuncSig, Type}; pub mod error; pub mod memory; pub mod module; +pub mod table; pub mod value; use error::{update_last_error, CApiError}; use memory::wasmer_memory_t; use module::wasmer_module_t; +use table::wasmer_table_t; use value::{wasmer_value, wasmer_value_t, wasmer_value_tag}; #[repr(C)] @@ -43,10 +45,6 @@ pub struct wasmer_global_descriptor_t { kind: wasmer_value_tag, } -#[repr(C)] -#[derive(Clone)] -pub struct wasmer_table_t; - #[repr(C)] #[derive(Clone)] pub struct wasmer_import_func_t; @@ -128,82 +126,6 @@ pub struct wasmer_byte_array { bytes_len: uint32_t, } -/// Creates a new Table for the given descriptor and initializes the given -/// pointer to pointer to a pointer to the new Table. -/// -/// The caller owns the object and should call `wasmer_table_destroy` to free it. -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[no_mangle] -pub unsafe extern "C" fn wasmer_table_new( - table: *mut *mut wasmer_table_t, - limits: wasmer_limits_t, -) -> wasmer_result_t { - let max = if limits.max.has_some { - Some(limits.max.some) - } else { - None - }; - let desc = TableDescriptor { - element: ElementType::Anyfunc, - minimum: limits.min, - maximum: max, - }; - let result = Table::new(desc); - let new_table = match result { - Ok(table) => table, - Err(error) => { - update_last_error(error); - return wasmer_result_t::WASMER_ERROR; - } - }; - *table = Box::into_raw(Box::new(new_table)) as *mut wasmer_table_t; - wasmer_result_t::WASMER_OK -} - -/// Grows a Table by the given number of elements. -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_table_grow( - table: *mut wasmer_table_t, - delta: uint32_t, -) -> wasmer_result_t { - let table = unsafe { &*(table as *mut Table) }; - let delta_result = table.grow(delta); - match delta_result { - Ok(_) => wasmer_result_t::WASMER_OK, - Err(grow_error) => { - update_last_error(grow_error); - wasmer_result_t::WASMER_ERROR - } - } -} - -/// Returns the current length of the given Table -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_table_length(table: *mut wasmer_table_t) -> uint32_t { - let table = unsafe { &*(table as *mut Table) }; - table.size() -} - -/// Frees memory for the given Table -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_table_destroy(table: *mut wasmer_table_t) { - if !table.is_null() { - unsafe { Box::from_raw(table as *mut Table) }; - } -} - /// Creates a new Global and returns a pointer to it. /// The caller owns the object and should call `wasmer_global_destroy` to free it. #[no_mangle] diff --git a/lib/runtime-c-api/src/table.rs b/lib/runtime-c-api/src/table.rs new file mode 100644 index 00000000000..84d3b794f89 --- /dev/null +++ b/lib/runtime-c-api/src/table.rs @@ -0,0 +1,86 @@ +//! Wasm tables. + +use crate::{error::update_last_error, wasmer_limits_t, wasmer_result_t}; +use libc::uint32_t; +use wasmer_runtime::Table; +use wasmer_runtime_core::types::{ElementType, TableDescriptor}; + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_table_t; + +/// Creates a new Table for the given descriptor and initializes the given +/// pointer to pointer to a pointer to the new Table. +/// +/// The caller owns the object and should call `wasmer_table_destroy` to free it. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +pub unsafe extern "C" fn wasmer_table_new( + table: *mut *mut wasmer_table_t, + limits: wasmer_limits_t, +) -> wasmer_result_t { + let max = if limits.max.has_some { + Some(limits.max.some) + } else { + None + }; + let desc = TableDescriptor { + element: ElementType::Anyfunc, + minimum: limits.min, + maximum: max, + }; + let result = Table::new(desc); + let new_table = match result { + Ok(table) => table, + Err(error) => { + update_last_error(error); + return wasmer_result_t::WASMER_ERROR; + } + }; + *table = Box::into_raw(Box::new(new_table)) as *mut wasmer_table_t; + wasmer_result_t::WASMER_OK +} + +/// Grows a Table by the given number of elements. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_table_grow( + table: *mut wasmer_table_t, + delta: uint32_t, +) -> wasmer_result_t { + let table = unsafe { &*(table as *mut Table) }; + let delta_result = table.grow(delta); + match delta_result { + Ok(_) => wasmer_result_t::WASMER_OK, + Err(grow_error) => { + update_last_error(grow_error); + wasmer_result_t::WASMER_ERROR + } + } +} + +/// Returns the current length of the given Table +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_table_length(table: *mut wasmer_table_t) -> uint32_t { + let table = unsafe { &*(table as *mut Table) }; + table.size() +} + +/// Frees memory for the given Table +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_table_destroy(table: *mut wasmer_table_t) { + if !table.is_null() { + unsafe { Box::from_raw(table as *mut Table) }; + } +} From d06d6b7ac8373a696d50e5fce402d5150575e98f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 29 Mar 2019 15:05:17 +0100 Subject: [PATCH 07/12] feat(runtime-c-api) Extract the `global` module. --- lib/runtime-c-api/src/global.rs | 70 +++++++++++++++++++++++++++++++++ lib/runtime-c-api/src/lib.rs | 68 +------------------------------- 2 files changed, 72 insertions(+), 66 deletions(-) create mode 100644 lib/runtime-c-api/src/global.rs diff --git a/lib/runtime-c-api/src/global.rs b/lib/runtime-c-api/src/global.rs new file mode 100644 index 00000000000..2e4ea645f9b --- /dev/null +++ b/lib/runtime-c-api/src/global.rs @@ -0,0 +1,70 @@ +//! Wasm global. + +use crate::value::{wasmer_value_t, wasmer_value_tag}; +use wasmer_runtime::Global; + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_global_descriptor_t { + mutable: bool, + kind: wasmer_value_tag, +} + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_global_t; + +/// Creates a new Global and returns a pointer to it. +/// The caller owns the object and should call `wasmer_global_destroy` to free it. +#[no_mangle] +pub unsafe extern "C" fn wasmer_global_new( + value: wasmer_value_t, + mutable: bool, +) -> *mut wasmer_global_t { + let global = if mutable { + Global::new_mutable(value.into()) + } else { + Global::new(value.into()) + }; + Box::into_raw(Box::new(global)) as *mut wasmer_global_t +} + +/// Gets the value stored by the given Global +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_global_get(global: *mut wasmer_global_t) -> wasmer_value_t { + let global = unsafe { &*(global as *mut Global) }; + let value: wasmer_value_t = global.get().into(); + value +} + +/// Sets the value stored by the given Global +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_global_set(global: *mut wasmer_global_t, value: wasmer_value_t) { + let global = unsafe { &*(global as *mut Global) }; + global.set(value.into()); +} + +/// Returns a descriptor (type, mutability) of the given Global +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_global_get_descriptor( + global: *mut wasmer_global_t, +) -> wasmer_global_descriptor_t { + let global = unsafe { &*(global as *mut Global) }; + let descriptor = global.descriptor(); + wasmer_global_descriptor_t { + mutable: descriptor.mutable, + kind: descriptor.ty.into(), + } +} + +/// Frees memory for the given Global +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_global_destroy(global: *mut wasmer_global_t) { + if !global.is_null() { + unsafe { Box::from_raw(global as *mut Global) }; + } +} diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 759c11a684d..841ab3b8386 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -14,12 +14,14 @@ use wasmer_runtime_core::module::{ExportIndex, ImportName}; use wasmer_runtime_core::types::{FuncSig, Type}; pub mod error; +pub mod global; pub mod memory; pub mod module; pub mod table; pub mod value; use error::{update_last_error, CApiError}; +use global::wasmer_global_t; use memory::wasmer_memory_t; use module::wasmer_module_t; use table::wasmer_table_t; @@ -38,13 +40,6 @@ pub enum wasmer_result_t { WASMER_ERROR = 2, } -#[repr(C)] -#[derive(Clone)] -pub struct wasmer_global_descriptor_t { - mutable: bool, - kind: wasmer_value_tag, -} - #[repr(C)] #[derive(Clone)] pub struct wasmer_import_func_t; @@ -53,10 +48,6 @@ pub struct wasmer_import_func_t; #[derive(Clone)] pub struct wasmer_export_func_t; -#[repr(C)] -#[derive(Clone)] -pub struct wasmer_global_t; - #[repr(C)] pub struct wasmer_limits_t { pub min: uint32_t, @@ -126,61 +117,6 @@ pub struct wasmer_byte_array { bytes_len: uint32_t, } -/// Creates a new Global and returns a pointer to it. -/// The caller owns the object and should call `wasmer_global_destroy` to free it. -#[no_mangle] -pub unsafe extern "C" fn wasmer_global_new( - value: wasmer_value_t, - mutable: bool, -) -> *mut wasmer_global_t { - let global = if mutable { - Global::new_mutable(value.into()) - } else { - Global::new(value.into()) - }; - Box::into_raw(Box::new(global)) as *mut wasmer_global_t -} - -/// Gets the value stored by the given Global -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_global_get(global: *mut wasmer_global_t) -> wasmer_value_t { - let global = unsafe { &*(global as *mut Global) }; - let value: wasmer_value_t = global.get().into(); - value -} - -/// Sets the value stored by the given Global -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_global_set(global: *mut wasmer_global_t, value: wasmer_value_t) { - let global = unsafe { &*(global as *mut Global) }; - global.set(value.into()); -} - -/// Returns a descriptor (type, mutability) of the given Global -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_global_get_descriptor( - global: *mut wasmer_global_t, -) -> wasmer_global_descriptor_t { - let global = unsafe { &*(global as *mut Global) }; - let descriptor = global.descriptor(); - wasmer_global_descriptor_t { - mutable: descriptor.mutable, - kind: descriptor.ty.into(), - } -} - -/// Frees memory for the given Global -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_global_destroy(global: *mut wasmer_global_t) { - if !global.is_null() { - unsafe { Box::from_raw(global as *mut Global) }; - } -} - /// Gets export descriptors for the given module /// /// The caller owns the object and should call `wasmer_export_descriptors_destroy` to free it. From f46be814da60bfd96935ccd12f5ecf0884159255 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 29 Mar 2019 15:14:05 +0100 Subject: [PATCH 08/12] feat(runtime-c-api) Extract the `instance` module. --- lib/runtime-c-api/src/instance.rs | 255 ++++++++++++++++++++++++++++++ lib/runtime-c-api/src/lib.rs | 251 +---------------------------- 2 files changed, 259 insertions(+), 247 deletions(-) create mode 100644 lib/runtime-c-api/src/instance.rs diff --git a/lib/runtime-c-api/src/instance.rs b/lib/runtime-c-api/src/instance.rs new file mode 100644 index 00000000000..14d05b9dc7d --- /dev/null +++ b/lib/runtime-c-api/src/instance.rs @@ -0,0 +1,255 @@ +//! Wasm instance. + +use crate::{ + error::{update_last_error, CApiError}, + memory::wasmer_memory_t, + value::{wasmer_value, wasmer_value_t, wasmer_value_tag}, + wasmer_exports_t, wasmer_import_export_kind, wasmer_import_t, wasmer_result_t, NamedExport, + NamedExports, +}; +use libc::{c_char, c_int, c_void, uint32_t, uint8_t}; +use std::{collections::HashMap, ffi::CStr, slice}; +use wasmer_runtime::{Ctx, Global, ImportObject, Instance, Memory, Table, Value}; +use wasmer_runtime_core::{export::Export, import::Namespace}; + +#[repr(C)] +pub struct wasmer_instance_t; + +#[repr(C)] +pub struct wasmer_instance_context_t; + +/// Creates a new Instance from the given wasm bytes and imports. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_instantiate( + instance: *mut *mut wasmer_instance_t, + wasm_bytes: *mut uint8_t, + wasm_bytes_len: uint32_t, + imports: *mut wasmer_import_t, + imports_len: c_int, +) -> wasmer_result_t { + if wasm_bytes.is_null() { + update_last_error(CApiError { + msg: "wasm bytes ptr is null".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + } + let imports: &[wasmer_import_t] = slice::from_raw_parts(imports, imports_len as usize); + let mut import_object = ImportObject::new(); + let mut namespaces = HashMap::new(); + for import in imports { + let module_name = slice::from_raw_parts( + import.module_name.bytes, + import.module_name.bytes_len as usize, + ); + let module_name = if let Ok(s) = std::str::from_utf8(module_name) { + s + } else { + update_last_error(CApiError { + msg: "error converting module name to string".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + }; + let import_name = slice::from_raw_parts( + import.import_name.bytes, + import.import_name.bytes_len as usize, + ); + let import_name = if let Ok(s) = std::str::from_utf8(import_name) { + s + } else { + update_last_error(CApiError { + msg: "error converting import_name to string".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + }; + + let namespace = namespaces.entry(module_name).or_insert_with(Namespace::new); + + let export = match import.tag { + wasmer_import_export_kind::WASM_MEMORY => { + let mem = import.value.memory as *mut Memory; + Export::Memory((&*mem).clone()) + } + wasmer_import_export_kind::WASM_FUNCTION => { + let func_export = import.value.func as *mut Export; + (&*func_export).clone() + } + wasmer_import_export_kind::WASM_GLOBAL => { + let global = import.value.global as *mut Global; + Export::Global((&*global).clone()) + } + wasmer_import_export_kind::WASM_TABLE => { + let table = import.value.table as *mut Table; + Export::Table((&*table).clone()) + } + }; + namespace.insert(import_name, export); + } + for (module_name, namespace) in namespaces.into_iter() { + import_object.register(module_name, namespace); + } + + let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize); + let result = wasmer_runtime::instantiate(bytes, &import_object); + let new_instance = match result { + Ok(instance) => instance, + Err(_error) => { + // TODO the trait bound `wasmer_runtime::error::Error: std::error::Error` is not satisfied + //update_last_error(error); + update_last_error(CApiError { + msg: "error instantiating".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + } + }; + *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t; + wasmer_result_t::WASMER_OK +} + +/// Calls an instances exported function by `name` with the provided parameters. +/// Results are set using the provided `results` pointer. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_instance_call( + instance: *mut wasmer_instance_t, + name: *const c_char, + params: *const wasmer_value_t, + params_len: c_int, + results: *mut wasmer_value_t, + results_len: c_int, +) -> wasmer_result_t { + if instance.is_null() { + update_last_error(CApiError { + msg: "instance ptr is null".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + } + if name.is_null() { + update_last_error(CApiError { + msg: "name ptr is null".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + } + if params.is_null() { + update_last_error(CApiError { + msg: "params ptr is null".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + } + + let params: &[wasmer_value_t] = slice::from_raw_parts(params, params_len as usize); + let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); + + let func_name_c = CStr::from_ptr(name); + let func_name_r = func_name_c.to_str().unwrap(); + + let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize); + let result = (&*(instance as *mut Instance)).call(func_name_r, ¶ms[..]); + + match result { + Ok(results_vec) => { + if !results_vec.is_empty() { + let ret = match results_vec[0] { + Value::I32(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_I32, + value: wasmer_value { I32: x }, + }, + Value::I64(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_I64, + value: wasmer_value { I64: x }, + }, + Value::F32(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_F32, + value: wasmer_value { F32: x }, + }, + Value::F64(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_F64, + value: wasmer_value { F64: x }, + }, + }; + results[0] = ret; + } + wasmer_result_t::WASMER_OK + } + Err(err) => { + update_last_error(err); + wasmer_result_t::WASMER_ERROR + } + } +} + +/// Gets Exports for the given instance +/// +/// The caller owns the object and should call `wasmer_exports_destroy` to free it. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_instance_exports( + instance: *mut wasmer_instance_t, + exports: *mut *mut wasmer_exports_t, +) { + let instance_ref = &mut *(instance as *mut Instance); + let mut exports_vec: Vec = Vec::with_capacity(instance_ref.exports().count()); + for (name, export) in instance_ref.exports() { + exports_vec.push(NamedExport { + name: name.clone(), + export: export.clone(), + instance: instance as *mut Instance, + }); + } + let named_exports: Box = Box::new(NamedExports(exports_vec)); + *exports = Box::into_raw(named_exports) as *mut wasmer_exports_t; +} + +/// Sets the `data` field of the instance context. This context will be +/// passed to all imported function for instance. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_instance_context_data_set( + instance: *mut wasmer_instance_t, + data_ptr: *mut c_void, +) { + let instance_ref = unsafe { &mut *(instance as *mut Instance) }; + instance_ref.context_mut().data = data_ptr; +} + +/// Gets the memory within the context at the index `memory_idx`. +/// The index is always 0 until multiple memories are supported. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_instance_context_memory( + ctx: *const wasmer_instance_context_t, + _memory_idx: uint32_t, +) -> *const wasmer_memory_t { + let ctx = unsafe { &*(ctx as *const Ctx) }; + let memory = ctx.memory(0); + memory as *const Memory as *const wasmer_memory_t +} + +/// Gets the `data` field within the context. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_instance_context_data_get( + ctx: *const wasmer_instance_context_t, +) -> *mut c_void { + let ctx = unsafe { &*(ctx as *const Ctx) }; + ctx.data +} + +/// Frees memory for the given Instance +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_instance_destroy(instance: *mut wasmer_instance_t) { + if !instance.is_null() { + unsafe { Box::from_raw(instance as *mut Instance) }; + } +} diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 841ab3b8386..45af7c71013 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -1,20 +1,18 @@ extern crate wasmer_runtime; extern crate wasmer_runtime_core; -use libc::{c_char, c_int, uint32_t, uint8_t}; -use std::collections::HashMap; -use std::ffi::CStr; +use libc::{c_int, uint32_t, uint8_t}; use std::slice; use std::sync::Arc; use std::{ffi::c_void, ptr}; -use wasmer_runtime::{Ctx, Global, ImportObject, Instance, Memory, Module, Table, Value}; +use wasmer_runtime::{Instance, Memory, Module, Value}; use wasmer_runtime_core::export::{Context, Export, FuncPointer}; -use wasmer_runtime_core::import::Namespace; use wasmer_runtime_core::module::{ExportIndex, ImportName}; use wasmer_runtime_core::types::{FuncSig, Type}; pub mod error; pub mod global; +pub mod instance; pub mod memory; pub mod module; pub mod table; @@ -22,17 +20,12 @@ pub mod value; use error::{update_last_error, CApiError}; use global::wasmer_global_t; +use instance::wasmer_instance_t; use memory::wasmer_memory_t; use module::wasmer_module_t; use table::wasmer_table_t; use value::{wasmer_value, wasmer_value_t, wasmer_value_tag}; -#[repr(C)] -pub struct wasmer_instance_t; - -#[repr(C)] -pub struct wasmer_instance_context_t; - #[allow(non_camel_case_types)] #[repr(C)] pub enum wasmer_result_t { @@ -373,210 +366,6 @@ pub unsafe extern "C" fn wasmer_import_descriptor_kind( named_import_descriptor.kind.clone() } -/// Creates a new Instance from the given wasm bytes and imports. -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_instantiate( - instance: *mut *mut wasmer_instance_t, - wasm_bytes: *mut uint8_t, - wasm_bytes_len: uint32_t, - imports: *mut wasmer_import_t, - imports_len: c_int, -) -> wasmer_result_t { - if wasm_bytes.is_null() { - update_last_error(CApiError { - msg: "wasm bytes ptr is null".to_string(), - }); - return wasmer_result_t::WASMER_ERROR; - } - let imports: &[wasmer_import_t] = slice::from_raw_parts(imports, imports_len as usize); - let mut import_object = ImportObject::new(); - let mut namespaces = HashMap::new(); - for import in imports { - let module_name = slice::from_raw_parts( - import.module_name.bytes, - import.module_name.bytes_len as usize, - ); - let module_name = if let Ok(s) = std::str::from_utf8(module_name) { - s - } else { - update_last_error(CApiError { - msg: "error converting module name to string".to_string(), - }); - return wasmer_result_t::WASMER_ERROR; - }; - let import_name = slice::from_raw_parts( - import.import_name.bytes, - import.import_name.bytes_len as usize, - ); - let import_name = if let Ok(s) = std::str::from_utf8(import_name) { - s - } else { - update_last_error(CApiError { - msg: "error converting import_name to string".to_string(), - }); - return wasmer_result_t::WASMER_ERROR; - }; - - let namespace = namespaces.entry(module_name).or_insert_with(Namespace::new); - - let export = match import.tag { - wasmer_import_export_kind::WASM_MEMORY => { - let mem = import.value.memory as *mut Memory; - Export::Memory((&*mem).clone()) - } - wasmer_import_export_kind::WASM_FUNCTION => { - let func_export = import.value.func as *mut Export; - (&*func_export).clone() - } - wasmer_import_export_kind::WASM_GLOBAL => { - let global = import.value.global as *mut Global; - Export::Global((&*global).clone()) - } - wasmer_import_export_kind::WASM_TABLE => { - let table = import.value.table as *mut Table; - Export::Table((&*table).clone()) - } - }; - namespace.insert(import_name, export); - } - for (module_name, namespace) in namespaces.into_iter() { - import_object.register(module_name, namespace); - } - - let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize); - let result = wasmer_runtime::instantiate(bytes, &import_object); - let new_instance = match result { - Ok(instance) => instance, - Err(_error) => { - // TODO the trait bound `wasmer_runtime::error::Error: std::error::Error` is not satisfied - //update_last_error(error); - update_last_error(CApiError { - msg: "error instantiating".to_string(), - }); - return wasmer_result_t::WASMER_ERROR; - } - }; - *instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t; - wasmer_result_t::WASMER_OK -} - -/// Calls an instances exported function by `name` with the provided parameters. -/// Results are set using the provided `results` pointer. -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_instance_call( - instance: *mut wasmer_instance_t, - name: *const c_char, - params: *const wasmer_value_t, - params_len: c_int, - results: *mut wasmer_value_t, - results_len: c_int, -) -> wasmer_result_t { - if instance.is_null() { - update_last_error(CApiError { - msg: "instance ptr is null".to_string(), - }); - return wasmer_result_t::WASMER_ERROR; - } - if name.is_null() { - update_last_error(CApiError { - msg: "name ptr is null".to_string(), - }); - return wasmer_result_t::WASMER_ERROR; - } - if params.is_null() { - update_last_error(CApiError { - msg: "params ptr is null".to_string(), - }); - return wasmer_result_t::WASMER_ERROR; - } - - let params: &[wasmer_value_t] = slice::from_raw_parts(params, params_len as usize); - let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); - - let func_name_c = CStr::from_ptr(name); - let func_name_r = func_name_c.to_str().unwrap(); - - let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize); - let result = (&*(instance as *mut Instance)).call(func_name_r, ¶ms[..]); - - match result { - Ok(results_vec) => { - if !results_vec.is_empty() { - let ret = match results_vec[0] { - Value::I32(x) => wasmer_value_t { - tag: wasmer_value_tag::WASM_I32, - value: wasmer_value { I32: x }, - }, - Value::I64(x) => wasmer_value_t { - tag: wasmer_value_tag::WASM_I64, - value: wasmer_value { I64: x }, - }, - Value::F32(x) => wasmer_value_t { - tag: wasmer_value_tag::WASM_F32, - value: wasmer_value { F32: x }, - }, - Value::F64(x) => wasmer_value_t { - tag: wasmer_value_tag::WASM_F64, - value: wasmer_value { F64: x }, - }, - }; - results[0] = ret; - } - wasmer_result_t::WASMER_OK - } - Err(err) => { - update_last_error(err); - wasmer_result_t::WASMER_ERROR - } - } -} - -/// Gets Exports for the given instance -/// -/// The caller owns the object and should call `wasmer_exports_destroy` to free it. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_instance_exports( - instance: *mut wasmer_instance_t, - exports: *mut *mut wasmer_exports_t, -) { - let instance_ref = &mut *(instance as *mut Instance); - let mut exports_vec: Vec = Vec::with_capacity(instance_ref.exports().count()); - for (name, export) in instance_ref.exports() { - exports_vec.push(NamedExport { - name: name.clone(), - export: export.clone(), - instance: instance as *mut Instance, - }); - } - let named_exports: Box = Box::new(NamedExports(exports_vec)); - *exports = Box::into_raw(named_exports) as *mut wasmer_exports_t; -} - -/// Sets the `data` field of the instance context. This context will be -/// passed to all imported function for instance. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_instance_context_data_set( - instance: *mut wasmer_instance_t, - data_ptr: *mut c_void, -) { - let instance_ref = unsafe { &mut *(instance as *mut Instance) }; - instance_ref.context_mut().data = data_ptr; -} - pub struct NamedExports(Vec); /// Frees the memory for the given exports @@ -995,38 +784,6 @@ pub unsafe extern "C" fn wasmer_export_func_call( } } -/// Gets the memory within the context at the index `memory_idx`. -/// The index is always 0 until multiple memories are supported. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_instance_context_memory( - ctx: *const wasmer_instance_context_t, - _memory_idx: uint32_t, -) -> *const wasmer_memory_t { - let ctx = unsafe { &*(ctx as *const Ctx) }; - let memory = ctx.memory(0); - memory as *const Memory as *const wasmer_memory_t -} - -/// Gets the `data` field within the context. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_instance_context_data_get( - ctx: *const wasmer_instance_context_t, -) -> *mut c_void { - let ctx = unsafe { &*(ctx as *const Ctx) }; - ctx.data -} - -/// Frees memory for the given Instance -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_instance_destroy(instance: *mut wasmer_instance_t) { - if !instance.is_null() { - unsafe { Box::from_raw(instance as *mut Instance) }; - } -} - impl From for Value { fn from(v: wasmer_value_t) -> Self { unsafe { From 9c4696eb5bce82bbc19be9f6ce46fae22383a792 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 29 Mar 2019 15:38:12 +0100 Subject: [PATCH 09/12] feat(runtime-c-api) Extract the `export` module. --- lib/runtime-c-api/src/export.rs | 439 ++++++++++++++++++++++++++++++ lib/runtime-c-api/src/instance.rs | 4 +- lib/runtime-c-api/src/lib.rs | 433 +---------------------------- 3 files changed, 445 insertions(+), 431 deletions(-) create mode 100644 lib/runtime-c-api/src/export.rs diff --git a/lib/runtime-c-api/src/export.rs b/lib/runtime-c-api/src/export.rs new file mode 100644 index 00000000000..ea37fdad60b --- /dev/null +++ b/lib/runtime-c-api/src/export.rs @@ -0,0 +1,439 @@ +//! Wasm exports. + +use crate::{ + error::{update_last_error, CApiError}, + global::wasmer_global_t, + memory::wasmer_memory_t, + module::wasmer_module_t, + table::wasmer_table_t, + value::{wasmer_value, wasmer_value_t, wasmer_value_tag}, + wasmer_byte_array, wasmer_import_func_t, wasmer_result_t, +}; +use libc::{c_int, uint32_t}; +use std::{ptr, slice}; +use wasmer_runtime::{Instance, Memory, Module, Value}; +use wasmer_runtime_core::{export::Export, module::ExportIndex}; + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_export_t; + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_exports_t; + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_export_func_t; + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_export_descriptor_t; + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_export_descriptors_t; + +#[repr(C)] +#[derive(Clone, Copy)] +pub union wasmer_import_export_value { + pub func: *const wasmer_import_func_t, + pub table: *const wasmer_table_t, + pub memory: *const wasmer_memory_t, + pub global: *const wasmer_global_t, +} + +#[allow(non_camel_case_types)] +#[repr(u32)] +#[derive(Clone)] +pub enum wasmer_import_export_kind { + WASM_FUNCTION, + WASM_GLOBAL, + WASM_MEMORY, + WASM_TABLE, +} + +/// Gets export descriptors for the given module +/// +/// The caller owns the object and should call `wasmer_export_descriptors_destroy` to free it. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_export_descriptors( + module: *const wasmer_module_t, + export_descriptors: *mut *mut wasmer_export_descriptors_t, +) { + let module = &*(module as *const Module); + + let named_export_descriptors: Box = Box::new(NamedExportDescriptors( + module.info().exports.iter().map(|e| e.into()).collect(), + )); + *export_descriptors = + Box::into_raw(named_export_descriptors) as *mut wasmer_export_descriptors_t; +} + +pub struct NamedExportDescriptors(Vec); + +/// Frees the memory for the given export descriptors +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_export_descriptors_destroy( + export_descriptors: *mut wasmer_export_descriptors_t, +) { + if !export_descriptors.is_null() { + unsafe { Box::from_raw(export_descriptors as *mut NamedExportDescriptors) }; + } +} + +/// Gets the length of the export descriptors +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_export_descriptors_len( + exports: *mut wasmer_export_descriptors_t, +) -> c_int { + if exports.is_null() { + return 0; + } + (*(exports as *mut NamedExportDescriptors)).0.len() as c_int +} + +/// Gets export descriptor by index +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_export_descriptors_get( + export_descriptors: *mut wasmer_export_descriptors_t, + idx: c_int, +) -> *mut wasmer_export_descriptor_t { + if export_descriptors.is_null() { + return ptr::null_mut(); + } + let named_export_descriptors = &mut *(export_descriptors as *mut NamedExportDescriptors); + &mut (*named_export_descriptors).0[idx as usize] as *mut NamedExportDescriptor + as *mut wasmer_export_descriptor_t +} + +/// Gets name for the export descriptor +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_descriptor_name( + export_descriptor: *mut wasmer_export_descriptor_t, +) -> wasmer_byte_array { + let named_export_descriptor = &*(export_descriptor as *mut NamedExportDescriptor); + wasmer_byte_array { + bytes: named_export_descriptor.name.as_ptr(), + bytes_len: named_export_descriptor.name.len() as u32, + } +} + +/// Gets export descriptor kind +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_descriptor_kind( + export: *mut wasmer_export_descriptor_t, +) -> wasmer_import_export_kind { + let named_export_descriptor = &*(export as *mut NamedExportDescriptor); + named_export_descriptor.kind.clone() +} + +pub(crate) struct NamedExports(pub Vec); + +/// Frees the memory for the given exports +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_exports_destroy(exports: *mut wasmer_exports_t) { + if !exports.is_null() { + unsafe { Box::from_raw(exports as *mut NamedExports) }; + } +} + +/// Gets the length of the exports +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_exports_len(exports: *mut wasmer_exports_t) -> c_int { + if exports.is_null() { + return 0; + } + (*(exports as *mut NamedExports)).0.len() as c_int +} + +/// Gets wasmer_export by index +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_exports_get( + exports: *mut wasmer_exports_t, + idx: c_int, +) -> *mut wasmer_export_t { + if exports.is_null() { + return ptr::null_mut(); + } + let named_exports = &mut *(exports as *mut NamedExports); + &mut (*named_exports).0[idx as usize] as *mut NamedExport as *mut wasmer_export_t +} + +/// Gets wasmer_export kind +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_kind( + export: *mut wasmer_export_t, +) -> wasmer_import_export_kind { + let named_export = &*(export as *mut NamedExport); + match named_export.export { + Export::Table(_) => wasmer_import_export_kind::WASM_TABLE, + Export::Function { .. } => wasmer_import_export_kind::WASM_FUNCTION, + Export::Global(_) => wasmer_import_export_kind::WASM_GLOBAL, + Export::Memory(_) => wasmer_import_export_kind::WASM_MEMORY, + } +} + +/// Sets the result parameter to the arity of the params of the wasmer_export_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_func_params_arity( + func: *const wasmer_export_func_t, + result: *mut uint32_t, +) -> wasmer_result_t { + let named_export = &*(func as *const NamedExport); + let export = &named_export.export; + if let Export::Function { ref signature, .. } = *export { + *result = signature.params().len() as uint32_t; + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_export_func_params_arity".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } +} + +/// Sets the params buffer to the parameter types of the given wasmer_export_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_func_params( + func: *const wasmer_export_func_t, + params: *mut wasmer_value_tag, + params_len: c_int, +) -> wasmer_result_t { + let named_export = &*(func as *const NamedExport); + let export = &named_export.export; + if let Export::Function { ref signature, .. } = *export { + let params: &mut [wasmer_value_tag] = + slice::from_raw_parts_mut(params, params_len as usize); + for (i, item) in signature.params().iter().enumerate() { + params[i] = item.into(); + } + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_export_func_params".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } +} + +/// Sets the returns buffer to the parameter types of the given wasmer_export_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_func_returns( + func: *const wasmer_export_func_t, + returns: *mut wasmer_value_tag, + returns_len: c_int, +) -> wasmer_result_t { + let named_export = &*(func as *const NamedExport); + let export = &named_export.export; + if let Export::Function { ref signature, .. } = *export { + let returns: &mut [wasmer_value_tag] = + slice::from_raw_parts_mut(returns, returns_len as usize); + for (i, item) in signature.returns().iter().enumerate() { + returns[i] = item.into(); + } + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_export_func_returns".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } +} + +/// Sets the result parameter to the arity of the returns of the wasmer_export_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_func_returns_arity( + func: *const wasmer_export_func_t, + result: *mut uint32_t, +) -> wasmer_result_t { + let named_export = &*(func as *const NamedExport); + let export = &named_export.export; + if let Export::Function { ref signature, .. } = *export { + *result = signature.returns().len() as uint32_t; + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_export_func_results_arity".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } +} + +/// Gets export func from export +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_to_func( + export: *const wasmer_export_t, +) -> *const wasmer_export_func_t { + export as *const wasmer_export_func_t +} + +/// Gets a memory pointer from an export pointer. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_to_memory( + export: *const wasmer_export_t, + memory: *mut *mut wasmer_memory_t, +) -> wasmer_result_t { + let named_export = &*(export as *const NamedExport); + let export = &named_export.export; + + if let Export::Memory(exported_memory) = export { + *memory = exported_memory as *const Memory as *mut wasmer_memory_t; + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "cannot cast the `wasmer_export_t` pointer to a `wasmer_memory_t` \ + pointer because it does not represent a memory export." + .to_string(), + }); + wasmer_result_t::WASMER_ERROR + } +} + +/// Gets name from wasmer_export +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_name(export: *mut wasmer_export_t) -> wasmer_byte_array { + let named_export = &*(export as *mut NamedExport); + wasmer_byte_array { + bytes: named_export.name.as_ptr(), + bytes_len: named_export.name.len() as u32, + } +} + +/// Calls a `func` with the provided parameters. +/// Results are set using the provided `results` pointer. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_export_func_call( + func: *const wasmer_export_func_t, + params: *const wasmer_value_t, + params_len: c_int, + results: *mut wasmer_value_t, + results_len: c_int, +) -> wasmer_result_t { + if func.is_null() { + update_last_error(CApiError { + msg: "func ptr is null".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + } + if params.is_null() { + update_last_error(CApiError { + msg: "params ptr is null".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + } + + let params: &[wasmer_value_t] = slice::from_raw_parts(params, params_len as usize); + let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); + + let named_export = &*(func as *mut NamedExport); + + let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize); + + let instance = &*named_export.instance; + let result = instance.call(&named_export.name, ¶ms[..]); + match result { + Ok(results_vec) => { + if !results_vec.is_empty() { + let ret = match results_vec[0] { + Value::I32(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_I32, + value: wasmer_value { I32: x }, + }, + Value::I64(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_I64, + value: wasmer_value { I64: x }, + }, + Value::F32(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_F32, + value: wasmer_value { F32: x }, + }, + Value::F64(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_F64, + value: wasmer_value { F64: x }, + }, + }; + results[0] = ret; + } + wasmer_result_t::WASMER_OK + } + Err(err) => { + update_last_error(err); + wasmer_result_t::WASMER_ERROR + } + } +} + +impl From<(&std::string::String, &ExportIndex)> for NamedExportDescriptor { + fn from((name, export_index): (&String, &ExportIndex)) -> Self { + let kind = match *export_index { + ExportIndex::Memory(_) => wasmer_import_export_kind::WASM_MEMORY, + ExportIndex::Global(_) => wasmer_import_export_kind::WASM_GLOBAL, + ExportIndex::Table(_) => wasmer_import_export_kind::WASM_TABLE, + ExportIndex::Func(_) => wasmer_import_export_kind::WASM_FUNCTION, + }; + NamedExportDescriptor { + name: name.clone(), + kind, + } + } +} + +pub(crate) struct NamedExport { + pub(crate) name: String, + pub(crate) export: Export, + pub(crate) instance: *mut Instance, +} + +pub(crate) struct NamedExportDescriptor { + name: String, + kind: wasmer_import_export_kind, +} diff --git a/lib/runtime-c-api/src/instance.rs b/lib/runtime-c-api/src/instance.rs index 14d05b9dc7d..093d381e913 100644 --- a/lib/runtime-c-api/src/instance.rs +++ b/lib/runtime-c-api/src/instance.rs @@ -2,10 +2,10 @@ use crate::{ error::{update_last_error, CApiError}, + export::{wasmer_exports_t, NamedExport, NamedExports}, memory::wasmer_memory_t, value::{wasmer_value, wasmer_value_t, wasmer_value_tag}, - wasmer_exports_t, wasmer_import_export_kind, wasmer_import_t, wasmer_result_t, NamedExport, - NamedExports, + wasmer_import_export_kind, wasmer_import_t, wasmer_result_t, }; use libc::{c_char, c_int, c_void, uint32_t, uint8_t}; use std::{collections::HashMap, ffi::CStr, slice}; diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 45af7c71013..b1b6724d0eb 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -5,12 +5,13 @@ use libc::{c_int, uint32_t, uint8_t}; use std::slice; use std::sync::Arc; use std::{ffi::c_void, ptr}; -use wasmer_runtime::{Instance, Memory, Module, Value}; +use wasmer_runtime::{Module, Value}; use wasmer_runtime_core::export::{Context, Export, FuncPointer}; -use wasmer_runtime_core::module::{ExportIndex, ImportName}; +use wasmer_runtime_core::module::ImportName; use wasmer_runtime_core::types::{FuncSig, Type}; pub mod error; +pub mod export; pub mod global; pub mod instance; pub mod memory; @@ -19,11 +20,9 @@ pub mod table; pub mod value; use error::{update_last_error, CApiError}; -use global::wasmer_global_t; +use export::{wasmer_import_export_kind, wasmer_import_export_value}; use instance::wasmer_instance_t; -use memory::wasmer_memory_t; use module::wasmer_module_t; -use table::wasmer_table_t; use value::{wasmer_value, wasmer_value_t, wasmer_value_tag}; #[allow(non_camel_case_types)] @@ -37,10 +36,6 @@ pub enum wasmer_result_t { #[derive(Clone)] pub struct wasmer_import_func_t; -#[repr(C)] -#[derive(Clone)] -pub struct wasmer_export_func_t; - #[repr(C)] pub struct wasmer_limits_t { pub min: uint32_t, @@ -69,128 +64,12 @@ pub struct wasmer_import_descriptor_t; #[derive(Clone)] pub struct wasmer_import_descriptors_t; -#[repr(C)] -#[derive(Clone)] -pub struct wasmer_export_t; - -#[repr(C)] -#[derive(Clone)] -pub struct wasmer_exports_t; - -#[repr(C)] -#[derive(Clone)] -pub struct wasmer_export_descriptor_t; - -#[repr(C)] -#[derive(Clone)] -pub struct wasmer_export_descriptors_t; - -#[allow(non_camel_case_types)] -#[repr(u32)] -#[derive(Clone)] -pub enum wasmer_import_export_kind { - WASM_FUNCTION, - WASM_GLOBAL, - WASM_MEMORY, - WASM_TABLE, -} - -#[repr(C)] -#[derive(Clone, Copy)] -pub union wasmer_import_export_value { - func: *const wasmer_import_func_t, - table: *const wasmer_table_t, - memory: *const wasmer_memory_t, - global: *const wasmer_global_t, -} - #[repr(C)] pub struct wasmer_byte_array { bytes: *const uint8_t, bytes_len: uint32_t, } -/// Gets export descriptors for the given module -/// -/// The caller owns the object and should call `wasmer_export_descriptors_destroy` to free it. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_export_descriptors( - module: *const wasmer_module_t, - export_descriptors: *mut *mut wasmer_export_descriptors_t, -) { - let module = &*(module as *const Module); - - let named_export_descriptors: Box = Box::new(NamedExportDescriptors( - module.info().exports.iter().map(|e| e.into()).collect(), - )); - *export_descriptors = - Box::into_raw(named_export_descriptors) as *mut wasmer_export_descriptors_t; -} - -pub struct NamedExportDescriptors(Vec); - -/// Frees the memory for the given export descriptors -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_export_descriptors_destroy( - export_descriptors: *mut wasmer_export_descriptors_t, -) { - if !export_descriptors.is_null() { - unsafe { Box::from_raw(export_descriptors as *mut NamedExportDescriptors) }; - } -} - -/// Gets the length of the export descriptors -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_export_descriptors_len( - exports: *mut wasmer_export_descriptors_t, -) -> c_int { - if exports.is_null() { - return 0; - } - (*(exports as *mut NamedExportDescriptors)).0.len() as c_int -} - -/// Gets export descriptor by index -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_export_descriptors_get( - export_descriptors: *mut wasmer_export_descriptors_t, - idx: c_int, -) -> *mut wasmer_export_descriptor_t { - if export_descriptors.is_null() { - return ptr::null_mut(); - } - let named_export_descriptors = &mut *(export_descriptors as *mut NamedExportDescriptors); - &mut (*named_export_descriptors).0[idx as usize] as *mut NamedExportDescriptor - as *mut wasmer_export_descriptor_t -} - -/// Gets name for the export descriptor -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_export_descriptor_name( - export_descriptor: *mut wasmer_export_descriptor_t, -) -> wasmer_byte_array { - let named_export_descriptor = &*(export_descriptor as *mut NamedExportDescriptor); - wasmer_byte_array { - bytes: named_export_descriptor.name.as_ptr(), - bytes_len: named_export_descriptor.name.len() as u32, - } -} - -/// Gets export descriptor kind -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_export_descriptor_kind( - export: *mut wasmer_export_descriptor_t, -) -> wasmer_import_export_kind { - let named_export_descriptor = &*(export as *mut NamedExportDescriptor); - named_export_descriptor.kind.clone() -} - /// Gets import descriptors for the given module /// /// The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it. @@ -366,166 +245,6 @@ pub unsafe extern "C" fn wasmer_import_descriptor_kind( named_import_descriptor.kind.clone() } -pub struct NamedExports(Vec); - -/// Frees the memory for the given exports -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_exports_destroy(exports: *mut wasmer_exports_t) { - if !exports.is_null() { - unsafe { Box::from_raw(exports as *mut NamedExports) }; - } -} - -/// Gets the length of the exports -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_exports_len(exports: *mut wasmer_exports_t) -> c_int { - if exports.is_null() { - return 0; - } - (*(exports as *mut NamedExports)).0.len() as c_int -} - -/// Gets wasmer_export by index -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_exports_get( - exports: *mut wasmer_exports_t, - idx: c_int, -) -> *mut wasmer_export_t { - if exports.is_null() { - return ptr::null_mut(); - } - let named_exports = &mut *(exports as *mut NamedExports); - &mut (*named_exports).0[idx as usize] as *mut NamedExport as *mut wasmer_export_t -} - -/// Gets wasmer_export kind -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_export_kind( - export: *mut wasmer_export_t, -) -> wasmer_import_export_kind { - let named_export = &*(export as *mut NamedExport); - match named_export.export { - Export::Table(_) => wasmer_import_export_kind::WASM_TABLE, - Export::Function { .. } => wasmer_import_export_kind::WASM_FUNCTION, - Export::Global(_) => wasmer_import_export_kind::WASM_GLOBAL, - Export::Memory(_) => wasmer_import_export_kind::WASM_MEMORY, - } -} - -/// Sets the result parameter to the arity of the params of the wasmer_export_func_t -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_export_func_params_arity( - func: *const wasmer_export_func_t, - result: *mut uint32_t, -) -> wasmer_result_t { - let named_export = &*(func as *const NamedExport); - let export = &named_export.export; - if let Export::Function { ref signature, .. } = *export { - *result = signature.params().len() as uint32_t; - wasmer_result_t::WASMER_OK - } else { - update_last_error(CApiError { - msg: "func ptr error in wasmer_export_func_params_arity".to_string(), - }); - wasmer_result_t::WASMER_ERROR - } -} - -/// Sets the params buffer to the parameter types of the given wasmer_export_func_t -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_export_func_params( - func: *const wasmer_export_func_t, - params: *mut wasmer_value_tag, - params_len: c_int, -) -> wasmer_result_t { - let named_export = &*(func as *const NamedExport); - let export = &named_export.export; - if let Export::Function { ref signature, .. } = *export { - let params: &mut [wasmer_value_tag] = - slice::from_raw_parts_mut(params, params_len as usize); - for (i, item) in signature.params().iter().enumerate() { - params[i] = item.into(); - } - wasmer_result_t::WASMER_OK - } else { - update_last_error(CApiError { - msg: "func ptr error in wasmer_export_func_params".to_string(), - }); - wasmer_result_t::WASMER_ERROR - } -} - -/// Sets the returns buffer to the parameter types of the given wasmer_export_func_t -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_export_func_returns( - func: *const wasmer_export_func_t, - returns: *mut wasmer_value_tag, - returns_len: c_int, -) -> wasmer_result_t { - let named_export = &*(func as *const NamedExport); - let export = &named_export.export; - if let Export::Function { ref signature, .. } = *export { - let returns: &mut [wasmer_value_tag] = - slice::from_raw_parts_mut(returns, returns_len as usize); - for (i, item) in signature.returns().iter().enumerate() { - returns[i] = item.into(); - } - wasmer_result_t::WASMER_OK - } else { - update_last_error(CApiError { - msg: "func ptr error in wasmer_export_func_returns".to_string(), - }); - wasmer_result_t::WASMER_ERROR - } -} - -/// Sets the result parameter to the arity of the returns of the wasmer_export_func_t -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_export_func_returns_arity( - func: *const wasmer_export_func_t, - result: *mut uint32_t, -) -> wasmer_result_t { - let named_export = &*(func as *const NamedExport); - let export = &named_export.export; - if let Export::Function { ref signature, .. } = *export { - *result = signature.returns().len() as uint32_t; - wasmer_result_t::WASMER_OK - } else { - update_last_error(CApiError { - msg: "func ptr error in wasmer_export_func_results_arity".to_string(), - }); - wasmer_result_t::WASMER_ERROR - } -} - /// Sets the result parameter to the arity of the params of the wasmer_import_func_t /// /// Returns `wasmer_result_t::WASMER_OK` upon success. @@ -666,124 +385,6 @@ pub extern "C" fn wasmer_import_func_destroy(func: *mut wasmer_import_func_t) { } } -/// Gets export func from export -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_export_to_func( - export: *const wasmer_export_t, -) -> *const wasmer_export_func_t { - export as *const wasmer_export_func_t -} - -/// Gets a memory pointer from an export pointer. -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_export_to_memory( - export: *const wasmer_export_t, - memory: *mut *mut wasmer_memory_t, -) -> wasmer_result_t { - let named_export = &*(export as *const NamedExport); - let export = &named_export.export; - - if let Export::Memory(exported_memory) = export { - *memory = exported_memory as *const Memory as *mut wasmer_memory_t; - wasmer_result_t::WASMER_OK - } else { - update_last_error(CApiError { - msg: "cannot cast the `wasmer_export_t` pointer to a `wasmer_memory_t` \ - pointer because it does not represent a memory export." - .to_string(), - }); - wasmer_result_t::WASMER_ERROR - } -} - -/// Gets name from wasmer_export -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_export_name(export: *mut wasmer_export_t) -> wasmer_byte_array { - let named_export = &*(export as *mut NamedExport); - wasmer_byte_array { - bytes: named_export.name.as_ptr(), - bytes_len: named_export.name.len() as u32, - } -} - -/// Calls a `func` with the provided parameters. -/// Results are set using the provided `results` pointer. -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_export_func_call( - func: *const wasmer_export_func_t, - params: *const wasmer_value_t, - params_len: c_int, - results: *mut wasmer_value_t, - results_len: c_int, -) -> wasmer_result_t { - if func.is_null() { - update_last_error(CApiError { - msg: "func ptr is null".to_string(), - }); - return wasmer_result_t::WASMER_ERROR; - } - if params.is_null() { - update_last_error(CApiError { - msg: "params ptr is null".to_string(), - }); - return wasmer_result_t::WASMER_ERROR; - } - - let params: &[wasmer_value_t] = slice::from_raw_parts(params, params_len as usize); - let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); - - let named_export = &*(func as *mut NamedExport); - - let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize); - - let instance = &*named_export.instance; - let result = instance.call(&named_export.name, ¶ms[..]); - match result { - Ok(results_vec) => { - if !results_vec.is_empty() { - let ret = match results_vec[0] { - Value::I32(x) => wasmer_value_t { - tag: wasmer_value_tag::WASM_I32, - value: wasmer_value { I32: x }, - }, - Value::I64(x) => wasmer_value_t { - tag: wasmer_value_tag::WASM_I64, - value: wasmer_value { I64: x }, - }, - Value::F32(x) => wasmer_value_t { - tag: wasmer_value_tag::WASM_F32, - value: wasmer_value { F32: x }, - }, - Value::F64(x) => wasmer_value_t { - tag: wasmer_value_tag::WASM_F64, - value: wasmer_value { F64: x }, - }, - }; - results[0] = ret; - } - wasmer_result_t::WASMER_OK - } - Err(err) => { - update_last_error(err); - wasmer_result_t::WASMER_ERROR - } - } -} - impl From for Value { fn from(v: wasmer_value_t) -> Self { unsafe { @@ -868,34 +469,8 @@ impl From<&wasmer_runtime::wasm::Type> for wasmer_value_tag { } } -impl From<(&std::string::String, &ExportIndex)> for NamedExportDescriptor { - fn from((name, export_index): (&String, &ExportIndex)) -> Self { - let kind = match *export_index { - ExportIndex::Memory(_) => wasmer_import_export_kind::WASM_MEMORY, - ExportIndex::Global(_) => wasmer_import_export_kind::WASM_GLOBAL, - ExportIndex::Table(_) => wasmer_import_export_kind::WASM_TABLE, - ExportIndex::Func(_) => wasmer_import_export_kind::WASM_FUNCTION, - }; - NamedExportDescriptor { - name: name.clone(), - kind, - } - } -} - struct NamedImportDescriptor { module: String, name: String, kind: wasmer_import_export_kind, } - -struct NamedExport { - name: String, - export: Export, - instance: *mut Instance, -} - -struct NamedExportDescriptor { - name: String, - kind: wasmer_import_export_kind, -} From 361ff81db7f847fc92c20db7808e2673d8abae1c Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 29 Mar 2019 15:50:16 +0100 Subject: [PATCH 10/12] feat(runtime-c-api) Extract the `import` module. --- lib/runtime-c-api/src/export.rs | 3 +- lib/runtime-c-api/src/import.rs | 358 ++++++++++++++++++++++++++++++ lib/runtime-c-api/src/instance.rs | 5 +- lib/runtime-c-api/src/lib.rs | 356 +---------------------------- lib/runtime-c-api/src/module.rs | 5 +- 5 files changed, 370 insertions(+), 357 deletions(-) create mode 100644 lib/runtime-c-api/src/import.rs diff --git a/lib/runtime-c-api/src/export.rs b/lib/runtime-c-api/src/export.rs index ea37fdad60b..6bcae32f272 100644 --- a/lib/runtime-c-api/src/export.rs +++ b/lib/runtime-c-api/src/export.rs @@ -3,11 +3,12 @@ use crate::{ error::{update_last_error, CApiError}, global::wasmer_global_t, + import::wasmer_import_func_t, memory::wasmer_memory_t, module::wasmer_module_t, table::wasmer_table_t, value::{wasmer_value, wasmer_value_t, wasmer_value_tag}, - wasmer_byte_array, wasmer_import_func_t, wasmer_result_t, + wasmer_byte_array, wasmer_result_t, }; use libc::{c_int, uint32_t}; use std::{ptr, slice}; diff --git a/lib/runtime-c-api/src/import.rs b/lib/runtime-c-api/src/import.rs new file mode 100644 index 00000000000..cc3598078b2 --- /dev/null +++ b/lib/runtime-c-api/src/import.rs @@ -0,0 +1,358 @@ +//! Wasm imports. + +use crate::{ + error::{update_last_error, CApiError}, + export::{wasmer_import_export_kind, wasmer_import_export_value}, + module::wasmer_module_t, + value::wasmer_value_tag, + wasmer_byte_array, wasmer_result_t, +}; +use libc::{c_int, uint32_t}; +use std::{ffi::c_void, ptr, slice, sync::Arc}; +use wasmer_runtime::Module; +use wasmer_runtime_core::{ + export::{Context, Export, FuncPointer}, + module::ImportName, + types::{FuncSig, Type}, +}; + +#[repr(C)] +pub struct wasmer_import_t { + pub module_name: wasmer_byte_array, + pub import_name: wasmer_byte_array, + pub tag: wasmer_import_export_kind, + pub value: wasmer_import_export_value, +} + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_import_func_t; + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_import_descriptor_t; + +#[repr(C)] +#[derive(Clone)] +pub struct wasmer_import_descriptors_t; + +/// Gets import descriptors for the given module +/// +/// The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_import_descriptors( + module: *const wasmer_module_t, + import_descriptors: *mut *mut wasmer_import_descriptors_t, +) { + let module = &*(module as *const Module); + let total_imports = module.info().imported_functions.len() + + module.info().imported_tables.len() + + module.info().imported_globals.len() + + module.info().imported_memories.len(); + let mut descriptors: Vec = Vec::with_capacity(total_imports); + + for ( + _index, + ImportName { + namespace_index, + name_index, + }, + ) in &module.info().imported_functions + { + let namespace = module.info().namespace_table.get(*namespace_index); + let name = module.info().name_table.get(*name_index); + descriptors.push(NamedImportDescriptor { + module: namespace.to_string(), + name: name.to_string(), + kind: wasmer_import_export_kind::WASM_FUNCTION, + }); + } + + for ( + _index, + ( + ImportName { + namespace_index, + name_index, + }, + _, + ), + ) in &module.info().imported_tables + { + let namespace = module.info().namespace_table.get(*namespace_index); + let name = module.info().name_table.get(*name_index); + descriptors.push(NamedImportDescriptor { + module: namespace.to_string(), + name: name.to_string(), + kind: wasmer_import_export_kind::WASM_TABLE, + }); + } + + for ( + _index, + ( + ImportName { + namespace_index, + name_index, + }, + _, + ), + ) in &module.info().imported_globals + { + let namespace = module.info().namespace_table.get(*namespace_index); + let name = module.info().name_table.get(*name_index); + descriptors.push(NamedImportDescriptor { + module: namespace.to_string(), + name: name.to_string(), + kind: wasmer_import_export_kind::WASM_GLOBAL, + }); + } + + for ( + _index, + ( + ImportName { + namespace_index, + name_index, + }, + _, + ), + ) in &module.info().imported_memories + { + let namespace = module.info().namespace_table.get(*namespace_index); + let name = module.info().name_table.get(*name_index); + descriptors.push(NamedImportDescriptor { + module: namespace.to_string(), + name: name.to_string(), + kind: wasmer_import_export_kind::WASM_MEMORY, + }); + } + + let named_import_descriptors: Box = + Box::new(NamedImportDescriptors(descriptors)); + *import_descriptors = + Box::into_raw(named_import_descriptors) as *mut wasmer_import_descriptors_t; +} + +pub struct NamedImportDescriptors(Vec); + +/// Frees the memory for the given import descriptors +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_import_descriptors_destroy( + import_descriptors: *mut wasmer_import_descriptors_t, +) { + if !import_descriptors.is_null() { + unsafe { Box::from_raw(import_descriptors as *mut NamedImportDescriptors) }; + } +} + +/// Gets the length of the import descriptors +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_import_descriptors_len( + exports: *mut wasmer_import_descriptors_t, +) -> c_int { + if exports.is_null() { + return 0; + } + (*(exports as *mut NamedImportDescriptors)).0.len() as c_int +} + +/// Gets import descriptor by index +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_import_descriptors_get( + import_descriptors: *mut wasmer_import_descriptors_t, + idx: c_int, +) -> *mut wasmer_import_descriptor_t { + if import_descriptors.is_null() { + return ptr::null_mut(); + } + let named_import_descriptors = &mut *(import_descriptors as *mut NamedImportDescriptors); + &mut (*named_import_descriptors).0[idx as usize] as *mut NamedImportDescriptor + as *mut wasmer_import_descriptor_t +} + +/// Gets name for the import descriptor +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_import_descriptor_name( + import_descriptor: *mut wasmer_import_descriptor_t, +) -> wasmer_byte_array { + let named_import_descriptor = &*(import_descriptor as *mut NamedImportDescriptor); + wasmer_byte_array { + bytes: named_import_descriptor.name.as_ptr(), + bytes_len: named_import_descriptor.name.len() as u32, + } +} + +/// Gets module name for the import descriptor +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_import_descriptor_module_name( + import_descriptor: *mut wasmer_import_descriptor_t, +) -> wasmer_byte_array { + let named_import_descriptor = &*(import_descriptor as *mut NamedImportDescriptor); + wasmer_byte_array { + bytes: named_import_descriptor.module.as_ptr(), + bytes_len: named_import_descriptor.module.len() as u32, + } +} + +/// Gets export descriptor kind +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_import_descriptor_kind( + export: *mut wasmer_import_descriptor_t, +) -> wasmer_import_export_kind { + let named_import_descriptor = &*(export as *mut NamedImportDescriptor); + named_import_descriptor.kind.clone() +} + +/// Sets the result parameter to the arity of the params of the wasmer_import_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_import_func_params_arity( + func: *const wasmer_import_func_t, + result: *mut uint32_t, +) -> wasmer_result_t { + let export = &*(func as *const Export); + if let Export::Function { ref signature, .. } = *export { + *result = signature.params().len() as uint32_t; + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_import_func_params_arity".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } +} + +/// Creates new func +/// +/// The caller owns the object and should call `wasmer_import_func_destroy` to free it. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_import_func_new( + func: extern "C" fn(data: *mut c_void), + params: *const wasmer_value_tag, + params_len: c_int, + returns: *const wasmer_value_tag, + returns_len: c_int, +) -> *mut wasmer_import_func_t { + let params: &[wasmer_value_tag] = slice::from_raw_parts(params, params_len as usize); + let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); + let returns: &[wasmer_value_tag] = slice::from_raw_parts(returns, returns_len as usize); + let returns: Vec = returns.iter().cloned().map(|x| x.into()).collect(); + + let export = Box::new(Export::Function { + func: FuncPointer::new(func as _), + ctx: Context::Internal, + signature: Arc::new(FuncSig::new(params, returns)), + }); + Box::into_raw(export) as *mut wasmer_import_func_t +} + +/// Sets the params buffer to the parameter types of the given wasmer_import_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_import_func_params( + func: *const wasmer_import_func_t, + params: *mut wasmer_value_tag, + params_len: c_int, +) -> wasmer_result_t { + let export = &*(func as *const Export); + if let Export::Function { ref signature, .. } = *export { + let params: &mut [wasmer_value_tag] = + slice::from_raw_parts_mut(params, params_len as usize); + for (i, item) in signature.params().iter().enumerate() { + params[i] = item.into(); + } + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_import_func_params".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } +} + +/// Sets the returns buffer to the parameter types of the given wasmer_import_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_import_func_returns( + func: *const wasmer_import_func_t, + returns: *mut wasmer_value_tag, + returns_len: c_int, +) -> wasmer_result_t { + let export = &*(func as *const Export); + if let Export::Function { ref signature, .. } = *export { + let returns: &mut [wasmer_value_tag] = + slice::from_raw_parts_mut(returns, returns_len as usize); + for (i, item) in signature.returns().iter().enumerate() { + returns[i] = item.into(); + } + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_import_func_returns".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } +} + +/// Sets the result parameter to the arity of the returns of the wasmer_import_func_t +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_import_func_returns_arity( + func: *const wasmer_import_func_t, + result: *mut uint32_t, +) -> wasmer_result_t { + let export = &*(func as *const Export); + if let Export::Function { ref signature, .. } = *export { + *result = signature.returns().len() as uint32_t; + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "func ptr error in wasmer_import_func_results_arity".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } +} + +/// Frees memory for the given Func +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_import_func_destroy(func: *mut wasmer_import_func_t) { + if !func.is_null() { + unsafe { Box::from_raw(func as *mut Export) }; + } +} + +struct NamedImportDescriptor { + module: String, + name: String, + kind: wasmer_import_export_kind, +} diff --git a/lib/runtime-c-api/src/instance.rs b/lib/runtime-c-api/src/instance.rs index 093d381e913..a9d7d5555a6 100644 --- a/lib/runtime-c-api/src/instance.rs +++ b/lib/runtime-c-api/src/instance.rs @@ -2,10 +2,11 @@ use crate::{ error::{update_last_error, CApiError}, - export::{wasmer_exports_t, NamedExport, NamedExports}, + export::{wasmer_exports_t, wasmer_import_export_kind, NamedExport, NamedExports}, + import::wasmer_import_t, memory::wasmer_memory_t, value::{wasmer_value, wasmer_value_t, wasmer_value_tag}, - wasmer_import_export_kind, wasmer_import_t, wasmer_result_t, + wasmer_result_t, }; use libc::{c_char, c_int, c_void, uint32_t, uint8_t}; use std::{collections::HashMap, ffi::CStr, slice}; diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index b1b6724d0eb..2baa9b273b0 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -1,28 +1,21 @@ extern crate wasmer_runtime; extern crate wasmer_runtime_core; -use libc::{c_int, uint32_t, uint8_t}; -use std::slice; -use std::sync::Arc; -use std::{ffi::c_void, ptr}; -use wasmer_runtime::{Module, Value}; -use wasmer_runtime_core::export::{Context, Export, FuncPointer}; -use wasmer_runtime_core::module::ImportName; -use wasmer_runtime_core::types::{FuncSig, Type}; +use libc::{uint32_t, uint8_t}; +use wasmer_runtime::Value; +use wasmer_runtime_core::types::Type; pub mod error; pub mod export; pub mod global; +pub mod import; pub mod instance; pub mod memory; pub mod module; pub mod table; pub mod value; -use error::{update_last_error, CApiError}; -use export::{wasmer_import_export_kind, wasmer_import_export_value}; use instance::wasmer_instance_t; -use module::wasmer_module_t; use value::{wasmer_value, wasmer_value_t, wasmer_value_tag}; #[allow(non_camel_case_types)] @@ -32,10 +25,6 @@ pub enum wasmer_result_t { WASMER_ERROR = 2, } -#[repr(C)] -#[derive(Clone)] -pub struct wasmer_import_func_t; - #[repr(C)] pub struct wasmer_limits_t { pub min: uint32_t, @@ -48,343 +37,12 @@ pub struct wasmer_limit_option_t { pub some: uint32_t, } -#[repr(C)] -pub struct wasmer_import_t { - module_name: wasmer_byte_array, - import_name: wasmer_byte_array, - tag: wasmer_import_export_kind, - value: wasmer_import_export_value, -} - -#[repr(C)] -#[derive(Clone)] -pub struct wasmer_import_descriptor_t; - -#[repr(C)] -#[derive(Clone)] -pub struct wasmer_import_descriptors_t; - #[repr(C)] pub struct wasmer_byte_array { bytes: *const uint8_t, bytes_len: uint32_t, } -/// Gets import descriptors for the given module -/// -/// The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it. -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_import_descriptors( - module: *const wasmer_module_t, - import_descriptors: *mut *mut wasmer_import_descriptors_t, -) { - let module = &*(module as *const Module); - let total_imports = module.info().imported_functions.len() - + module.info().imported_tables.len() - + module.info().imported_globals.len() - + module.info().imported_memories.len(); - let mut descriptors: Vec = Vec::with_capacity(total_imports); - - for ( - _index, - ImportName { - namespace_index, - name_index, - }, - ) in &module.info().imported_functions - { - let namespace = module.info().namespace_table.get(*namespace_index); - let name = module.info().name_table.get(*name_index); - descriptors.push(NamedImportDescriptor { - module: namespace.to_string(), - name: name.to_string(), - kind: wasmer_import_export_kind::WASM_FUNCTION, - }); - } - - for ( - _index, - ( - ImportName { - namespace_index, - name_index, - }, - _, - ), - ) in &module.info().imported_tables - { - let namespace = module.info().namespace_table.get(*namespace_index); - let name = module.info().name_table.get(*name_index); - descriptors.push(NamedImportDescriptor { - module: namespace.to_string(), - name: name.to_string(), - kind: wasmer_import_export_kind::WASM_TABLE, - }); - } - - for ( - _index, - ( - ImportName { - namespace_index, - name_index, - }, - _, - ), - ) in &module.info().imported_globals - { - let namespace = module.info().namespace_table.get(*namespace_index); - let name = module.info().name_table.get(*name_index); - descriptors.push(NamedImportDescriptor { - module: namespace.to_string(), - name: name.to_string(), - kind: wasmer_import_export_kind::WASM_GLOBAL, - }); - } - - for ( - _index, - ( - ImportName { - namespace_index, - name_index, - }, - _, - ), - ) in &module.info().imported_memories - { - let namespace = module.info().namespace_table.get(*namespace_index); - let name = module.info().name_table.get(*name_index); - descriptors.push(NamedImportDescriptor { - module: namespace.to_string(), - name: name.to_string(), - kind: wasmer_import_export_kind::WASM_MEMORY, - }); - } - - let named_import_descriptors: Box = - Box::new(NamedImportDescriptors(descriptors)); - *import_descriptors = - Box::into_raw(named_import_descriptors) as *mut wasmer_import_descriptors_t; -} - -pub struct NamedImportDescriptors(Vec); - -/// Frees the memory for the given import descriptors -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_import_descriptors_destroy( - import_descriptors: *mut wasmer_import_descriptors_t, -) { - if !import_descriptors.is_null() { - unsafe { Box::from_raw(import_descriptors as *mut NamedImportDescriptors) }; - } -} - -/// Gets the length of the import descriptors -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_import_descriptors_len( - exports: *mut wasmer_import_descriptors_t, -) -> c_int { - if exports.is_null() { - return 0; - } - (*(exports as *mut NamedImportDescriptors)).0.len() as c_int -} - -/// Gets import descriptor by index -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub unsafe extern "C" fn wasmer_import_descriptors_get( - import_descriptors: *mut wasmer_import_descriptors_t, - idx: c_int, -) -> *mut wasmer_import_descriptor_t { - if import_descriptors.is_null() { - return ptr::null_mut(); - } - let named_import_descriptors = &mut *(import_descriptors as *mut NamedImportDescriptors); - &mut (*named_import_descriptors).0[idx as usize] as *mut NamedImportDescriptor - as *mut wasmer_import_descriptor_t -} - -/// Gets name for the import descriptor -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_import_descriptor_name( - import_descriptor: *mut wasmer_import_descriptor_t, -) -> wasmer_byte_array { - let named_import_descriptor = &*(import_descriptor as *mut NamedImportDescriptor); - wasmer_byte_array { - bytes: named_import_descriptor.name.as_ptr(), - bytes_len: named_import_descriptor.name.len() as u32, - } -} - -/// Gets module name for the import descriptor -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_import_descriptor_module_name( - import_descriptor: *mut wasmer_import_descriptor_t, -) -> wasmer_byte_array { - let named_import_descriptor = &*(import_descriptor as *mut NamedImportDescriptor); - wasmer_byte_array { - bytes: named_import_descriptor.module.as_ptr(), - bytes_len: named_import_descriptor.module.len() as u32, - } -} - -/// Gets export descriptor kind -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_import_descriptor_kind( - export: *mut wasmer_import_descriptor_t, -) -> wasmer_import_export_kind { - let named_import_descriptor = &*(export as *mut NamedImportDescriptor); - named_import_descriptor.kind.clone() -} - -/// Sets the result parameter to the arity of the params of the wasmer_import_func_t -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_import_func_params_arity( - func: *const wasmer_import_func_t, - result: *mut uint32_t, -) -> wasmer_result_t { - let export = &*(func as *const Export); - if let Export::Function { ref signature, .. } = *export { - *result = signature.params().len() as uint32_t; - wasmer_result_t::WASMER_OK - } else { - update_last_error(CApiError { - msg: "func ptr error in wasmer_import_func_params_arity".to_string(), - }); - wasmer_result_t::WASMER_ERROR - } -} - -/// Creates new func -/// -/// The caller owns the object and should call `wasmer_import_func_destroy` to free it. -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_import_func_new( - func: extern "C" fn(data: *mut c_void), - params: *const wasmer_value_tag, - params_len: c_int, - returns: *const wasmer_value_tag, - returns_len: c_int, -) -> *mut wasmer_import_func_t { - let params: &[wasmer_value_tag] = slice::from_raw_parts(params, params_len as usize); - let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); - let returns: &[wasmer_value_tag] = slice::from_raw_parts(returns, returns_len as usize); - let returns: Vec = returns.iter().cloned().map(|x| x.into()).collect(); - - let export = Box::new(Export::Function { - func: FuncPointer::new(func as _), - ctx: Context::Internal, - signature: Arc::new(FuncSig::new(params, returns)), - }); - Box::into_raw(export) as *mut wasmer_import_func_t -} - -/// Sets the params buffer to the parameter types of the given wasmer_import_func_t -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_import_func_params( - func: *const wasmer_import_func_t, - params: *mut wasmer_value_tag, - params_len: c_int, -) -> wasmer_result_t { - let export = &*(func as *const Export); - if let Export::Function { ref signature, .. } = *export { - let params: &mut [wasmer_value_tag] = - slice::from_raw_parts_mut(params, params_len as usize); - for (i, item) in signature.params().iter().enumerate() { - params[i] = item.into(); - } - wasmer_result_t::WASMER_OK - } else { - update_last_error(CApiError { - msg: "func ptr error in wasmer_import_func_params".to_string(), - }); - wasmer_result_t::WASMER_ERROR - } -} - -/// Sets the returns buffer to the parameter types of the given wasmer_import_func_t -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_import_func_returns( - func: *const wasmer_import_func_t, - returns: *mut wasmer_value_tag, - returns_len: c_int, -) -> wasmer_result_t { - let export = &*(func as *const Export); - if let Export::Function { ref signature, .. } = *export { - let returns: &mut [wasmer_value_tag] = - slice::from_raw_parts_mut(returns, returns_len as usize); - for (i, item) in signature.returns().iter().enumerate() { - returns[i] = item.into(); - } - wasmer_result_t::WASMER_OK - } else { - update_last_error(CApiError { - msg: "func ptr error in wasmer_import_func_returns".to_string(), - }); - wasmer_result_t::WASMER_ERROR - } -} - -/// Sets the result parameter to the arity of the returns of the wasmer_import_func_t -/// -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. -#[no_mangle] -#[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_import_func_returns_arity( - func: *const wasmer_import_func_t, - result: *mut uint32_t, -) -> wasmer_result_t { - let export = &*(func as *const Export); - if let Export::Function { ref signature, .. } = *export { - *result = signature.returns().len() as uint32_t; - wasmer_result_t::WASMER_OK - } else { - update_last_error(CApiError { - msg: "func ptr error in wasmer_import_func_results_arity".to_string(), - }); - wasmer_result_t::WASMER_ERROR - } -} - -/// Frees memory for the given Func -#[allow(clippy::cast_ptr_alignment)] -#[no_mangle] -pub extern "C" fn wasmer_import_func_destroy(func: *mut wasmer_import_func_t) { - if !func.is_null() { - unsafe { Box::from_raw(func as *mut Export) }; - } -} - impl From for Value { fn from(v: wasmer_value_t) -> Self { unsafe { @@ -468,9 +126,3 @@ impl From<&wasmer_runtime::wasm::Type> for wasmer_value_tag { } } } - -struct NamedImportDescriptor { - module: String, - name: String, - kind: wasmer_import_export_kind, -} diff --git a/lib/runtime-c-api/src/module.rs b/lib/runtime-c-api/src/module.rs index 18f1696212d..0e4961ab148 100644 --- a/lib/runtime-c-api/src/module.rs +++ b/lib/runtime-c-api/src/module.rs @@ -2,8 +2,9 @@ use crate::{ error::{update_last_error, CApiError}, - wasmer_byte_array, wasmer_import_export_kind, wasmer_import_t, wasmer_instance_t, - wasmer_result_t, + export::wasmer_import_export_kind, + import::wasmer_import_t, + wasmer_byte_array, wasmer_instance_t, wasmer_result_t, }; use libc::{c_int, uint32_t, uint8_t}; use std::{collections::HashMap, slice}; From 849af629110cd4d69f33524e646d7222bebdfb36 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 29 Mar 2019 15:52:41 +0100 Subject: [PATCH 11/12] feat(runtime-c-api) Finish to extract last pieces of code. --- lib/runtime-c-api/src/lib.rs | 89 --------------------------------- lib/runtime-c-api/src/module.rs | 3 +- lib/runtime-c-api/src/value.rs | 86 +++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 90 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index 2baa9b273b0..aa6455f6060 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -2,8 +2,6 @@ extern crate wasmer_runtime; extern crate wasmer_runtime_core; use libc::{uint32_t, uint8_t}; -use wasmer_runtime::Value; -use wasmer_runtime_core::types::Type; pub mod error; pub mod export; @@ -15,9 +13,6 @@ pub mod module; pub mod table; pub mod value; -use instance::wasmer_instance_t; -use value::{wasmer_value, wasmer_value_t, wasmer_value_tag}; - #[allow(non_camel_case_types)] #[repr(C)] pub enum wasmer_result_t { @@ -42,87 +37,3 @@ pub struct wasmer_byte_array { bytes: *const uint8_t, bytes_len: uint32_t, } - -impl From for Value { - fn from(v: wasmer_value_t) -> Self { - unsafe { - match v { - wasmer_value_t { - tag: wasmer_value_tag::WASM_I32, - value: wasmer_value { I32 }, - } => Value::I32(I32), - wasmer_value_t { - tag: wasmer_value_tag::WASM_I64, - value: wasmer_value { I64 }, - } => Value::I64(I64), - wasmer_value_t { - tag: wasmer_value_tag::WASM_F32, - value: wasmer_value { F32 }, - } => Value::F32(F32), - wasmer_value_t { - tag: wasmer_value_tag::WASM_F64, - value: wasmer_value { F64 }, - } => Value::F64(F64), - _ => panic!("not implemented"), - } - } - } -} - -impl From for wasmer_value_t { - fn from(val: Value) -> Self { - match val { - Value::I32(x) => wasmer_value_t { - tag: wasmer_value_tag::WASM_I32, - value: wasmer_value { I32: x }, - }, - Value::I64(x) => wasmer_value_t { - tag: wasmer_value_tag::WASM_I64, - value: wasmer_value { I64: x }, - }, - Value::F32(x) => wasmer_value_t { - tag: wasmer_value_tag::WASM_F32, - value: wasmer_value { F32: x }, - }, - Value::F64(x) => wasmer_value_t { - tag: wasmer_value_tag::WASM_F64, - value: wasmer_value { F64: x }, - }, - } - } -} - -impl From for wasmer_value_tag { - fn from(ty: Type) -> Self { - match ty { - Type::I32 => wasmer_value_tag::WASM_I32, - Type::I64 => wasmer_value_tag::WASM_I64, - Type::F32 => wasmer_value_tag::WASM_F32, - Type::F64 => wasmer_value_tag::WASM_F64, - _ => panic!("not implemented"), - } - } -} - -impl From for Type { - fn from(v: wasmer_value_tag) -> Self { - match v { - wasmer_value_tag::WASM_I32 => Type::I32, - wasmer_value_tag::WASM_I64 => Type::I64, - wasmer_value_tag::WASM_F32 => Type::F32, - wasmer_value_tag::WASM_F64 => Type::F64, - _ => panic!("not implemented"), - } - } -} - -impl From<&wasmer_runtime::wasm::Type> for wasmer_value_tag { - fn from(ty: &Type) -> Self { - match *ty { - Type::I32 => wasmer_value_tag::WASM_I32, - Type::I64 => wasmer_value_tag::WASM_I64, - Type::F32 => wasmer_value_tag::WASM_F32, - Type::F64 => wasmer_value_tag::WASM_F64, - } - } -} diff --git a/lib/runtime-c-api/src/module.rs b/lib/runtime-c-api/src/module.rs index 0e4961ab148..42d9815a68b 100644 --- a/lib/runtime-c-api/src/module.rs +++ b/lib/runtime-c-api/src/module.rs @@ -4,7 +4,8 @@ use crate::{ error::{update_last_error, CApiError}, export::wasmer_import_export_kind, import::wasmer_import_t, - wasmer_byte_array, wasmer_instance_t, wasmer_result_t, + instance::wasmer_instance_t, + wasmer_byte_array, wasmer_result_t, }; use libc::{c_int, uint32_t, uint8_t}; use std::{collections::HashMap, slice}; diff --git a/lib/runtime-c-api/src/value.rs b/lib/runtime-c-api/src/value.rs index fc4e791a064..03a03dc5faf 100644 --- a/lib/runtime-c-api/src/value.rs +++ b/lib/runtime-c-api/src/value.rs @@ -1,6 +1,8 @@ //! Wasm values. use libc::{int32_t, int64_t}; +use wasmer_runtime::Value; +use wasmer_runtime_core::types::Type; #[allow(non_camel_case_types)] #[repr(u32)] @@ -27,3 +29,87 @@ pub struct wasmer_value_t { pub tag: wasmer_value_tag, pub value: wasmer_value, } + +impl From for Value { + fn from(v: wasmer_value_t) -> Self { + unsafe { + match v { + wasmer_value_t { + tag: wasmer_value_tag::WASM_I32, + value: wasmer_value { I32 }, + } => Value::I32(I32), + wasmer_value_t { + tag: wasmer_value_tag::WASM_I64, + value: wasmer_value { I64 }, + } => Value::I64(I64), + wasmer_value_t { + tag: wasmer_value_tag::WASM_F32, + value: wasmer_value { F32 }, + } => Value::F32(F32), + wasmer_value_t { + tag: wasmer_value_tag::WASM_F64, + value: wasmer_value { F64 }, + } => Value::F64(F64), + _ => panic!("not implemented"), + } + } + } +} + +impl From for wasmer_value_t { + fn from(val: Value) -> Self { + match val { + Value::I32(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_I32, + value: wasmer_value { I32: x }, + }, + Value::I64(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_I64, + value: wasmer_value { I64: x }, + }, + Value::F32(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_F32, + value: wasmer_value { F32: x }, + }, + Value::F64(x) => wasmer_value_t { + tag: wasmer_value_tag::WASM_F64, + value: wasmer_value { F64: x }, + }, + } + } +} + +impl From for wasmer_value_tag { + fn from(ty: Type) -> Self { + match ty { + Type::I32 => wasmer_value_tag::WASM_I32, + Type::I64 => wasmer_value_tag::WASM_I64, + Type::F32 => wasmer_value_tag::WASM_F32, + Type::F64 => wasmer_value_tag::WASM_F64, + _ => panic!("not implemented"), + } + } +} + +impl From for Type { + fn from(v: wasmer_value_tag) -> Self { + match v { + wasmer_value_tag::WASM_I32 => Type::I32, + wasmer_value_tag::WASM_I64 => Type::I64, + wasmer_value_tag::WASM_F32 => Type::F32, + wasmer_value_tag::WASM_F64 => Type::F64, + _ => panic!("not implemented"), + } + } +} + +impl From<&wasmer_runtime::wasm::Type> for wasmer_value_tag { + fn from(ty: &Type) -> Self { + match *ty { + Type::I32 => wasmer_value_tag::WASM_I32, + Type::I64 => wasmer_value_tag::WASM_I64, + Type::F32 => wasmer_value_tag::WASM_F32, + Type::F64 => wasmer_value_tag::WASM_F64, + } + } +} From 8ee0f16c8a783dff5739f3b2c6676e9fdbe74352 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 29 Mar 2019 15:56:08 +0100 Subject: [PATCH 12/12] fix(runtime-c-api) Remove last warnings. --- lib/runtime-c-api/src/value.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/runtime-c-api/src/value.rs b/lib/runtime-c-api/src/value.rs index 03a03dc5faf..c0a3e64d8f0 100644 --- a/lib/runtime-c-api/src/value.rs +++ b/lib/runtime-c-api/src/value.rs @@ -16,6 +16,7 @@ pub enum wasmer_value_tag { #[repr(C)] #[derive(Clone, Copy)] +#[allow(non_snake_case)] pub union wasmer_value { pub I32: int32_t, pub I64: int64_t, @@ -33,6 +34,7 @@ pub struct wasmer_value_t { impl From for Value { fn from(v: wasmer_value_t) -> Self { unsafe { + #[allow(unreachable_patterns, non_snake_case)] match v { wasmer_value_t { tag: wasmer_value_tag::WASM_I32, @@ -81,6 +83,7 @@ impl From for wasmer_value_t { impl From for wasmer_value_tag { fn from(ty: Type) -> Self { + #[allow(unreachable_patterns)] match ty { Type::I32 => wasmer_value_tag::WASM_I32, Type::I64 => wasmer_value_tag::WASM_I64, @@ -93,6 +96,7 @@ impl From for wasmer_value_tag { impl From for Type { fn from(v: wasmer_value_tag) -> Self { + #[allow(unreachable_patterns)] match v { wasmer_value_tag::WASM_I32 => Type::I32, wasmer_value_tag::WASM_I64 => Type::I64,