From a1f88ab5769ba5368a192141b809eabc0931b2fb Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 30 Nov 2020 15:17:26 +0100 Subject: [PATCH 01/17] doc(c-api) Document the `module` module. --- lib/c-api/src/wasm_c_api/module.rs | 386 ++++++++++++++++++++++++++++- 1 file changed, 382 insertions(+), 4 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index e5f811dd855..9b234723555 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -24,7 +24,7 @@ pub struct wasm_module_t { /// Before the code is compiled, it will be validated using the store /// features. /// -/// # Examples +/// # Example /// /// ```rust /// # use inline_c::assert_c; @@ -33,16 +33,22 @@ pub struct wasm_module_t { /// # #include "tests/wasmer_wasm.h" /// # /// int main() { +/// // Create the engine and the store. /// wasm_engine_t* engine = wasm_engine_new(); /// wasm_store_t* store = wasm_store_new(engine); -/// +/// +/// // Create a WebAssembly module from a WAT definition. /// wasm_byte_vec_t wat; /// wasmer_byte_vec_new_from_string(&wat, "(module)"); /// wasm_byte_vec_t* wasm = wat2wasm(&wat); -/// +/// +/// // Create the module. /// wasm_module_t* module = wasm_module_new(store, wasm); +/// +/// // It works! /// assert(module); -/// +/// +/// // Free everything. /// wasm_byte_vec_delete(wasm); /// wasm_byte_vec_delete(&wat); /// wasm_module_delete(module); @@ -71,9 +77,54 @@ pub unsafe extern "C" fn wasm_module_new( })) } +/// Destruct a WebAssembly module. +/// +/// # Example +/// +/// See `wasm_module_new`. #[no_mangle] pub unsafe extern "C" fn wasm_module_delete(_module: Option>) {} +/// Validates a new WebAssembly module given the configuration +/// in the `wasm_store_t`. +/// +/// This validation is normally pretty fast and checks the enabled +/// WebAssembly features in the store engine (`wasm_engine_t`) to +/// assure deterministic validation of the module. +/// +/// # Example +/// +/// ```rust +/// # use inline_c::assert_c; +/// # fn main() { +/// # (assert_c! { +/// # #include "tests/wasmer_wasm.h" +/// # +/// int main() { +/// // Create the engine and the store. +/// wasm_engine_t* engine = wasm_engine_new(); +/// wasm_store_t* store = wasm_store_new(engine); +/// +/// // Create a WebAssembly module from a WAT definition. +/// wasm_byte_vec_t wat; +/// wasmer_byte_vec_new_from_string(&wat, "(module)"); +/// wasm_byte_vec_t* wasm = wat2wasm(&wat); +/// +/// // Validate that the WebAssembly module is correct. +/// assert(wasm_module_validate(store, wasm)); +/// +/// // Free everything. +/// wasm_byte_vec_delete(wasm); +/// wasm_byte_vec_delete(&wat); +/// wasm_store_delete(store); +/// wasm_engine_delete(engine); +/// +/// return 0; +/// } +/// # }) +/// # .success(); +/// # } +/// ``` #[no_mangle] pub unsafe extern "C" fn wasm_module_validate( store: Option<&wasm_store_t>, @@ -102,6 +153,113 @@ pub unsafe extern "C" fn wasm_module_validate( } } +/// Returns an array of the exported types in the module. +/// +/// The order of the exports is guaranteed to be the same as in the +/// WebAssembly bytecode. +/// +/// # Example +/// +/// ```rust +/// # use inline_c::assert_c; +/// # fn main() { +/// # (assert_c! { +/// # #include "tests/wasmer_wasm.h" +/// # +/// int main() { +/// // Create the engine and the store. +/// wasm_engine_t* engine = wasm_engine_new(); +/// wasm_store_t* store = wasm_store_new(engine); +/// +/// // Create a WebAssembly module from a WAT definition. +/// wasm_byte_vec_t wat; +/// wasmer_byte_vec_new_from_string( +/// &wat, +/// "(module\n" +/// " (func (export \"function\") (param i32 i64))\n" +/// " (global (export \"global\") i32 (i32.const 7))\n" +/// " (table (export \"table\") 0 funcref)\n" +/// " (memory (export \"memory\") 1))" +/// ); +/// wasm_byte_vec_t* wasm = wat2wasm(&wat); +/// +/// // Create the module. +/// wasm_module_t* module = wasm_module_new(store, wasm); +/// assert(module); +/// +/// // Extract the types exported by this module. +/// wasm_exporttype_vec_t export_types; +/// wasm_module_exports(module, &export_types); +/// +/// // We have 4 of them. +/// assert(export_types.size == 4); +/// +/// // The first one is a function. Use +/// // `wasm_externtype_as_functype_const` to continue to inspect the +/// // type. +/// { +/// wasm_exporttype_t* export_type = export_types.data[0]; +/// +/// const wasm_name_t* export_name = wasm_exporttype_name(export_type); +/// wasmer_assert_name(export_name, "function"); +/// +/// const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type); +/// assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_FUNC); +/// } +/// +/// // The second one is a global. Use +/// // `wasm_externtype_as_globaltype_const` to continue to inspect the +/// // type. +/// { +/// wasm_exporttype_t* export_type = export_types.data[1]; +/// +/// const wasm_name_t* export_name = wasm_exporttype_name(export_type); +/// wasmer_assert_name(export_name, "global"); +/// +/// const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type); +/// assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_GLOBAL); +/// } +/// +/// // The third one is a table. Use +/// // `wasm_externtype_as_tabletype_const` to continue to inspect the +/// // type. +/// { +/// wasm_exporttype_t* export_type = export_types.data[2]; +/// +/// const wasm_name_t* export_name = wasm_exporttype_name(export_type); +/// wasmer_assert_name(export_name, "table"); +/// +/// const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type); +/// assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_TABLE); +/// } +/// +/// // The fourth one is a memory. Use +/// // `wasm_externtype_as_memorytype_const` to continue to inspect the +/// // type. +/// { +/// wasm_exporttype_t* export_type = export_types.data[3]; +/// +/// const wasm_name_t* export_name = wasm_exporttype_name(export_type); +/// wasmer_assert_name(export_name, "memory"); +/// +/// const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type); +/// assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_MEMORY); +/// } +/// +/// // Free everything. +/// wasm_exporttype_vec_delete(&export_types); +/// wasm_byte_vec_delete(wasm); +/// wasm_byte_vec_delete(&wat); +/// wasm_module_delete(module); +/// wasm_store_delete(store); +/// wasm_engine_delete(engine); +/// +/// return 0; +/// } +/// # }) +/// # .success(); +/// # } +/// ``` #[no_mangle] pub unsafe extern "C" fn wasm_module_exports( module: &wasm_module_t, @@ -118,6 +276,130 @@ pub unsafe extern "C" fn wasm_module_exports( *out = exports.into(); } +/// Returns an array of the imported types in the module. +/// +/// The order of the imports is guaranteed to be the same as in the +/// WebAssembly bytecode. +/// +/// # Example +/// +/// ```rust +/// # use inline_c::assert_c; +/// # fn main() { +/// # (assert_c! { +/// # #include "tests/wasmer_wasm.h" +/// # +/// int main() { +/// // Create the engine and the store. +/// wasm_engine_t* engine = wasm_engine_new(); +/// wasm_store_t* store = wasm_store_new(engine); +/// +/// // Create a WebAssembly module from a WAT definition. +/// wasm_byte_vec_t wat; +/// wasmer_byte_vec_new_from_string( +/// &wat, +/// "(module\n" +/// " (import \"ns\" \"function\" (func))\n" +/// " (import \"ns\" \"global\" (global f32))\n" +/// " (import \"ns\" \"table\" (table 1 2 anyfunc))\n" +/// " (import \"ns\" \"memory\" (memory 3 4)))" +/// ); +/// wasm_byte_vec_t* wasm = wat2wasm(&wat); +/// +/// // Create the module. +/// wasm_module_t* module = wasm_module_new(store, wasm); +/// assert(module); +/// +/// // Extract the types imported by the module. +/// wasm_importtype_vec_t import_types; +/// wasm_module_imports(module, &import_types); +/// +/// // We have 4 of them. +/// assert(import_types.size == 4); +/// +/// // The first one is a function. Use +/// // `wasm_externtype_as_functype_const` to continue to inspect the +/// // type. +/// { +/// const wasm_importtype_t* import_type = import_types.data[0]; +/// +/// const wasm_name_t* import_module = wasm_importtype_module(import_type); +/// wasmer_assert_name(import_module, "ns"); +/// +/// const wasm_name_t* import_name = wasm_importtype_name(import_type); +/// wasmer_assert_name(import_name, "function"); +/// +/// const wasm_externtype_t* extern_type = wasm_importtype_type(import_type); +/// assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_FUNC); +/// } +/// +/// // The second one is a global. Use +/// // `wasm_externtype_as_globaltype_const` to continue to inspect +/// // the type. +/// { +/// const wasm_importtype_t* import_type = import_types.data[1]; +/// +/// const wasm_name_t* import_module = wasm_importtype_module(import_type); +/// wasmer_assert_name(import_module, "ns"); +/// +/// const wasm_name_t* import_name = wasm_importtype_name(import_type); +/// wasmer_assert_name(import_name, "global"); +/// +/// const wasm_externtype_t* extern_type = wasm_importtype_type(import_type); +/// assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_GLOBAL); +/// } +/// +/// // The third one is a table. Use +/// // `wasm_externtype_as_tabletype_const` to continue to inspect +/// // the type. +/// { +/// const wasm_importtype_t* import_type = import_types.data[2]; +/// +/// const wasm_name_t* import_module = wasm_importtype_module(import_type); +/// wasmer_assert_name(import_module, "ns"); +/// +/// const wasm_name_t* import_name = wasm_importtype_name(import_type); +/// wasmer_assert_name(import_name, "table"); +/// +/// const wasm_externtype_t* extern_type = wasm_importtype_type(import_type); +/// assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_TABLE); +/// } +/// +/// // The fourth one is a memory. Use +/// // `wasm_externtype_as_memorytype_const` to continue to inspect +/// // the type. +/// { +/// const wasm_importtype_t* import_type = import_types.data[3]; +/// +/// const wasm_name_t* import_module = wasm_importtype_module(import_type); +/// wasmer_assert_name(import_module, "ns"); +/// +/// const wasm_name_t* import_name = wasm_importtype_name(import_type); +/// wasmer_assert_name(import_name, "memory"); +/// +/// const wasm_externtype_t* extern_type = wasm_importtype_type(import_type); +/// assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_MEMORY); +/// +/// const wasm_memorytype_t* memory_type = wasm_externtype_as_memorytype_const(extern_type); +/// const wasm_limits_t* memory_limits = wasm_memorytype_limits(memory_type); +/// assert(memory_limits->min == 3); +/// assert(memory_limits->max == 4); +/// } +/// +/// // Free everything. +/// wasm_importtype_vec_delete(&import_types); +/// wasm_module_delete(module); +/// wasm_byte_vec_delete(wasm); +/// wasm_byte_vec_delete(&wat); +/// wasm_store_delete(store); +/// wasm_engine_delete(engine); +/// +/// return 0; +/// } +/// # }) +/// # .success(); +/// # } +/// ``` #[no_mangle] pub unsafe extern "C" fn wasm_module_imports( module: &wasm_module_t, @@ -134,6 +416,88 @@ pub unsafe extern "C" fn wasm_module_imports( *out = imports.into(); } +/// Deserializes a serialized module binary into a `wasm_module_t`. +/// +/// Note: the module has to be serialized before with the +/// `wasm_module_serialize` function. +/// +/// # Safety +/// +/// This function is inherently **unsafe** as the provided bytes: +/// +/// 1. Are going to be deserialized directly into Rust and C objects, +/// 2. Contains the function assembly bodies and, if intercepted, +/// a malicious actor could inject code into executable +/// memory. +/// +/// And as such, the `wasm_module_deserialize` method is unsafe. +/// +/// # Example +/// +/// ```rust +/// # use inline_c::assert_c; +/// # fn main() { +/// # (assert_c! { +/// # #include "tests/wasmer_wasm.h" +/// # +/// int main() { +/// // Create the engine and the store. +/// wasm_engine_t* engine = wasm_engine_new(); +/// wasm_store_t* store = wasm_store_new(engine); +/// +/// // Create a WebAssembly module from a WAT definition. +/// wasm_byte_vec_t wat; +/// wasmer_byte_vec_new_from_string( +/// &wat, +/// "(module\n" +/// " (func (export \"function\") (param i32 i64))\n" +/// " (global (export \"global\") i32 (i32.const 7))\n" +/// " (table (export \"table\") 0 funcref)\n" +/// " (memory (export \"memory\") 1))" +/// ); +/// wasm_byte_vec_t* wasm = wat2wasm(&wat); +/// +/// // Create the module. +/// wasm_module_t* module = wasm_module_new(store, wasm); +/// assert(module); +/// +/// // Serialize the module into bytes. +/// wasm_byte_vec_t serialized_module; +/// wasm_module_serialize(module, &serialized_module); +/// assert(serialized_module.size > 0); +/// +/// // Free the module. +/// wasm_module_delete(module); +/// +/// // Deserialize the serialized module. Note that the store must +/// // be the same as the one used to serialize. +/// wasm_module_t* deserialized_module = wasm_module_deserialize( +/// store, +/// &serialized_module +/// ); +/// wasm_byte_vec_delete(&serialized_module); +/// assert(deserialized_module); +/// +/// // Check we have our 4 export types. +/// wasm_exporttype_vec_t export_types; +/// wasm_module_exports(deserialized_module, &export_types); +/// +/// assert(export_types.size == 4); +/// +/// // Free everything. +/// wasm_exporttype_vec_delete(&export_types); +/// wasm_module_delete(deserialized_module); +/// wasm_byte_vec_delete(wasm); +/// wasm_byte_vec_delete(&wat); +/// wasm_store_delete(store); +/// wasm_engine_delete(engine); +/// +/// return 0; +/// } +/// # }) +/// # .success(); +/// # } +/// ``` #[no_mangle] pub unsafe extern "C" fn wasm_module_deserialize( store: &wasm_store_t, @@ -160,6 +524,12 @@ pub unsafe extern "C" fn wasm_module_deserialize( )))) } +/// Serializes a module into a binary representation that the engine +/// (`wasm_engine_t`) can later process via `wasm_module_deserialize`. +/// +/// # Example +/// +/// See `wasm_module_deserialize`. #[no_mangle] pub unsafe extern "C" fn wasm_module_serialize( module: &wasm_module_t, @@ -333,6 +703,8 @@ mod tests { wasm_module_delete(module); wasm_store_delete(store); wasm_engine_delete(engine); + + return 0; } }) .success(); @@ -448,6 +820,8 @@ mod tests { wasm_byte_vec_delete(&wat); wasm_store_delete(store); wasm_engine_delete(engine); + + return 0; } }) .success(); @@ -479,6 +853,8 @@ mod tests { wasm_byte_vec_delete(&wat); wasm_store_delete(store); wasm_engine_delete(engine); + + return 0; } }) .success(); @@ -530,6 +906,8 @@ mod tests { wasm_byte_vec_delete(&wat); wasm_store_delete(store); wasm_engine_delete(engine); + + return 0; } }) .success(); From 581ca917adc3543c212afa2751e7519c969c5a43 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 30 Nov 2020 15:41:34 +0100 Subject: [PATCH 02/17] doc(c-api) Document the `module` module. --- lib/c-api/src/wasm_c_api/mod.rs | 6 ++++++ lib/c-api/src/wasm_c_api/module.rs | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 58eefb2a0e3..e7a046beb41 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -11,6 +11,12 @@ pub mod externals; /// cbindgen:ignore pub mod instance; +/// A WebAssembly module contains stateless WebAssembly code that has +/// already been compiled and can be instantiated multiple times. +/// +/// Entry points: A WebAssembly is created with `wasm_module_new` and +/// freed with `wasm_module_delete`. +/// /// cbindgen:ignore pub mod module; diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index 9b234723555..62b69d8fc41 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -8,6 +8,7 @@ use std::ptr::NonNull; use std::sync::Arc; use wasmer::Module; +/// Opaque type representing a WebAssembly module. #[allow(non_camel_case_types)] pub struct wasm_module_t { pub(crate) inner: Arc, @@ -54,7 +55,7 @@ pub struct wasm_module_t { /// wasm_module_delete(module); /// wasm_store_delete(store); /// wasm_engine_delete(engine); -/// +/// /// return 0; /// } /// # }) From 5a71aceb45a08c4bbbdc6aa8ffaf67b97aa5aafd Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 30 Nov 2020 15:41:54 +0100 Subject: [PATCH 03/17] doc(c-api) Document the `engine` module. --- lib/c-api/src/wasm_c_api/engine.rs | 180 ++++++++++++++++++++++++++--- lib/c-api/src/wasm_c_api/mod.rs | 1 + 2 files changed, 168 insertions(+), 13 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index 2d331a7aaaf..58d6ff2389b 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -79,7 +79,35 @@ pub struct wasm_config_t { compiler: wasmer_compiler_t, } -/// Create a new Wasmer configuration. +/// Create a new default Wasmer configuration. +/// +/// # Example +/// +/// ```rust +/// # use inline_c::assert_c; +/// # fn main() { +/// # (assert_c! { +/// # #include "tests/wasmer_wasm.h" +/// # +/// int main() { +/// // Create the configuration. +/// wasm_config_t* config = wasm_config_new(); +/// +/// // Create the engine. +/// wasm_engine_t* engine = wasm_engine_new_with_config(config); +/// +/// // Check we have an engine! +/// assert(engine); +/// +/// // Free everything. +/// wasm_engine_delete(engine); +/// +/// return 0; +/// } +/// # }) +/// # .success(); +/// # } +/// ``` /// /// cbindgen:ignore #[no_mangle] @@ -87,7 +115,38 @@ pub extern "C" fn wasm_config_new() -> Box { Box::new(wasm_config_t::default()) } -/// Configure the compiler to use. +/// Updates the configuration to specify a particular compiler to use. +/// +/// # Example +/// +/// ```rust +/// # use inline_c::assert_c; +/// # fn main() { +/// # (assert_c! { +/// # #include "tests/wasmer_wasm.h" +/// # +/// int main() { +/// // Create the configuration. +/// wasm_config_t* config = wasm_config_new(); +/// +/// // Use the Cranelift compiler. +/// wasm_config_set_compiler(config, CRANELIFT); +/// +/// // Create the engine. +/// wasm_engine_t* engine = wasm_engine_new_with_config(config); +/// +/// // Check we have an engine! +/// assert(engine); +/// +/// // Free everything. +/// wasm_engine_delete(engine); +/// +/// return 0; +/// } +/// # }) +/// # .success(); +/// # } +/// ``` #[cfg(feature = "compiler")] #[no_mangle] pub extern "C" fn wasm_config_set_compiler( @@ -97,7 +156,38 @@ pub extern "C" fn wasm_config_set_compiler( config.compiler = compiler; } -/// Configure the engine to use. +/// Updates the configuration to specify a particular engine to use. +/// +/// # Example +/// +/// ```rust +/// # use inline_c::assert_c; +/// # fn main() { +/// # (assert_c! { +/// # #include "tests/wasmer_wasm.h" +/// # +/// int main() { +/// // Create the configuration. +/// wasm_config_t* config = wasm_config_new(); +/// +/// // Use the JIT engine. +/// wasm_config_set_engine(config, JIT); +/// +/// // Create the engine. +/// wasm_engine_t* engine = wasm_engine_new_with_config(config); +/// +/// // Check we have an engine! +/// assert(engine); +/// +/// // Free everything. +/// wasm_engine_delete(engine); +/// +/// return 0; +/// } +/// # }) +/// # .success(); +/// # } +/// ``` #[no_mangle] pub extern "C" fn wasm_config_set_engine(config: &mut wasm_config_t, engine: wasmer_engine_t) { config.engine = engine; @@ -132,6 +222,12 @@ fn get_default_compiler_config() -> Box { cfg_if! { if #[cfg(all(feature = "jit", feature = "compiler"))] { + /// Creates a new JIT engine with the default compiler. + /// + /// # Example + /// + /// See `wasm_engine_delete`. + /// /// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { @@ -139,17 +235,26 @@ cfg_if! { let engine: Arc = Arc::new(JIT::new(&*compiler_config).engine()); Box::new(wasm_engine_t { inner: engine }) } - } - else if #[cfg(feature = "jit")] { - // Headless JIT + } else if #[cfg(feature = "jit")] { + /// Creates a new headless JIT engine. + /// + /// # Example + /// + /// See `wasm_engine_delete`. + /// /// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { let engine: Arc = Arc::new(JIT::headless().engine()); Box::new(wasm_engine_t { inner: engine }) } - } - else if #[cfg(all(feature = "native", feature = "compiler"))] { + } else if #[cfg(all(feature = "native", feature = "compiler"))] { + /// Creates a new native engine with the default compiler. + /// + /// # Example + /// + /// See `wasm_engine_delete`. + /// /// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { @@ -157,8 +262,13 @@ cfg_if! { let engine: Arc = Arc::new(Native::new(&mut *compiler_config).engine()); Box::new(wasm_engine_t { inner: engine }) } - } - else if #[cfg(feature = "native")] { + } else if #[cfg(feature = "native")] { + /// Creates a new headless native engine. + /// + /// # Example + /// + /// See `wasm_engine_delete`. + /// /// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { @@ -169,26 +279,70 @@ cfg_if! { // There are currently no uses of the object-file engine + compiler from the C API. // So if we get here, we default to headless mode regardless of if `compiler` is enabled. else if #[cfg(feature = "object-file")] { + /// Creates a new headless object-file engine. + /// + /// # Example + /// + /// See `wasm_engine_delete`. + /// /// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { let engine: Arc = Arc::new(ObjectFile::headless().engine()); Box::new(wasm_engine_t { inner: engine }) } - } - else { + } else { + /// Creates a new unknown engine, i.e. it will panic with an error message. + /// + /// # Example + /// + /// See `wasm_engine_delete`. + /// /// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { - unimplemented!("The JITEngine is not attached; You might want to recompile `wasmer_c_api` with `--feature jit`"); + unimplemented!("No engine attached; You might want to recompile `wasmer_c_api` with for example `--feature jit`"); } } } +/// Deletes an engine. +/// +/// # Example +/// +/// ```rust +/// # use inline_c::assert_c; +/// # fn main() { +/// # (assert_c! { +/// # #include "tests/wasmer_wasm.h" +/// # +/// int main() { +/// // Create a default engine. +/// wasm_engine_t* engine = wasm_engine_new(); +/// +/// // Check we have an engine! +/// assert(engine); +/// +/// // Free everything. +/// wasm_engine_delete(engine); +/// +/// return 0; +/// } +/// # }) +/// # .success(); +/// # } +/// ``` +/// /// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_engine_delete(_engine: Option>) {} +/// Creates an engine with a particular configuration. +/// +/// # Example +/// +/// See `wasm_config_new`. +/// /// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_engine_new_with_config( diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index e7a046beb41..e29a1731bb7 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -3,6 +3,7 @@ #[macro_use] pub mod macros; +/// The engine drives the compilation and the runtime. pub mod engine; /// cbindgen:ignore From 34530306e663f8a53c22ad2fe0026846c24f13d8 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 30 Nov 2020 15:42:04 +0100 Subject: [PATCH 04/17] test(c-api) Test the `engine` module. --- lib/c-api/src/wasm_c_api/engine.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index 58d6ff2389b..0163f61938a 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -459,3 +459,25 @@ pub extern "C" fn wasm_engine_new_with_config( } } } + +#[cfg(test)] +mod tests { + use inline_c::assert_c; + + #[test] + fn test_engine_new() { + (assert_c! { + #include "tests/wasmer_wasm.h" + + int main() { + wasm_engine_t* engine = wasm_engine_new(); + assert(engine); + + wasm_engine_delete(engine); + + return 0; + } + }) + .success(); + } +} From ca54997cbd0552355bed5d2fd3962d6dcaf2c2c0 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 30 Nov 2020 15:43:12 +0100 Subject: [PATCH 05/17] doc(c-api) Document the `engine` module. --- lib/c-api/src/wasm_c_api/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index e29a1731bb7..a1e6292e658 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -4,6 +4,9 @@ pub mod macros; /// The engine drives the compilation and the runtime. +/// +/// Entry points: A default engine is created with `wasm_engine_new` +/// and freed with `wasm_engine_delete`. pub mod engine; /// cbindgen:ignore From eb01733839ebaa24ec40d0ba984b57708844c3d4 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 30 Nov 2020 16:56:45 +0100 Subject: [PATCH 06/17] doc(c-api) Document the `instance` module. --- lib/c-api/src/wasm_c_api/instance.rs | 23 +++++++++++++++++++++++ lib/c-api/src/wasm_c_api/mod.rs | 14 ++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index 84437b04f13..e90d3408b48 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -7,11 +7,28 @@ use std::mem; use std::sync::Arc; use wasmer::{Extern, Instance, InstantiationError}; +/// Opaque type representing a WebAssembly instance. #[allow(non_camel_case_types)] pub struct wasm_instance_t { pub(crate) inner: Arc, } +/// Creates a new instance from a WebAssembly module and a +/// set of imports. +/// +/// ## Errors +/// +/// The function can fail in 2 ways, as defined by the specification: +/// +/// 1. Link errors that happen when plugging the imports into the +/// instance, +/// 2. Runtime errors that happen when running the module `start` +/// function. +/// +/// # Notes +/// +/// The `store` argument is ignored. The store from the given module +/// will be used. #[no_mangle] pub unsafe extern "C" fn wasm_instance_new( _store: Option<&wasm_store_t>, @@ -54,9 +71,15 @@ pub unsafe extern "C" fn wasm_instance_new( Some(Box::new(wasm_instance_t { inner: instance })) } +/// Deletes an instance. +/// +/// # Example +/// +/// See `wasm_instance_new`. #[no_mangle] pub unsafe extern "C" fn wasm_instance_delete(_instance: Option>) {} +/// Gets the exports of the instance. #[no_mangle] pub unsafe extern "C" fn wasm_instance_exports( instance: &wasm_instance_t, diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index a1e6292e658..5fa5cf29bea 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -12,14 +12,24 @@ pub mod engine; /// cbindgen:ignore pub mod externals; +/// A WebAssembly instance is a stateful, executable instance of a +/// WebAssembly module. +/// +/// Instance objects contain all the exported WebAssembly functions, +/// memories, tables and globals that allow interacting with +/// WebAssembly. +/// +/// Entry points: A WebAssembly instance is created with +/// `wasm_instance_new` and freed with `wasm_instance_delete`. +/// /// cbindgen:ignore pub mod instance; /// A WebAssembly module contains stateless WebAssembly code that has /// already been compiled and can be instantiated multiple times. /// -/// Entry points: A WebAssembly is created with `wasm_module_new` and -/// freed with `wasm_module_delete`. +/// Entry points: A WebAssembly module is created with +/// `wasm_module_new` and freed with `wasm_module_delete`. /// /// cbindgen:ignore pub mod module; From 37240bdc10ec21f28cf5a6e0a45f29ce57f0b654 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 30 Nov 2020 16:56:56 +0100 Subject: [PATCH 07/17] test(c-api) Start testing the `instance` module. --- lib/c-api/src/wasm_c_api/instance.rs | 107 +++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index e90d3408b48..ab080374da4 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -110,3 +110,110 @@ pub unsafe extern "C" fn wasm_instance_exports( mem::forget(extern_vec); } + +#[cfg(test)] +mod tests { + use inline_c::assert_c; + + #[test] + fn test_instance_new() { + (assert_c! { + #include "tests/wasmer_wasm.h" + + // The `sum` host function implementation. + wasm_trap_t* sum_callback( + const wasm_val_vec_t* arguments, + wasm_val_vec_t* results + ) { + uint32_t sum = arguments->data[0].of.i32 + arguments->data[1].of.i32; + wasm_val_t result = { + .kind = WASM_I32, + .of = result + }; + results->data[0] = result; + + return NULL; + } + + int main() { + // Create the engine and the store. + wasm_engine_t* engine = wasm_engine_new(); + wasm_store_t* store = wasm_store_new(engine); + + // Create a WebAssembly module from a WAT definition. + wasm_byte_vec_t wat; + wasmer_byte_vec_new_from_string( + &wat, + "(module\n" + " (import \"math\" \"sum\" (func $sum (param i32 i32) (result i32)))\n" + " (func (export \"add_one\") (param i32) (result i32)\n" + " local.get 0\n" + " i32.const 1\n" + " call $sum))" + ); + wasm_byte_vec_t* wasm = wat2wasm(&wat); + + // Create the module. + wasm_module_t* module = wasm_module_new(store, wasm); + + assert(module); + + // Prepare the imports. + // Create the type for the `sum` host function. + wasm_functype_t* sum_type = wasm_functype_new_2_1( + wasm_valtype_new_i32(), + wasm_valtype_new_i32(), + wasm_valtype_new_i32() + ); + + // Create the `sum` host function. + wasm_func_t* sum_function = wasm_func_new(store, sum_type, sum_callback); + + // Create the imports. + wasm_extern_t* externs[] = { wasm_func_as_extern(sum_function) }; + wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs); + + // Instantiate the module. + wasm_trap_t* traps = NULL; + wasm_instance_t* instance = wasm_instance_new(store, module, &imports, &traps); + + assert(instance); + + // Run the exported function. + wasm_extern_vec_t exports; + wasm_instance_exports(instance, &exports); + + assert(exports.size == 1); + + // Get the `add_one` exported function. + const wasm_func_t* run_function = wasm_extern_as_func(exports.data[0]); + assert(run_function); + + // And call it as `add_one(1)`. + wasm_val_t arguments[1] = { WASM_I32_VAL(1) }; + wasm_val_t results[1] = { WASM_INIT_VAL }; + + wasm_val_vec_t arguments_as_array = WASM_ARRAY_VEC(arguments); + wasm_val_vec_t results_as_array = WASM_ARRAY_VEC(results); + + wasm_trap_t* trap = wasm_func_call(run_function, &arguments_as_array, &results_as_array); + + // Check the result! + assert(trap == NULL); + assert(results[0].of.i32 == 2); + + // Free everything. + wasm_func_delete(sum_function); + wasm_instance_delete(instance); + wasm_module_delete(module); + wasm_byte_vec_delete(wasm); + wasm_byte_vec_delete(&wat); + wasm_store_delete(store); + wasm_engine_delete(engine); + + return 0; + } + }) + .success(); + } +} From 527b7061cc0fc8c4a918d501973ecea25c604622 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 1 Dec 2020 14:25:59 +0100 Subject: [PATCH 08/17] fix(c-api) Fix memory leak in `wasm_$name_vec_delete`. This patch does several things: 1. It applies our Rust patterns for C API by replacing the raw pointer by `Option>`, 2. It allows `wasm_$name_vec_delete` to handle null pointer, 3. Because it takes ownership of the `wasm_$name_vec_t`, the pointer is correctly dropped (which fix the memory leak). --- lib/c-api/src/wasm_c_api/macros.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index ffd95b701e9..1b6fb4b88b4 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -102,10 +102,15 @@ macro_rules! wasm_declare_vec { #[no_mangle] - pub unsafe extern "C" fn [](ptr: *mut []) { - let vec = &mut *ptr; + pub unsafe extern "C" fn [](ptr: Option]>>) { + if ptr.is_none() { + return; + } + + let mut vec = ptr.unwrap(); + if !vec.data.is_null() { - Vec::from_raw_parts(vec.data, vec.size, vec.size); + let _ = Vec::from_raw_parts(vec.data, vec.size, vec.size); vec.data = ::std::ptr::null_mut(); vec.size = 0; } From 25bcc9b7fc0925b2c1a7c32b322b6df973940009 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 1 Dec 2020 15:29:41 +0100 Subject: [PATCH 09/17] fixup --- lib/c-api/src/wasm_c_api/macros.rs | 32 ++++++++++++++++-------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index 1b6fb4b88b4..77a7448e1e0 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -25,14 +25,17 @@ macro_rules! wasm_declare_vec { } impl<'a> From]>> for [] { - fn from(other: Vec<[]>) -> Self { - let mut boxed_slice = other.into_boxed_slice(); - let size = boxed_slice.len(); - let data = boxed_slice.as_mut_ptr(); - ::std::mem::forget(boxed_slice); + fn from(mut vec: Vec<[]>) -> Self { + vec.shrink_to_fit(); + + let length = vec.len(); + let pointer = vec.as_mut_ptr(); + + ::std::mem::forget(vec); + Self { - size, - data, + size: length, + data: pointer, } } } @@ -100,20 +103,19 @@ macro_rules! wasm_declare_vec { ::std::mem::forget(bytes); } - #[no_mangle] - pub unsafe extern "C" fn [](ptr: Option]>>) { - if ptr.is_none() { + pub unsafe extern "C" fn [](subject: Option]>>) { + if subject.is_none() { return; } - let mut vec = ptr.unwrap(); + let subject: Box<[]> = subject.unwrap(); - if !vec.data.is_null() { - let _ = Vec::from_raw_parts(vec.data, vec.size, vec.size); - vec.data = ::std::ptr::null_mut(); - vec.size = 0; + if !subject.data.is_null() { + let _ = Vec::from_raw_parts(subject.data, subject.size, subject.size); } + + ::std::ptr::drop_in_place(Box::into_raw(subject)); } } From 4740202e90e434c82c6be707dd827fd15e7414d6 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 10 Dec 2020 16:14:13 +0100 Subject: [PATCH 10/17] test(c-api) Fix tests. --- lib/c-api/src/wasm_c_api/instance.rs | 26 ++++++++++---------------- lib/c-api/src/wasm_c_api/module.rs | 8 ++++---- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index 1805ba59d4a..400424777ba 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -131,12 +131,11 @@ mod tests { const wasm_val_vec_t* arguments, wasm_val_vec_t* results ) { - uint32_t sum = arguments->data[0].of.i32 + arguments->data[1].of.i32; - wasm_val_t result = { + wasm_val_t sum = { .kind = WASM_I32, - .of = result + .of = { arguments->data[0].of.i32 + arguments->data[1].of.i32 }, }; - results->data[0] = result; + results->data[0] = sum; return NULL; } @@ -157,25 +156,21 @@ mod tests { " i32.const 1\n" " call $sum))" ); - wasm_byte_vec_t* wasm = wat2wasm(&wat); + wasm_byte_vec_t wasm; + wat2wasm(&wat, &wasm); // Create the module. - wasm_module_t* module = wasm_module_new(store, wasm); + wasm_module_t* module = wasm_module_new(store, &wasm); assert(module); // Prepare the imports. - // Create the type for the `sum` host function. wasm_functype_t* sum_type = wasm_functype_new_2_1( wasm_valtype_new_i32(), wasm_valtype_new_i32(), wasm_valtype_new_i32() ); - - // Create the `sum` host function. wasm_func_t* sum_function = wasm_func_new(store, sum_type, sum_callback); - - // Create the imports. wasm_extern_t* externs[] = { wasm_func_as_extern(sum_function) }; wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs); @@ -191,11 +186,10 @@ mod tests { assert(exports.size == 1); - // Get the `add_one` exported function. const wasm_func_t* run_function = wasm_extern_as_func(exports.data[0]); + assert(run_function); - // And call it as `add_one(1)`. wasm_val_t arguments[1] = { WASM_I32_VAL(1) }; wasm_val_t results[1] = { WASM_INIT_VAL }; @@ -204,15 +198,15 @@ mod tests { wasm_trap_t* trap = wasm_func_call(run_function, &arguments_as_array, &results_as_array); - // Check the result! assert(trap == NULL); assert(results[0].of.i32 == 2); // Free everything. - wasm_func_delete(sum_function); wasm_instance_delete(instance); + wasm_func_delete(sum_function); + wasm_functype_delete(sum_type); wasm_module_delete(module); - wasm_byte_vec_delete(wasm); + wasm_byte_vec_delete(&wasm); wasm_byte_vec_delete(&wat); wasm_store_delete(store); wasm_engine_delete(engine); diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index 59715cb4967..feddc94f4a0 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -114,7 +114,7 @@ pub unsafe extern "C" fn wasm_module_delete(_module: Option>) /// wat2wasm(&wat, &wasm); /// /// // Validate that the WebAssembly module is correct. -/// assert(wasm_module_validate(store, wasm)); +/// assert(wasm_module_validate(store, &wasm)); /// /// // Free everything. /// wasm_byte_vec_delete(&wasm); @@ -188,7 +188,7 @@ pub unsafe extern "C" fn wasm_module_validate( /// wat2wasm(&wat, &wasm); /// /// // Create the module. -/// wasm_module_t* module = wasm_module_new(store, wasm); +/// wasm_module_t* module = wasm_module_new(store, &wasm); /// assert(module); /// /// // Extract the types exported by this module. @@ -312,7 +312,7 @@ pub unsafe extern "C" fn wasm_module_exports( /// wat2wasm(&wat, &wasm); /// /// // Create the module. -/// wasm_module_t* module = wasm_module_new(store, wasm); +/// wasm_module_t* module = wasm_module_new(store, &wasm); /// assert(module); /// /// // Extract the types imported by the module. @@ -464,7 +464,7 @@ pub unsafe extern "C" fn wasm_module_imports( /// wat2wasm(&wat, &wasm); /// /// // Create the module. -/// wasm_module_t* module = wasm_module_new(store, wasm); +/// wasm_module_t* module = wasm_module_new(store, &wasm); /// assert(module); /// /// // Serialize the module into bytes. From 6e7cd024256f778aeffee53551f3a98cc28b6d83 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 10 Dec 2020 16:18:10 +0100 Subject: [PATCH 11/17] doc(c-api) Specify when functions are Wasmer-specific. --- lib/c-api/src/wasm_c_api/engine.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index fca5cf00a90..5205d67bcaf 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -117,6 +117,8 @@ pub extern "C" fn wasm_config_new() -> Box { /// Updates the configuration to specify a particular compiler to use. /// +/// This is a Wasmer-specific function. +/// /// # Example /// /// ```rust @@ -158,6 +160,8 @@ pub extern "C" fn wasm_config_set_compiler( /// Updates the configuration to specify a particular engine to use. /// +/// This is a Wasmer-specific function. +/// /// # Example /// /// ```rust From 6d7416346211504972d6441bf89372cd26ac05da Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 10 Dec 2020 16:18:32 +0100 Subject: [PATCH 12/17] doc(c-api) Specify that the code does not panic. --- lib/c-api/src/wasm_c_api/instance.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index 400424777ba..893ba3fb192 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -18,13 +18,16 @@ pub struct wasm_instance_t { /// /// ## Errors /// -/// The function can fail in 2 ways, as defined by the specification: +/// The function can fail in 2 ways: /// /// 1. Link errors that happen when plugging the imports into the /// instance, /// 2. Runtime errors that happen when running the module `start` /// function. /// +/// Failures are stored in the `traps` argument; the program doesn't +/// panic. +/// /// # Notes /// /// The `store` argument is ignored. The store from the given module From ae38fdd3a593266c954252047c89152d6a11e65b Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 10 Dec 2020 16:20:03 +0100 Subject: [PATCH 13/17] doc(changelog) Add #1851. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8c5cc0b61d..b60403771d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ ### Changed +- [#1851](https://github.com/wasmerio/wasmer/pull/1851) Improve test suite and documentation of the Wasmer C API - [#1874](https://github.com/wasmerio/wasmer/pull/1874) Set `CompilerConfig` to be owned (following wasm-c-api) - [#1880](https://github.com/wasmerio/wasmer/pull/1880) Remove cmake dependency for tests From bcf65008c42d36ec278848f7652dba8ac1bb8b42 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 10 Dec 2020 16:44:35 +0100 Subject: [PATCH 14/17] test(c-api) Disable on doctest, it cannot run if JIT is disabled. --- lib/c-api/src/wasm_c_api/engine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index 5205d67bcaf..bbde336a1bd 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -164,7 +164,7 @@ pub extern "C" fn wasm_config_set_compiler( /// /// # Example /// -/// ```rust +/// ```rust,ignore /// # use inline_c::assert_c; /// # fn main() { /// # (assert_c! { From 90778f6d665bcd8d72ffc3cc8bba6d4e5890ae28 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 10 Dec 2020 17:14:16 +0100 Subject: [PATCH 15/17] test(c-api) Change `ignore` to `no_run`. --- lib/c-api/src/wasm_c_api/engine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index bbde336a1bd..8a25490ac11 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -164,7 +164,7 @@ pub extern "C" fn wasm_config_set_compiler( /// /// # Example /// -/// ```rust,ignore +/// ```rust,no_run /// # use inline_c::assert_c; /// # fn main() { /// # (assert_c! { From 401b9e4db5da953ef3b3b222fa52b57c84f03ee7 Mon Sep 17 00:00:00 2001 From: jubianchi Date: Thu, 10 Dec 2020 18:41:47 +0100 Subject: [PATCH 16/17] test(c-api) Add `no_run` to engine tests. Because we test the C API with many features combination, we can't ensure tests will pass with every combination --- lib/c-api/src/wasm_c_api/engine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index 8a25490ac11..0174032ec56 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -121,7 +121,7 @@ pub extern "C" fn wasm_config_new() -> Box { /// /// # Example /// -/// ```rust +/// ```rust,no_run /// # use inline_c::assert_c; /// # fn main() { /// # (assert_c! { From 62fa2e506ed994b7b4364757fa294480bb56564f Mon Sep 17 00:00:00 2001 From: jubianchi Date: Thu, 10 Dec 2020 18:42:41 +0100 Subject: [PATCH 17/17] chore: update wamser_wasm.h --- lib/c-api/wasmer_wasm.h | 70 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index 40a8c375dcb..c04d85ea470 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -180,13 +180,79 @@ wasi_version_t wasi_get_wasi_version(const wasm_module_t *module); #if defined(WASMER_COMPILER_ENABLED) /** - * Configure the compiler to use. + * Updates the configuration to specify a particular compiler to use. + * + * This is a Wasmer-specific function. + * + * # Example + * + * ```rust,no_run + * # use inline_c::assert_c; + * # fn main() { + * # (assert_c! { + * # #include "tests/wasmer_wasm.h" + * # + * int main() { + * // Create the configuration. + * wasm_config_t* config = wasm_config_new(); + * + * // Use the Cranelift compiler. + * wasm_config_set_compiler(config, CRANELIFT); + * + * // Create the engine. + * wasm_engine_t* engine = wasm_engine_new_with_config(config); + * + * // Check we have an engine! + * assert(engine); + * + * // Free everything. + * wasm_engine_delete(engine); + * + * return 0; + * } + * # }) + * # .success(); + * # } + * ``` */ void wasm_config_set_compiler(wasm_config_t *config, wasmer_compiler_t compiler); #endif /** - * Configure the engine to use. + * Updates the configuration to specify a particular engine to use. + * + * This is a Wasmer-specific function. + * + * # Example + * + * ```rust,no_run + * # use inline_c::assert_c; + * # fn main() { + * # (assert_c! { + * # #include "tests/wasmer_wasm.h" + * # + * int main() { + * // Create the configuration. + * wasm_config_t* config = wasm_config_new(); + * + * // Use the JIT engine. + * wasm_config_set_engine(config, JIT); + * + * // Create the engine. + * wasm_engine_t* engine = wasm_engine_new_with_config(config); + * + * // Check we have an engine! + * assert(engine); + * + * // Free everything. + * wasm_engine_delete(engine); + * + * return 0; + * } + * # }) + * # .success(); + * # } + * ``` */ void wasm_config_set_engine(wasm_config_t *config, wasmer_engine_t engine);