use crate::config::LLVMConfig; use crate::trampoline::FuncTrampoline; use crate::translator::FuncTranslator; use rayon::prelude::{IntoParallelRefIterator, ParallelIterator}; use wasm_common::entity::{EntityRef, PrimaryMap, SecondaryMap}; use wasm_common::LocalFunctionIndex; use wasmer_compiler::{ Compilation, CompileError, CompileModuleInfo, Compiler, CompilerConfig, FunctionBodyData, ModuleTranslationState, RelocationTarget, SectionIndex, Target, }; //use std::sync::{Arc, Mutex}; /// A compiler that compiles a WebAssembly module with LLVM, translating the Wasm to LLVM IR, /// optimizing it and then translating to assembly. pub struct LLVMCompiler { config: LLVMConfig, } impl LLVMCompiler { /// Creates a new LLVM compiler pub fn new(config: &LLVMConfig) -> LLVMCompiler { LLVMCompiler { config: config.clone(), } } /// Gets the config for this Compiler fn config(&self) -> &LLVMConfig { &self.config } } impl Compiler for LLVMCompiler { /// Gets the target associated to this Compiler. fn target(&self) -> &Target { self.config.target() } /// Compile the module using LLVM, producing a compilation result with /// associated relocations. fn compile_module<'data, 'module>( &self, compile_info: &'module CompileModuleInfo, module_translation: &ModuleTranslationState, function_body_inputs: PrimaryMap>, ) -> Result { //let data = Arc::new(Mutex::new(0)); let mut func_names = SecondaryMap::new(); let memory_plans = &compile_info.memory_plans; let table_plans = &compile_info.table_plans; let module = &compile_info.module; // TODO: merge constants in sections. for (func_index, _) in &module.functions { func_names[func_index] = module .func_names .get(&func_index) .cloned() .unwrap_or_else(|| format!("fn{}", func_index.index())); } let mut module_custom_sections = PrimaryMap::new(); let functions = function_body_inputs .into_iter() .collect::)>>() .par_iter() .map_init(FuncTranslator::new, |func_translator, (i, input)| { // TODO: remove (to serialize) //let mut data = data.lock().unwrap(); func_translator.translate( &module, module_translation, i, input, self.config(), &memory_plans, &table_plans, &func_names, ) }) .collect::, CompileError>>()? .into_iter() .map(|(mut compiled_function, function_custom_sections)| { let first_section = module_custom_sections.len() as u32; for (_, custom_section) in function_custom_sections.iter() { // TODO: remove this call to clone() let mut custom_section = custom_section.clone(); for mut reloc in &mut custom_section.relocations { if let RelocationTarget::CustomSection(index) = reloc.reloc_target { reloc.reloc_target = RelocationTarget::CustomSection( SectionIndex::from_u32(first_section + index.as_u32()), ) } } module_custom_sections.push(custom_section); } for mut reloc in &mut compiled_function.relocations { if let RelocationTarget::CustomSection(index) = reloc.reloc_target { reloc.reloc_target = RelocationTarget::CustomSection( SectionIndex::from_u32(first_section + index.as_u32()), ) } } compiled_function }) .collect::>(); let function_call_trampolines = module .signatures .values() .collect::>() .par_iter() .map_init(FuncTrampoline::new, |func_trampoline, sig| { func_trampoline.trampoline(sig, self.config()) }) .collect::>() .into_iter() .collect::, CompileError>>()?; let dynamic_function_trampolines = module .imported_function_types() .collect::>() .par_iter() .map_init(FuncTrampoline::new, |func_trampoline, func_type| { func_trampoline.dynamic_trampoline(&func_type, self.config()) }) .collect::, CompileError>>()? .into_iter() .collect::>(); Ok(Compilation::new( functions, module_custom_sections, function_call_trampolines, dynamic_function_trampolines, None, )) } }