use bytes::Bytes;
use std::{path::Path, sync::Arc};
use wasmer_types::{
CompileError, DeserializeError, Features,
target::{Target, UserCompilerOptimizations},
};
#[cfg(feature = "sys")]
use wasmer_compiler::Artifact;
#[cfg(feature = "compiler")]
use wasmer_compiler::CompilerConfig;
use crate::{BackendKind, IntoBytes, Store};
mod engine_ref;
mod inner;
pub(crate) use inner::BackendEngine;
pub use engine_ref::*;
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct EngineId(u64);
#[derive(Debug, Clone)]
pub struct Engine {
pub(crate) be: BackendEngine,
pub(crate) id: u64,
}
impl Default for Engine {
fn default() -> Self {
Self {
be: Default::default(),
id: Self::atomic_next_engine_id(),
}
}
}
impl Engine {
pub(crate) fn atomic_next_engine_id() -> u64 {
#[cfg(target_has_atomic = "64")]
{
static ENGINE_ID_COUNTER: std::sync::atomic::AtomicU64 =
std::sync::atomic::AtomicU64::new(0);
return ENGINE_ID_COUNTER.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
}
#[allow(unreachable_code)]
#[cfg(target_has_atomic = "32")]
{
static ENGINE_ID_COUNTER: std::sync::atomic::AtomicU32 =
std::sync::atomic::AtomicU32::new(0);
ENGINE_ID_COUNTER.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as _
}
}
pub fn deterministic_id(&self) -> String {
self.be.deterministic_id()
}
pub fn id(&self) -> EngineId {
EngineId(self.id)
}
pub fn default_features_for_backend(backend: &crate::BackendKind, target: &Target) -> Features {
match backend {
#[cfg(feature = "cranelift")]
crate::BackendKind::Cranelift => {
wasmer_compiler_cranelift::Cranelift::default().default_features_for_target(target)
}
#[cfg(feature = "llvm")]
crate::BackendKind::LLVM => {
wasmer_compiler_llvm::LLVM::default().default_features_for_target(target)
}
#[cfg(feature = "singlepass")]
crate::BackendKind::Singlepass => wasmer_compiler_singlepass::Singlepass::default()
.default_features_for_target(target),
#[cfg(feature = "v8")]
crate::BackendKind::V8 => {
crate::backend::v8::engine::Engine::default_features()
}
#[cfg(feature = "wamr")]
crate::BackendKind::Wamr => {
crate::backend::wamr::engine::Engine::default_features()
}
#[cfg(feature = "wasmi")]
crate::BackendKind::Wasmi => {
crate::backend::wasmi::engine::Engine::default_features()
}
#[cfg(feature = "js")]
crate::BackendKind::Js => {
crate::backend::js::engine::Engine::default_features()
}
#[cfg(feature = "jsc")]
crate::BackendKind::Jsc => {
crate::backend::jsc::engine::Engine::default_features()
}
_ => Features::default(),
}
}
pub fn supported_features_for_backend(
backend: &crate::BackendKind,
target: &Target,
) -> Features {
match backend {
#[cfg(feature = "cranelift")]
crate::BackendKind::Cranelift => wasmer_compiler_cranelift::Cranelift::default()
.supported_features_for_target(target),
#[cfg(feature = "llvm")]
crate::BackendKind::LLVM => {
wasmer_compiler_llvm::LLVM::default().supported_features_for_target(target)
}
#[cfg(feature = "singlepass")]
crate::BackendKind::Singlepass => wasmer_compiler_singlepass::Singlepass::default()
.supported_features_for_target(target),
#[cfg(feature = "v8")]
crate::BackendKind::V8 => {
crate::backend::v8::engine::Engine::supported_features()
}
#[cfg(feature = "wamr")]
crate::BackendKind::Wamr => {
crate::backend::wamr::engine::Engine::supported_features()
}
#[cfg(feature = "wasmi")]
crate::BackendKind::Wasmi => {
crate::backend::wasmi::engine::Engine::supported_features()
}
#[cfg(feature = "js")]
crate::BackendKind::Js => {
crate::backend::js::engine::Engine::supported_features()
}
#[cfg(feature = "jsc")]
crate::BackendKind::Jsc => {
crate::backend::jsc::engine::Engine::supported_features()
}
_ => Features::default(),
}
}
#[cfg(all(feature = "sys", not(target_arch = "wasm32")))]
unsafe fn deserialize_unchecked(
&self,
bytes: impl IntoBytes,
) -> Result<Arc<Artifact>, DeserializeError> {
unsafe { self.be.deserialize_unchecked(bytes) }
}
#[cfg(all(feature = "sys", not(target_arch = "wasm32")))]
unsafe fn deserialize(&self, bytes: impl IntoBytes) -> Result<Arc<Artifact>, DeserializeError> {
unsafe { self.be.deserialize(bytes) }
}
#[cfg(all(feature = "sys", not(target_arch = "wasm32")))]
unsafe fn deserialize_from_file_unchecked(
&self,
file_ref: &Path,
) -> Result<Arc<Artifact>, DeserializeError> {
unsafe { self.be.deserialize_from_file_unchecked(file_ref) }
}
#[cfg(all(feature = "sys", not(target_arch = "wasm32")))]
unsafe fn deserialize_from_file(
&self,
file_ref: &Path,
) -> Result<Arc<Artifact>, DeserializeError> {
unsafe { self.be.deserialize_from_file_unchecked(file_ref) }
}
pub fn with_opts(
&mut self,
suggested_opts: &UserCompilerOptimizations,
) -> Result<(), CompileError> {
match self.be {
#[cfg(feature = "sys")]
BackendEngine::Sys(ref mut e) => e.with_opts(suggested_opts),
_ => Ok(()),
}
}
#[cfg(feature = "experimental-async")]
pub fn supports_async(&self) -> bool {
match self.be {
#[cfg(feature = "sys")]
BackendEngine::Sys(ref e) => true,
_ => false,
}
}
}