#![allow(unused_imports, dead_code)]
use crate::{compiler::SinglepassCompiler, machine::AssemblyComment};
use std::{
collections::HashMap,
fs::File,
io::{self, Write},
num::NonZero,
path::PathBuf,
sync::Arc,
};
use target_lexicon::Architecture;
use wasmer_compiler::{
Compiler, CompilerConfig, Engine, EngineBuilder, ModuleMiddleware,
misc::{CompiledKind, function_kind_to_filename, save_assembly_to_file},
};
use wasmer_types::{
Features,
target::{CpuFeature, Target},
};
#[derive(Debug, Clone)]
pub struct SinglepassCallbacks {
debug_dir: PathBuf,
}
impl SinglepassCallbacks {
pub fn new(debug_dir: PathBuf) -> Result<Self, io::Error> {
std::fs::create_dir_all(&debug_dir)?;
Ok(Self { debug_dir })
}
fn base_path(&self, module_hash: &Option<String>) -> PathBuf {
let mut path = self.debug_dir.clone();
if let Some(hash) = module_hash {
path.push(hash);
}
std::fs::create_dir_all(&path)
.unwrap_or_else(|_| panic!("cannot create debug directory: {}", path.display()));
path
}
pub fn obj_memory_buffer(
&self,
kind: &CompiledKind,
module_hash: &Option<String>,
mem_buffer: &[u8],
) {
let mut path = self.base_path(module_hash);
path.push(function_kind_to_filename(kind, ".o"));
let mut file =
File::create(path).expect("Error while creating debug file from Cranelift object");
file.write_all(mem_buffer).unwrap();
}
pub fn asm_memory_buffer(
&self,
kind: &CompiledKind,
module_hash: &Option<String>,
arch: Architecture,
mem_buffer: &[u8],
assembly_comments: HashMap<usize, AssemblyComment>,
) -> Result<(), wasmer_types::CompileError> {
let mut path = self.base_path(module_hash);
path.push(function_kind_to_filename(kind, ".s"));
save_assembly_to_file(arch, path, mem_buffer, assembly_comments)
}
}
#[derive(Debug, Clone)]
pub struct Singlepass {
pub(crate) enable_nan_canonicalization: bool,
pub(crate) middlewares: Vec<Arc<dyn ModuleMiddleware>>,
pub(crate) callbacks: Option<SinglepassCallbacks>,
pub num_threads: NonZero<usize>,
}
impl Singlepass {
pub fn new() -> Self {
Self {
enable_nan_canonicalization: true,
middlewares: vec![],
callbacks: None,
num_threads: std::thread::available_parallelism().unwrap_or(NonZero::new(1).unwrap()),
}
}
pub fn canonicalize_nans(&mut self, enable: bool) -> &mut Self {
self.enable_nan_canonicalization = enable;
self
}
pub fn callbacks(&mut self, callbacks: Option<SinglepassCallbacks>) -> &mut Self {
self.callbacks = callbacks;
self
}
pub fn num_threads(&mut self, num_threads: NonZero<usize>) -> &mut Self {
self.num_threads = num_threads;
self
}
}
impl CompilerConfig for Singlepass {
fn enable_pic(&mut self) {
}
fn compiler(self: Box<Self>) -> Box<dyn Compiler> {
Box::new(SinglepassCompiler::new(*self))
}
fn supported_features_for_target(&self, _target: &Target) -> Features {
Features::default()
}
fn push_middleware(&mut self, middleware: Arc<dyn ModuleMiddleware>) {
self.middlewares.push(middleware);
}
}
impl Default for Singlepass {
fn default() -> Singlepass {
Self::new()
}
}
impl From<Singlepass> for Engine {
fn from(config: Singlepass) -> Self {
EngineBuilder::new(config).engine()
}
}