diff --git a/mk/rustllvm.mk b/mk/rustllvm.mk index a62386818c1..44225020811 100644 --- a/mk/rustllvm.mk +++ b/mk/rustllvm.mk @@ -22,7 +22,8 @@ LLVM_EXTRA_INCDIRS_$(1)= -iquote $(S)src/llvm/include \ -iquote $$(CFG_LLVM_BUILD_DIR_$(1))/include endif -RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, RustWrapper.cpp PassWrapper.cpp) +RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, \ + ExecutionEngineWrapper.cpp RustWrapper.cpp PassWrapper.cpp) RUSTLLVM_DEF_$(1) := $(1)/rustllvm/rustllvm$(CFG_DEF_SUFFIX_$(1)) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 6cddcaca1e4..9ed4f46c168 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -47,12 +47,6 @@ pub fn compile_input(sess: Session, outdir: &Option, output: &Option, addl_plugins: Option) { - // These may be left in an incoherent state after a previous compile. - // `clear_tables` and `get_ident_interner().clear()` can be used to free - // memory, but they do not restore the initial state. - syntax::ext::mtwt::reset_tables(); - token::reset_ident_interner(); - // We need nested scopes here, because the intermediate results can keep // large chunks of memory alive and we want to free them as soon as // possible to keep the peak memory usage low @@ -116,6 +110,12 @@ pub fn source_name(input: &Input) -> String { pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input) -> ast::Crate { + // These may be left in an incoherent state after a previous compile. + // `clear_tables` and `get_ident_interner().clear()` can be used to free + // memory, but they do not restore the initial state. + syntax::ext::mtwt::reset_tables(); + token::reset_ident_interner(); + let krate = time(sess.time_passes(), "parsing", (), |_| { match *input { Input::File(ref file) => { diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 5e63f185c94..b052c8755cb 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -466,6 +466,9 @@ pub type BuilderRef = *mut Builder_opaque; pub enum ExecutionEngine_opaque {} pub type ExecutionEngineRef = *mut ExecutionEngine_opaque; #[allow(missing_copy_implementations)] +pub enum RustJITMemoryManager_opaque {} +pub type RustJITMemoryManagerRef = *mut RustJITMemoryManager_opaque; +#[allow(missing_copy_implementations)] pub enum MemoryBuffer_opaque {} pub type MemoryBufferRef = *mut MemoryBuffer_opaque; #[allow(missing_copy_implementations)] @@ -1064,7 +1067,18 @@ extern { Instr: ValueRef, Name: *const c_char); pub fn LLVMDisposeBuilder(Builder: BuilderRef); + + /* Execution engine */ + pub fn LLVMRustCreateJITMemoryManager(morestack: *const ()) + -> RustJITMemoryManagerRef; + pub fn LLVMBuildExecutionEngine(Mod: ModuleRef, + MM: RustJITMemoryManagerRef) -> ExecutionEngineRef; pub fn LLVMDisposeExecutionEngine(EE: ExecutionEngineRef); + pub fn LLVMExecutionEngineFinalizeObject(EE: ExecutionEngineRef); + pub fn LLVMRustLoadDynamicLibrary(path: *const c_char) -> Bool; + pub fn LLVMExecutionEngineAddModule(EE: ExecutionEngineRef, M: ModuleRef); + pub fn LLVMExecutionEngineRemoveModule(EE: ExecutionEngineRef, M: ModuleRef) + -> Bool; /* Metadata */ pub fn LLVMSetCurrentDebugLocation(Builder: BuilderRef, L: ValueRef); diff --git a/src/rustllvm/ExecutionEngineWrapper.cpp b/src/rustllvm/ExecutionEngineWrapper.cpp new file mode 100644 index 00000000000..d37cf9d12a5 --- /dev/null +++ b/src/rustllvm/ExecutionEngineWrapper.cpp @@ -0,0 +1,112 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#include "rustllvm.h" + +#include "llvm/ExecutionEngine/SectionMemoryManager.h" + +using namespace llvm; +using namespace llvm::sys; +using namespace llvm::object; + +class RustJITMemoryManager : public SectionMemoryManager +{ + typedef SectionMemoryManager Base; + + const void *morestack; + + public: + + RustJITMemoryManager(const void *morestack_ptr) + : morestack(morestack_ptr) + {} + + uint64_t getSymbolAddress(const std::string &Name) override + { + if (Name == "__morestack" || Name == "___morestack") + return reinterpret_cast(morestack); + + return Base::getSymbolAddress(Name); + } +}; + +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(RustJITMemoryManager, LLVMRustJITMemoryManagerRef) + +extern "C" LLVMRustJITMemoryManagerRef LLVMRustCreateJITMemoryManager(void *morestack) +{ + return wrap(new RustJITMemoryManager(morestack)); +} + +extern "C" LLVMBool LLVMRustLoadDynamicLibrary(const char *path) +{ + std::string err; + DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(path, &err); + + if (!lib.isValid()) + LLVMRustSetLastError(err.c_str()); + + return lib.isValid(); +} + +// Calls LLVMAddModule; +// exists for consistency with LLVMExecutionEngineRemoveModule +extern "C" void LLVMExecutionEngineAddModule( + LLVMExecutionEngineRef eeref, LLVMModuleRef mref) +{ + LLVMAddModule(eeref, mref); +} + +// LLVMRemoveModule exists in LLVM's C bindings, +// but it requires pointless parameters +extern "C" LLVMBool LLVMExecutionEngineRemoveModule( + LLVMExecutionEngineRef eeref, LLVMModuleRef mref) +{ + ExecutionEngine *ee = unwrap(eeref); + Module *m = unwrap(mref); + + return ee->removeModule(m); +} + +extern "C" LLVMExecutionEngineRef LLVMBuildExecutionEngine( + LLVMModuleRef mod, LLVMRustJITMemoryManagerRef mref) +{ + // These are necessary for code generation to work properly. + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + + std::unique_ptr m(unwrap(mod)); + RustJITMemoryManager *mm = unwrap(mref); + + std::string error_str; + TargetOptions options; + + options.JITEmitDebugInfo = true; + options.NoFramePointerElim = true; + + ExecutionEngine *ee = EngineBuilder(std::move(m)) + .setEngineKind(EngineKind::JIT) + .setErrorStr(&error_str) + .setMCJITMemoryManager(mm) + .setTargetOptions(options) + .create(); + + if (!ee) + LLVMRustSetLastError(error_str.c_str()); + + return wrap(ee); +} + +extern "C" void LLVMExecutionEngineFinalizeObject(LLVMExecutionEngineRef eeref) +{ + ExecutionEngine *ee = unwrap(eeref); + + ee->finalizeObject(); +} diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h index 2b324a37865..33dec63a728 100644 --- a/src/rustllvm/rustllvm.h +++ b/src/rustllvm/rustllvm.h @@ -72,6 +72,7 @@ typedef struct OpaqueRustString *RustStringRef; typedef struct LLVMOpaqueTwine *LLVMTwineRef; typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef; typedef struct LLVMOpaqueSMDiagnostic *LLVMSMDiagnosticRef; +typedef struct LLVMOpaqueRustJITMemoryManager *LLVMRustJITMemoryManagerRef; extern "C" void rust_llvm_string_write_impl(RustStringRef str, const char *ptr, size_t size);