Skip to content

Commit a90fffe

Browse files
committed
Revert "Revert "Have JIT execution take ownership of the LLVMContextRef""
This reverts commit 19adece.
1 parent 1a3edec commit a90fffe

File tree

8 files changed

+88
-60
lines changed

8 files changed

+88
-60
lines changed

src/librustc/back/link.rs

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ pub mod jit {
102102
use back::link::llvm_err;
103103
use driver::session::Session;
104104
use lib::llvm::llvm;
105-
use lib::llvm::{ModuleRef, PassManagerRef};
105+
use lib::llvm::{ModuleRef, PassManagerRef, ContextRef};
106106
use metadata::cstore;
107107

108108
use core::cast;
@@ -125,6 +125,7 @@ pub mod jit {
125125

126126
pub fn exec(sess: Session,
127127
pm: PassManagerRef,
128+
c: ContextRef,
128129
m: ModuleRef,
129130
opt: c_int,
130131
stacks: bool) {
@@ -153,26 +154,43 @@ pub mod jit {
153154
});
154155
}
155156

156-
// The execute function will return a void pointer
157-
// to the _rust_main function. We can do closure
158-
// magic here to turn it straight into a callable rust
159-
// closure. It will also cleanup the memory manager
160-
// for us.
161-
162-
let entry = llvm::LLVMRustExecuteJIT(manager,
163-
pm, m, opt, stacks);
164-
165-
if ptr::is_null(entry) {
166-
llvm_err(sess, ~"Could not JIT");
167-
} else {
168-
let closure = Closure {
169-
code: entry,
170-
env: ptr::null()
171-
};
172-
let func: &fn() = cast::transmute(closure);
157+
// We custom-build a JIT execution engine via some rust wrappers
158+
// first. This wrappers takes ownership of the module passed in.
159+
let ee = llvm::LLVMRustBuildJIT(manager, pm, m, opt, stacks);
160+
if ee.is_null() {
161+
llvm::LLVMContextDispose(c);
162+
llvm_err(sess, ~"Could not create the JIT");
163+
}
173164

174-
func();
165+
// Next, we need to get a handle on the _rust_main function by
166+
// looking up it's corresponding ValueRef and then requesting that
167+
// the execution engine compiles the function.
168+
let fun = do str::as_c_str("_rust_main") |entry| {
169+
llvm::LLVMGetNamedFunction(m, entry)
170+
};
171+
if fun.is_null() {
172+
llvm::LLVMDisposeExecutionEngine(ee);
173+
llvm::LLVMContextDispose(c);
174+
llvm_err(sess, ~"Could not find _rust_main in the JIT");
175175
}
176+
177+
// Finally, once we have the pointer to the code, we can do some
178+
// closure magic here to turn it straight into a callable rust
179+
// closure
180+
let code = llvm::LLVMGetPointerToGlobal(ee, fun);
181+
assert!(!code.is_null());
182+
let closure = Closure {
183+
code: code,
184+
env: ptr::null()
185+
};
186+
let func: &fn() = cast::transmute(closure);
187+
func();
188+
189+
// Sadly, there currently is no interface to re-use this execution
190+
// engine, so it's disposed of here along with the context to
191+
// prevent leaks.
192+
llvm::LLVMDisposeExecutionEngine(ee);
193+
llvm::LLVMContextDispose(c);
176194
}
177195
}
178196
}
@@ -189,6 +207,7 @@ pub mod write {
189207
use driver::session;
190208
use lib::llvm::llvm;
191209
use lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data};
210+
use lib::llvm::{ContextRef};
192211
use lib;
193212

194213
use back::passes;
@@ -207,6 +226,7 @@ pub mod write {
207226
}
208227

