Merge branch 'master' into feat-c-api-wasi-unordered-imports

This commit is contained in:
Ivan Enderlin
2021-02-02 12:17:01 +01:00
18 changed files with 499 additions and 48 deletions

View File

@@ -1,3 +1,5 @@
pub use super::unstable::engine::wasm_config_set_target;
use super::unstable::target_lexicon::wasm_target_t;
use crate::error::{update_last_error, CApiError};
use cfg_if::cfg_if;
use std::sync::Arc;
@@ -93,6 +95,7 @@ pub struct wasm_config_t {
engine: wasmer_engine_t,
#[cfg(feature = "compiler")]
compiler: wasmer_compiler_t,
pub(super) target: Option<Box<wasm_target_t>>,
}
/// Create a new default Wasmer configuration.
@@ -396,7 +399,7 @@ pub unsafe extern "C" fn wasm_engine_delete(_engine: Option<Box<wasm_engine_t>>)
/// cbindgen:ignore
#[no_mangle]
pub extern "C" fn wasm_engine_new_with_config(
config: Box<wasm_config_t>,
config: Option<Box<wasm_config_t>>,
) -> Option<Box<wasm_engine_t>> {
#[allow(dead_code)]
fn return_with_error<M>(msg: M) -> Option<Box<wasm_engine_t>>
@@ -408,7 +411,9 @@ pub extern "C" fn wasm_engine_new_with_config(
});
return None;
};
}
let config = config?;
cfg_if! {
if #[cfg(feature = "compiler")] {
@@ -447,7 +452,13 @@ pub extern "C" fn wasm_engine_new_with_config(
wasmer_engine_t::JIT => {
cfg_if! {
if #[cfg(feature = "jit")] {
Arc::new(JIT::new(compiler_config).engine())
let mut builder = JIT::new(compiler_config);
if let Some(target) = config.target {
builder = builder.target(target.inner);
}
Arc::new(builder.engine())
} else {
return return_with_error("Wasmer has not been compiled with the `jit` feature.");
}
@@ -456,7 +467,13 @@ pub extern "C" fn wasm_engine_new_with_config(
wasmer_engine_t::NATIVE => {
cfg_if! {
if #[cfg(feature = "native")] {
Arc::new(Native::new(compiler_config).engine())
let mut builder = Native::new(compiler_config);
if let Some(target) = config.target {
builder = builder.target(target.inner);
}
Arc::new(builder.engine())
} else {
return return_with_error("Wasmer has not been compiled with the `native` feature.");
}
@@ -467,7 +484,13 @@ pub extern "C" fn wasm_engine_new_with_config(
// There are currently no uses of the object-file engine + compiler from the C API.
// So we run in headless mode.
if #[cfg(feature = "object-file")] {
Arc::new(ObjectFile::headless().engine())
let mut builder = ObjectFile::headless();
if let Some(target) = config.target {
builder = builder.target(target.inner);
}
Arc::new(builder.engine())
} else {
return return_with_error("Wasmer has not been compiled with the `object-file` feature.");
}
@@ -480,7 +503,13 @@ pub extern "C" fn wasm_engine_new_with_config(
wasmer_engine_t::JIT => {
cfg_if! {
if #[cfg(feature = "jit")] {
Arc::new(JIT::headless().engine())
let mut builder = JIT::headless();
if let Some(target) = config.target {
builder = builder.target(target.inner);
}
Arc::new(builder.engine())
} else {
return return_with_error("Wasmer has not been compiled with the `jit` feature.");
}
@@ -489,7 +518,13 @@ pub extern "C" fn wasm_engine_new_with_config(
wasmer_engine_t::NATIVE => {
cfg_if! {
if #[cfg(feature = "native")] {
Arc::new(Native::headless().engine())
let mut builder = Native::headless();
if let Some(target) = config.target {
builder = builder.target(target.inner);
}
Arc::new(builder.engine())
} else {
return return_with_error("Wasmer has not been compiled with the `native` feature.");
}
@@ -498,7 +533,13 @@ pub extern "C" fn wasm_engine_new_with_config(
wasmer_engine_t::OBJECT_FILE => {
cfg_if! {
if #[cfg(feature = "object-file")] {
Arc::new(ObjectFile::headless().engine())
let mut builder = ObjectFile::headless();
if let Some(target) = config.target {
builder = builder.target(target.inner);
}
Arc::new(builder.engine())
} else {
return return_with_error("Wasmer has not been compiled with the `object-file` feature.");
}

View File

@@ -105,8 +105,8 @@ pub unsafe extern "C" fn wasm_func_new_with_env(
#[repr(C)]
struct WrapperEnv {
env: *mut c_void,
finalizer: Option<wasm_env_finalizer_t>,
};
finalizer: Arc<Option<wasm_env_finalizer_t>>,
}
// Only relevant when using multiple threads in the C API;
// Synchronization will be done via the C API / on the C side.
@@ -115,8 +115,13 @@ pub unsafe extern "C" fn wasm_func_new_with_env(
impl Drop for WrapperEnv {
fn drop(&mut self) {
if let Some(finalizer) = self.finalizer {
unsafe { (finalizer)(self.env as _) }
if let Some(finalizer) = Arc::get_mut(&mut self.finalizer)
.map(Option::take)
.flatten()
{
if !self.env.is_null() {
unsafe { (finalizer)(self.env as _) }
}
}
}
}
@@ -160,7 +165,10 @@ pub unsafe extern "C" fn wasm_func_new_with_env(
let function = Function::new_with_env(
&store.inner,
func_sig,
WrapperEnv { env, finalizer },
WrapperEnv {
env,
finalizer: Arc::new(finalizer),
},
inner_callback,
);

View File

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

View File

@@ -0,0 +1,49 @@
//! Unstable non-standard Wasmer-specific types for the
//! `wasm_engine_t` and siblings.
use super::super::engine::wasm_config_t;
use super::target_lexicon::wasm_target_t;
/// Unstable non-standard Wasmer-specific API to update the
/// configuration to specify a particular target for the engine.
///
/// # Example
///
/// ```rust
/// # use inline_c::assert_c;
/// # fn main() {
/// # (assert_c! {
/// # #include "tests/wasmer_wasm.h"
/// #
/// int main() {
/// // Create the configuration.
/// wasm_config_t* config = wasm_config_new();
///
/// // Set the target.
/// {
/// wasm_triple_t* triple = wasm_triple_new_from_host();
/// wasm_cpu_features_t* cpu_features = wasm_cpu_features_new();
/// wasm_target_t* target = wasm_target_new(triple, cpu_features);
///
/// wasm_config_set_target(config, target);
/// }
///
/// // Create the engine.
/// wasm_engine_t* engine = wasm_engine_new_with_config(config);
///
/// // Check we have an engine!
/// assert(engine);
///
/// // Free everything.
/// wasm_engine_delete(engine);
///
/// return 0;
/// }
/// # })
/// # .success();
/// # }
/// ```
#[no_mangle]
pub extern "C" fn wasm_config_set_target(config: &mut wasm_config_t, target: Box<wasm_target_t>) {
config.target = Some(target);
}

View File

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

View File

@@ -0,0 +1,314 @@
//! Unstable non-standard Wasmer-specific API that contains everything
//! to create a target with a triple and CPU features.
//!
//! This is useful for cross-compilation.
//!
//! # Example
//!
//! ```rust
//! # use inline_c::assert_c;
//! # fn main() {
//! # (assert_c! {
//! # #include "tests/wasmer_wasm.h"
//! #
//! int main() {
//! // Declare the target triple.
//! wasm_triple_t* triple;
//!
//! {
//! wasm_name_t triple_name;
//! wasm_name_new_from_string(&triple_name, "x86_64-apple-darwin");
//!
//! triple = wasm_triple_new(&triple_name);
//!
//! wasm_name_delete(&triple_name);
//! }
//!
//! assert(triple);
//!
//! // Declare the target CPU features.
//! wasm_cpu_features_t* cpu_features = wasm_cpu_features_new();
//!
//! {
//! wasm_name_t cpu_feature_name;
//! wasm_name_new_from_string(&cpu_feature_name, "sse2");
//!
//! wasm_cpu_features_add(cpu_features, &cpu_feature_name);
//!
//! wasm_name_delete(&cpu_feature_name);
//! }
//!
//! assert(cpu_features);
//!
//! // Create the target!
//! wasm_target_t* target = wasm_target_new(triple, cpu_features);
//! assert(target);
//!
//! wasm_target_delete(target);
//!
//! return 0;
//! }
//! # })
//! # .success();
//! # }
//! ```
use super::super::types::wasm_name_t;
use crate::error::CApiError;
use enumset::EnumSet;
use std::slice;
use std::str::{self, FromStr};
use wasmer_compiler::{CpuFeature, Target, Triple};
/// Unstable non-standard Wasmer-specific API to represent a triple +
/// CPU features pair.
///
/// # Example
///
/// See the module's documentation.
#[derive(Debug)]
#[allow(non_camel_case_types)]
pub struct wasm_target_t {
pub(crate) inner: Target,
}
/// Creates a new [`wasm_target_t`].
///
/// It takes ownership of `triple` and `cpu_features`.
///
/// # Example
///
/// See the module's documentation.
#[no_mangle]
pub 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 extern "C" fn wasm_target_delete(_target: Option<Box<wasm_target_t>>) {}
/// Unstable non-standard Wasmer-specific API to represent a target
/// “triple”.
///
/// Historically such things had three fields, though they have added
/// additional fields over time.
///
/// # Example
///
/// ```rust
/// # use inline_c::assert_c;
/// # fn main() {
/// # (assert_c! {
/// # #include "tests/wasmer_wasm.h"
/// #
/// int main() {
/// wasm_name_t triple_name;
/// wasm_name_new_from_string(&triple_name, "x86_64-apple-darwin");
///
/// wasm_triple_t* triple = wasm_triple_new(&triple_name);
/// assert(triple);
///
/// wasm_triple_delete(triple);
/// wasm_name_delete(&triple_name);
///
/// return 0;
/// }
/// # })
/// # .success();
/// # }
/// ```
///
/// See also [`wasm_triple_new_from_host`].
#[allow(non_camel_case_types)]
pub struct wasm_triple_t {
inner: Triple,
}
/// Create a new [`wasm_triple_t`] based on a triple string.
///
/// # Example
///
/// See [`wasm_triple_t`] or [`wasm_triple_new_from_host`].
#[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!(str::from_utf8(slice::from_raw_parts(
triple.data,
triple.size
)));
Some(Box::new(wasm_triple_t {
inner: c_try!(Triple::from_str(triple).map_err(|e| CApiError { msg: e.to_string() })),
}))
}
/// Create the [`wasm_triple_t`] for the current host.
///
/// # Example
///
/// ```rust
/// # use inline_c::assert_c;
/// # fn main() {
/// # (assert_c! {
/// # #include "tests/wasmer_wasm.h"
/// #
/// int main() {
/// wasm_triple_t* triple = wasm_triple_new_from_host();
/// assert(triple);
///
/// wasm_triple_delete(triple);
///
/// return 0;
/// }
/// # })
/// # .success();
/// # }
/// ```
///
/// See also [`wasm_triple_new`].
#[no_mangle]
pub extern "C" fn wasm_triple_new_from_host() -> Box<wasm_triple_t> {
Box::new(wasm_triple_t {
inner: Triple::host(),
})
}
/// Delete a [`wasm_triple_t`].
///
/// # Example
///
/// See [`wasm_triple_t`].
#[no_mangle]
pub extern "C" fn wasm_triple_delete(_triple: Option<Box<wasm_triple_t>>) {}
/// Unstable non-standard Wasmer-specific API to represent a set of
/// CPU features.
///
/// CPU features are identified by their stringified names. The
/// reference is the GCC options:
///
/// * <https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html>,
/// * <https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html>,
/// * <https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html>.
///
/// At the time of writing this documentation (it might be outdated in
/// the future), the supported features are the following:
///
/// * `sse2`,
/// * `sse3`,
/// * `ssse3`,
/// * `sse4.1`,
/// * `sse4.2`,
/// * `popcnt`,
/// * `avx`,
/// * `bmi`,
/// * `bmi2`,
/// * `avx2`,
/// * `avx512dq`,
/// * `avx512vl`,
/// * `lzcnt`.
///
/// # Example
///
/// ```rust
/// # use inline_c::assert_c;
/// # fn main() {
/// # (assert_c! {
/// # #include "tests/wasmer_wasm.h"
/// #
/// int main() {
/// // Create a new CPU feature set.
/// wasm_cpu_features_t* cpu_features = wasm_cpu_features_new();
///
/// // Create a new feature name, here `sse2`, and add it to the set.
/// {
/// wasm_name_t cpu_feature_name;
/// wasm_name_new_from_string(&cpu_feature_name, "sse2");
///
/// wasm_cpu_features_add(cpu_features, &cpu_feature_name);
///
/// wasm_name_delete(&cpu_feature_name);
/// }
///
/// wasm_cpu_features_delete(cpu_features);
///
/// return 0;
/// }
/// # })
/// # .success();
/// # }
/// ```
#[allow(non_camel_case_types)]
pub struct wasm_cpu_features_t {
inner: EnumSet<CpuFeature>,
}
/// Create a new [`wasm_cpu_features_t`].
///
/// # Example
///
/// See [`wasm_cpu_features_t`].
#[no_mangle]
pub extern "C" fn wasm_cpu_features_new() -> Box<wasm_cpu_features_t> {
Box::new(wasm_cpu_features_t {
inner: CpuFeature::set(),
})
}
/// Delete a [`wasm_cpu_features_t`].
///
/// # Example
///
/// See [`wasm_cpu_features_t`].
#[no_mangle]
pub extern "C" fn wasm_cpu_features_delete(_cpu_features: Option<Box<wasm_cpu_features_t>>) {}
/// Add a new CPU feature into the set represented by
/// [`wasm_cpu_features_t`].
///
/// # Example
///
/// See [`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!(
str::from_utf8(slice::from_raw_parts(
feature.data,
feature.size + 1,
));
otherwise false
);
cpu_features.inner.insert(c_try!(
CpuFeature::from_str(feature);
otherwise false
));
true
}

View File

@@ -204,7 +204,7 @@ pub extern "C" fn wasi_env_delete(_state: Option<Box<wasi_env_t>>) {}
/// This function is deprecated. You may safely remove all calls to it and everything
/// will continue to work.
///
/// cbindgen:prefix=DEPRECATED("This function is longer necessary. You may safely remove all calls to it and everything will continue to work.")
/// cbindgen:prefix=DEPRECATED("This function is no longer necessary. You may safely remove all calls to it and everything will continue to work.")
#[no_mangle]
pub extern "C" fn wasi_env_set_instance(
_env: &mut wasi_env_t,