Skip to content

Commit ad6b167

Browse files
committed
---
yaml --- r: 30814 b: refs/heads/incoming c: 887b59b h: refs/heads/master v: v3
1 parent 58dfbe3 commit ad6b167

File tree

5 files changed

+113
-35
lines changed

5 files changed

+113
-35
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ refs/heads/try: d324a424d8f84b1eb049b12cf34182bda91b0024
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: d0c6ce338884ee21843f4b40bf6bf18d222ce5df
9-
refs/heads/incoming: 996ec62cbfce9f25ecc8b573a0b9eb7f4a1b6db9
9+
refs/heads/incoming: 887b59b7bea4d795ebe30655ac051f7872aa6a44
1010
refs/heads/dist-snap: 2f32a1581f522e524009138b33b1c7049ced668d
1111
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1212
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/incoming/src/rustc/back/link.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,44 @@ mod jit {
7474
m: ModuleRef,
7575
opt: c_int,
7676
stacks: bool) unsafe {
77-
let ptr = llvm::LLVMRustJIT(rusti::morestack_addr(),
78-
pm, m, opt, stacks);
77+
let manager = llvm::LLVMRustPrepareJIT(rusti::morestack_addr());
78+
79+
// We need to tell JIT where to resolve all linked
80+
// symbols from. The equivalent of -lstd, -lcore, etc.
81+
// By default the JIT will resolve symbols from the std and
82+
// core linked into rustc. We don't want that,
83+
// incase the user wants to use an older std library.
84+
85+
let cstore = sess.cstore;
86+
for cstore::get_used_crate_files(cstore).each |cratepath| {
87+
let path = cratepath.to_str();
88+
89+
debug!("linking: %s", path);
90+
91+
let _: () = str::as_c_str(
92+
path,
93+
|buf_t| {
94+
if !llvm::LLVMRustLoadCrate(manager, buf_t) {
95+
llvm_err(sess, ~"Could not link");
96+
}
97+
debug!("linked: %s", path);
98+
});
99+
}
100+
101+
// The execute function will return a void pointer
102+
// to the _rust_main function. We can do closure
103+
// magic here to turn it straight into a callable rust
104+
// closure. It will also cleanup the memory manager
105+
// for us.
106+
107+
let entry = llvm::LLVMRustExecuteJIT(manager,
108+
pm, m, opt, stacks);
79109

80-
if ptr::is_null(ptr) {
110+
if ptr::is_null(entry) {
81111
llvm_err(sess, ~"Could not JIT");
82112
} else {
83113
let closure = Closure {
84-
code: ptr,
114+
code: entry,
85115
env: ptr::null()
86116
};
87117
let func: fn(~[~str]) = cast::transmute(move closure);

branches/incoming/src/rustc/lib/llvm.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -990,15 +990,19 @@ extern mod llvm {
990990
call. */
991991
fn LLVMRustGetLastError() -> *c_char;
992992

993-
/** Load a shared library to resolve symbols against. */
994-
fn LLVMRustLoadLibrary(Filename: *c_char) -> bool;
995-
996-
/** Create and execute the JIT engine. */
997-
fn LLVMRustJIT(__morestack: *(),
998-
PM: PassManagerRef,
999-
M: ModuleRef,
1000-
OptLevel: c_int,
1001-
EnableSegmentedStacks: bool) -> *();
993+
/** Prepare the JIT. Returns a memory manager that can load crates. */
994+
fn LLVMRustPrepareJIT(__morestack: *()) -> *();
995+
996+
/** Load a crate into the memory manager. */
997+
fn LLVMRustLoadCrate(MM: *(),
998+
Filename: *c_char) -> bool;
999+
1000+
/** Execute the JIT engine. */
1001+
fn LLVMRustExecuteJIT(MM: *(),
1002+
PM: PassManagerRef,
1003+
M: ModuleRef,
1004+
OptLevel: c_int,
1005+
EnableSegmentedStacks: bool) -> *();
10021006

10031007
/** Parses the bitcode in the given memory buffer. */
10041008
fn LLVMRustParseBitcode(MemBuf: MemoryBufferRef) -> ModuleRef;

branches/incoming/src/rustllvm/RustWrapper.cpp

Lines changed: 62 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "llvm/Transforms/Scalar.h"
2121
#include "llvm/Transforms/IPO.h"
2222
#include "llvm/ADT/Triple.h"
23+
#include "llvm/ADT/DenseSet.h"
2324
#include "llvm/Assembly/Parser.h"
2425
#include "llvm/Assembly/PrintModulePass.h"
2526
#include "llvm/Support/FormattedStream.h"
@@ -42,7 +43,6 @@
4243
#include "llvm-c/Core.h"
4344
#include "llvm-c/BitReader.h"
4445
#include "llvm-c/Object.h"
45-
#include <cstdlib>
4646

4747
// Used by RustMCJITMemoryManager::getPointerToNamedFunction()
4848
// to get around glibc issues. See the function for more information.
@@ -53,6 +53,7 @@
5353
#endif
5454

5555
using namespace llvm;
56+
using namespace llvm::sys;
5657

5758
static const char *LLVMRustError;
5859

@@ -100,18 +101,6 @@ void LLVMRustInitializeTargets() {
100101
LLVMInitializeX86AsmParser();
101102
}
102103

103-
extern "C" bool
104-
LLVMRustLoadLibrary(const char* file) {
105-
std::string err;
106-
107-
if(llvm::sys::DynamicLibrary::LoadLibraryPermanently(file, &err)) {
108-
LLVMRustError = err.c_str();
109-
return false;
110-
}
111-
112-
return true;
113-
}
114-
115104
// Custom memory manager for MCJITting. It needs special features
116105
// that the generic JIT memory manager doesn't entail. Based on
117106
// code from LLI, change where needed for Rust.
@@ -121,10 +110,13 @@ class RustMCJITMemoryManager : public JITMemoryManager {
121110
SmallVector<sys::MemoryBlock, 16> AllocatedCodeMem;
122111
SmallVector<sys::MemoryBlock, 16> FreeCodeMem;
123112
void* __morestack;
113+
DenseSet<DynamicLibrary*> crates;
124114

125115
RustMCJITMemoryManager(void* sym) : __morestack(sym) { }
126116
~RustMCJITMemoryManager();
127117

118+
bool loadCrate(const char*, std::string*);
119+
128120
virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
129121
unsigned SectionID);
130122

@@ -197,6 +189,19 @@ class RustMCJITMemoryManager : public JITMemoryManager {
197189
}
198190
};
199191

192+
bool RustMCJITMemoryManager::loadCrate(const char* file, std::string* err) {
193+
DynamicLibrary crate = DynamicLibrary::getPermanentLibrary(file,
194+
err);
195+
196+
if(crate.isValid()) {
197+
crates.insert(&crate);
198+
199+
return true;
200+
}
201+
202+
return false;
203+
}
204+
200205
uint8_t *RustMCJITMemoryManager::allocateDataSection(uintptr_t Size,
201206
unsigned Alignment,
202207
unsigned SectionID) {
@@ -276,6 +281,19 @@ void *RustMCJITMemoryManager::getPointerToNamedFunction(const std::string &Name,
276281
if (Name == "__morestack") return &__morestack;
277282

278283
const char *NameStr = Name.c_str();
284+
285+
// Look through loaded crates for symbols.
286+
287+
for (DenseSet<DynamicLibrary*>::iterator I = crates.begin(),
288+
E = crates.end(); I != E; ++I) {
289+
void *Ptr = (*I)->getAddressOfSymbol(NameStr);
290+
291+
if (Ptr) return Ptr;
292+
}
293+
294+
// Fallback to using any symbols LLVM has loaded (generally
295+
// from the main program).
296+
279297
void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
280298
if (Ptr) return Ptr;
281299

@@ -293,11 +311,34 @@ RustMCJITMemoryManager::~RustMCJITMemoryManager() {
293311
}
294312

295313
extern "C" void*
296-
LLVMRustJIT(void* __morestack,
297-
LLVMPassManagerRef PMR,
298-
LLVMModuleRef M,
299-
CodeGenOpt::Level OptLevel,
300-
bool EnableSegmentedStacks) {
314+
LLVMRustPrepareJIT(void* __morestack) {
315+
// An execution engine will take ownership of this later
316+
// and clean it up for us.
317+
318+
return (void*) new RustMCJITMemoryManager(__morestack);
319+
}
320+
321+
extern "C" bool
322+
LLVMRustLoadCrate(void* mem, const char* crate) {
323+
RustMCJITMemoryManager* manager = (RustMCJITMemoryManager*) mem;
324+
std::string Err;
325+
326+
assert(manager);
327+
328+
if(!manager->loadCrate(crate, &Err)) {
329+
LLVMRustError = Err.c_str();
330+
return false;
331+
}
332+
333+
return true;
334+
}
335+
336+
extern "C" void*
337+
LLVMRustExecuteJIT(void* mem,
338+
LLVMPassManagerRef PMR,
339+
LLVMModuleRef M,
340+
CodeGenOpt::Level OptLevel,
341+
bool EnableSegmentedStacks) {
301342

302343
InitializeNativeTarget();
303344
InitializeNativeTargetAsmPrinter();
@@ -308,6 +349,9 @@ LLVMRustJIT(void* __morestack,
308349
Options.NoFramePointerElim = true;
309350
Options.EnableSegmentedStacks = EnableSegmentedStacks;
310351
PassManager *PM = unwrap<PassManager>(PMR);
352+
RustMCJITMemoryManager* MM = (RustMCJITMemoryManager*) mem;
353+
354+
assert(MM);
311355

312356
PM->add(createBasicAliasAnalysisPass());
313357
PM->add(createInstructionCombiningPass());
@@ -318,7 +362,6 @@ LLVMRustJIT(void* __morestack,
318362
PM->add(createPromoteMemoryToRegisterPass());
319363
PM->run(*unwrap(M));
320364

321-
RustMCJITMemoryManager* MM = new RustMCJITMemoryManager(__morestack);
322365
ExecutionEngine* EE = EngineBuilder(unwrap(M))
323366
.setTargetOptions(Options)
324367
.setJITMemoryManager(MM)

branches/incoming/src/rustllvm/rustllvm.def.in

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ LLVMRustWriteOutputFile
44
LLVMRustGetLastError
55
LLVMRustConstSmallInt
66
LLVMRustConstInt
7-
LLVMRustLoadLibrary
8-
LLVMRustJIT
7+
LLVMRustLoadCrate
8+
LLVMRustPrepareJIT
9+
LLVMRustExecuteJIT
910
LLVMRustParseBitcode
1011
LLVMRustParseAssemblyFile
1112
LLVMRustPrintPassTimings

0 commit comments

Comments
 (0)