wasmer_c_api/wasm_c_api/engine/
mod.rs

1pub use super::unstable::engine::wasm_config_set_features;
2use super::unstable::features::wasmer_features_t;
3
4use wasmer_api::{BackendKind, Engine};
5
6mod config;
7#[allow(unused_imports)]
8pub use config::*;
9
10/// Kind of engines that can be used by the store.
11///
12/// This is a Wasmer-specific type with Wasmer-specific functions for
13/// manipulating it.
14#[derive(Debug, Copy, Clone)]
15#[repr(C)]
16#[allow(non_camel_case_types)]
17pub enum wasmer_backend_t {
18    /// The cranelift backend.
19    CRANELIFT = 0,
20
21    /// The LLVM backend.
22    LLVM,
23
24    /// The singlepass backend.
25    SINGLEPASS,
26
27    /// The headless backend.
28    HEADLESS,
29
30    /// The V8 backend.
31    V8,
32
33    /// The WASMI backend.
34    WASMI,
35
36    /// The WAMR backend.
37    WAMR,
38
39    /// The JSC backend.
40    JSC,
41}
42
43impl From<BackendKind> for wasmer_backend_t {
44    fn from(value: BackendKind) -> Self {
45        match value {
46            #[cfg(feature = "cranelift")]
47            BackendKind::Cranelift => Self::CRANELIFT,
48            #[cfg(feature = "llvm")]
49            BackendKind::LLVM => Self::LLVM,
50            #[cfg(feature = "singlepass")]
51            BackendKind::Singlepass => Self::SINGLEPASS,
52            #[cfg(feature = "sys")]
53            BackendKind::Headless => Self::HEADLESS,
54            #[cfg(feature = "wamr")]
55            BackendKind::Wamr => Self::WAMR,
56            #[cfg(feature = "wasmi")]
57            BackendKind::Wasmi => Self::WASMI,
58            #[cfg(feature = "v8")]
59            BackendKind::V8 => Self::V8,
60            #[cfg(feature = "jsc")]
61            BackendKind::Jsc => Self::JSC,
62            v => panic!("Unsupported backend kind {v:?}"),
63        }
64    }
65}
66
67impl Default for wasmer_backend_t {
68    fn default() -> Self {
69        // Let the `wasmer_api` crate decide which is the default engine, given the enabled
70        // features.
71        wasmer_api::BackendKind::default().into()
72    }
73}
74
75/// An engine is used by the store to drive the compilation and the
76/// execution of a WebAssembly module.
77///
78/// cbindgen:ignore
79#[repr(C)]
80// We can let the API decide which engine is default with the given set of
81// features.
82//
83// See the impl of `Default` for `BackendEngine` in the `wasmer` (API) crate.
84#[derive(Default)]
85pub struct wasm_engine_t {
86    pub(crate) inner: Engine,
87}
88
89#[unsafe(no_mangle)]
90#[allow(unreachable_code)]
91pub extern "C" fn wasm_engine_new() -> Box<wasm_engine_t> {
92    Box::new(wasm_engine_t::default())
93}
94
95/// Deletes an engine.
96///
97/// # Example
98///
99/// ```rust
100/// # use wasmer_inline_c::assert_c;
101/// # fn main() {
102/// #    (assert_c! {
103/// # #include "tests/wasmer.h"
104/// #
105/// int main() {
106///     // Create a default engine.
107///     wasm_engine_t* engine = wasm_engine_new();
108///     int error_length = wasmer_last_error_length();
109///     if (error_length > 0) {
110///         char *error_message = malloc(error_length);
111///         wasmer_last_error_message(error_message, error_length);
112///
113///         printf("Attempted to set an immutable global: `%s`\n", error_message);
114///         free(error_message);
115///     }
116///
117///     // Check we have an engine!
118///     assert(engine);
119///
120///     // Free everything.
121///     wasm_engine_delete(engine);
122///
123///     return 0;
124/// }
125/// #    })
126/// #    .success();
127/// # }
128/// ```
129///
130/// cbindgen:ignore
131#[unsafe(no_mangle)]
132pub unsafe extern "C" fn wasm_engine_delete(_engine: Option<Box<wasm_engine_t>>) {}
133
134/// Creates an engine with a particular configuration.
135///
136/// # Example
137///
138/// See [`wasm_config_new`].
139///
140/// cbindgen:ignore
141#[unsafe(no_mangle)]
142pub extern "C" fn wasm_engine_new_with_config(
143    config: Option<Box<wasm_config_t>>,
144) -> Option<Box<wasm_engine_t>> {
145    #[allow(unused)]
146    let config = *(config?);
147
148    match config.backend {
149        #[cfg(feature = "llvm")]
150        wasmer_backend_t::LLVM => config::sys::wasm_sys_engine_new_with_config(config),
151        #[cfg(feature = "cranelift")]
152        wasmer_backend_t::CRANELIFT => config::sys::wasm_sys_engine_new_with_config(config),
153        #[cfg(feature = "singlepass")]
154        wasmer_backend_t::SINGLEPASS => config::sys::wasm_sys_engine_new_with_config(config),
155        #[cfg(feature = "sys")]
156        wasmer_backend_t::HEADLESS => config::sys::wasm_sys_engine_new_with_config(config),
157        #[cfg(feature = "v8")]
158        wasmer_backend_t::V8 => config::v8::wasm_v8_engine_new_with_config(config),
159        #[cfg(feature = "wasmi")]
160        wasmer_backend_t::WASMI => config::wasmi::wasm_wasmi_engine_new_with_config(config),
161        #[cfg(feature = "wamr")]
162        wasmer_backend_t::WAMR => config::wamr::wasm_wamr_engine_new_with_config(config),
163        #[cfg(feature = "jsc")]
164        wasmer_backend_t::JSC => config::jsc::wasm_jsc_engine_new_with_config(config),
165        #[allow(unreachable_patterns)]
166        _ => unreachable!(),
167    }
168}
169
170/// A configuration holds the compiler and the engine used by the store.
171///
172/// cbindgen:ignore
173#[derive(Debug, Default)]
174#[repr(C)]
175pub struct wasm_config_t {
176    pub(super) backend: wasmer_backend_t,
177    pub(super) backend_config: wasmer_backend_config_t,
178    pub(super) features: Option<Box<wasmer_features_t>>,
179}
180
181/// Create a new default Wasmer configuration.
182///
183/// # Example
184///
185/// ```rust
186/// # use wasmer_inline_c::assert_c;
187/// # fn main() {
188/// #    (assert_c! {
189/// # #include "tests/wasmer.h"
190/// #
191/// int main() {
192///     // Create the configuration.
193///     wasm_config_t* config = wasm_config_new();
194///
195///     // Create the engine.
196///     wasm_engine_t* engine = wasm_engine_new_with_config(config);
197///
198///     // Check we have an engine!
199///     assert(engine);
200///
201///     // Free everything.
202///     wasm_engine_delete(engine);
203///
204///     return 0;
205/// }
206/// #    })
207/// #    .success();
208/// # }
209/// ```
210///
211/// cbindgen:ignore
212#[unsafe(no_mangle)]
213pub extern "C" fn wasm_config_new() -> Box<wasm_config_t> {
214    Box::<wasm_config_t>::default()
215}
216
217/// Delete a Wasmer config object.
218///
219/// This function does not need to be called if `wasm_engine_new_with_config` or
220/// another function that takes ownership of the `wasm_config_t` is called.
221///
222/// # Example
223///
224/// ```rust
225/// # use wasmer_inline_c::assert_c;
226/// # fn main() {
227/// #    (assert_c! {
228/// # #include "tests/wasmer.h"
229/// #
230/// int main() {
231///     // Create the configuration.
232///     wasm_config_t* config = wasm_config_new();
233///
234///     // Delete the configuration
235///     wasm_config_delete(config);
236///
237///     return 0;
238/// }
239/// #    })
240/// #    .success();
241/// # }
242/// ```
243/// cbindgen:ignore
244#[unsafe(no_mangle)]
245pub extern "C" fn wasm_config_delete(_config: Option<Box<wasm_config_t>>) {}
246
247/// Updates the configuration to specify a particular engine to use.
248///
249/// This is a Wasmer-specific function.
250///
251/// # Example
252///
253/// ```rust
254/// # use wasmer_inline_c::assert_c;
255/// # fn main() {
256/// #    (assert_c! {
257/// # #include "tests/wasmer.h"
258/// #
259/// int main() {
260///     // Create the configuration.
261///     wasm_config_t* config = wasm_config_new();
262///
263///     // Create the engine.
264///     wasm_engine_t* engine = wasm_engine_new_with_config(config);
265///
266///     // Check we have an engine!
267///     assert(engine);
268///
269///     // Free everything.
270///     wasm_engine_delete(engine);
271///
272///     return 0;
273/// }
274/// #    })
275/// #    .success();
276/// # }
277/// ```
278#[unsafe(no_mangle)]
279pub extern "C" fn wasm_config_set_backend(config: &mut wasm_config_t, engine: wasmer_backend_t) {
280    config.backend = engine;
281}
282
283#[cfg(test)]
284mod tests {
285    #[cfg(not(target_os = "windows"))]
286    use inline_c::assert_c;
287    #[cfg(target_os = "windows")]
288    use wasmer_inline_c::assert_c;
289
290    #[allow(
291        unexpected_cfgs,
292        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
293    )]
294    #[cfg_attr(coverage_nightly, coverage(off))]
295    #[test]
296    fn test_engine_new() {
297        (assert_c! {
298            #include "tests/wasmer.h"
299
300            int main() {
301                wasm_engine_t* engine = wasm_engine_new();
302                assert(engine);
303
304                wasm_engine_delete(engine);
305
306                return 0;
307            }
308        })
309        .success();
310    }
311}