about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-12-15 08:32:45 +0000
committerbors <bors@rust-lang.org>2014-12-15 08:32:45 +0000
commitb677746b1e4412cc49efb9a59aaaa25f3e8fd87e (patch)
treee1e33823753ad0bfd0f2e4251cf2a21688be2236 /src
parent126db549b038c84269a1e4fe46f051b2c15d6970 (diff)
parent04b4b500b9c602c45c7cd5264e969e1a91c1a99d (diff)
downloadrust-b677746b1e4412cc49efb9a59aaaa25f3e8fd87e.tar.gz
rust-b677746b1e4412cc49efb9a59aaaa25f3e8fd87e.zip
auto merge of #19750 : murarth/rust/rusti-support, r=brson
Makes a couple changes that support the implementation of a REPL:

* Implementation of wrapper code for LLVM ExecutionEngine API
* Fixing a change I made earlier to reset compiler state in `phase_1_[...]`
  instead of `compile_input` as the latter is not used in a REPL
Diffstat (limited to 'src')
-rw-r--r--src/librustc_driver/driver.rs12
-rw-r--r--src/librustc_llvm/lib.rs14
-rw-r--r--src/rustllvm/ExecutionEngineWrapper.cpp112
-rw-r--r--src/rustllvm/rustllvm.h1
4 files changed, 133 insertions, 6 deletions
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<Path>,
                      output: &Option<Path>,
                      addl_plugins: Option<Plugins>) {
-    // 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<uint64_t>(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<Module> 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);