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}