wasmer_c_api/wasm_c_api/unstable/
target_lexicon.rs

1//! Unstable non-standard Wasmer-specific API that contains everything
2//! to create a target with a triple and CPU features.
3//!
4//! This is useful for cross-compilation.
5//!
6//! # Example
7//!
8//! ```rust
9//! # use wasmer_inline_c::assert_c;
10//! # fn main() {
11//! #    (assert_c! {
12//! # #include "tests/wasmer.h"
13//! #
14//! int main() {
15//!     // Declare the target triple.
16//!     wasmer_triple_t* triple;
17//!
18//!     {
19//!         wasm_name_t triple_name;
20//!         wasm_name_new_from_string(&triple_name, "x86_64-apple-darwin");
21//!
22//!         triple = wasmer_triple_new(&triple_name);
23//!
24//!         wasm_name_delete(&triple_name);
25//!     }
26//!
27//!     assert(triple);
28//!
29//!     // Declare the target CPU features.
30//!     wasmer_cpu_features_t* cpu_features = wasmer_cpu_features_new();
31//!
32//!     {
33//!         wasm_name_t cpu_feature_name;
34//!         wasm_name_new_from_string(&cpu_feature_name, "sse2");
35//!
36//!         wasmer_cpu_features_add(cpu_features, &cpu_feature_name);
37//!
38//!         wasm_name_delete(&cpu_feature_name);
39//!     }
40//!
41//!     assert(cpu_features);
42//!
43//!     // Create the target!
44//!     wasmer_target_t* target = wasmer_target_new(triple, cpu_features);
45//!     assert(target);
46//!
47//!     wasmer_target_delete(target);
48//!
49//!     return 0;
50//! }
51//! #    })
52//! #    .success();
53//! # }
54//! ```
55
56use super::super::types::wasm_name_t;
57use enumset::EnumSet;
58use std::slice;
59use std::str::{self, FromStr};
60use wasmer_types::target::{CpuFeature, Target, Triple};
61
62/// Unstable non-standard Wasmer-specific API to represent a triple +
63/// CPU features pair.
64///
65/// # Example
66///
67/// See the module's documentation.
68#[derive(Debug)]
69#[allow(non_camel_case_types)]
70pub struct wasmer_target_t {
71    #[allow(unused)]
72    pub(crate) inner: Target,
73}
74
75/// Creates a new [`wasmer_target_t`].
76///
77/// It takes ownership of `triple` and `cpu_features`.
78///
79/// # Example
80///
81/// See the module's documentation.
82#[unsafe(no_mangle)]
83pub extern "C" fn wasmer_target_new(
84    triple: Option<Box<wasmer_triple_t>>,
85    cpu_features: Option<Box<wasmer_cpu_features_t>>,
86) -> Option<Box<wasmer_target_t>> {
87    let triple = triple?;
88    let cpu_features = cpu_features?;
89
90    Some(Box::new(wasmer_target_t {
91        inner: Target::new(triple.inner.clone(), cpu_features.inner),
92    }))
93}
94
95/// Delete a [`wasmer_target_t`].
96///
97/// # Example
98///
99/// See the module's documentation.
100#[unsafe(no_mangle)]
101pub extern "C" fn wasmer_target_delete(_target: Option<Box<wasmer_target_t>>) {}
102
103/// Unstable non-standard Wasmer-specific API to represent a target
104/// “triple”.
105///
106/// Historically such things had three fields, though they have added
107/// additional fields over time.
108///
109/// # Example
110///
111/// ```rust
112/// # use wasmer_inline_c::assert_c;
113/// # fn main() {
114/// #    (assert_c! {
115/// # #include "tests/wasmer.h"
116/// #
117/// int main() {
118///     wasm_name_t triple_name;
119///     wasm_name_new_from_string(&triple_name, "x86_64-apple-darwin");
120///
121///     wasmer_triple_t* triple = wasmer_triple_new(&triple_name);
122///     assert(triple);
123///
124///     wasmer_triple_delete(triple);
125///     wasm_name_delete(&triple_name);
126///
127///     return 0;
128/// }
129/// #    })
130/// #    .success();
131/// # }
132/// ```
133///
134/// See also [`wasmer_triple_new_from_host`].
135#[allow(non_camel_case_types)]
136pub struct wasmer_triple_t {
137    inner: Triple,
138}
139
140/// Create a new [`wasmer_triple_t`] based on a triple string.
141///
142/// # Example
143///
144/// See [`wasmer_triple_t`] or [`wasmer_triple_new_from_host`].
145#[unsafe(no_mangle)]
146pub unsafe extern "C" fn wasmer_triple_new(
147    triple: Option<&wasm_name_t>,
148) -> Option<Box<wasmer_triple_t>> {
149    let triple = triple?;
150    let triple = c_try!(str::from_utf8(unsafe {
151        slice::from_raw_parts(triple.data, triple.size)
152    }));
153
154    Some(Box::new(wasmer_triple_t {
155        inner: c_try!(Triple::from_str(triple)),
156    }))
157}
158
159/// Create the [`wasmer_triple_t`] for the current host.
160///
161/// # Example
162///
163/// ```rust
164/// # use wasmer_inline_c::assert_c;
165/// # fn main() {
166/// #    (assert_c! {
167/// # #include "tests/wasmer.h"
168/// #
169/// int main() {
170///     wasmer_triple_t* triple = wasmer_triple_new_from_host();
171///     assert(triple);
172///
173///     wasmer_triple_delete(triple);
174///
175///     return 0;
176/// }
177/// #    })
178/// #    .success();
179/// # }
180/// ```
181///
182/// See also [`wasmer_triple_new`].
183#[unsafe(no_mangle)]
184pub extern "C" fn wasmer_triple_new_from_host() -> Box<wasmer_triple_t> {
185    Box::new(wasmer_triple_t {
186        inner: Triple::host(),
187    })
188}
189
190/// Delete a [`wasmer_triple_t`].
191///
192/// # Example
193///
194/// See [`wasmer_triple_t`].
195#[unsafe(no_mangle)]
196pub extern "C" fn wasmer_triple_delete(_triple: Option<Box<wasmer_triple_t>>) {}
197
198/// Unstable non-standard Wasmer-specific API to represent a set of
199/// CPU features.
200///
201/// CPU features are identified by their stringified names. The
202/// reference is the GCC options:
203///
204/// * <https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html>,
205/// * <https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html>,
206/// * <https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html>.
207///
208/// At the time of writing this documentation (it might be outdated in
209/// the future), the supported features are the following:
210///
211/// * `sse2`,
212/// * `sse3`,
213/// * `ssse3`,
214/// * `sse4.1`,
215/// * `sse4.2`,
216/// * `popcnt`,
217/// * `avx`,
218/// * `bmi`,
219/// * `bmi2`,
220/// * `avx2`,
221/// * `avx512dq`,
222/// * `avx512vl`,
223/// * `lzcnt`.
224///
225/// # Example
226///
227/// ```rust
228/// # use wasmer_inline_c::assert_c;
229/// # fn main() {
230/// #    (assert_c! {
231/// # #include "tests/wasmer.h"
232/// #
233/// int main() {
234///     // Create a new CPU feature set.
235///     wasmer_cpu_features_t* cpu_features = wasmer_cpu_features_new();
236///
237///     // Create a new feature name, here `sse2`, and add it to the set.
238///     {
239///         wasm_name_t cpu_feature_name;
240///         wasm_name_new_from_string(&cpu_feature_name, "sse2");
241///
242///         wasmer_cpu_features_add(cpu_features, &cpu_feature_name);
243///
244///         wasm_name_delete(&cpu_feature_name);
245///     }
246///
247///     wasmer_cpu_features_delete(cpu_features);
248///
249///     return 0;
250/// }
251/// #    })
252/// #    .success();
253/// # }
254/// ```
255#[allow(non_camel_case_types)]
256pub struct wasmer_cpu_features_t {
257    inner: EnumSet<CpuFeature>,
258}
259
260/// Create a new [`wasmer_cpu_features_t`].
261///
262/// # Example
263///
264/// See [`wasmer_cpu_features_t`].
265#[unsafe(no_mangle)]
266pub extern "C" fn wasmer_cpu_features_new() -> Box<wasmer_cpu_features_t> {
267    Box::new(wasmer_cpu_features_t {
268        inner: CpuFeature::set(),
269    })
270}
271
272/// Delete a [`wasmer_cpu_features_t`].
273///
274/// # Example
275///
276/// See [`wasmer_cpu_features_t`].
277#[unsafe(no_mangle)]
278pub extern "C" fn wasmer_cpu_features_delete(_cpu_features: Option<Box<wasmer_cpu_features_t>>) {}
279
280/// Add a new CPU feature into the set represented by
281/// [`wasmer_cpu_features_t`].
282///
283/// # Example
284///
285/// See [`wasmer_cpu_features_t`].
286#[unsafe(no_mangle)]
287pub unsafe extern "C" fn wasmer_cpu_features_add(
288    cpu_features: Option<&mut wasmer_cpu_features_t>,
289    feature: Option<&wasm_name_t>,
290) -> bool {
291    let cpu_features = match cpu_features {
292        Some(cpu_features) => cpu_features,
293        _ => return false,
294    };
295    let feature = match feature {
296        Some(feature) => feature,
297        _ => return false,
298    };
299    let feature = c_try!(
300        str::from_utf8(unsafe {
301            slice::from_raw_parts(
302                feature.data,
303                feature.size,
304            )
305        });
306        otherwise false
307    );
308
309    cpu_features.inner.insert(c_try!(
310        CpuFeature::from_str(feature);
311        otherwise false
312    ));
313
314    true
315}