Skip to content

Commit b677746

Browse files
committed
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
2 parents 126db54 + 04b4b50 commit b677746

File tree

5 files changed

+135
-7
lines changed

5 files changed

+135
-7
lines changed

mk/rustllvm.mk

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ LLVM_EXTRA_INCDIRS_$(1)= -iquote $(S)src/llvm/include \
2222
-iquote $$(CFG_LLVM_BUILD_DIR_$(1))/include
2323
endif
2424

25-
RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, RustWrapper.cpp PassWrapper.cpp)
25+
RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, \
26+
ExecutionEngineWrapper.cpp RustWrapper.cpp PassWrapper.cpp)
2627

2728
RUSTLLVM_DEF_$(1) := $(1)/rustllvm/rustllvm$(CFG_DEF_SUFFIX_$(1))
2829

src/librustc_driver/driver.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,6 @@ pub fn compile_input(sess: Session,
4747
outdir: &Option<Path>,
4848
output: &Option<Path>,
4949
addl_plugins: Option<Plugins>) {
50-
// These may be left in an incoherent state after a previous compile.
51-
// `clear_tables` and `get_ident_interner().clear()` can be used to free
52-
// memory, but they do not restore the initial state.
53-
syntax::ext::mtwt::reset_tables();
54-
token::reset_ident_interner();
55-
5650
// We need nested scopes here, because the intermediate results can keep
5751
// large chunks of memory alive and we want to free them as soon as
5852
// possible to keep the peak memory usage low
@@ -116,6 +110,12 @@ pub fn source_name(input: &Input) -> String {
116110

117111
pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
118112
-> ast::Crate {
113+
// These may be left in an incoherent state after a previous compile.
114+
// `clear_tables` and `get_ident_interner().clear()` can be used to free
115+
// memory, but they do not restore the initial state.
116+
syntax::ext::mtwt::reset_tables();
117+
token::reset_ident_interner();
118+
119119
let krate = time(sess.time_passes(), "parsing", (), |_| {
120120
match *input {
121121
Input::File(ref file) => {

src/librustc_llvm/lib.rs

+14
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,9 @@ pub type BuilderRef = *mut Builder_opaque;
466466
pub enum ExecutionEngine_opaque {}
467467
pub type ExecutionEngineRef = *mut ExecutionEngine_opaque;
468468
#[allow(missing_copy_implementations)]
469+
pub enum RustJITMemoryManager_opaque {}
470+
pub type RustJITMemoryManagerRef = *mut RustJITMemoryManager_opaque;
471+
#[allow(missing_copy_implementations)]
469472
pub enum MemoryBuffer_opaque {}
470473
pub type MemoryBufferRef = *mut MemoryBuffer_opaque;
471474
#[allow(missing_copy_implementations)]
@@ -1064,7 +1067,18 @@ extern {
10641067
Instr: ValueRef,
10651068
Name: *const c_char);
10661069
pub fn LLVMDisposeBuilder(Builder: BuilderRef);
1070+
1071+
/* Execution engine */
1072+
pub fn LLVMRustCreateJITMemoryManager(morestack: *const ())
1073+
-> RustJITMemoryManagerRef;
1074+
pub fn LLVMBuildExecutionEngine(Mod: ModuleRef,
1075+
MM: RustJITMemoryManagerRef) -> ExecutionEngineRef;
10671076
pub fn LLVMDisposeExecutionEngine(EE: ExecutionEngineRef);
1077+
pub fn LLVMExecutionEngineFinalizeObject(EE: ExecutionEngineRef);
1078+
pub fn LLVMRustLoadDynamicLibrary(path: *const c_char) -> Bool;
1079+
pub fn LLVMExecutionEngineAddModule(EE: ExecutionEngineRef, M: ModuleRef);
1080+
pub fn LLVMExecutionEngineRemoveModule(EE: ExecutionEngineRef, M: ModuleRef)
1081+
-> Bool;
10681082

10691083
/* Metadata */
10701084
pub fn LLVMSetCurrentDebugLocation(Builder: BuilderRef, L: ValueRef);
+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#include "rustllvm.h"
12+
13+
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
14+
15+
using namespace llvm;
16+
using namespace llvm::sys;
17+
using namespace llvm::object;
18+
19+
class RustJITMemoryManager : public SectionMemoryManager
20+
{
21+
typedef SectionMemoryManager Base;
22+
23+
const void *morestack;
24+
25+
public:
26+
27+
RustJITMemoryManager(const void *morestack_ptr)
28+
: morestack(morestack_ptr)
29+
{}
30+
31+
uint64_t getSymbolAddress(const std::string &Name) override
32+
{
33+
if (Name == "__morestack" || Name == "___morestack")
34+
return reinterpret_cast<uint64_t>(morestack);
35+
36+
return Base::getSymbolAddress(Name);
37+
}
38+
};
39+
40+
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(RustJITMemoryManager, LLVMRustJITMemoryManagerRef)
41+
42+
extern "C" LLVMRustJITMemoryManagerRef LLVMRustCreateJITMemoryManager(void *morestack)
43+
{
44+
return wrap(new RustJITMemoryManager(morestack));
45+
}
46+
47+
extern "C" LLVMBool LLVMRustLoadDynamicLibrary(const char *path)
48+
{
49+
std::string err;
50+
DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(path, &err);
51+
52+
if (!lib.isValid())
53+
LLVMRustSetLastError(err.c_str());
54+
55+
return lib.isValid();
56+
}
57+
58+
// Calls LLVMAddModule;
59+
// exists for consistency with LLVMExecutionEngineRemoveModule
60+
extern "C" void LLVMExecutionEngineAddModule(
61+
LLVMExecutionEngineRef eeref, LLVMModuleRef mref)
62+
{
63+
LLVMAddModule(eeref, mref);
64+
}
65+
66+
// LLVMRemoveModule exists in LLVM's C bindings,
67+
// but it requires pointless parameters
68+
extern "C" LLVMBool LLVMExecutionEngineRemoveModule(
69+
LLVMExecutionEngineRef eeref, LLVMModuleRef mref)
70+
{
71+
ExecutionEngine *ee = unwrap(eeref);
72+
Module *m = unwrap(mref);
73+
74+
return ee->removeModule(m);
75+
}
76+
77+
extern "C" LLVMExecutionEngineRef LLVMBuildExecutionEngine(
78+
LLVMModuleRef mod, LLVMRustJITMemoryManagerRef mref)
79+
{
80+
// These are necessary for code generation to work properly.
81+
InitializeNativeTarget();
82+
InitializeNativeTargetAsmPrinter();
83+
InitializeNativeTargetAsmParser();
84+
85+
std::unique_ptr<Module> m(unwrap(mod));
86+
RustJITMemoryManager *mm = unwrap(mref);
87+
88+
std::string error_str;
89+
TargetOptions options;
90+
91+
options.JITEmitDebugInfo = true;
92+
options.NoFramePointerElim = true;
93+
94+
ExecutionEngine *ee = EngineBuilder(std::move(m))
95+
.setEngineKind(EngineKind::JIT)
96+
.setErrorStr(&error_str)
97+
.setMCJITMemoryManager(mm)
98+
.setTargetOptions(options)
99+
.create();
100+
101+
if (!ee)
102+
LLVMRustSetLastError(error_str.c_str());
103+
104+
return wrap(ee);
105+
}
106+
107+
extern "C" void LLVMExecutionEngineFinalizeObject(LLVMExecutionEngineRef eeref)
108+
{
109+
ExecutionEngine *ee = unwrap(eeref);
110+
111+
ee->finalizeObject();
112+
}

src/rustllvm/rustllvm.h

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ typedef struct OpaqueRustString *RustStringRef;
7272
typedef struct LLVMOpaqueTwine *LLVMTwineRef;
7373
typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;
7474
typedef struct LLVMOpaqueSMDiagnostic *LLVMSMDiagnosticRef;
75+
typedef struct LLVMOpaqueRustJITMemoryManager *LLVMRustJITMemoryManagerRef;
7576

7677
extern "C" void
7778
rust_llvm_string_write_impl(RustStringRef str, const char *ptr, size_t size);

0 commit comments

Comments
 (0)