wasmer_compiler_singlepass/
config.rs1#![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 num::NonZero,
10 path::PathBuf,
11 sync::Arc,
12};
13use target_lexicon::Architecture;
14use wasmer_compiler::{
15 Compiler, CompilerConfig, Debugger, Engine, EngineBuilder, ModuleMiddleware,
16 misc::{CompiledKind, function_kind_to_filename, save_assembly_to_file},
17};
18use wasmer_types::{
19 Features,
20 target::{CpuFeature, Target},
21};
22
23#[derive(Debug, Clone)]
25pub struct SinglepassCallbacks {
26 debug_dir: PathBuf,
27}
28
29impl SinglepassCallbacks {
30 pub fn new(debug_dir: PathBuf) -> Result<Self, io::Error> {
32 std::fs::create_dir_all(&debug_dir)?;
34 Ok(Self { debug_dir })
35 }
36
37 pub fn debug_dir(&self) -> &PathBuf {
39 &self.debug_dir
40 }
41
42 fn base_path(&self, module_hash: &Option<String>) -> PathBuf {
43 let mut path = self.debug_dir.clone();
44 if let Some(hash) = module_hash {
45 path.push(hash);
46 }
47 std::fs::create_dir_all(&path)
48 .unwrap_or_else(|_| panic!("cannot create debug directory: {}", path.display()));
49 path
50 }
51
52 pub fn obj_memory_buffer(
54 &self,
55 kind: &CompiledKind,
56 module_hash: &Option<String>,
57 mem_buffer: &[u8],
58 ) {
59 let mut path = self.base_path(module_hash);
60 path.push(function_kind_to_filename(kind, ".o"));
61 let mut file =
62 File::create(path).expect("Error while creating debug file from Cranelift object");
63 file.write_all(mem_buffer).unwrap();
64 }
65
66 pub fn asm_memory_buffer(
68 &self,
69 kind: &CompiledKind,
70 module_hash: &Option<String>,
71 arch: Architecture,
72 mem_buffer: &[u8],
73 assembly_comments: HashMap<usize, AssemblyComment>,
74 ) -> Result<(), wasmer_types::CompileError> {
75 let mut path = self.base_path(module_hash);
76 path.push(function_kind_to_filename(kind, ".s"));
77 save_assembly_to_file(arch, path, mem_buffer, assembly_comments)
78 }
79}
80
81#[derive(Debug, Clone)]
82pub struct Singlepass {
83 pub(crate) enable_nan_canonicalization: bool,
84 pub(crate) allow_experimental_unaligned_memory_accesses: bool,
85 pub(crate) debugger: Option<Debugger>,
86 pub(crate) experimental_artifact: bool,
87
88 pub(crate) middlewares: Vec<Arc<dyn ModuleMiddleware>>,
90
91 pub(crate) callbacks: Option<SinglepassCallbacks>,
92
93 pub num_threads: NonZero<usize>,
95}
96
97impl Singlepass {
98 pub fn new() -> Self {
101 Self {
102 enable_nan_canonicalization: true,
103 allow_experimental_unaligned_memory_accesses: false,
104 debugger: None,
105 experimental_artifact: false,
106 middlewares: vec![],
107 callbacks: None,
108 num_threads: std::thread::available_parallelism().unwrap_or(NonZero::new(1).unwrap()),
109 }
110 }
111
112 pub fn experimental_artifact(&mut self, enable: bool) -> &mut Self {
114 self.experimental_artifact = enable;
115 self
116 }
117
118 pub fn canonicalize_nans(&mut self, enable: bool) -> &mut Self {
119 self.enable_nan_canonicalization = enable;
120 self
121 }
122
123 pub fn allow_experimental_unaligned_memory_accesses(&mut self, enable: bool) -> &mut Self {
130 self.allow_experimental_unaligned_memory_accesses = enable;
131 self
132 }
133
134 pub fn callbacks(&mut self, callbacks: Option<SinglepassCallbacks>) -> &mut Self {
137 self.callbacks = callbacks;
138 self
139 }
140
141 pub fn num_threads(&mut self, num_threads: NonZero<usize>) -> &mut Self {
143 self.num_threads = num_threads;
144 self
145 }
146}
147
148impl CompilerConfig for Singlepass {
149 fn experimental_artifact(&mut self, enable: bool) {
150 self.experimental_artifact = enable;
151 }
152
153 fn enable_pic(&mut self) {
154 }
157
158 fn enable_debugger(&mut self, debugger: Debugger) {
159 self.debugger = Some(debugger);
160 }
161
162 fn compiler(self: Box<Self>) -> Box<dyn Compiler> {
164 Box::new(SinglepassCompiler::new(*self))
165 }
166
167 fn supported_features_for_target(&self, _target: &Target) -> Features {
169 Features::default()
170 }
171
172 fn push_middleware(&mut self, middleware: Arc<dyn ModuleMiddleware>) {
174 self.middlewares.push(middleware);
175 }
176}
177
178impl Default for Singlepass {
179 fn default() -> Singlepass {
180 Self::new()
181 }
182}
183
184impl From<Singlepass> for Engine {
185 fn from(config: Singlepass) -> Self {
186 EngineBuilder::new(config).engine()
187 }
188}