feat(c-api) Start implementing wasm_target_t, wasm_triple_t and wasm_cpu_features_t.

This commit is contained in:
Ivan Enderlin
2021-01-28 17:26:15 +01:00
parent 2f82d5536f
commit b201f12494
7 changed files with 274 additions and 3 deletions

View File

@@ -27,6 +27,7 @@ wasmer-engine-native = { version = "1.0.1", path = "../engine-native", optional
wasmer-engine-object-file = { version = "1.0.1", path = "../engine-object-file", optional = true } wasmer-engine-object-file = { version = "1.0.1", path = "../engine-object-file", optional = true }
wasmer-wasi = { version = "1.0.1", path = "../wasi", optional = true } wasmer-wasi = { version = "1.0.1", path = "../wasi", optional = true }
wasmer-types = { version = "1.0.1", path = "../wasmer-types" } wasmer-types = { version = "1.0.1", path = "../wasmer-types" }
enumset = "1.0"
cfg-if = "1.0" cfg-if = "1.0"
lazy_static = "1.4" lazy_static = "1.4"
libc = { version = "^0.2", default-features = false } libc = { version = "^0.2", default-features = false }

View File

@@ -256,7 +256,7 @@ pub struct wasm_engine_t {
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
use wasmer_compiler::CompilerConfig; use wasmer_compiler::CompilerConfig;
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
fn get_default_compiler_config() -> Box<dyn CompilerConfig> { pub(crate) fn get_default_compiler_config() -> Box<dyn CompilerConfig> {
cfg_if! { cfg_if! {
if #[cfg(feature = "cranelift")] { if #[cfg(feature = "cranelift")] {
Box::new(wasmer_compiler_cranelift::Cranelift::default()) Box::new(wasmer_compiler_cranelift::Cranelift::default())

View File

@@ -467,16 +467,19 @@ macro_rules! wasm_declare_own {
#[macro_export] #[macro_export]
macro_rules! c_try { macro_rules! c_try {
($expr:expr) => {{ ($expr:expr; otherwise $return:expr) => {{
let res: Result<_, _> = $expr; let res: Result<_, _> = $expr;
match res { match res {
Ok(val) => val, Ok(val) => val,
Err(err) => { Err(err) => {
crate::error::update_last_error(err); crate::error::update_last_error(err);
return None; return $return;
} }
} }
}}; }};
($expr:expr) => {{
c_try!($expr; otherwise None)
}};
($expr:expr, $e:expr) => {{ ($expr:expr, $e:expr) => {{
let opt: Option<_> = $expr; let opt: Option<_> = $expr;
c_try!(opt.ok_or_else(|| $e)) c_try!(opt.ok_or_else(|| $e))

View File

@@ -0,0 +1,69 @@
#[cfg(feature = "compiler")]
use super::super::engine::get_default_compiler_config;
use super::super::engine::wasm_engine_t;
use super::target_lexicon::wasm_target_t;
use cfg_if::cfg_if;
use std::sync::Arc;
#[cfg(feature = "compiler")]
use wasmer_compiler::CompilerConfig;
use wasmer_engine::Engine;
#[cfg(feature = "jit")]
use wasmer_engine_jit::JIT;
#[cfg(feature = "native")]
use wasmer_engine_native::Native;
#[cfg(feature = "object-file")]
use wasmer_engine_object_file::ObjectFile;
cfg_if! {
if #[cfg(all(feature = "jit", feature = "compiler"))] {
#[no_mangle]
pub extern "C" fn wasm_new_engine_with_target(target: Option<Box<wasm_target_t>>) -> Option<Box<wasm_engine_t>> {
let target = target?;
let compiler_config: Box<dyn CompilerConfig> = get_default_compiler_config();
let engine: Arc<dyn Engine + Send + Sync> = Arc::new(JIT::new(compiler_config).target(target.inner).engine());
Some(Box::new(wasm_engine_t { inner: engine }))
}
} else if #[cfg(feature = "jit")] {
#[no_mangle]
pub extern "C" fn wasm_new_engine_with_target(target: Option<Box<wasm_target_t>>) -> Option<Box<wasm_engine_t>> {
let target = target?;
let engine: Arc<dyn Engine + Send + Sync> = Arc::new(JIT::headless().target(target.inner).engine());
Some(Box::new(wasm_engine_t { inner: engine }))
}
} else if #[cfg(all(feature = "native", feature = "compiler"))] {
#[no_mangle]
pub extern "C" fn wasm_new_engine_with_target(target: Option<Box<wasm_target_t>>) -> Option<Box<wasm_engine_t>> {
let target = target?;
let mut compiler_config: Box<dyn CompilerConfig> = get_default_compiler_config();
let engine: Arc<dyn Engine + Send + Sync> = Arc::new(Native::new(compiler_config).target(target.inner).engine());
Some(Box::new(wasm_engine_t { inner: engine }))
}
} else if #[cfg(feature = "native")] {
#[no_mangle]
pub extern "C" fn wasm_new_engine_with_target(target: Option<Box<wasm_target_t>>) -> Option<Box<wasm_engine_t>>> {
let target = target?;
let engine: Arc<dyn Engine + Send + Sync> = Arc::new(Native::headless().target(target.inner).engine());
Some(Box::new(wasm_engine_t { inner: engine }))
}
}
// There are currently no uses of the object-file engine + compiler from the C API.
// So if we get here, we default to headless mode regardless of if `compiler` is enabled.
else if #[cfg(feature = "object-file")] {
#[no_mangle]
pub extern "C" fn wasm_new_engine_with_target(target: Option<Box<wasm_target_t>>) -> Option<Box<wasm_engine_t>> {
let target = target?;
let engine: Arc<dyn Engine + Send + Sync> = Arc::new(ObjectFile::headless().target(target.inner).engine());
Some(Box::new(wasm_engine_t { inner: engine }))
}
} else {
#[no_mangle]
pub extern "C" fn wasm_new_engine_with_target(_target: Option<Box<wasm_target_t>>) -> Option<Box<wasm_engine_t>> {
unimplemented!("No engine attached; You might want to recompile `wasmer_c_api` with for example `--feature jit`");
}
}
}

View File

@@ -1 +1,3 @@
pub mod engine;
pub mod module; pub mod module;
pub mod target_lexicon;

View File

@@ -0,0 +1,155 @@
//! Contains everything to create a target with a triple and CPU featurres.
//!
//! # Example
//!
//! ```rust
//! # use inline_c::assert_c;
//! # fn main() {
//! # (assert_c! {
//! # #include "tests/wasmer_wasm.h"
//! #
//! int main() {
//! wasm_byte_vec_t triple_name;
//! wasmer_byte_vec_new_from_string(&triple_name, "x86_64-apple-darwin");
//!
//! wasm_triple_t* triple = wasm_triple_new((wasm_name_t*) &triple_name);
//! assert(triple);
//!
//! wasm_byte_vec_t cpu_feature_name;
//! wasmer_byte_vec_new_from_string(&cpu_feature_name, "sse2");
//!
//! wasm_cpu_features_t* cpu_features = wasm_cpu_features_new();
//! wasm_cpu_features_add(cpu_features, (wasm_name_t*) &cpu_feature_name);
//!
//! wasm_target_t* target = wasm_target_new(triple, cpu_features);
//! assert(target);
//!
//! wasm_target_delete(target);
//! wasm_byte_vec_delete(&cpu_feature_name);
//! wasm_byte_vec_delete(&triple_name);
//!
//! return 0;
//! }
//! # })
//! # .success();
//! # }
//! ```
use super::super::types::wasm_name_t;
use crate::error::CApiError;
use enumset::EnumSet;
use std::ffi::CStr;
use std::slice;
use std::str::FromStr;
use wasmer_compiler::{CpuFeature, Target, Triple};
/// Represents a triple + CPU features pair.
#[allow(non_camel_case_types)]
pub struct wasm_target_t {
pub(crate) inner: Target,
}
/// Createas a new `wasm_target_`.
///
/// It takes ownership of `triple` and `cpu_features`.
///
/// # Example
///
/// See the module's documentation.
#[no_mangle]
pub unsafe extern "C" fn wasm_target_new(
triple: Option<Box<wasm_triple_t>>,
cpu_features: Option<Box<wasm_cpu_features_t>>,
) -> Option<Box<wasm_target_t>> {
let triple = triple?;
let cpu_features = cpu_features?;
Some(Box::new(wasm_target_t {
inner: Target::new(triple.inner.clone(), cpu_features.inner.clone()),
}))
}
/// Delete a `wasm_target_t`.
///
/// # Example
///
/// See the module's documentation.
#[no_mangle]
pub unsafe extern "C" fn wasm_target_delete(_target: Option<Box<wasm_target_t>>) {}
#[allow(non_camel_case_types)]
pub struct wasm_triple_t {
inner: Triple,
}
#[no_mangle]
pub unsafe extern "C" fn wasm_triple_new(
triple: Option<&wasm_name_t>,
) -> Option<Box<wasm_triple_t>> {
let triple = triple?;
let triple = c_try!(CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(
triple.data,
triple.size + 1
))
.to_str());
Some(Box::new(wasm_triple_t {
inner: c_try!(Triple::from_str(triple).map_err(|e| CApiError { msg: e.to_string() })),
}))
}
#[no_mangle]
pub unsafe extern "C" fn wasm_triple_new_from_host() -> Box<wasm_triple_t> {
Box::new(wasm_triple_t {
inner: Triple::host(),
})
}
#[no_mangle]
pub unsafe extern "C" fn wasm_triple_delete(_triple: Option<Box<wasm_triple_t>>) {}
#[allow(non_camel_case_types)]
pub struct wasm_cpu_features_t {
inner: EnumSet<CpuFeature>,
}
#[no_mangle]
pub unsafe extern "C" fn wasm_cpu_features_new() -> Box<wasm_cpu_features_t> {
Box::new(wasm_cpu_features_t {
inner: CpuFeature::set(),
})
}
#[no_mangle]
pub unsafe extern "C" fn wasm_cpu_features_delete(_cpu_features: Option<Box<wasm_cpu_features_t>>) {
}
#[no_mangle]
pub unsafe extern "C" fn wasm_cpu_features_add(
cpu_features: Option<&mut wasm_cpu_features_t>,
feature: Option<&wasm_name_t>,
) -> bool {
let cpu_features = match cpu_features {
Some(cpu_features) => cpu_features,
_ => return false,
};
let feature = match feature {
Some(feature) => feature,
_ => return false,
};
let feature = c_try!(
CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(
feature.data,
feature.size + 1,
))
.to_str();
otherwise false
);
cpu_features.inner.insert(c_try!(
CpuFeature::from_str(feature);
otherwise false
));
true
}

View File

@@ -162,6 +162,15 @@ typedef struct wasi_config_t wasi_config_t;
typedef struct wasi_env_t wasi_env_t; typedef struct wasi_env_t wasi_env_t;
#endif #endif
typedef struct wasm_cpu_features_t wasm_cpu_features_t;
/**
* Represents a triple + CPU features pair.
*/
typedef struct wasm_target_t wasm_target_t;
typedef struct wasm_triple_t wasm_triple_t;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif // __cplusplus #endif // __cplusplus
@@ -337,6 +346,12 @@ void wasm_config_set_compiler(wasm_config_t *config, wasmer_compiler_t compiler)
*/ */
void wasm_config_set_engine(wasm_config_t *config, wasmer_engine_t engine); void wasm_config_set_engine(wasm_config_t *config, wasmer_engine_t engine);
bool wasm_cpu_features_add(wasm_cpu_features_t *cpu_features, const wasm_name_t *feature);
void wasm_cpu_features_delete(wasm_cpu_features_t *_cpu_features);
wasm_cpu_features_t *wasm_cpu_features_new(void);
/** /**
* Unstable non-standard Wasmer-specific API to get the module's * Unstable non-standard Wasmer-specific API to get the module's
* name, otherwise `out->size` is set to `0` and `out->data` to * name, otherwise `out->size` is set to `0` and `out->data` to
@@ -458,6 +473,32 @@ void wasm_module_name(const wasm_module_t *module, wasm_name_t *out);
*/ */
bool wasm_module_set_name(wasm_module_t *module, const wasm_name_t *name); bool wasm_module_set_name(wasm_module_t *module, const wasm_name_t *name);
/**
* Delete a `wasm_target_t`.
*
* # Example
*
* See the module's documentation.
*/
void wasm_target_delete(wasm_target_t *_target);
/**
* Createas a new `wasm_target_`.
*
* It takes ownership of `triple` and `cpu_features`.
*
* # Example
*
* See the module's documentation.
*/
wasm_target_t *wasm_target_new(wasm_triple_t *triple, wasm_cpu_features_t *cpu_features);
void wasm_triple_delete(wasm_triple_t *_triple);
wasm_triple_t *wasm_triple_new(const wasm_name_t *triple);
wasm_triple_t *wasm_triple_new_from_host(void);
/** /**
* Gets the length in bytes of the last error if any, zero otherwise. * Gets the length in bytes of the last error if any, zero otherwise.
* *