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