From d1fc49d9c2403ea17c6770451a5aae4bd5697ea4 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 1 Mar 2021 16:02:43 +0100 Subject: [PATCH] feat(c-api) Introduce the `wasmer_features_t` unstable API. This API is a wrapper around the `wasmer_types::Features` API. A new function `wasm_config_set_features` allows to define features for the engine and the compiler. --- lib/c-api/src/wasm_c_api/engine.rs | 29 +- lib/c-api/src/wasm_c_api/unstable/engine.rs | 47 +++ lib/c-api/src/wasm_c_api/unstable/features.rs | 364 ++++++++++++++++++ lib/c-api/src/wasm_c_api/unstable/mod.rs | 1 + 4 files changed, 440 insertions(+), 1 deletion(-) create mode 100644 lib/c-api/src/wasm_c_api/unstable/features.rs diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index a94bf662f..195d36d0a 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -1,6 +1,8 @@ pub use super::unstable::engine::{ - wasm_config_set_target, wasmer_is_compiler_available, wasmer_is_engine_available, + wasm_config_set_features, wasm_config_set_target, wasmer_is_compiler_available, + wasmer_is_engine_available, }; +use super::unstable::features::wasmer_features_t; use super::unstable::target_lexicon::wasmer_target_t; use crate::error::{update_last_error, CApiError}; use cfg_if::cfg_if; @@ -97,6 +99,7 @@ pub struct wasm_config_t { engine: wasmer_engine_t, #[cfg(feature = "compiler")] compiler: wasmer_compiler_t, + pub(super) features: Option>, pub(super) target: Option>, } @@ -478,6 +481,10 @@ pub extern "C" fn wasm_engine_new_with_config( builder = builder.target(target.inner); } + if let Some(features) = config.features { + builder = builder.features(features.inner); + } + Arc::new(builder.engine()) } else { return return_with_error("Wasmer has not been compiled with the `jit` feature."); @@ -493,6 +500,10 @@ pub extern "C" fn wasm_engine_new_with_config( builder = builder.target(target.inner); } + if let Some(features) = config.features { + builder = builder.features(features.inner); + } + Arc::new(builder.engine()) } else { return return_with_error("Wasmer has not been compiled with the `native` feature."); @@ -510,6 +521,10 @@ pub extern "C" fn wasm_engine_new_with_config( builder = builder.target(target.inner); } + if let Some(features) = config.features { + builder = builder.features(features.inner); + } + Arc::new(builder.engine()) } else { return return_with_error("Wasmer has not been compiled with the `object-file` feature."); @@ -529,6 +544,10 @@ pub extern "C" fn wasm_engine_new_with_config( builder = builder.target(target.inner); } + if let Some(features) = config.features { + builder = builder.features(features.inner); + } + Arc::new(builder.engine()) } else { return return_with_error("Wasmer has not been compiled with the `jit` feature."); @@ -544,6 +563,10 @@ pub extern "C" fn wasm_engine_new_with_config( builder = builder.target(target.inner); } + if let Some(features) = config.features { + builder = builder.features(features.inner); + } + Arc::new(builder.engine()) } else { return return_with_error("Wasmer has not been compiled with the `native` feature."); @@ -559,6 +582,10 @@ pub extern "C" fn wasm_engine_new_with_config( builder = builder.target(target.inner); } + if let Some(features) = config.features { + builder = builder.features(features.inner); + } + Arc::new(builder.engine()) } else { return return_with_error("Wasmer has not been compiled with the `object-file` feature."); diff --git a/lib/c-api/src/wasm_c_api/unstable/engine.rs b/lib/c-api/src/wasm_c_api/unstable/engine.rs index 882087779..f20d00742 100644 --- a/lib/c-api/src/wasm_c_api/unstable/engine.rs +++ b/lib/c-api/src/wasm_c_api/unstable/engine.rs @@ -2,6 +2,7 @@ //! `wasm_engine_t` and siblings. use super::super::engine::{wasm_config_t, wasmer_compiler_t, wasmer_engine_t}; +use super::features::wasmer_features_t; use super::target_lexicon::wasmer_target_t; /// Unstable non-standard Wasmer-specific API to update the @@ -48,6 +49,52 @@ pub extern "C" fn wasm_config_set_target(config: &mut wasm_config_t, target: Box config.target = Some(target); } +/// Unstable non-standard Wasmer-specific API to update the +/// configuration to specify particular features for the engine. +/// +/// # 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(); +/// +/// // Set the target. +/// { +/// wasmer_features_t* features = wasmer_features_new(); +/// wasmer_features_simd(features, true); +/// +/// wasm_config_set_features(config, features); +/// } +/// +/// // 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_features( + config: &mut wasm_config_t, + features: Box, +) { + config.features = Some(features); +} + /// Check whether the given compiler is available, i.e. part of this /// compiled library. #[no_mangle] diff --git a/lib/c-api/src/wasm_c_api/unstable/features.rs b/lib/c-api/src/wasm_c_api/unstable/features.rs new file mode 100644 index 000000000..8c781488c --- /dev/null +++ b/lib/c-api/src/wasm_c_api/unstable/features.rs @@ -0,0 +1,364 @@ +//! Unstable non-standard Wasmer-specific API that contains a Features +//! API for the engine and the compiler. +//! +//! +//! # Example +//! +//! ```rust +//! # use inline_c::assert_c; +//! # fn main() { +//! # (assert_c! { +//! # #include "tests/wasmer_wasm.h" +//! # +//! int main() { +//! // Declare features. +//! wasmer_features_t* features = wasmer_features_new(); +//! +//! // Now, let's enable de SIMD feature. +//! wasmer_features_simd(features, true); +//! +//! // And also the memory64 feature. +//! wasmer_features_memory64(features, true); +//! +//! wasmer_features_delete(features); +//! +//! return 0; +//! } +//! # }) +//! # .success(); +//! # } +//! ``` +//! +//! To go further, see +//! [`wasm_config_set_features`](super::engine::wasm_config_set_features). + +use wasmer_types::Features; + +/// Controls which experimental features will be enabled. +/// Features usually have a corresponding [WebAssembly proposal]. +/// +/// [WebAssembly proposal]: https://github.com/WebAssembly/proposals +/// +/// # Example +/// +/// See the module's documentation. +#[derive(Debug)] +#[allow(non_camel_case_types)] +pub struct wasmer_features_t { + pub(crate) inner: Features, +} + +/// Creates a new [`wasmer_features_t`]. +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub extern "C" fn wasmer_features_new() -> Box { + Box::new(wasmer_features_t { + inner: Features::new(), + }) +} + +/// Delete a [`wasmer_features_t`]. +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub extern "C" fn wasmer_features_delete(_features: Option>) {} + +/// Configures whether the WebAssembly threads proposal will be enabled. +/// +/// The [WebAssembly threads proposal][threads] is not currently fully +/// standardized and is undergoing development. Support for this feature can +/// be enabled through this method for appropriate WebAssembly modules. +/// +/// This feature gates items such as shared memories and atomic +/// instructions. +/// +/// This is `false` by default. +/// +/// [threads]: https://github.com/webassembly/threads +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub extern "C" fn wasmer_features_threads( + features: Option<&mut wasmer_features_t>, + enable: bool, +) -> bool { + let features = match features { + Some(features) => features, + _ => return false, + }; + + features.inner.threads(enable); + + true +} + +/// Configures whether the WebAssembly reference types proposal will be +/// enabled. +/// +/// The [WebAssembly reference types proposal][proposal] is not currently +/// fully standardized and is undergoing development. Support for this +/// feature can be enabled through this method for appropriate WebAssembly +/// modules. +/// +/// This feature gates items such as the `externref` type and multiple tables +/// being in a module. Note that enabling the reference types feature will +/// also enable the bulk memory feature. +/// +/// This is `false` by default. +/// +/// [proposal]: https://github.com/webassembly/reference-types +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub extern "C" fn wasmer_features_reference_types( + features: Option<&mut wasmer_features_t>, + enable: bool, +) -> bool { + let features = match features { + Some(features) => features, + _ => return false, + }; + + features.inner.reference_types(enable); + + true +} + +/// Configures whether the WebAssembly SIMD proposal will be +/// enabled. +/// +/// The [WebAssembly SIMD proposal][proposal] is not currently +/// fully standardized and is undergoing development. Support for this +/// feature can be enabled through this method for appropriate WebAssembly +/// modules. +/// +/// This feature gates items such as the `v128` type and all of its +/// operators being in a module. +/// +/// This is `false` by default. +/// +/// [proposal]: https://github.com/webassembly/simd +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub extern "C" fn wasmer_features_simd( + features: Option<&mut wasmer_features_t>, + enable: bool, +) -> bool { + let features = match features { + Some(features) => features, + _ => return false, + }; + + features.inner.simd(enable); + + true +} + +/// Configures whether the WebAssembly bulk memory operations proposal will +/// be enabled. +/// +/// The [WebAssembly bulk memory operations proposal][proposal] is not +/// currently fully standardized and is undergoing development. +/// Support for this feature can be enabled through this method for +/// appropriate WebAssembly modules. +/// +/// This feature gates items such as the `memory.copy` instruction, passive +/// data/table segments, etc, being in a module. +/// +/// This is `false` by default. +/// +/// [proposal]: https://github.com/webassembly/bulk-memory-operations +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub extern "C" fn wasmer_features_bulk_memory( + features: Option<&mut wasmer_features_t>, + enable: bool, +) -> bool { + let features = match features { + Some(features) => features, + _ => return false, + }; + + features.inner.bulk_memory(enable); + + true +} + +/// Configures whether the WebAssembly multi-value proposal will +/// be enabled. +/// +/// The [WebAssembly multi-value proposal][proposal] is not +/// currently fully standardized and is undergoing development. +/// Support for this feature can be enabled through this method for +/// appropriate WebAssembly modules. +/// +/// This feature gates functions and blocks returning multiple values in a +/// module, for example. +/// +/// This is `false` by default. +/// +/// [proposal]: https://github.com/webassembly/multi-value +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub extern "C" fn wasmer_features_multi_value( + features: Option<&mut wasmer_features_t>, + enable: bool, +) -> bool { + let features = match features { + Some(features) => features, + _ => return false, + }; + + features.inner.multi_value(enable); + + true +} + +/// Configures whether the WebAssembly tail-call proposal will +/// be enabled. +/// +/// The [WebAssembly tail-call proposal][proposal] is not +/// currently fully standardized and is undergoing development. +/// Support for this feature can be enabled through this method for +/// appropriate WebAssembly modules. +/// +/// This feature gates tail-call functions in WebAssembly. +/// +/// This is `false` by default. +/// +/// [proposal]: https://github.com/webassembly/tail-call +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub extern "C" fn wasmer_features_tail_call( + features: Option<&mut wasmer_features_t>, + enable: bool, +) -> bool { + let features = match features { + Some(features) => features, + _ => return false, + }; + + features.inner.tail_call(enable); + + true +} + +/// Configures whether the WebAssembly tail-call proposal will +/// be enabled. +/// +/// The [WebAssembly tail-call proposal][proposal] is not +/// currently fully standardized and is undergoing development. +/// Support for this feature can be enabled through this method for +/// appropriate WebAssembly modules. +/// +/// This feature allows WebAssembly modules to define, import and +/// export modules and instances. +/// +/// This is `false` by default. +/// +/// [proposal]: https://github.com/webassembly/module-linking +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub extern "C" fn wasmer_features_module_linking( + features: Option<&mut wasmer_features_t>, + enable: bool, +) -> bool { + let features = match features { + Some(features) => features, + _ => return false, + }; + + features.inner.module_linking(enable); + + true +} + +/// Configures whether the WebAssembly multi-memory proposal will +/// be enabled. +/// +/// The [WebAssembly multi-memory proposal][proposal] is not +/// currently fully standardized and is undergoing development. +/// Support for this feature can be enabled through this method for +/// appropriate WebAssembly modules. +/// +/// This feature adds the ability to use multiple memories within a +/// single Wasm module. +/// +/// This is `false` by default. +/// +/// [proposal]: https://github.com/WebAssembly/multi-memory +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub extern "C" fn wasmer_features_multi_memory( + features: Option<&mut wasmer_features_t>, + enable: bool, +) -> bool { + let features = match features { + Some(features) => features, + _ => return false, + }; + + features.inner.multi_memory(enable); + + true +} + +/// Configures whether the WebAssembly 64-bit memory proposal will +/// be enabled. +/// +/// The [WebAssembly 64-bit memory proposal][proposal] is not +/// currently fully standardized and is undergoing development. +/// Support for this feature can be enabled through this method for +/// appropriate WebAssembly modules. +/// +/// This feature gates support for linear memory of sizes larger than +/// 2^32 bits. +/// +/// This is `false` by default. +/// +/// [proposal]: https://github.com/WebAssembly/memory64 +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub extern "C" fn wasmer_features_memory64( + features: Option<&mut wasmer_features_t>, + enable: bool, +) -> bool { + let features = match features { + Some(features) => features, + _ => return false, + }; + + features.inner.memory64(enable); + + true +} diff --git a/lib/c-api/src/wasm_c_api/unstable/mod.rs b/lib/c-api/src/wasm_c_api/unstable/mod.rs index bf6586894..4fa8a5880 100644 --- a/lib/c-api/src/wasm_c_api/unstable/mod.rs +++ b/lib/c-api/src/wasm_c_api/unstable/mod.rs @@ -1,4 +1,5 @@ pub mod engine; +pub mod features; pub mod module; pub mod target_lexicon;