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, DEFAULT_MAX_TABLE_ELEMENTS, Debugger, Engine, EngineBuilder,
16 ModuleMiddleware,
17 misc::{CompiledKind, function_kind_to_filename, save_assembly_to_file},
18};
19use wasmer_types::{
20 Features,
21 target::{CpuFeature, Target},
22};
23
24#[derive(Debug, Clone)]
26pub struct SinglepassCallbacks {
27 debug_dir: PathBuf,
28}
29
30impl SinglepassCallbacks {
31 pub fn new(debug_dir: PathBuf) -> Result<Self, io::Error> {
33 std::fs::create_dir_all(&debug_dir)?;
35 Ok(Self { debug_dir })
36 }
37
38 pub fn debug_dir(&self) -> &PathBuf {
40 &self.debug_dir
41 }
42
43 fn base_path(&self, module_hash: &Option<String>) -> PathBuf {
44 let mut path = self.debug_dir.clone();
45 if let Some(hash) = module_hash {
46 path.push(hash);
47 }
48 std::fs::create_dir_all(&path)
49 .unwrap_or_else(|_| panic!("cannot create debug directory: {}", path.display()));
50 path
51 }
52
53 pub fn obj_memory_buffer(
55 &self,
56 kind: &CompiledKind,
57 module_hash: &Option<String>,
58 mem_buffer: &[u8],
59 ) {
60 let mut path = self.base_path(module_hash);
61 path.push(function_kind_to_filename(kind, ".o"));
62 let mut file =
63 File::create(path).expect("Error while creating debug file from Cranelift object");
64 file.write_all(mem_buffer).unwrap();
65 }
66
67 pub fn asm_memory_buffer(
69 &self,
70 kind: &CompiledKind,
71 module_hash: &Option<String>,
72 arch: Architecture,
73 mem_buffer: &[u8],
74 assembly_comments: HashMap<usize, AssemblyComment>,
75 ) -> Result<(), wasmer_types::CompileError> {
76 let mut path = self.base_path(module_hash);
77 path.push(function_kind_to_filename(kind, ".s"));
78 save_assembly_to_file(arch, path, mem_buffer, assembly_comments)
79 }
80}
81
82#[derive(Debug, Clone)]
83pub struct Singlepass {
84 pub(crate) enable_nan_canonicalization: bool,
85 pub(crate) allow_experimental_unaligned_memory_accesses: bool,
86 pub(crate) debugger: Option<Debugger>,
87 pub(crate) experimental_artifact: bool,
88 pub(crate) max_table_elements: u32,
89
90 pub(crate) middlewares: Vec<Arc<dyn ModuleMiddleware>>,
92
93 pub(crate) callbacks: Option<SinglepassCallbacks>,
94
95 pub num_threads: NonZero<usize>,
97}
98
99impl Singlepass {
100 pub fn new() -> Self {
103 Self {
104 enable_nan_canonicalization: true,
105 allow_experimental_unaligned_memory_accesses: false,
106 debugger: None,
107 experimental_artifact: false,
108 max_table_elements: DEFAULT_MAX_TABLE_ELEMENTS,
109 middlewares: vec![],
110 callbacks: None,
111 num_threads: std::thread::available_parallelism().unwrap_or(NonZero::new(1).unwrap()),
112 }
113 }
114
115 pub fn experimental_artifact(&mut self, enable: bool) -> &mut Self {
117 self.experimental_artifact = enable;
118 self
119 }
120
121 pub fn canonicalize_nans(&mut self, enable: bool) -> &mut Self {
122 self.enable_nan_canonicalization = enable;
123 self
124 }
125
126 pub fn max_table_elements(&mut self, max_table_elements: u32) -> &mut Self {
128 self.max_table_elements = max_table_elements;
129 self
130 }
131
132 pub fn allow_experimental_unaligned_memory_accesses(&mut self, enable: bool) -> &mut Self {
139 self.allow_experimental_unaligned_memory_accesses = enable;
140 self
141 }
142
143 pub fn callbacks(&mut self, callbacks: Option<SinglepassCallbacks>) -> &mut Self {
146 self.callbacks = callbacks;
147 self
148 }
149
150 pub fn num_threads(&mut self, num_threads: NonZero<usize>) -> &mut Self {
152 self.num_threads = num_threads;
153 self
154 }
155}
156
157impl CompilerConfig for Singlepass {
158 fn experimental_artifact(&mut self, enable: bool) {
159 self.experimental_artifact = enable;
160 }
161
162 fn max_table_elements(&mut self, max_table_elements: u32) {
163 self.max_table_elements = max_table_elements;
164 }
165
166 fn enable_pic(&mut self) {
167 }
170
171 fn enable_debugger(&mut self, debugger: Debugger) {
172 self.debugger = Some(debugger);
173 }
174
175 fn compiler(self: Box<Self>) -> Box<dyn Compiler> {
177 Box::new(SinglepassCompiler::new(*self))
178 }
179
180 fn supported_features_for_target(&self, _target: &Target) -> Features {
182 Features::default()
183 }
184
185 fn push_middleware(&mut self, middleware: Arc<dyn ModuleMiddleware>) {
187 self.middlewares.push(middleware);
188 }
189}
190
191impl Default for Singlepass {
192 fn default() -> Singlepass {
193 Self::new()
194 }
195}
196
197impl From<Singlepass> for Engine {
198 fn from(config: Singlepass) -> Self {
199 EngineBuilder::new(config).engine()
200 }
201}