diff --git a/Cargo.lock b/Cargo.lock index 977f7280b..c3cf75ae4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "aho-corasick" version = "0.6.10" diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index 9265f8739..9d1d8c731 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -4,24 +4,20 @@ struct MemoryManager : llvm::RuntimeDyld::MemoryManager { public: - MemoryManager(callbacks_t *callbacks) : callbacks(callbacks) {} + MemoryManager(callbacks_t callbacks) : callbacks(callbacks) {} - virtual ~MemoryManager() { + virtual ~MemoryManager() override { // Deallocate all of the allocated memory. - callbacks->dealloc_memory(code_section.base, code_section.size); - callbacks->dealloc_memory(read_section.base, read_section.size); - callbacks->dealloc_memory(readwrite_section.base, readwrite_section.size); + callbacks.dealloc_memory(code_section.base, code_section.size); + callbacks.dealloc_memory(read_section.base, read_section.size); + callbacks.dealloc_memory(readwrite_section.base, readwrite_section.size); } virtual uint8_t* allocateCodeSection(uintptr_t size, unsigned alignment, unsigned section_id, llvm::StringRef section_name) override { - std::cout << "code section name: " << (std::string)section_name << std::endl; - return allocate_bump(code_section, code_bump_ptr, size, alignment); } virtual uint8_t* allocateDataSection(uintptr_t size, unsigned alignment, unsigned section_id, llvm::StringRef section_name, bool read_only) override { - std::cout << "data section name: " << (std::string)section_name << std::endl; - // Allocate from the read-only section or the read-write section, depending on if this allocation // should be read-only or not. if (read_only) { @@ -41,21 +37,21 @@ public: ) override { uint8_t *code_ptr_out = nullptr; size_t code_size_out = 0; - auto code_result = callbacks->alloc_memory(code_size, PROTECT_READ_WRITE, &code_ptr_out, &code_size_out); + auto code_result = callbacks.alloc_memory(code_size, PROTECT_READ_WRITE, &code_ptr_out, &code_size_out); assert(code_result == RESULT_OK); code_section = Section { code_ptr_out, code_size_out }; code_bump_ptr = (uintptr_t)code_ptr_out; uint8_t *read_ptr_out = nullptr; size_t read_size_out = 0; - auto read_result = callbacks->alloc_memory(read_data_size, PROTECT_READ_WRITE, &read_ptr_out, &read_size_out); + auto read_result = callbacks.alloc_memory(read_data_size, PROTECT_READ_WRITE, &read_ptr_out, &read_size_out); assert(read_result == RESULT_OK); read_section = Section { read_ptr_out, read_size_out }; read_bump_ptr = (uintptr_t)read_ptr_out; uint8_t *readwrite_ptr_out = nullptr; size_t readwrite_size_out = 0; - auto readwrite_result = callbacks->alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &readwrite_ptr_out, &readwrite_size_out); + auto readwrite_result = callbacks.alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &readwrite_ptr_out, &readwrite_size_out); assert(readwrite_result == RESULT_OK); readwrite_section = Section { readwrite_ptr_out, readwrite_size_out }; readwrite_bump_ptr = (uintptr_t)readwrite_ptr_out; @@ -75,12 +71,12 @@ public: } virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override { - auto code_result = callbacks->protect_memory(code_section.base, code_section.size, mem_protect_t::PROTECT_READ_EXECUTE); + auto code_result = callbacks.protect_memory(code_section.base, code_section.size, mem_protect_t::PROTECT_READ_EXECUTE); if (code_result != RESULT_OK) { return false; } - auto read_result = callbacks->protect_memory(read_section.base, read_section.size, mem_protect_t::PROTECT_READ); + auto read_result = callbacks.protect_memory(read_section.base, read_section.size, mem_protect_t::PROTECT_READ); if (read_result != RESULT_OK) { return false; } @@ -116,7 +112,7 @@ private: Section code_section, read_section, readwrite_section; uintptr_t code_bump_ptr, read_bump_ptr, readwrite_bump_ptr; - callbacks_t *callbacks; + callbacks_t callbacks; }; struct SymbolLookup : llvm::JITSymbolResolver { @@ -153,34 +149,28 @@ private: WasmModule::WasmModule( const uint8_t *object_start, size_t object_size, - callbacks_t *callbacks -) : memory_manager(std::unique_ptr(new MemoryManager(callbacks))) + callbacks_t callbacks +) : memory_manager(new MemoryManager(callbacks)) { object_file = llvm::cantFail(llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef( llvm::StringRef((const char *)object_start, object_size), "object" ))); SymbolLookup symbol_resolver; - llvm::RuntimeDyld loader(*memory_manager, symbol_resolver); + runtime_dyld = std::unique_ptr(new llvm::RuntimeDyld(*memory_manager, symbol_resolver)); - loader.setProcessAllSections(true); + runtime_dyld->setProcessAllSections(true); - auto loaded_object_info = loader.loadObject(*object_file); - loader.finalizeWithMemoryManagerLocking(); + runtime_dyld->loadObject(*object_file); + runtime_dyld->finalizeWithMemoryManagerLocking(); - assert(!loader.hasError()); - - symbol_table = loader.getSymbolTable(); - - for (auto const& pair : symbol_table) { - std::cout << "symbol: (" << (std::string)pair.first << ") => " << (void*)pair.second.getAddress() << std::endl; + if (runtime_dyld->hasError()) { + std::cout << "RuntimeDyld error: " << (std::string)runtime_dyld->getErrorString() << std::endl; + abort(); } } void* WasmModule::get_func(llvm::StringRef name) const { - try { - return (void*)symbol_table.at(name).getAddress(); - } catch (const std::out_of_range& e) { - return nullptr; - } + auto symbol = runtime_dyld->getSymbol(name); + return (void*)symbol.getAddress(); } \ No newline at end of file diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 9db12ce96..969f16150 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -31,30 +31,32 @@ typedef struct { lookup_vm_symbol_t lookup_vm_symbol; } callbacks_t; - - class WasmModule { public: WasmModule( const uint8_t *object_start, size_t object_size, - callbacks_t *callbacks + callbacks_t callbacks ); void *get_func(llvm::StringRef name) const; private: - std::unique_ptr memory_manager; + llvm::RuntimeDyld::MemoryManager* memory_manager; std::unique_ptr object_file; - std::map symbol_table; + std::unique_ptr runtime_dyld; }; extern "C" { - result_t object_load(const uint8_t* mem_ptr, size_t mem_size, callbacks_t* callbacks, WasmModule** module_out) { + result_t module_load(const uint8_t* mem_ptr, size_t mem_size, callbacks_t callbacks, WasmModule** module_out) { *module_out = new WasmModule(mem_ptr, mem_size, callbacks); return RESULT_OK; } + void module_delete(WasmModule* module) { + delete module; + } + void* get_func_symbol(WasmModule* module, const char* name) { return module->get_func(llvm::StringRef(name)); } diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 94310fd79..6e55d55fe 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -1,5 +1,6 @@ use crate::intrinsics::Intrinsics; use inkwell::{ + memory_buffer::MemoryBuffer, module::Module, targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine}, OptimizationLevel, @@ -25,6 +26,7 @@ struct LLVMModule { _private: [u8; 0], } +#[allow(non_camel_case_types, dead_code)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[repr(C)] enum MemProtect { @@ -34,6 +36,7 @@ enum MemProtect { READ_EXECUTE, } +#[allow(non_camel_case_types, dead_code)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[repr(C)] enum LLVMResult { @@ -54,12 +57,13 @@ struct Callbacks { } extern "C" { - fn object_load( + fn module_load( mem_ptr: *const u8, mem_size: usize, - callbacks: *const Callbacks, + callbacks: Callbacks, module_out: &mut *mut LLVMModule, ) -> LLVMResult; + fn module_delete(module: *mut LLVMModule); fn get_func_symbol(module: *mut LLVMModule, name: *const c_char) -> *const vm::Func; } @@ -74,11 +78,11 @@ fn get_callbacks() -> Callbacks { ptr_out: &mut *mut u8, size_out: &mut usize, ) -> LLVMResult { - println!("size: {}", size); + let size = round_up_to_page_size(size); let ptr = unsafe { mmap( ptr::null_mut(), - round_up_to_page_size(size), + size, match protect { MemProtect::NONE => PROT_NONE, MemProtect::READ => PROT_READ, @@ -99,7 +103,6 @@ fn get_callbacks() -> Callbacks { } extern "C" fn protect_memory(ptr: *mut u8, size: usize, protect: MemProtect) -> LLVMResult { - println!("protect memory: {:p}:{} -> {:?}", ptr, size, protect); let res = unsafe { mprotect( ptr as _, @@ -121,7 +124,6 @@ fn get_callbacks() -> Callbacks { } extern "C" fn dealloc_memory(ptr: *mut u8, size: usize) -> LLVMResult { - println!("dealloc_memory"); let res = unsafe { munmap(ptr as _, round_up_to_page_size(size)) }; if res == 0 { @@ -148,6 +150,8 @@ unsafe impl Sync for LLVMBackend {} pub struct LLVMBackend { module: *mut LLVMModule, + #[allow(dead_code)] + memory_buffer: MemoryBuffer, } impl LLVMBackend { @@ -182,10 +186,10 @@ impl LLVMBackend { let mut module: *mut LLVMModule = ptr::null_mut(); let res = unsafe { - object_load( + module_load( mem_buf_slice.as_ptr(), mem_buf_slice.len(), - &callbacks, + callbacks, &mut module, ) }; @@ -194,7 +198,10 @@ impl LLVMBackend { panic!("failed to load object") } - Self { module } + Self { + module, + memory_buffer, + } } pub fn get_func( @@ -209,20 +216,19 @@ impl LLVMBackend { format!("fn{}", index) }; - println!("name: {}", name); - let c_str = CString::new(name).ok()?; - let ptr = unsafe { get_func_symbol(self.module, c_str.as_ptr()) }; - unsafe { - disass_ptr(ptr as _, 0x20, 4); - } - NonNull::new(ptr as _) } } +impl Drop for LLVMBackend { + fn drop(&mut self) { + unsafe { module_delete(self.module) } + } +} + impl FuncResolver for LLVMBackend { fn get( &self, diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 70382bd0b..3b72dd309 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -1,7 +1,7 @@ use inkwell::{ builder::Builder, context::Context, - module::Module, + module::{Linkage, Module}, passes::PassManager, types::{BasicType, BasicTypeEnum, FunctionType, PointerType}, values::{BasicValue, FunctionValue, PhiValue, PointerValue}, @@ -10,7 +10,7 @@ use inkwell::{ use smallvec::SmallVec; use wasmer_runtime_core::{ memory::MemoryType, - module::ModuleInfo, + module::{ExportIndex, ModuleInfo}, structures::{Map, SliceMap, TypedIndex}, types::{ FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, @@ -80,7 +80,7 @@ pub fn parse_function_bodies( module.add_function( &format!("fn{}", func_index.index()), signatures[sig_index], - None, + Some(Linkage::External), ) }) .collect(); @@ -106,6 +106,7 @@ pub fn parse_function_bodies( } let pass_manager = PassManager::create_for_module(); + pass_manager.add_function_inlining_pass(); pass_manager.add_promote_memory_to_register_pass(); pass_manager.add_cfg_simplification_pass(); pass_manager.add_instruction_combining_pass(); @@ -113,13 +114,11 @@ pub fn parse_function_bodies( // 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_new_gvn_pass(); pass_manager.add_aggressive_dce_pass(); - pass_manager.add_verifier_pass(); + // pass_manager.add_verifier_pass(); pass_manager.run_on_module(&module); - println!("{}", module.print_to_string().to_string()); - Ok((module, intrinsics)) } @@ -1791,7 +1790,6 @@ fn parse_function( state.push1(result.try_as_basic_value().left().unwrap()); } op @ _ => { - println!("{}", module.print_to_string().to_string()); unimplemented!("{:?}", op); } } diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index a209c12dc..6015a4bb1 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -11,6 +11,12 @@ static WAT: &'static str = r#" (export "foo" (func $foo)) (func $foo (type $t0) (param i32) (result i32) get_local 0 + call $bar + ) + (func $bar (type $t0) (param i32) (result i32) + get_local 0 + i32.const 10 + i32.add ) ) "#;