Start work on object loader using llvm's RuntimeDyld api.

This commit is contained in:
Lachlan Sneff
2019-02-25 18:07:22 -08:00
parent 2a913f5663
commit 4f833876e0
9 changed files with 579 additions and 122 deletions

View File

@ -1,45 +1,76 @@
use crate::intrinsics::Intrinsics;
use dlopen::symbor::Library;
use inkwell::{
module::Module,
execution_engine::{ExecutionEngine, JitFunction},
targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine},
OptimizationLevel,
};
use crate::intrinsics::Intrinsics;
use std::ptr::NonNull;
use std::{io::Write, ptr::NonNull};
use tempfile::NamedTempFile;
use wasmer_runtime_core::{
module::ModuleInner,
types::LocalFuncIndex,
structures::TypedIndex,
backend::{FuncResolver, vm},
backend::FuncResolver, module::ModuleInner, structures::TypedIndex, types::LocalFuncIndex, vm,
};
pub struct LLVMBackend {
exec_engine: ExecutionEngine,
tempfile: NamedTempFile,
library: Library,
}
impl LLVMBackend {
pub fn new(module: Module, intrinsics: Intrinsics) -> Self {
let exec_engine = module.create_jit_execution_engine(OptimizationLevel::Default).unwrap();
Target::initialize_x86(&InitializationConfig {
asm_parser: true,
asm_printer: true,
base: true,
disassembler: true,
info: true,
machine_code: true,
});
let triple = TargetMachine::get_default_triple().to_string();
let target = Target::from_triple(&triple).unwrap();
let target_machine = target
.create_target_machine(
&triple,
&TargetMachine::get_host_cpu_name().to_string(),
&TargetMachine::get_host_cpu_features().to_string(),
OptimizationLevel::Default,
RelocMode::PIC,
CodeModel::Default,
)
.unwrap();
exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_local, vmcalls::local_dynamic_memory_grow as usize);
exec_engine.add_global_mapping(&intrinsics.memory_grow_static_local, vmcalls::local_static_memory_grow as usize);
exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_import, vmcalls::imported_dynamic_memory_grow as usize);
exec_engine.add_global_mapping(&intrinsics.memory_grow_static_import, vmcalls::imported_static_memory_grow as usize);
exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_local, vmcalls::local_dynamic_memory_size as usize);
exec_engine.add_global_mapping(&intrinsics.memory_size_static_local, vmcalls::local_static_memory_size as usize);
exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_import, vmcalls::imported_dynamic_memory_size as usize);
exec_engine.add_global_mapping(&intrinsics.memory_size_static_import, vmcalls::imported_static_memory_size as usize);
let memory_buffer = target_machine
.write_to_memory_buffer(&module, FileType::Object)
.unwrap();
Self { exec_engine }
let mut tempfile = NamedTempFile::new().unwrap();
tempfile.write_all(memory_buffer.as_slice()).unwrap();
tempfile.flush().unwrap();
let library = Library::open(tempfile.path()).unwrap();
Self { tempfile, library }
}
}
impl FuncResolver for LLVMBackend {
fn get(&self, module: &ModuleInner, local_func_index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
fn get(
&self,
module: &ModuleInner,
local_func_index: LocalFuncIndex,
) -> Option<NonNull<vm::Func>> {
let index = module.info.imported_functions.len() + local_func_index.index();
let name = format!("fn{}", index);
let name = if cfg!(macos) {
format!("_fn{}", index)
} else {
format!("fn{}", index)
};
unsafe {
let func: JitFunction<unsafe extern fn()> = self.exec_engine.get_function(&name).ok()?;
self.library
.symbol::<NonNull<vm::Func>>(&name)
.ok()
.map(|symbol| *symbol)
}
}
}
}