wasmer_compiler_singlepass/
config.rs

1// Allow unused imports while developing
2#![allow(unused_imports, dead_code)]
3
4use crate::{compiler::SinglepassCompiler, machine::AssemblyComment};
5use std::{
6    collections::HashMap,
7    fs::File,
8    io::{self, Write},
9    path::PathBuf,
10    sync::Arc,
11};
12use target_lexicon::Architecture;
13use wasmer_compiler::{
14    Compiler, CompilerConfig, Engine, EngineBuilder, ModuleMiddleware,
15    misc::{CompiledKind, function_kind_to_filename, save_assembly_to_file},
16};
17use wasmer_types::{
18    Features,
19    target::{CpuFeature, Target},
20};
21
22/// Callbacks to the different Cranelift compilation phases.
23#[derive(Debug, Clone)]
24pub struct SinglepassCallbacks {
25    debug_dir: PathBuf,
26}
27
28impl SinglepassCallbacks {
29    /// Creates a new instance of `SinglepassCallbacks` with the specified debug directory.
30    pub fn new(debug_dir: PathBuf) -> Result<Self, io::Error> {
31        // Create the debug dir in case it doesn't exist
32        std::fs::create_dir_all(&debug_dir)?;
33        Ok(Self { debug_dir })
34    }
35
36    /// Writes the object file memory buffer to a debug file.
37    pub fn obj_memory_buffer(&self, kind: &CompiledKind, mem_buffer: &[u8]) {
38        let mut path = self.debug_dir.clone();
39        path.push(function_kind_to_filename(kind, ".o"));
40        let mut file =
41            File::create(path).expect("Error while creating debug file from Cranelift object");
42        file.write_all(mem_buffer).unwrap();
43    }
44
45    /// Writes the assembly memory buffer to a debug file.
46    pub fn asm_memory_buffer(
47        &self,
48        kind: &CompiledKind,
49        arch: Architecture,
50        mem_buffer: &[u8],
51        assembly_comments: HashMap<usize, AssemblyComment>,
52    ) -> Result<(), wasmer_types::CompileError> {
53        let mut path = self.debug_dir.clone();
54        path.push(function_kind_to_filename(kind, ".s"));
55        save_assembly_to_file(arch, path, mem_buffer, assembly_comments)
56    }
57}
58
59#[derive(Debug, Clone)]
60pub struct Singlepass {
61    pub(crate) enable_nan_canonicalization: bool,
62
63    /// The middleware chain.
64    pub(crate) middlewares: Vec<Arc<dyn ModuleMiddleware>>,
65
66    pub(crate) callbacks: Option<SinglepassCallbacks>,
67}
68
69impl Singlepass {
70    /// Creates a new configuration object with the default configuration
71    /// specified.
72    pub fn new() -> Self {
73        Self {
74            enable_nan_canonicalization: true,
75            middlewares: vec![],
76            callbacks: None,
77        }
78    }
79
80    pub fn canonicalize_nans(&mut self, enable: bool) -> &mut Self {
81        self.enable_nan_canonicalization = enable;
82        self
83    }
84
85    /// Callbacks that will triggered in the different compilation
86    /// phases in Singlepass.
87    pub fn callbacks(&mut self, callbacks: Option<SinglepassCallbacks>) -> &mut Self {
88        self.callbacks = callbacks;
89        self
90    }
91}
92
93impl CompilerConfig for Singlepass {
94    fn enable_pic(&mut self) {
95        // Do nothing, since singlepass already emits
96        // PIC code.
97    }
98
99    /// Transform it into the compiler
100    fn compiler(self: Box<Self>) -> Box<dyn Compiler> {
101        Box::new(SinglepassCompiler::new(*self))
102    }
103
104    /// Gets the supported features for this compiler in the given target
105    fn supported_features_for_target(&self, _target: &Target) -> Features {
106        Features::default()
107    }
108
109    /// Pushes a middleware onto the back of the middleware chain.
110    fn push_middleware(&mut self, middleware: Arc<dyn ModuleMiddleware>) {
111        self.middlewares.push(middleware);
112    }
113}
114
115impl Default for Singlepass {
116    fn default() -> Singlepass {
117        Self::new()
118    }
119}
120
121impl From<Singlepass> for Engine {
122    fn from(config: Singlepass) -> Self {
123        EngineBuilder::new(config).engine()
124    }
125}