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}