From 9916c9bc5cd2af982f1dbb24eb44f76ea1c707bf Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 3 Dec 2020 11:12:16 -0800 Subject: [PATCH] Update the C API with module linking support This commit does everything necessary (ideally) to support the module linking proposal in the C API. The changes here are: * New `wasm_{module,instance}type_t` types and accessors * New `wasm_{module,instance}_type` functions * Conversions between `wasm_extern_t` and `wasm_{instance,module}_t`, as well as `wasm_externtype_t` and the new types. * Addition of `WASM_EXTERN_{MODULE,INSTANCE}` constants * New `wasm_config_t` modifier to enable/disable module linking With these functions it should be possible to pass instances/modules to instances and also acquire them from exports. Altogether this should enable everything for module linking. An important point for this is that I've opted to add all these items under the `wasm_*` name prefix instead of `wasmtime_*`. I've done this since they're all following the idioms of existing APIs and while not standard the intention would be to standardize them (unlike many other Wasmtime-specific APIs). cc #2094 --- crates/c-api/include/doc-wasm.h | 3 + crates/c-api/include/wasmtime.h | 286 +++++++++++++++++++++++++++++ crates/c-api/src/config.rs | 5 + crates/c-api/src/extern.rs | 32 +++- crates/c-api/src/instance.rs | 44 ++++- crates/c-api/src/linker.rs | 6 +- crates/c-api/src/module.rs | 140 +++++++------- crates/c-api/src/types/extern.rs | 8 +- crates/c-api/src/types/instance.rs | 41 ++++- crates/c-api/src/types/module.rs | 64 ++++++- crates/c-api/src/vec.rs | 27 ++- 11 files changed, 542 insertions(+), 114 deletions(-) diff --git a/crates/c-api/include/doc-wasm.h b/crates/c-api/include/doc-wasm.h index 301989437d54..c3f4d8c33073 100644 --- a/crates/c-api/include/doc-wasm.h +++ b/crates/c-api/include/doc-wasm.h @@ -795,6 +795,9 @@ * * \enum wasm_externkind_enum * \brief Kinds of external items for a wasm module. + * + * Note that this also includes `WASM_EXTERN_INSTANCE` as well as + * `WASM_EXTERN_MODULE`. */ /** diff --git a/crates/c-api/include/wasmtime.h b/crates/c-api/include/wasmtime.h index 75880ce02053..d61b1395f74f 100644 --- a/crates/c-api/include/wasmtime.h +++ b/crates/c-api/include/wasmtime.h @@ -208,6 +208,14 @@ WASMTIME_CONFIG_PROP(void, wasm_bulk_memory, bool) */ WASMTIME_CONFIG_PROP(void, wasm_multi_value, bool) +/** + * \brief Configures whether the WebAssembly module linking proposal is + * enabled. + * + * This setting is `false` by default. + */ +WASMTIME_CONFIG_PROP(void, wasm_module_linking, bool) + /** * \brief Configures how JIT code will be compiled. * @@ -961,6 +969,284 @@ WASM_API_EXTERN own wasmtime_error_t *wasmtime_module_deserialize( own wasm_module_t **ret ); +/** + * \struct wasm_instancetype_t + * \brief An opaque object representing the type of a function. + * + * \typedef wasm_instancetype_t + * \brief Convenience alias for #wasm_instancetype_t + * + * \struct wasm_instancetype_vec_t + * \brief A list of #wasm_instancetype_t values. + * + * \var wasm_instancetype_vec_t::size + * \brief Length of this vector. + * + * \var wasm_instancetype_vec_t::data + * \brief Pointer to the base of this vector + * + * \typedef wasm_instancetype_vec_t + * \brief Convenience alias for #wasm_instancetype_vec_t + * + * \fn void wasm_instancetype_delete(own wasm_instancetype_t *); + * \brief Deletes a type. + * + * \fn void wasm_instancetype_vec_new_empty(own wasm_instancetype_vec_t *out); + * \brief Creates an empty vector. + * + * See #wasm_byte_vec_new_empty for more information. + * + * \fn void wasm_instancetype_vec_new_uninitialized(own wasm_instancetype_vec_t *out, size_t); + * \brief Creates a vector with the given capacity. + * + * See #wasm_byte_vec_new_uninitialized for more information. + * + * \fn void wasm_instancetype_vec_new(own wasm_instancetype_vec_t *out, size_t, own wasm_instancetype_t *const[]); + * \brief Creates a vector with the provided contents. + * + * See #wasm_byte_vec_new for more information. + * + * \fn void wasm_instancetype_vec_copy(own wasm_instancetype_vec_t *out, const wasm_instancetype_vec_t *) + * \brief Copies one vector to another + * + * See #wasm_byte_vec_copy for more information. + * + * \fn void wasm_instancetype_vec_delete(own wasm_instancetype_vec_t *out) + * \brief Deallocates memory for a vector. + * + * See #wasm_byte_vec_delete for more information. + * + * \fn own wasm_instancetype_t* wasm_instancetype_copy(wasm_instancetype_t *) + * \brief Creates a new value which matches the provided one. + * + * The caller is responsible for deleting the returned value. + */ +WASM_DECLARE_TYPE(instancetype) + +/** + * \brief Returns the list of exports that this instance type provides. + * + * This function does not take ownership of the provided instance type but + * ownership of `out` is passed to the caller. Note that `out` is treated as + * uninitialized when passed to this function. + */ +WASM_API_EXTERN void wasm_instancetype_exports(const wasm_instancetype_t*, own wasm_exporttype_vec_t* out); + +/** + * \brief Converts a #wasm_instancetype_t to a #wasm_externtype_t + * + * The returned value is owned by the #wasm_instancetype_t argument and should not + * be deleted. + */ +WASM_API_EXTERN wasm_externtype_t* wasm_instancetype_as_externtype(wasm_instancetype_t*); + +/** + * \brief Attempts to convert a #wasm_externtype_t to a #wasm_instancetype_t + * + * The returned value is owned by the #wasm_instancetype_t argument and should not + * be deleted. Returns `NULL` if the provided argument is not a + * #wasm_instancetype_t. + */ +WASM_API_EXTERN wasm_instancetype_t* wasm_externtype_as_instancetype(wasm_externtype_t*); + +/** + * \brief Converts a #wasm_instancetype_t to a #wasm_externtype_t + * + * The returned value is owned by the #wasm_instancetype_t argument and should not + * be deleted. + */ +WASM_API_EXTERN const wasm_externtype_t* wasm_instancetype_as_externtype_const(const wasm_instancetype_t*); + +/** + * \brief Attempts to convert a #wasm_externtype_t to a #wasm_instancetype_t + * + * The returned value is owned by the #wasm_instancetype_t argument and should not + * be deleted. Returns `NULL` if the provided argument is not a + * #wasm_instancetype_t. + */ +WASM_API_EXTERN const wasm_instancetype_t* wasm_externtype_as_instancetype_const(const wasm_externtype_t*); + +/** + * \struct wasm_moduletype_t + * \brief An opaque object representing the type of a function. + * + * \typedef wasm_moduletype_t + * \brief Convenience alias for #wasm_moduletype_t + * + * \struct wasm_moduletype_vec_t + * \brief A list of #wasm_moduletype_t values. + * + * \var wasm_moduletype_vec_t::size + * \brief Length of this vector. + * + * \var wasm_moduletype_vec_t::data + * \brief Pointer to the base of this vector + * + * \typedef wasm_moduletype_vec_t + * \brief Convenience alias for #wasm_moduletype_vec_t + * + * \fn void wasm_moduletype_delete(own wasm_moduletype_t *); + * \brief Deletes a type. + * + * \fn void wasm_moduletype_vec_new_empty(own wasm_moduletype_vec_t *out); + * \brief Creates an empty vector. + * + * See #wasm_byte_vec_new_empty for more information. + * + * \fn void wasm_moduletype_vec_new_uninitialized(own wasm_moduletype_vec_t *out, size_t); + * \brief Creates a vector with the given capacity. + * + * See #wasm_byte_vec_new_uninitialized for more information. + * + * \fn void wasm_moduletype_vec_new(own wasm_moduletype_vec_t *out, size_t, own wasm_moduletype_t *const[]); + * \brief Creates a vector with the provided contents. + * + * See #wasm_byte_vec_new for more information. + * + * \fn void wasm_moduletype_vec_copy(own wasm_moduletype_vec_t *out, const wasm_moduletype_vec_t *) + * \brief Copies one vector to another + * + * See #wasm_byte_vec_copy for more information. + * + * \fn void wasm_moduletype_vec_delete(own wasm_moduletype_vec_t *out) + * \brief Deallocates memory for a vector. + * + * See #wasm_byte_vec_delete for more information. + * + * \fn own wasm_moduletype_t* wasm_moduletype_copy(wasm_moduletype_t *) + * \brief Creates a new value which matches the provided one. + * + * The caller is responsible for deleting the returned value. + */ +WASM_DECLARE_TYPE(moduletype) + +/** + * \brief Returns the list of imports that this module type requires. + * + * This function does not take ownership of the provided module type but + * ownership of `out` is passed to the caller. Note that `out` is treated as + * uninitialized when passed to this function. + */ +WASM_API_EXTERN void wasm_moduletype_imports(const wasm_moduletype_t*, own wasm_importtype_vec_t* out); + +/** + * \brief Returns the list of exports that this module type provides. + * + * This function does not take ownership of the provided module type but + * ownership of `out` is passed to the caller. Note that `out` is treated as + * uninitialized when passed to this function. + */ +WASM_API_EXTERN void wasm_moduletype_exports(const wasm_moduletype_t*, own wasm_exporttype_vec_t* out); + +/** + * \brief Converts a #wasm_moduletype_t to a #wasm_externtype_t + * + * The returned value is owned by the #wasm_moduletype_t argument and should not + * be deleted. + */ +WASM_API_EXTERN wasm_externtype_t* wasm_moduletype_as_externtype(wasm_moduletype_t*); + +/** + * \brief Attempts to convert a #wasm_externtype_t to a #wasm_moduletype_t + * + * The returned value is owned by the #wasm_moduletype_t argument and should not + * be deleted. Returns `NULL` if the provided argument is not a + * #wasm_moduletype_t. + */ +WASM_API_EXTERN wasm_moduletype_t* wasm_externtype_as_moduletype(wasm_externtype_t*); + +/** + * \brief Converts a #wasm_moduletype_t to a #wasm_externtype_t + * + * The returned value is owned by the #wasm_moduletype_t argument and should not + * be deleted. + */ +WASM_API_EXTERN const wasm_externtype_t* wasm_moduletype_as_externtype_const(const wasm_moduletype_t*); + +/** + * \brief Attempts to convert a #wasm_externtype_t to a #wasm_moduletype_t + * + * The returned value is owned by the #wasm_moduletype_t argument and should not + * be deleted. Returns `NULL` if the provided argument is not a + * #wasm_moduletype_t. + */ +WASM_API_EXTERN const wasm_moduletype_t* wasm_externtype_as_moduletype_const(const wasm_externtype_t*); + +/** + * \brief Converts a #wasm_module_t to #wasm_extern_t. + * + * The returned #wasm_extern_t is owned by the #wasm_module_t argument. Callers + * should not delete the returned value, and it only lives as long as the + * #wasm_module_t argument. + */ +WASM_API_EXTERN wasm_extern_t* wasm_module_as_extern(wasm_module_t*); + +/** + * \brief Converts a #wasm_extern_t to #wasm_module_t. + * + * The returned #wasm_module_t is owned by the #wasm_extern_t argument. Callers + * should not delete the returned value, and it only lives as long as the + * #wasm_extern_t argument. + * + * If the #wasm_extern_t argument isn't a #wasm_module_t then `NULL` is returned. + */ +WASM_API_EXTERN wasm_module_t* wasm_extern_as_module(wasm_extern_t*); + +/** + * \brief Converts a #wasm_extern_t to #wasm_instance_t. + * + * The returned #wasm_instance_t is owned by the #wasm_extern_t argument. Callers + * should not delete the returned value, and it only lives as long as the + * #wasm_extern_t argument. + */ +WASM_API_EXTERN const wasm_module_t* wasm_extern_as_module_const(const wasm_extern_t*); + +/** + * \brief Converts a #wasm_instance_t to #wasm_extern_t. + * + * The returned #wasm_extern_t is owned by the #wasm_instance_t argument. Callers + * should not delete the returned value, and it only lives as long as the + * #wasm_instance_t argument. + */ +WASM_API_EXTERN wasm_extern_t* wasm_instance_as_extern(wasm_instance_t*); + +/** + * \brief Converts a #wasm_extern_t to #wasm_instance_t. + * + * The returned #wasm_instance_t is owned by the #wasm_extern_t argument. Callers + * should not delete the returned value, and it only lives as long as the + * #wasm_extern_t argument. + * + * If the #wasm_extern_t argument isn't a #wasm_instance_t then `NULL` is returned. + */ +WASM_API_EXTERN wasm_instance_t* wasm_extern_as_instance(wasm_extern_t*); + +/** + * \brief Converts a #wasm_extern_t to #wasm_instance_t. + * + * The returned #wasm_instance_t is owned by the #wasm_extern_t argument. Callers + * should not delete the returned value, and it only lives as long as the + * #wasm_extern_t argument. + */ +WASM_API_EXTERN const wasm_instance_t* wasm_extern_as_instance_const(const wasm_extern_t*); + +/** + * \brief Returns the type of this instance. + * + * The returned #wasm_instancetype_t is expected to be deallocated by the caller. + */ +WASM_API_EXTERN own wasm_instancetype_t* wasm_instance_type(const wasm_instance_t*); + +/** + * \brief Returns the type of this module. + * + * The returned #wasm_moduletype_t is expected to be deallocated by the caller. + */ +WASM_API_EXTERN own wasm_moduletype_t* wasm_module_type(const wasm_module_t*); + +#define WASM_EXTERN_MODULE 4 +#define WASM_EXTERN_INSTANCE 5 + #undef own #ifdef __cplusplus diff --git a/crates/c-api/src/config.rs b/crates/c-api/src/config.rs index 49dce19841dd..08da598ec136 100644 --- a/crates/c-api/src/config.rs +++ b/crates/c-api/src/config.rs @@ -85,6 +85,11 @@ pub extern "C" fn wasmtime_config_wasm_multi_value_set(c: &mut wasm_config_t, en c.config.wasm_multi_value(enable); } +#[no_mangle] +pub extern "C" fn wasmtime_config_wasm_module_linking_set(c: &mut wasm_config_t, enable: bool) { + c.config.wasm_module_linking(enable); +} + #[no_mangle] pub extern "C" fn wasmtime_config_strategy_set( c: &mut wasm_config_t, diff --git a/crates/c-api/src/extern.rs b/crates/c-api/src/extern.rs index 6a08a6e13ea2..414946a293bb 100644 --- a/crates/c-api/src/extern.rs +++ b/crates/c-api/src/extern.rs @@ -1,5 +1,7 @@ -use crate::wasm_externkind_t; -use crate::{wasm_externtype_t, wasm_func_t, wasm_global_t, wasm_memory_t, wasm_table_t}; +use crate::{ + wasm_externkind_t, wasm_externtype_t, wasm_func_t, wasm_global_t, wasm_instance_t, + wasm_memory_t, wasm_module_t, wasm_table_t, +}; use wasmtime::Extern; #[derive(Clone)] @@ -16,10 +18,8 @@ pub extern "C" fn wasm_extern_kind(e: &wasm_extern_t) -> wasm_externkind_t { Extern::Global(_) => crate::WASM_EXTERN_GLOBAL, Extern::Table(_) => crate::WASM_EXTERN_TABLE, Extern::Memory(_) => crate::WASM_EXTERN_MEMORY, - - // FIXME(#2094) - Extern::Instance(_) => unimplemented!(), - Extern::Module(_) => unimplemented!(), + Extern::Instance(_) => crate::WASM_EXTERN_INSTANCE, + Extern::Module(_) => crate::WASM_EXTERN_MODULE, } } @@ -67,3 +67,23 @@ pub extern "C" fn wasm_extern_as_memory(e: &wasm_extern_t) -> Option<&wasm_memor pub extern "C" fn wasm_extern_as_memory_const(e: &wasm_extern_t) -> Option<&wasm_memory_t> { wasm_extern_as_memory(e) } + +#[no_mangle] +pub extern "C" fn wasm_extern_as_module(e: &wasm_extern_t) -> Option<&wasm_module_t> { + wasm_module_t::try_from(e) +} + +#[no_mangle] +pub extern "C" fn wasm_extern_as_module_const(e: &wasm_extern_t) -> Option<&wasm_module_t> { + wasm_extern_as_module(e) +} + +#[no_mangle] +pub extern "C" fn wasm_extern_as_instance(e: &wasm_extern_t) -> Option<&wasm_instance_t> { + wasm_instance_t::try_from(e) +} + +#[no_mangle] +pub extern "C" fn wasm_extern_as_instance_const(e: &wasm_extern_t) -> Option<&wasm_instance_t> { + wasm_extern_as_instance(e) +} diff --git a/crates/c-api/src/instance.rs b/crates/c-api/src/instance.rs index 6fa20888861d..5a41d68a1ccb 100644 --- a/crates/c-api/src/instance.rs +++ b/crates/c-api/src/instance.rs @@ -1,20 +1,38 @@ use crate::{wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_trap_t}; -use crate::{wasm_store_t, wasmtime_error_t}; +use crate::{wasm_instancetype_t, wasm_store_t, wasmtime_error_t}; use anyhow::Result; use std::ptr; -use wasmtime::{Instance, Trap}; +use wasmtime::{Extern, Instance, Trap}; -#[repr(C)] #[derive(Clone)] +#[repr(transparent)] pub struct wasm_instance_t { - pub(crate) instance: Instance, + ext: wasm_extern_t, } wasmtime_c_api_macros::declare_ref!(wasm_instance_t); impl wasm_instance_t { pub(crate) fn new(instance: Instance) -> wasm_instance_t { - wasm_instance_t { instance: instance } + wasm_instance_t { + ext: wasm_extern_t { + which: instance.into(), + }, + } + } + + pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_instance_t> { + match &e.which { + Extern::Instance(_) => Some(unsafe { &*(e as *const _ as *const _) }), + _ => None, + } + } + + pub(crate) fn instance(&self) -> &Instance { + match &self.ext.which { + Extern::Instance(i) => i, + _ => unreachable!(), + } } } @@ -31,7 +49,7 @@ pub unsafe extern "C" fn wasm_instance_new( store, wasm_module, imports, - wasm_module.imports.len(), + wasm_module.module().imports().len(), &mut instance, &mut trap, ); @@ -92,7 +110,7 @@ fn _wasmtime_instance_new( .map(|import| import.which.clone()) .collect::>(); handle_instantiate( - Instance::new(store, &module.module, &imports), + Instance::new(store, module.module(), &imports), instance_ptr, trap_ptr, ) @@ -122,11 +140,16 @@ pub fn handle_instantiate( } } +#[no_mangle] +pub extern "C" fn wasm_instance_as_extern(m: &wasm_instance_t) -> &wasm_extern_t { + &m.ext +} + #[no_mangle] pub extern "C" fn wasm_instance_exports(instance: &wasm_instance_t, out: &mut wasm_extern_vec_t) { out.set_buffer( instance - .instance + .instance() .exports() .map(|e| { Some(Box::new(wasm_extern_t { @@ -136,3 +159,8 @@ pub extern "C" fn wasm_instance_exports(instance: &wasm_instance_t, out: &mut wa .collect(), ); } + +#[no_mangle] +pub extern "C" fn wasm_instance_type(f: &wasm_instance_t) -> Box { + Box::new(wasm_instancetype_t::new(f.instance().ty())) +} diff --git a/crates/c-api/src/linker.rs b/crates/c-api/src/linker.rs index ee77001c505d..80aa3fa94507 100644 --- a/crates/c-api/src/linker.rs +++ b/crates/c-api/src/linker.rs @@ -68,7 +68,7 @@ pub extern "C" fn wasmtime_linker_define_instance( Ok(s) => s, Err(_) => return bad_utf8(), }; - handle_result(linker.instance(name, &instance.instance), |_linker| ()) + handle_result(linker.instance(name, instance.instance()), |_linker| ()) } #[no_mangle] @@ -78,7 +78,7 @@ pub extern "C" fn wasmtime_linker_instantiate( instance_ptr: &mut *mut wasm_instance_t, trap_ptr: &mut *mut wasm_trap_t, ) -> Option> { - let result = linker.linker.instantiate(&module.module); + let result = linker.linker.instantiate(module.module()); super::instance::handle_instantiate(result, instance_ptr, trap_ptr) } @@ -93,7 +93,7 @@ pub extern "C" fn wasmtime_linker_module( Ok(s) => s, Err(_) => return bad_utf8(), }; - handle_result(linker.module(name, &module.module), |_linker| ()) + handle_result(linker.module(name, module.module()), |_linker| ()) } #[no_mangle] diff --git a/crates/c-api/src/module.rs b/crates/c-api/src/module.rs index 52f5768ce2b8..c31f125b70b3 100644 --- a/crates/c-api/src/module.rs +++ b/crates/c-api/src/module.rs @@ -1,20 +1,43 @@ use crate::{ handle_result, wasm_byte_vec_t, wasm_engine_t, wasm_exporttype_t, wasm_exporttype_vec_t, - wasm_importtype_t, wasm_importtype_vec_t, wasm_store_t, wasmtime_error_t, + wasm_extern_t, wasm_importtype_t, wasm_importtype_vec_t, wasm_moduletype_t, wasm_store_t, + wasmtime_error_t, }; use std::ptr; -use wasmtime::{Engine, Module}; +use wasmtime::{Engine, Extern, Module}; -#[repr(C)] #[derive(Clone)] +#[repr(transparent)] pub struct wasm_module_t { - pub(crate) module: Module, - pub(crate) imports: Vec, - pub(crate) exports: Vec, + ext: wasm_extern_t, } wasmtime_c_api_macros::declare_ref!(wasm_module_t); +impl wasm_module_t { + pub(crate) fn new(module: Module) -> wasm_module_t { + wasm_module_t { + ext: wasm_extern_t { + which: module.into(), + }, + } + } + + pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_module_t> { + match &e.which { + Extern::Module(_) => Some(unsafe { &*(e as *const _ as *const _) }), + _ => None, + } + } + + pub(crate) fn module(&self) -> &Module { + match &self.ext.which { + Extern::Module(i) => i, + _ => unreachable!(), + } + } +} + #[repr(C)] #[derive(Clone)] pub struct wasm_shared_module_t { @@ -49,25 +72,7 @@ pub extern "C" fn wasmtime_module_new( ) -> Option> { let binary = binary.as_slice(); handle_result(Module::from_binary(&engine.engine, binary), |module| { - let imports = module - .imports() - .map(|i| { - wasm_importtype_t::new( - i.module().to_owned(), - i.name().map(|s| s.to_owned()), - i.ty(), - ) - }) - .collect::>(); - let exports = module - .exports() - .map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty())) - .collect::>(); - let module = Box::new(wasm_module_t { - module: module, - imports, - exports, - }); + let module = Box::new(wasm_module_t::new(module)); *ret = Box::into_raw(module); }) } @@ -86,30 +91,46 @@ pub extern "C" fn wasmtime_module_validate( handle_result(Module::validate(store.store.engine(), binary), |()| {}) } +#[no_mangle] +pub extern "C" fn wasm_module_as_extern(m: &wasm_module_t) -> &wasm_extern_t { + &m.ext +} + #[no_mangle] pub extern "C" fn wasm_module_exports(module: &wasm_module_t, out: &mut wasm_exporttype_vec_t) { - let buffer = module - .exports - .iter() - .map(|et| Some(Box::new(et.clone()))) + let exports = module + .module() + .exports() + .map(|e| { + Some(Box::new(wasm_exporttype_t::new( + e.name().to_owned(), + e.ty(), + ))) + }) .collect::>(); - out.set_buffer(buffer); + out.set_buffer(exports); } #[no_mangle] pub extern "C" fn wasm_module_imports(module: &wasm_module_t, out: &mut wasm_importtype_vec_t) { - let buffer = module - .imports - .iter() - .map(|it| Some(Box::new(it.clone()))) + let imports = module + .module() + .imports() + .map(|i| { + Some(Box::new(wasm_importtype_t::new( + i.module().to_owned(), + i.name().map(|s| s.to_owned()), + i.ty(), + ))) + }) .collect::>(); - out.set_buffer(buffer); + out.set_buffer(imports); } #[no_mangle] pub extern "C" fn wasm_module_share(module: &wasm_module_t) -> Box { Box::new(wasm_shared_module_t { - module: module.module.clone(), + module: module.module().clone(), }) } @@ -122,25 +143,7 @@ pub extern "C" fn wasm_module_obtain( if !Engine::same(store.store.engine(), module.engine()) { return None; } - let imports = module - .imports() - .map(|i| { - wasm_importtype_t::new( - i.module().to_owned(), - i.name().map(|s| s.to_owned()), - i.ty(), - ) - }) - .collect::>(); - let exports = module - .exports() - .map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty())) - .collect::>(); - Some(Box::new(wasm_module_t { - module: module, - imports, - exports, - })) + Some(Box::new(wasm_module_t::new(module))) } #[no_mangle] @@ -171,7 +174,7 @@ pub extern "C" fn wasmtime_module_serialize( module: &wasm_module_t, ret: &mut wasm_byte_vec_t, ) -> Option> { - handle_result(module.module.serialize(), |buf| { + handle_result(module.module().serialize(), |buf| { ret.set_buffer(buf); }) } @@ -185,26 +188,13 @@ pub extern "C" fn wasmtime_module_deserialize( handle_result( Module::deserialize(&engine.engine, binary.as_slice()), |module| { - let imports = module - .imports() - .map(|i| { - wasm_importtype_t::new( - i.module().to_owned(), - i.name().map(|s| s.to_owned()), - i.ty(), - ) - }) - .collect::>(); - let exports = module - .exports() - .map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty())) - .collect::>(); - let module = Box::new(wasm_module_t { - module: module, - imports, - exports, - }); + let module = Box::new(wasm_module_t::new(module)); *ret = Box::into_raw(module); }, ) } + +#[no_mangle] +pub extern "C" fn wasm_module_type(f: &wasm_module_t) -> Box { + Box::new(wasm_moduletype_t::new(f.module().ty())) +} diff --git a/crates/c-api/src/types/extern.rs b/crates/c-api/src/types/extern.rs index fefc62c511e0..d86a9e081030 100644 --- a/crates/c-api/src/types/extern.rs +++ b/crates/c-api/src/types/extern.rs @@ -27,8 +27,8 @@ pub const WASM_EXTERN_FUNC: wasm_externkind_t = 0; pub const WASM_EXTERN_GLOBAL: wasm_externkind_t = 1; pub const WASM_EXTERN_TABLE: wasm_externkind_t = 2; pub const WASM_EXTERN_MEMORY: wasm_externkind_t = 3; -pub const WASMTIME_EXTERN_MODULE: wasm_externkind_t = 4; -pub const WASMTIME_EXTERN_INSTANCE: wasm_externkind_t = 5; +pub const WASM_EXTERN_MODULE: wasm_externkind_t = 4; +pub const WASM_EXTERN_INSTANCE: wasm_externkind_t = 5; impl wasm_externtype_t { pub(crate) fn new(ty: ExternType) -> wasm_externtype_t { @@ -63,8 +63,8 @@ pub extern "C" fn wasm_externtype_kind(et: &wasm_externtype_t) -> wasm_externkin CExternType::Table(_) => WASM_EXTERN_TABLE, CExternType::Global(_) => WASM_EXTERN_GLOBAL, CExternType::Memory(_) => WASM_EXTERN_MEMORY, - CExternType::Instance(_) => WASMTIME_EXTERN_INSTANCE, - CExternType::Module(_) => WASMTIME_EXTERN_MODULE, + CExternType::Instance(_) => WASM_EXTERN_INSTANCE, + CExternType::Module(_) => WASM_EXTERN_MODULE, } } diff --git a/crates/c-api/src/types/instance.rs b/crates/c-api/src/types/instance.rs index 83ec12d893df..373431c3624c 100644 --- a/crates/c-api/src/types/instance.rs +++ b/crates/c-api/src/types/instance.rs @@ -1,5 +1,4 @@ -use crate::{wasm_externtype_t, wasm_limits_t, CExternType}; -use once_cell::unsync::OnceCell; +use crate::{wasm_exporttype_t, wasm_exporttype_vec_t, wasm_externtype_t, CExternType}; use wasmtime::InstanceType; #[repr(transparent)] @@ -13,24 +12,33 @@ wasmtime_c_api_macros::declare_ty!(wasm_instancetype_t); #[derive(Clone)] pub(crate) struct CInstanceType { pub(crate) ty: InstanceType, - limits_cache: OnceCell, } impl wasm_instancetype_t { + pub(crate) fn new(ty: InstanceType) -> wasm_instancetype_t { + wasm_instancetype_t { + ext: wasm_externtype_t::new(ty.into()), + } + } + pub(crate) fn try_from(e: &wasm_externtype_t) -> Option<&wasm_instancetype_t> { match &e.which { CExternType::Instance(_) => Some(unsafe { &*(e as *const _ as *const _) }), _ => None, } } + + pub(crate) fn ty(&self) -> &CInstanceType { + match &self.ext.which { + CExternType::Instance(f) => &f, + _ => unreachable!(), + } + } } impl CInstanceType { pub(crate) fn new(ty: InstanceType) -> CInstanceType { - CInstanceType { - ty, - limits_cache: OnceCell::new(), - } + CInstanceType { ty } } } #[no_mangle] @@ -44,3 +52,22 @@ pub extern "C" fn wasm_instancetype_as_externtype_const( ) -> &wasm_externtype_t { &ty.ext } + +#[no_mangle] +pub extern "C" fn wasm_instancetype_exports( + instance: &wasm_instancetype_t, + out: &mut wasm_exporttype_vec_t, +) { + let exports = instance + .ty() + .ty + .exports() + .map(|e| { + Some(Box::new(wasm_exporttype_t::new( + e.name().to_owned(), + e.ty(), + ))) + }) + .collect::>(); + out.set_buffer(exports); +} diff --git a/crates/c-api/src/types/module.rs b/crates/c-api/src/types/module.rs index 3ac3b80757be..eaa681c6089f 100644 --- a/crates/c-api/src/types/module.rs +++ b/crates/c-api/src/types/module.rs @@ -1,5 +1,7 @@ -use crate::{wasm_externtype_t, wasm_limits_t, CExternType}; -use once_cell::unsync::OnceCell; +use crate::{ + wasm_exporttype_t, wasm_exporttype_vec_t, wasm_externtype_t, wasm_importtype_t, + wasm_importtype_vec_t, CExternType, +}; use wasmtime::ModuleType; #[repr(transparent)] @@ -13,24 +15,33 @@ wasmtime_c_api_macros::declare_ty!(wasm_moduletype_t); #[derive(Clone)] pub(crate) struct CModuleType { pub(crate) ty: ModuleType, - limits_cache: OnceCell, } impl wasm_moduletype_t { + pub(crate) fn new(ty: ModuleType) -> wasm_moduletype_t { + wasm_moduletype_t { + ext: wasm_externtype_t::new(ty.into()), + } + } + pub(crate) fn try_from(e: &wasm_externtype_t) -> Option<&wasm_moduletype_t> { match &e.which { CExternType::Module(_) => Some(unsafe { &*(e as *const _ as *const _) }), _ => None, } } + + pub(crate) fn ty(&self) -> &CModuleType { + match &self.ext.which { + CExternType::Module(f) => &f, + _ => unreachable!(), + } + } } impl CModuleType { pub(crate) fn new(ty: ModuleType) -> CModuleType { - CModuleType { - ty, - limits_cache: OnceCell::new(), - } + CModuleType { ty } } } @@ -45,3 +56,42 @@ pub extern "C" fn wasm_moduletype_as_externtype_const( ) -> &wasm_externtype_t { &ty.ext } + +#[no_mangle] +pub extern "C" fn wasm_moduletype_exports( + module: &wasm_moduletype_t, + out: &mut wasm_exporttype_vec_t, +) { + let exports = module + .ty() + .ty + .exports() + .map(|e| { + Some(Box::new(wasm_exporttype_t::new( + e.name().to_owned(), + e.ty(), + ))) + }) + .collect::>(); + out.set_buffer(exports); +} + +#[no_mangle] +pub extern "C" fn wasm_moduletype_imports( + module: &wasm_moduletype_t, + out: &mut wasm_importtype_vec_t, +) { + let imports = module + .ty() + .ty + .imports() + .map(|i| { + Some(Box::new(wasm_importtype_t::new( + i.module().to_owned(), + i.name().map(|s| s.to_owned()), + i.ty(), + ))) + }) + .collect::>(); + out.set_buffer(imports); +} diff --git a/crates/c-api/src/vec.rs b/crates/c-api/src/vec.rs index 2952e6553eb2..21a47f071750 100644 --- a/crates/c-api/src/vec.rs +++ b/crates/c-api/src/vec.rs @@ -1,7 +1,8 @@ -use crate::wasm_valtype_t; -use crate::{wasm_exporttype_t, wasm_extern_t, wasm_frame_t, wasm_val_t}; -use crate::{wasm_externtype_t, wasm_importtype_t, wasm_memorytype_t}; -use crate::{wasm_functype_t, wasm_globaltype_t, wasm_tabletype_t}; +use crate::{ + wasm_exporttype_t, wasm_extern_t, wasm_externtype_t, wasm_frame_t, wasm_functype_t, + wasm_globaltype_t, wasm_importtype_t, wasm_instancetype_t, wasm_memorytype_t, + wasm_moduletype_t, wasm_tabletype_t, wasm_val_t, wasm_valtype_t, +}; use std::mem; use std::ptr; use std::slice; @@ -172,6 +173,24 @@ declare_vecs! { copy: wasm_memorytype_vec_copy, delete: wasm_memorytype_vec_delete, ) + ( + name: wasm_instancetype_vec_t, + ty: Option>, + new: wasm_instancetype_vec_new, + empty: wasm_instancetype_vec_new_empty, + uninit: wasm_instancetype_vec_new_uninitialized, + copy: wasm_instancetype_vec_copy, + delete: wasm_instancetype_vec_delete, + ) + ( + name: wasm_moduletype_vec_t, + ty: Option>, + new: wasm_moduletype_vec_new, + empty: wasm_moduletype_vec_new_empty, + uninit: wasm_moduletype_vec_new_uninitialized, + copy: wasm_moduletype_vec_copy, + delete: wasm_moduletype_vec_delete, + ) ( name: wasm_externtype_vec_t, ty: Option>,