Revert "Revert "Have JIT execution take ownership of the LLVMContextRef""
This reverts commit 19adece68b
.
This commit is contained in:
parent
1a3edecbf2
commit
a90fffe367
@ -102,7 +102,7 @@ pub mod jit {
|
||||
use back::link::llvm_err;
|
||||
use driver::session::Session;
|
||||
use lib::llvm::llvm;
|
||||
use lib::llvm::{ModuleRef, PassManagerRef};
|
||||
use lib::llvm::{ModuleRef, PassManagerRef, ContextRef};
|
||||
use metadata::cstore;
|
||||
|
||||
use core::cast;
|
||||
@ -125,6 +125,7 @@ pub struct Closure {
|
||||
|
||||
pub fn exec(sess: Session,
|
||||
pm: PassManagerRef,
|
||||
c: ContextRef,
|
||||
m: ModuleRef,
|
||||
opt: c_int,
|
||||
stacks: bool) {
|
||||
@ -153,26 +154,43 @@ pub fn exec(sess: Session,
|
||||
});
|
||||
}
|
||||
|
||||
// The execute function will return a void pointer
|
||||
// to the _rust_main function. We can do closure
|
||||
// magic here to turn it straight into a callable rust
|
||||
// closure. It will also cleanup the memory manager
|
||||
// for us.
|
||||
|
||||
let entry = llvm::LLVMRustExecuteJIT(manager,
|
||||
pm, m, opt, stacks);
|
||||
|
||||
if ptr::is_null(entry) {
|
||||
llvm_err(sess, ~"Could not JIT");
|
||||
} else {
|
||||
let closure = Closure {
|
||||
code: entry,
|
||||
env: ptr::null()
|
||||
};
|
||||
let func: &fn() = cast::transmute(closure);
|
||||
|
||||
func();
|
||||
// We custom-build a JIT execution engine via some rust wrappers
|
||||
// first. This wrappers takes ownership of the module passed in.
|
||||
let ee = llvm::LLVMRustBuildJIT(manager, pm, m, opt, stacks);
|
||||
if ee.is_null() {
|
||||
llvm::LLVMContextDispose(c);
|
||||
llvm_err(sess, ~"Could not create the JIT");
|
||||
}
|
||||
|
||||
// Next, we need to get a handle on the _rust_main function by
|
||||
// looking up it's corresponding ValueRef and then requesting that
|
||||
// the execution engine compiles the function.
|
||||
let fun = do str::as_c_str("_rust_main") |entry| {
|
||||
llvm::LLVMGetNamedFunction(m, entry)
|
||||
};
|
||||
if fun.is_null() {
|
||||
llvm::LLVMDisposeExecutionEngine(ee);
|
||||
llvm::LLVMContextDispose(c);
|
||||
llvm_err(sess, ~"Could not find _rust_main in the JIT");
|
||||
}
|
||||
|
||||
// Finally, once we have the pointer to the code, we can do some
|
||||
// closure magic here to turn it straight into a callable rust
|
||||
// closure
|
||||
let code = llvm::LLVMGetPointerToGlobal(ee, fun);
|
||||
assert!(!code.is_null());
|
||||
let closure = Closure {
|
||||
code: code,
|
||||
env: ptr::null()
|
||||
};
|
||||
let func: &fn() = cast::transmute(closure);
|
||||
func();
|
||||
|
||||
// Sadly, there currently is no interface to re-use this execution
|
||||
// engine, so it's disposed of here along with the context to
|
||||
// prevent leaks.
|
||||
llvm::LLVMDisposeExecutionEngine(ee);
|
||||
llvm::LLVMContextDispose(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -189,6 +207,7 @@ pub mod write {
|
||||
use driver::session;
|
||||
use lib::llvm::llvm;
|
||||
use lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data};
|
||||
use lib::llvm::{ContextRef};
|
||||
use lib;
|
||||
|
||||
use back::passes;
|
||||
@ -207,6 +226,7 @@ pub fn is_object_or_assembly_or_exe(ot: output_type) -> bool {
|
||||
}
|
||||
|
||||
pub fn run_passes(sess: Session,
|
||||
llcx: ContextRef,
|
||||
llmod: ModuleRef,
|
||||
output_type: output_type,
|
||||
output: &Path) {
|
||||
@ -281,7 +301,7 @@ pub fn run_passes(sess: Session,
|
||||
// JIT execution takes ownership of the module,
|
||||
// so don't dispose and return.
|
||||
|
||||
jit::exec(sess, pm.llpm, llmod, CodeGenOptLevel, true);
|
||||
jit::exec(sess, pm.llpm, llcx, llmod, CodeGenOptLevel, true);
|
||||
|
||||
if sess.time_llvm_passes() {
|
||||
llvm::LLVMRustPrintPassTimings();
|
||||
@ -349,6 +369,7 @@ pub fn run_passes(sess: Session,
|
||||
// Clean up and return
|
||||
|
||||
llvm::LLVMDisposeModule(llmod);
|
||||
llvm::LLVMContextDispose(llcx);
|
||||
if sess.time_llvm_passes() {
|
||||
llvm::LLVMRustPrintPassTimings();
|
||||
}
|
||||
@ -367,6 +388,7 @@ pub fn run_passes(sess: Session,
|
||||
}
|
||||
|
||||
llvm::LLVMDisposeModule(llmod);
|
||||
llvm::LLVMContextDispose(llcx);
|
||||
if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
|
||||
}
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ pub fn compile_rest(sess: Session,
|
||||
|
||||
let mut crate = crate_opt.unwrap();
|
||||
|
||||
let (llmod, link_meta) = {
|
||||
let (llcx, llmod, link_meta) = {
|
||||
crate = time(time_passes, ~"intrinsic injection", ||
|
||||
front::intrinsic_inject::inject_intrinsic(sess, crate));
|
||||
|
||||
@ -339,14 +339,14 @@ pub fn compile_rest(sess: Session,
|
||||
let obj_filename = outputs.obj_filename.with_filetype("s");
|
||||
|
||||
time(time_passes, ~"LLVM passes", ||
|
||||
link::write::run_passes(sess, llmod, output_type,
|
||||
&obj_filename));
|
||||
link::write::run_passes(sess, llcx, llmod, output_type,
|
||||
&obj_filename));
|
||||
|
||||
link::write::run_ndk(sess, &obj_filename, &outputs.obj_filename);
|
||||
} else {
|
||||
time(time_passes, ~"LLVM passes", ||
|
||||
link::write::run_passes(sess, llmod, sess.opts.output_type,
|
||||
&outputs.obj_filename));
|
||||
link::write::run_passes(sess, llcx, llmod, sess.opts.output_type,
|
||||
&outputs.obj_filename));
|
||||
}
|
||||
|
||||
let stop_after_codegen =
|
||||
|
@ -205,6 +205,8 @@ pub enum BasicBlock_opaque {}
|
||||
pub type BasicBlockRef = *BasicBlock_opaque;
|
||||
pub enum Builder_opaque {}
|
||||
pub type BuilderRef = *Builder_opaque;
|
||||
pub enum ExecutionEngine_opaque {}
|
||||
pub type ExecutionEngineRef = *ExecutionEngine_opaque;
|
||||
pub enum MemoryBuffer_opaque {}
|
||||
pub type MemoryBufferRef = *MemoryBuffer_opaque;
|
||||
pub enum PassManager_opaque {}
|
||||
@ -223,7 +225,7 @@ pub enum Pass_opaque {}
|
||||
pub type PassRef = *Pass_opaque;
|
||||
|
||||
pub mod llvm {
|
||||
use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef};
|
||||
use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef, ExecutionEngineRef};
|
||||
use super::{Bool, BuilderRef, ContextRef, MemoryBufferRef, ModuleRef};
|
||||
use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef};
|
||||
use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef};
|
||||
@ -363,6 +365,10 @@ pub unsafe fn LLVMVectorType(ElementType: TypeRef,
|
||||
pub unsafe fn LLVMGetPointerAddressSpace(PointerTy: TypeRef)
|
||||
-> c_uint;
|
||||
#[fast_ffi]
|
||||
pub unsafe fn LLVMGetPointerToGlobal(EE: ExecutionEngineRef,
|
||||
V: ValueRef)
|
||||
-> *();
|
||||
#[fast_ffi]
|
||||
pub unsafe fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint;
|
||||
|
||||
/* Operations on other types */
|
||||
@ -1003,6 +1009,8 @@ pub unsafe fn LLVMInsertIntoBuilderWithName(Builder: BuilderRef,
|
||||
Name: *c_char);
|
||||
#[fast_ffi]
|
||||
pub unsafe fn LLVMDisposeBuilder(Builder: BuilderRef);
|
||||
#[fast_ffi]
|
||||
pub unsafe fn LLVMDisposeExecutionEngine(EE: ExecutionEngineRef);
|
||||
|
||||
/* Metadata */
|
||||
#[fast_ffi]
|
||||
@ -1819,11 +1827,11 @@ pub unsafe fn LLVMRustLoadCrate(MM: *(),
|
||||
|
||||
/** Execute the JIT engine. */
|
||||
#[fast_ffi]
|
||||
pub unsafe fn LLVMRustExecuteJIT(MM: *(),
|
||||
pub unsafe fn LLVMRustBuildJIT(MM: *(),
|
||||
PM: PassManagerRef,
|
||||
M: ModuleRef,
|
||||
OptLevel: c_int,
|
||||
EnableSegmentedStacks: bool) -> *();
|
||||
EnableSegmentedStacks: bool) -> ExecutionEngineRef;
|
||||
|
||||
/** Parses the bitcode in the given memory buffer. */
|
||||
#[fast_ffi]
|
||||
|
@ -3018,7 +3018,7 @@ pub fn trans_crate(sess: session::Session,
|
||||
tcx: ty::ctxt,
|
||||
output: &Path,
|
||||
emap2: resolve::ExportMap2,
|
||||
maps: astencode::Maps) -> (ModuleRef, LinkMeta) {
|
||||
maps: astencode::Maps) -> (ContextRef, ModuleRef, LinkMeta) {
|
||||
|
||||
let symbol_hasher = @mut hash::default_state();
|
||||
let link_meta = link::build_link_meta(sess, crate, output, symbol_hasher);
|
||||
@ -3040,9 +3040,11 @@ pub fn trans_crate(sess: session::Session,
|
||||
let llmod_id = link_meta.name.to_owned() + ".rc";
|
||||
|
||||
unsafe {
|
||||
if !llvm::LLVMRustStartMultithreading() {
|
||||
sess.bug("couldn't enable multi-threaded LLVM");
|
||||
}
|
||||
// FIXME(#6511): get LLVM building with --enable-threads so this
|
||||
// function can be called
|
||||
// if !llvm::LLVMRustStartMultithreading() {
|
||||
// sess.bug("couldn't enable multi-threaded LLVM");
|
||||
// }
|
||||
let llcx = llvm::LLVMContextCreate();
|
||||
set_task_llcx(llcx);
|
||||
let llmod = str::as_c_str(llmod_id, |buf| {
|
||||
@ -3178,7 +3180,8 @@ pub fn trans_crate(sess: session::Session,
|
||||
io::println(fmt!("%-7u %s", v, k));
|
||||
}
|
||||
}
|
||||
return (llmod, link_meta);
|
||||
unset_task_llcx();
|
||||
return (llcx, llmod, link_meta);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3189,8 +3192,10 @@ pub fn task_llcx() -> ContextRef {
|
||||
*opt.expect("task-local LLVMContextRef wasn't ever set!")
|
||||
}
|
||||
|
||||
fn set_task_llcx(c: ContextRef) {
|
||||
unsafe {
|
||||
local_data::local_data_set(task_local_llcx_key, @c);
|
||||
}
|
||||
unsafe fn set_task_llcx(c: ContextRef) {
|
||||
local_data::local_data_set(task_local_llcx_key, @c);
|
||||
}
|
||||
|
||||
unsafe fn unset_task_llcx() {
|
||||
local_data::local_data_pop(task_local_llcx_key);
|
||||
}
|
||||
|
@ -648,9 +648,5 @@ mod tests {
|
||||
fn f() {}
|
||||
f()
|
||||
");
|
||||
|
||||
debug!("regression test for #5803");
|
||||
run_cmds(["spawn( || println(\"Please don't segfault\") );",
|
||||
"do spawn { println(\"Please?\"); }"]);
|
||||
}
|
||||
}
|
||||
|
@ -329,12 +329,12 @@ LLVMRustLoadCrate(void* mem, const char* crate) {
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" void*
|
||||
LLVMRustExecuteJIT(void* mem,
|
||||
LLVMPassManagerRef PMR,
|
||||
LLVMModuleRef M,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool EnableSegmentedStacks) {
|
||||
extern "C" LLVMExecutionEngineRef
|
||||
LLVMRustBuildJIT(void* mem,
|
||||
LLVMPassManagerRef PMR,
|
||||
LLVMModuleRef M,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool EnableSegmentedStacks) {
|
||||
|
||||
InitializeNativeTarget();
|
||||
InitializeNativeTargetAsmPrinter();
|
||||
@ -371,21 +371,15 @@ LLVMRustExecuteJIT(void* mem,
|
||||
|
||||
if(!EE || Err != "") {
|
||||
LLVMRustError = Err.c_str();
|
||||
return 0;
|
||||
// The EngineBuilder only takes ownership of these two structures if the
|
||||
// create() call is successful, but here it wasn't successful.
|
||||
LLVMDisposeModule(M);
|
||||
delete MM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MM->invalidateInstructionCache();
|
||||
Function* func = EE->FindFunctionNamed("_rust_main");
|
||||
|
||||
if(!func || Err != "") {
|
||||
LLVMRustError = Err.c_str();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* entry = EE->getPointerToFunction(func);
|
||||
assert(entry);
|
||||
|
||||
return entry;
|
||||
return wrap(EE);
|
||||
}
|
||||
|
||||
extern "C" bool
|
||||
|
@ -6,13 +6,14 @@ LLVMRustConstSmallInt
|
||||
LLVMRustConstInt
|
||||
LLVMRustLoadCrate
|
||||
LLVMRustPrepareJIT
|
||||
LLVMRustExecuteJIT
|
||||
LLVMRustBuildJIT
|
||||
LLVMRustParseBitcode
|
||||
LLVMRustParseAssemblyFile
|
||||
LLVMRustPrintPassTimings
|
||||
LLVMRustStartMultithreading
|
||||
LLVMCreateObjectFile
|
||||
LLVMDisposeObjectFile
|
||||
LLVMDisposeExecutionEngine
|
||||
LLVMGetSections
|
||||
LLVMDisposeSectionIterator
|
||||
LLVMIsSectionIteratorAtEnd
|
||||
@ -356,6 +357,7 @@ LLVMGetParamParent
|
||||
LLVMGetParamTypes
|
||||
LLVMGetParams
|
||||
LLVMGetPointerAddressSpace
|
||||
LLVMGetPointerToGlobal
|
||||
LLVMGetPreviousBasicBlock
|
||||
LLVMGetPreviousFunction
|
||||
LLVMGetPreviousGlobal
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "llvm/Transforms/Vectorize.h"
|
||||
#include "llvm-c/Core.h"
|
||||
#include "llvm-c/BitReader.h"
|
||||
#include "llvm-c/ExecutionEngine.h"
|
||||
#include "llvm-c/Object.h"
|
||||
|
||||
// Used by RustMCJITMemoryManager::getPointerToNamedFunction()
|
||||
|
Loading…
Reference in New Issue
Block a user