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