209228
pub fn run_passes(sess: Session,
229+
llcx: ContextRef,
210230
llmod: ModuleRef,
211231
output_type: output_type,
212232
output: &Path) {
@@ -281,7 +301,7 @@ pub mod write {
281301
// JIT execution takes ownership of the module,
282302
// so don't dispose and return.
283303

284-
jit::exec(sess, pm.llpm, llmod, CodeGenOptLevel, true);
304+
jit::exec(sess, pm.llpm, llcx, llmod, CodeGenOptLevel, true);
285305

286306
if sess.time_llvm_passes() {
287307
llvm::LLVMRustPrintPassTimings();
@@ -349,6 +369,7 @@ pub mod write {
349369
// Clean up and return
350370

351371
llvm::LLVMDisposeModule(llmod);
372+
llvm::LLVMContextDispose(llcx);
352373
if sess.time_llvm_passes() {
353374
llvm::LLVMRustPrintPassTimings();
354375
}
@@ -367,6 +388,7 @@ pub mod write {
367388
}
368389

369390
llvm::LLVMDisposeModule(llmod);
391+
llvm::LLVMContextDispose(llcx);
370392
if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
371393
}
372394
}

src/librustc/driver/driver.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ pub fn compile_rest(sess: Session,
216216

217217
let mut crate = crate_opt.unwrap();
218218

219-
let (llmod, link_meta) = {
219+
let (llcx, llmod, link_meta) = {
220220
crate = time(time_passes, ~"intrinsic injection", ||
221221
front::intrinsic_inject::inject_intrinsic(sess, crate));
222222

@@ -339,14 +339,14 @@ pub fn compile_rest(sess: Session,
339339
let obj_filename = outputs.obj_filename.with_filetype("s");
340340

341341
time(time_passes, ~"LLVM passes", ||
342-
link::write::run_passes(sess, llmod, output_type,
343-
&obj_filename));
342+
link::write::run_passes(sess, llcx, llmod, output_type,
343+
&obj_filename));
344344

345345
link::write::run_ndk(sess, &obj_filename, &outputs.obj_filename);
346346
} else {
347347
time(time_passes, ~"LLVM passes", ||
348-
link::write::run_passes(sess, llmod, sess.opts.output_type,
349-
&outputs.obj_filename));
348+
link::write::run_passes(sess, llcx, llmod, sess.opts.output_type,
349+
&outputs.obj_filename));
350350
}
351351

352352
let stop_after_codegen =

src/librustc/lib/llvm.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ pub enum BasicBlock_opaque {}
205205
pub type BasicBlockRef = *BasicBlock_opaque;
206206
pub enum Builder_opaque {}
207207
pub type BuilderRef = *Builder_opaque;
208+
pub enum ExecutionEngine_opaque {}
209+
pub type ExecutionEngineRef = *ExecutionEngine_opaque;
208210
pub enum MemoryBuffer_opaque {}
209211
pub type MemoryBufferRef = *MemoryBuffer_opaque;
210212
pub enum PassManager_opaque {}
@@ -223,7 +225,7 @@ pub enum Pass_opaque {}
223225
pub type PassRef = *Pass_opaque;
224226

225227
pub mod llvm {
226-
use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef};
228+
use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef, ExecutionEngineRef};
227229
use super::{Bool, BuilderRef, ContextRef, MemoryBufferRef, ModuleRef};
228230
use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef};
229231
use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef};
@@ -363,6 +365,10 @@ pub mod llvm {
363365
pub unsafe fn LLVMGetPointerAddressSpace(PointerTy: TypeRef)
364366
-> c_uint;
365367
#[fast_ffi]
368+
pub unsafe fn LLVMGetPointerToGlobal(EE: ExecutionEngineRef,
369+
V: ValueRef)
370+
-> *();
371+
#[fast_ffi]
366372
pub unsafe fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint;
367373

368374
/* Operations on other types */
@@ -1003,6 +1009,8 @@ pub mod llvm {
10031009
Name: *c_char);
10041010
#[fast_ffi]
10051011
pub unsafe fn LLVMDisposeBuilder(Builder: BuilderRef);
1012+
#[fast_ffi]
1013+
pub unsafe fn LLVMDisposeExecutionEngine(EE: ExecutionEngineRef);
10061014

10071015
/* Metadata */
10081016
#[fast_ffi]
@@ -1819,11 +1827,11 @@ pub mod llvm {
18191827

18201828
/** Execute the JIT engine. */
18211829
#[fast_ffi]
1822-
pub unsafe fn LLVMRustExecuteJIT(MM: *(),
1830+
pub unsafe fn LLVMRustBuildJIT(MM: *(),
18231831
PM: PassManagerRef,
18241832
M: ModuleRef,
18251833
OptLevel: c_int,
1826-
EnableSegmentedStacks: bool) -> *();
1834+
EnableSegmentedStacks: bool) -> ExecutionEngineRef;
18271835

18281836
/** Parses the bitcode in the given memory buffer. */
18291837
#[fast_ffi]

src/librustc/middle/trans/base.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3018,7 +3018,7 @@ pub fn trans_crate(sess: session::Session,
30183018
tcx: ty::ctxt,
30193019
output: &Path,
30203020
emap2: resolve::ExportMap2,
3021-
maps: astencode::Maps) -> (ModuleRef, LinkMeta) {
3021+
maps: astencode::Maps) -> (ContextRef, ModuleRef, LinkMeta) {
30223022
30233023
let symbol_hasher = @mut hash::default_state();
30243024
let link_meta = link::build_link_meta(sess, crate, output, symbol_hasher);
@@ -3040,9 +3040,11 @@ pub fn trans_crate(sess: session::Session,
30403040
let llmod_id = link_meta.name.to_owned() + ".rc";
30413041
30423042
unsafe {
3043-
if !llvm::LLVMRustStartMultithreading() {
3044-
sess.bug("couldn't enable multi-threaded LLVM");
3045-
}
3043+
// FIXME(#6511): get LLVM building with --enable-threads so this
3044+
// function can be called
3045+
// if !llvm::LLVMRustStartMultithreading() {
3046+
// sess.bug("couldn't enable multi-threaded LLVM");
3047+
// }
30463048
let llcx = llvm::LLVMContextCreate();
30473049
set_task_llcx(llcx);
30483050
let llmod = str::as_c_str(llmod_id, |buf| {
@@ -3178,7 +3180,8 @@ pub fn trans_crate(sess: session::Session,
31783180
io::println(fmt!("%-7u %s", v, k));
31793181
}
31803182
}
3181-
return (llmod, link_meta);
3183+
unset_task_llcx();
3184+
return (llcx, llmod, link_meta);
31823185
}
31833186
}
31843187
@@ -3189,8 +3192,10 @@ pub fn task_llcx() -> ContextRef {
31893192
*opt.expect("task-local LLVMContextRef wasn't ever set!")
31903193
}
31913194

3192-
fn set_task_llcx(c: ContextRef) {
3193-
unsafe {
3194-
local_data::local_data_set(task_local_llcx_key, @c);
3195-
}
3195+
unsafe fn set_task_llcx(c: ContextRef) {
3196+
local_data::local_data_set(task_local_llcx_key, @c);
3197+
}
3198+
3199+
unsafe fn unset_task_llcx() {
3200+
local_data::local_data_pop(task_local_llcx_key);
31963201
}

src/librusti/rusti.rc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -648,9 +648,5 @@ mod tests {
648648
fn f() {}
649649
f()
650650
");
651-
652-
debug!("regression test for #5803");
653-
run_cmds(["spawn( || println(\"Please don't segfault\") );",
654-
"do spawn { println(\"Please?\"); }"]);
655651
}
656652
}

src/rustllvm/RustWrapper.cpp

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -329,12 +329,12 @@ LLVMRustLoadCrate(void* mem, const char* crate) {
329329
return true;
330330
}
331331

332-
extern "C" void*
333-
LLVMRustExecuteJIT(void* mem,
334-
LLVMPassManagerRef PMR,
335-
LLVMModuleRef M,
336-
CodeGenOpt::Level OptLevel,
337-
bool EnableSegmentedStacks) {
332+
extern "C" LLVMExecutionEngineRef
333+
LLVMRustBuildJIT(void* mem,
334+
LLVMPassManagerRef PMR,
335+
LLVMModuleRef M,
336+
CodeGenOpt::Level OptLevel,
337+
bool EnableSegmentedStacks) {
338338

339339
InitializeNativeTarget();
340340
InitializeNativeTargetAsmPrinter();
@@ -371,21 +371,15 @@ LLVMRustExecuteJIT(void* mem,
371371

372372
if(!EE || Err != "") {
373373
LLVMRustError = Err.c_str();
374-
return 0;
374+
// The EngineBuilder only takes ownership of these two structures if the
375+
// create() call is successful, but here it wasn't successful.
376+
LLVMDisposeModule(M);
377+
delete MM;
378+
return NULL;
375379
}
376380

377381
MM->invalidateInstructionCache();
378-
Function* func = EE->FindFunctionNamed("_rust_main");
379-
380-
if(!func || Err != "") {
381-
LLVMRustError = Err.c_str();
382-
return 0;
383-
}
384-
385-
void* entry = EE->getPointerToFunction(func);
386-
assert(entry);
387-
388-
return entry;
382+
return wrap(EE);
389383
}
390384

391385
extern "C" bool

src/rustllvm/rustllvm.def.in

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ LLVMRustConstSmallInt
66
LLVMRustConstInt
77
LLVMRustLoadCrate
88
LLVMRustPrepareJIT
9-
LLVMRustExecuteJIT
9+
LLVMRustBuildJIT
1010
LLVMRustParseBitcode
1111
LLVMRustParseAssemblyFile
1212
LLVMRustPrintPassTimings
1313
LLVMRustStartMultithreading
1414
LLVMCreateObjectFile
1515
LLVMDisposeObjectFile
16+
LLVMDisposeExecutionEngine
1617
LLVMGetSections
1718
LLVMDisposeSectionIterator
1819
LLVMIsSectionIteratorAtEnd
@@ -356,6 +357,7 @@ LLVMGetParamParent
356357
LLVMGetParamTypes
357358
LLVMGetParams
358359
LLVMGetPointerAddressSpace
360+
LLVMGetPointerToGlobal
359361
LLVMGetPreviousBasicBlock
360362
LLVMGetPreviousFunction
361363
LLVMGetPreviousGlobal

src/rustllvm/rustllvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "llvm/Transforms/Vectorize.h"
4646
#include "llvm-c/Core.h"
4747
#include "llvm-c/BitReader.h"
48+
#include "llvm-c/ExecutionEngine.h"
4849
#include "llvm-c/Object.h"
4950

5051
// Used by RustMCJITMemoryManager::getPointerToNamedFunction()

0 commit comments

Comments
 (0)