Start producing object files with llvm

This commit is contained in:
Lachlan Sneff
2019-02-15 16:02:20 -08:00
parent 73b4f7d337
commit 108973dabe
6 changed files with 180 additions and 27 deletions

View File

@ -0,0 +1,45 @@
use inkwell::{
module::Module,
execution_engine::{ExecutionEngine, JitFunction},
};
use crate::intrinsics::Intrinsics;
use std::ptr::NonNull;
use wasmer_runtime_core::{
module::ModuleInner,
types::LocalFuncIndex,
structures::TypedIndex,
backend::{FuncResolver, vm},
};
pub struct LLVMBackend {
exec_engine: ExecutionEngine,
}
impl LLVMBackend {
pub fn new(module: Module, intrinsics: Intrinsics) -> Self {
let exec_engine = module.create_jit_execution_engine(OptimizationLevel::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);
Self { exec_engine }
}
}
impl FuncResolver for LLVMBackend {
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);
unsafe {
let func: JitFunction<unsafe extern fn()> = self.exec_engine.get_function(&name).ok()?;
}
}
}

View File

@ -59,7 +59,7 @@ fn type_to_llvm(intrinsics: &Intrinsics, ty: Type) -> BasicTypeEnum {
pub fn parse_function_bodies(
info: &ModuleInfo,
code_reader: CodeSectionReader,
) -> Result<(), BinaryReaderError> {
) -> Result<(Module, Intrinsics), BinaryReaderError> {
let context = Context::create();
let module = context.create_module("module");
let builder = context.create_builder();
@ -104,7 +104,22 @@ pub fn parse_function_bodies(
)?;
}
Ok(())
let pass_manager = PassManager::create_for_module();
pass_manager.add_promote_memory_to_register_pass();
pass_manager.add_cfg_simplification_pass();
pass_manager.add_instruction_combining_pass();
// pass_manager.add_aggressive_inst_combiner_pass();
// pass_manager.add_merged_load_store_motion_pass();
// pass_manager.add_sccp_pass();
pass_manager.add_gvn_pass();
pass_manager.add_new_gvn_pass();
pass_manager.add_aggressive_dce_pass();
pass_manager.add_verifier_pass();
pass_manager.run_on_module(&module);
println!("{}", module.print_to_string().to_string());
Ok((module, intrinsics))
}
fn parse_function(
@ -1668,30 +1683,14 @@ fn parse_function(
&state.var_name(),
);
state.push1(result.try_as_basic_value().left().unwrap());
} // op @ _ => {
// println!("{}", module.print_to_string().to_string());
// unimplemented!("{:?}", op);
// }
}
op @ _ => {
println!("{}", module.print_to_string().to_string());
unimplemented!("{:?}", op);
}
}
}
println!("finished translating");
let pass_manager = PassManager::create_for_module();
pass_manager.add_promote_memory_to_register_pass();
pass_manager.add_cfg_simplification_pass();
pass_manager.add_instruction_combining_pass();
// pass_manager.add_aggressive_inst_combiner_pass();
// pass_manager.add_merged_load_store_motion_pass();
// pass_manager.add_sccp_pass();
pass_manager.add_gvn_pass();
pass_manager.add_new_gvn_pass();
pass_manager.add_aggressive_dce_pass();
pass_manager.add_verifier_pass();
pass_manager.run_on_module(module);
println!("{}", module.print_to_string().to_string());
Ok(())
}

View File

@ -3,11 +3,17 @@ use wasmer_runtime_core::{
error::CompileError,
module::ModuleInner,
};
use inkwell::{
execution_engine::JitFunction,
targets::{TargetMachine, Target, RelocMode, CodeModel, InitializationConfig, FileType},
OptimizationLevel,
};
mod code;
mod intrinsics;
mod read_info;
mod state;
// mod backend;
pub struct LLVMCompiler {
_private: (),
@ -29,6 +35,7 @@ impl Compiler for LLVMCompiler {
#[test]
fn test_read_module() {
use wasmer_runtime_core::vmcalls;
use wabt::wat2wasm;
// let wasm = include_bytes!("../../spectests/examples/simple/simple.wasm") as &[u8];
let wat = r#"
@ -39,13 +46,75 @@ fn test_read_module() {
(global $g0 (mut i32) (i32.const 0))
(func $foo (type $t0) (param i32) (result i32)
get_local 0
set_global $g0
get_global $g0
call $foobar
memory.grow
)
(func $foobar (type $t0)
get_local 0
)
(func $bar (type $t0) (param i32) (result i32)
get_local 0
call $foo
))
"#;
let wasm = wat2wasm(wat).unwrap();
let (info, code_reader) = read_info::read_module(&wasm).unwrap();
code::parse_function_bodies(&info, code_reader).unwrap();
let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).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();
let memory_buffer = target_machine.write_to_memory_buffer(&module, FileType::Object).unwrap();
// std::fs::write("memory_buffer", memory_buffer.as_slice()).unwrap();
let mem_buf_slice = memory_buffer.as_slice();
let macho = goblin::mach::MachO::parse(mem_buf_slice, 0).unwrap();
let symbols = macho.symbols.as_ref().unwrap();
let relocations = macho.relocations().unwrap();
for (_, reloc_iter, section) in relocations.into_iter() {
println!("section: {:#?}", section);
for reloc_info in reloc_iter {
let reloc_info = reloc_info.unwrap();
println!("\treloc_info: {:#?}", reloc_info);
println!("\tsymbol: {:#?}", symbols.get(reloc_info.r_symbolnum()).unwrap());
}
}
}
let exec_engine = module.create_jit_execution_engine(OptimizationLevel::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);
// unsafe {
// let func: JitFunction<unsafe extern fn(*mut u8, i32) -> i32> = exec_engine.get_function("fn0").unwrap();
// let result = func.call(0 as _, 0);
// println!("result: {}", result);
// }
}