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