1use crate::config::LLVM;
2use crate::trampoline::FuncTrampoline;
3use crate::translator::FuncTranslator;
4use crate::CompiledKind;
5use inkwell::context::Context;
6use inkwell::memory_buffer::MemoryBuffer;
7use inkwell::module::{Linkage, Module};
8use inkwell::targets::FileType;
9use inkwell::DLLStorageClass;
10use rayon::iter::ParallelBridge;
11use rayon::prelude::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator};
12use std::sync::Arc;
13use wasmer_compiler::types::function::{Compilation, Dwarf};
14use wasmer_compiler::types::module::CompileModuleInfo;
15use wasmer_compiler::{
16 types::{
17 relocation::RelocationTarget,
18 section::{CustomSection, CustomSectionProtection, SectionBody, SectionIndex},
19 symbols::{Symbol, SymbolRegistry},
20 target::Target,
21 },
22 Compiler, FunctionBodyData, ModuleMiddleware, ModuleTranslationState,
23};
24use wasmer_types::entity::{EntityRef, PrimaryMap};
25use wasmer_types::{CompileError, FunctionIndex, LocalFunctionIndex, SignatureIndex};
26
27pub struct LLVMCompiler {
32 config: LLVM,
33}
34
35impl LLVMCompiler {
36 pub fn new(config: LLVM) -> LLVMCompiler {
38 LLVMCompiler { config }
39 }
40
41 fn config(&self) -> &LLVM {
43 &self.config
44 }
45}
46
47struct ShortNames {}
48
49impl SymbolRegistry for ShortNames {
50 fn symbol_to_name(&self, symbol: Symbol) -> String {
51 match symbol {
52 Symbol::Metadata => "M".to_string(),
53 Symbol::LocalFunction(index) => format!("f{}", index.index()),
54 Symbol::Section(index) => format!("s{}", index.index()),
55 Symbol::FunctionCallTrampoline(index) => format!("t{}", index.index()),
56 Symbol::DynamicFunctionTrampoline(index) => format!("d{}", index.index()),
57 }
58 }
59
60 fn name_to_symbol(&self, name: &str) -> Option<Symbol> {
61 if name.len() < 2 {
62 return None;
63 }
64 let (ty, idx) = name.split_at(1);
65 if ty.starts_with('M') {
66 return Some(Symbol::Metadata);
67 }
68
69 let idx = idx.parse::<u32>().ok()?;
70 match ty.chars().next().unwrap() {
71 'f' => Some(Symbol::LocalFunction(LocalFunctionIndex::from_u32(idx))),
72 's' => Some(Symbol::Section(SectionIndex::from_u32(idx))),
73 't' => Some(Symbol::FunctionCallTrampoline(SignatureIndex::from_u32(
74 idx,
75 ))),
76 'd' => Some(Symbol::DynamicFunctionTrampoline(FunctionIndex::from_u32(
77 idx,
78 ))),
79 _ => None,
80 }
81 }
82}
83
84impl LLVMCompiler {
85 fn compile_native_object(
86 &self,
87 target: &Target,
88 compile_info: &CompileModuleInfo,
89 module_translation: &ModuleTranslationState,
90 function_body_inputs: &PrimaryMap<LocalFunctionIndex, FunctionBodyData<'_>>,
91 symbol_registry: &dyn SymbolRegistry,
92 wasmer_metadata: &[u8],
93 ) -> Result<Vec<u8>, CompileError> {
94 let target_machine = self.config().target_machine(target);
95 let ctx = Context::create();
96
97 let merged_bitcode = function_body_inputs.into_iter().par_bridge().map_init(
100 || {
101 let target_machine = self.config().target_machine(target);
102 FuncTranslator::new(target_machine)
103 },
104 |func_translator, (i, input)| {
105 let module = func_translator.translate_to_module(
106 &compile_info.module,
107 module_translation,
108 &i,
109 input,
110 self.config(),
111 &compile_info.memory_styles,
112 &compile_info.table_styles,
113 symbol_registry,
114 )?;
115 Ok(module.write_bitcode_to_memory().as_slice().to_vec())
116 },
117 );
118
119 let trampolines_bitcode = compile_info.module.signatures.iter().par_bridge().map_init(
120 || {
121 let target_machine = self.config().target_machine(target);
122 FuncTrampoline::new(target_machine)
123 },
124 |func_trampoline, (i, sig)| {
125 let name = symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(i));
126 let module = func_trampoline.trampoline_to_module(sig, self.config(), &name)?;
127 Ok(module.write_bitcode_to_memory().as_slice().to_vec())
128 },
129 );
130
131 let dynamic_trampolines_bitcode =
132 compile_info.module.functions.iter().par_bridge().map_init(
133 || {
134 let target_machine = self.config().target_machine(target);
135 (
136 FuncTrampoline::new(target_machine),
137 &compile_info.module.signatures,
138 )
139 },
140 |(func_trampoline, signatures), (i, sig)| {
141 let sig = &signatures[*sig];
142 let name = symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(i));
143 let module =
144 func_trampoline.dynamic_trampoline_to_module(sig, self.config(), &name)?;
145 Ok(module.write_bitcode_to_memory().as_slice().to_vec())
146 },
147 );
148
149 let merged_bitcode = merged_bitcode
150 .chain(trampolines_bitcode)
151 .chain(dynamic_trampolines_bitcode)
152 .collect::<Result<Vec<_>, CompileError>>()?
153 .into_par_iter()
154 .reduce_with(|bc1, bc2| {
155 let ctx = Context::create();
156 let membuf = MemoryBuffer::create_from_memory_range(&bc1, "");
157 let m1 = Module::parse_bitcode_from_buffer(&membuf, &ctx).unwrap();
158 let membuf = MemoryBuffer::create_from_memory_range(&bc2, "");
159 let m2 = Module::parse_bitcode_from_buffer(&membuf, &ctx).unwrap();
160 m1.link_in_module(m2).unwrap();
161 m1.write_bitcode_to_memory().as_slice().to_vec()
162 });
163 let merged_module = if let Some(bc) = merged_bitcode {
164 let membuf = MemoryBuffer::create_from_memory_range(&bc, "");
165 Module::parse_bitcode_from_buffer(&membuf, &ctx).unwrap()
166 } else {
167 ctx.create_module("")
168 };
169
170 let i8_ty = ctx.i8_type();
171 let metadata_init = i8_ty.const_array(
172 wasmer_metadata
173 .iter()
174 .map(|v| i8_ty.const_int(*v as u64, false))
175 .collect::<Vec<_>>()
176 .as_slice(),
177 );
178 let metadata_gv = merged_module.add_global(
179 metadata_init.get_type(),
180 None,
181 &symbol_registry.symbol_to_name(wasmer_compiler::types::symbols::Symbol::Metadata),
182 );
183 metadata_gv.set_initializer(&metadata_init);
184 metadata_gv.set_linkage(Linkage::DLLExport);
185 metadata_gv.set_dll_storage_class(DLLStorageClass::Export);
186 metadata_gv.set_alignment(16);
187
188 if self.config().enable_verifier {
189 merged_module.verify().unwrap();
190 }
191
192 let memory_buffer = target_machine
193 .write_to_memory_buffer(&merged_module, FileType::Object)
194 .unwrap();
195 if let Some(ref callbacks) = self.config.callbacks {
196 callbacks.obj_memory_buffer(&CompiledKind::Module, &memory_buffer);
197 }
198
199 Ok(memory_buffer.as_slice().to_vec())
200 }
201}
202
203impl Compiler for LLVMCompiler {
204 fn name(&self) -> &str {
205 "llvm"
206 }
207
208 fn get_middlewares(&self) -> &[Arc<dyn ModuleMiddleware>] {
210 &self.config.middlewares
211 }
212
213 fn experimental_native_compile_module(
214 &self,
215 target: &Target,
216 compile_info: &CompileModuleInfo,
217 module_translation: &ModuleTranslationState,
218 function_body_inputs: &PrimaryMap<LocalFunctionIndex, FunctionBodyData<'_>>,
220 symbol_registry: &dyn SymbolRegistry,
221 wasmer_metadata: &[u8],
223 ) -> Option<Result<Vec<u8>, CompileError>> {
224 Some(self.compile_native_object(
225 target,
226 compile_info,
227 module_translation,
228 function_body_inputs,
229 symbol_registry,
230 wasmer_metadata,
231 ))
232 }
233
234 fn compile_module(
237 &self,
238 target: &Target,
239 compile_info: &CompileModuleInfo,
240 module_translation: &ModuleTranslationState,
241 function_body_inputs: PrimaryMap<LocalFunctionIndex, FunctionBodyData<'_>>,
242 ) -> Result<Compilation, CompileError> {
243 let memory_styles = &compile_info.memory_styles;
245 let table_styles = &compile_info.table_styles;
246
247 let module = &compile_info.module;
248
249 let mut module_custom_sections = PrimaryMap::new();
252 let mut frame_section_bytes = vec![];
253 let mut frame_section_relocations = vec![];
254 let functions = function_body_inputs
255 .iter()
256 .collect::<Vec<(LocalFunctionIndex, &FunctionBodyData<'_>)>>()
257 .par_iter()
258 .map_init(
259 || {
260 let target_machine = self.config().target_machine(target);
261 FuncTranslator::new(target_machine)
262 },
263 |func_translator, (i, input)| {
264 func_translator.translate(
267 module,
268 module_translation,
269 i,
270 input,
271 self.config(),
272 memory_styles,
273 table_styles,
274 &ShortNames {},
275 )
276 },
277 )
278 .collect::<Result<Vec<_>, CompileError>>()?
279 .into_iter()
280 .map(|mut compiled_function| {
281 let first_section = module_custom_sections.len() as u32;
282 for (section_index, custom_section) in compiled_function.custom_sections.iter() {
283 let mut custom_section = custom_section.clone();
285 for reloc in &mut custom_section.relocations {
286 if let RelocationTarget::CustomSection(index) = reloc.reloc_target {
287 reloc.reloc_target = RelocationTarget::CustomSection(
288 SectionIndex::from_u32(first_section + index.as_u32()),
289 )
290 }
291 }
292 if compiled_function
293 .eh_frame_section_indices
294 .contains(§ion_index)
295 {
296 let offset = frame_section_bytes.len() as u32;
297 for reloc in &mut custom_section.relocations {
298 reloc.offset += offset;
299 }
300 frame_section_bytes.extend_from_slice(custom_section.bytes.as_slice());
301 frame_section_relocations.extend(custom_section.relocations);
302 module_custom_sections.push(CustomSection {
304 protection: CustomSectionProtection::Read,
305 bytes: SectionBody::new_with_vec(vec![]),
306 relocations: vec![],
307 });
308 } else {
309 module_custom_sections.push(custom_section);
310 }
311 }
312 for reloc in &mut compiled_function.compiled_function.relocations {
313 if let RelocationTarget::CustomSection(index) = reloc.reloc_target {
314 reloc.reloc_target = RelocationTarget::CustomSection(
315 SectionIndex::from_u32(first_section + index.as_u32()),
316 )
317 }
318 }
319 compiled_function.compiled_function
320 })
321 .collect::<PrimaryMap<LocalFunctionIndex, _>>();
322
323 let dwarf = if !frame_section_bytes.is_empty() {
324 let dwarf = Some(Dwarf::new(SectionIndex::from_u32(
325 module_custom_sections.len() as u32,
326 )));
327 module_custom_sections.push(CustomSection {
331 protection: CustomSectionProtection::Read,
332 bytes: SectionBody::new_with_vec(frame_section_bytes),
333 relocations: frame_section_relocations,
334 });
335 dwarf
336 } else {
337 None
338 };
339
340 let function_call_trampolines = module
341 .signatures
342 .values()
343 .collect::<Vec<_>>()
344 .par_iter()
345 .map_init(
346 || {
347 let target_machine = self.config().target_machine(target);
348 FuncTrampoline::new(target_machine)
349 },
350 |func_trampoline, sig| func_trampoline.trampoline(sig, self.config(), ""),
351 )
352 .collect::<Vec<_>>()
353 .into_iter()
354 .collect::<Result<PrimaryMap<_, _>, CompileError>>()?;
355
356 let dynamic_function_trampolines = module
357 .imported_function_types()
358 .collect::<Vec<_>>()
359 .par_iter()
360 .map_init(
361 || {
362 let target_machine = self.config().target_machine(target);
363 FuncTrampoline::new(target_machine)
364 },
365 |func_trampoline, func_type| {
366 func_trampoline.dynamic_trampoline(func_type, self.config(), "")
367 },
368 )
369 .collect::<Result<Vec<_>, CompileError>>()?
370 .into_iter()
371 .collect::<PrimaryMap<_, _>>();
372
373 Ok(Compilation {
374 functions,
375 custom_sections: module_custom_sections,
376 function_call_trampolines,
377 dynamic_function_trampolines,
378 debug: dwarf,
379 })
380 }
381}