diff --git a/crates/c-api/include/doc-wasm.h b/crates/c-api/include/doc-wasm.h index 301989437d..73d57a647b 100644 --- a/crates/c-api/include/doc-wasm.h +++ b/crates/c-api/include/doc-wasm.h @@ -793,8 +793,15 @@ * \typedef wasm_externkind_t * \brief Classifier for #wasm_externtype_t, defined by #wasm_externkind_enum * + * This is returned from #wasm_extern_kind and #wasm_externtype_kind to + * determine what kind of type is wrapped. + * * \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 and is intended to be used when #wasm_externkind_t is + * used. */ /** diff --git a/crates/c-api/include/wasmtime.h b/crates/c-api/include/wasmtime.h index 75880ce020..769cfc1268 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,291 @@ 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*); + +/** + * \brief Value of #wasm_externkind_enum corresponding to a wasm module. + */ +#define WASM_EXTERN_MODULE 4 + +/** + * \brief Value of #wasm_externkind_enum corresponding to a wasm instance. + */ +#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 49dce19841..08da598ec1 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 6a08a6e13e..414946a293 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 6fa2088886..5a41d68a1c 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 ee77001c50..80aa3fa945 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 52f5768ce2..c31f125b70 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 fefc62c511..d86a9e0810 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 83ec12d893..373431c362 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 3ac3b80757..eaa681c608 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 2952e6553e..21a47f0717 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>,