use std::{path::Path, sync::Arc};
use shared_buffer::OwnedBuffer;
pub use wasmer_compiler::{Artifact, BaseTunables, Engine, EngineBuilder, Tunables};
use wasmer_types::{CompilationProgressCallback, DeserializeError, Features, target::Target};
use crate::{BackendEngine, BackendModule};
#[allow(unreachable_code)]
#[cfg(feature = "compiler")]
pub fn get_default_compiler_config() -> Option<Box<dyn wasmer_compiler::CompilerConfig>> {
cfg_if::cfg_if! {
if #[cfg(feature = "cranelift")] {
Some(Box::<wasmer_compiler_cranelift::Cranelift>::default())
} else if #[cfg(feature = "llvm")] {
Some(Box::<wasmer_compiler_llvm::LLVM>::default())
} else if #[cfg(feature = "singlepass")] {
Some(Box::<wasmer_compiler_singlepass::Singlepass>::default())
}
else {
None
}
}
}
pub fn default_engine() -> Engine {
#[cfg(feature = "compiler")]
fn get_engine() -> Engine {
if let Some(config) = get_default_compiler_config() {
EngineBuilder::new(config).engine()
} else {
EngineBuilder::headless().engine()
}
}
#[cfg(not(feature = "compiler"))]
fn get_engine() -> Engine {
EngineBuilder::headless().engine()
}
let mut engine = get_engine();
let tunables = BaseTunables::for_target(engine.target());
engine.set_tunables(tunables);
engine
}
pub trait NativeEngineExt {
#[cfg(feature = "compiler")]
fn new(
compiler_config: Box<dyn wasmer_compiler::CompilerConfig>,
target: Target,
features: Features,
) -> Self;
fn headless() -> Self;
fn target(&self) -> &Target;
fn set_tunables(&mut self, tunables: impl Tunables + Send + Sync + 'static);
fn tunables(&self) -> &dyn Tunables;
fn new_module_with_progress(
&self,
bytes: &[u8],
on_progress: CompilationProgressCallback,
) -> Result<crate::Module, wasmer_types::CompileError>;
unsafe fn deserialize_from_mmapped_file_unchecked(
&self,
file_ref: &Path,
) -> Result<crate::Module, DeserializeError>;
unsafe fn deserialize_from_mmapped_file(
&self,
file_ref: &Path,
) -> Result<crate::Module, DeserializeError>;
}
impl NativeEngineExt for crate::engine::Engine {
#[cfg(feature = "compiler")]
fn new(
compiler_config: Box<dyn wasmer_compiler::CompilerConfig>,
target: Target,
features: Features,
) -> Self {
Self {
be: BackendEngine::Sys(Engine::new(compiler_config, target, features)),
id: Self::atomic_next_engine_id(),
}
}
fn headless() -> Self {
Self {
be: BackendEngine::Sys(Engine::headless()),
id: Self::atomic_next_engine_id(),
}
}
fn target(&self) -> &Target {
match self.be {
BackendEngine::Sys(ref s) => s.target(),
_ => panic!("Not a `sys` engine!"),
}
}
fn set_tunables(&mut self, tunables: impl Tunables + Send + Sync + 'static) {
match self.be {
BackendEngine::Sys(ref mut s) => s.set_tunables(tunables),
_ => panic!("Not a `sys` engine!"),
}
}
fn tunables(&self) -> &dyn Tunables {
match self.be {
BackendEngine::Sys(ref s) => s.tunables(),
_ => panic!("Not a `sys` engine!"),
}
}
fn new_module_with_progress(
&self,
bytes: &[u8],
on_progress: CompilationProgressCallback,
) -> Result<crate::Module, wasmer_types::CompileError> {
crate::BackendModule::new_with_progress(self, bytes, on_progress).map(crate::Module)
}
unsafe fn deserialize_from_mmapped_file_unchecked(
&self,
file_ref: &Path,
) -> Result<crate::Module, DeserializeError> {
let file = std::fs::File::open(file_ref)?;
let buffer = OwnedBuffer::from_file(&file)
.map_err(|e| DeserializeError::Generic(format!("{e:?}")))?;
let artifact = unsafe { Arc::new(Artifact::deserialize_unchecked(self.as_sys(), buffer)?) };
Ok(crate::Module(BackendModule::Sys(
super::module::Module::from_artifact(artifact),
)))
}
unsafe fn deserialize_from_mmapped_file(
&self,
file_ref: &Path,
) -> Result<crate::Module, DeserializeError> {
let file = std::fs::File::open(file_ref)?;
let buffer = OwnedBuffer::from_file(&file)
.map_err(|e| DeserializeError::Generic(format!("{e:?}")))?;
let artifact = unsafe { Arc::new(Artifact::deserialize(self.as_sys(), buffer)?) };
Ok(crate::Module(BackendModule::Sys(
super::module::Module::from_artifact(artifact),
)))
}
}
impl crate::Engine {
pub fn into_sys(self) -> crate::backend::sys::engine::Engine {
match self.be {
BackendEngine::Sys(s) => s,
_ => panic!("Not a `sys` engine!"),
}
}
pub fn as_sys(&self) -> &crate::backend::sys::engine::Engine {
match self.be {
BackendEngine::Sys(ref s) => s,
_ => panic!("Not a `sys` engine!"),
}
}
pub fn as_sys_mut(&mut self) -> &mut crate::backend::sys::engine::Engine {
match self.be {
BackendEngine::Sys(ref mut s) => s,
_ => panic!("Not a `sys` engine!"),
}
}
pub fn is_sys(&self) -> bool {
matches!(self.be, BackendEngine::Sys(_))
}
}
impl From<Engine> for crate::Engine {
fn from(value: Engine) -> Self {
Self {
be: BackendEngine::Sys(value),
id: Self::atomic_next_engine_id(),
}
}
}
impl From<&Engine> for crate::Engine {
fn from(value: &Engine) -> Self {
Self {
be: BackendEngine::Sys(value.cloned()),
id: Self::atomic_next_engine_id(),
}
}
}
impl From<EngineBuilder> for crate::Engine {
fn from(value: EngineBuilder) -> Self {
Self {
be: BackendEngine::Sys(value.engine()),
id: Self::atomic_next_engine_id(),
}
}
}
#[cfg(feature = "cranelift")]
impl From<wasmer_compiler_cranelift::Cranelift> for crate::Engine {
fn from(value: wasmer_compiler_cranelift::Cranelift) -> Self {
Self {
be: BackendEngine::Sys(value.into()),
id: Self::atomic_next_engine_id(),
}
}
}
#[cfg(feature = "singlepass")]
impl From<wasmer_compiler_singlepass::Singlepass> for crate::Engine {
fn from(value: wasmer_compiler_singlepass::Singlepass) -> Self {
Self {
be: BackendEngine::Sys(value.into()),
id: Self::atomic_next_engine_id(),
}
}
}
#[cfg(feature = "llvm")]
impl From<wasmer_compiler_llvm::LLVM> for crate::Engine {
fn from(value: wasmer_compiler_llvm::LLVM) -> Self {
Self {
be: BackendEngine::Sys(value.into()),
id: Self::atomic_next_engine_id(),
}
}
}