From 779191cd4b8719e8efdf69fb6da93e2a8905ca1d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 16 May 2013 23:40:42 -0400 Subject: Remove all usage of the global LLVMContextRef This allows parallel usage of the rustc library --- src/rustllvm/RustWrapper.cpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'src/rustllvm/RustWrapper.cpp') diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 4ee5df28d24..17eb0f50b9b 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -447,9 +447,10 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, return true; } -extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(const char *Filename) { +extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(LLVMContextRef C, + const char *Filename) { SMDiagnostic d; - Module *m = ParseAssemblyFile(Filename, d, getGlobalContext()); + Module *m = ParseAssemblyFile(Filename, d, *unwrap(C)); if (m) { return wrap(m); } else { @@ -499,9 +500,6 @@ extern "C" LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M, extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) { return wrap(Type::getMetadataTy(*unwrap(C))); } -extern "C" LLVMTypeRef LLVMMetadataType(void) { - return LLVMMetadataTypeInContext(LLVMGetGlobalContext()); -} extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B, LLVMValueRef source, @@ -561,3 +559,24 @@ extern "C" LLVMValueRef LLVMInlineAsm(LLVMTypeRef Ty, Constraints, HasSideEffects, IsAlignStack, (InlineAsm::AsmDialect) Dialect)); } + +/** + * This function is intended to be a threadsafe interface into enabling a + * multithreaded LLVM. This is invoked at the start of the translation phase of + * compilation to ensure that LLVM is ready. + * + * All of trans properly isolates LLVM with the use of a different + * LLVMContextRef per task, thus allowing parallel compilation of different + * crates in the same process. At the time of this writing, the use case for + * this is unit tests for rusti, but there are possible other applications. + */ +extern "C" bool LLVMRustStartMultithreading() { + static Mutex lock; + bool ret = true; + assert(lock.acquire()); + if (!LLVMIsMultithreaded()) { + ret = LLVMStartMultithreaded(); + } + assert(lock.release()); + return ret; +} -- cgit 1.4.1-3-g733a5 From 5c5095d25e3652c434c8d4ec178e6844877e3c2d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 17 May 2013 19:44:50 -0400 Subject: Have JIT execution take ownership of the LLVMContextRef Also stop leaking the ExecutionEngine created for jit code by forcibly disposing of it after the JIT code has finished executing --- src/librustc/back/link.rs | 62 ++++++++++++++++++++++++++------------- src/librustc/driver/driver.rs | 10 +++---- src/librustc/lib/llvm.rs | 14 +++++++-- src/librustc/middle/trans/base.rs | 23 +++++++++------ src/librusti/rusti.rc | 8 +++-- src/rustllvm/RustWrapper.cpp | 30 ++++++++----------- src/rustllvm/rustllvm.def.in | 4 ++- src/rustllvm/rustllvm.h | 1 + 8 files changed, 93 insertions(+), 59 deletions(-) (limited to 'src/rustllvm/RustWrapper.cpp') diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 496c1f88a6c..5375425b853 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -103,7 +103,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; @@ -126,6 +126,7 @@ pub mod jit { pub fn exec(sess: Session, pm: PassManagerRef, + c: ContextRef, m: ModuleRef, opt: c_int, stacks: bool) { @@ -154,26 +155,43 @@ pub mod jit { }); } - // 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); + // 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"); + } - func(); + // 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); } } } @@ -190,6 +208,7 @@ pub mod write { use driver::session; use lib::llvm::llvm; use lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data}; + use lib::llvm::{False, ContextRef}; use lib; use back::passes; @@ -208,6 +227,7 @@ pub mod write { } pub fn run_passes(sess: Session, + llcx: ContextRef, llmod: ModuleRef, output_type: output_type, output: &Path) { @@ -282,7 +302,7 @@ pub mod write { // 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(); @@ -350,6 +370,7 @@ pub mod write { // Clean up and return llvm::LLVMDisposeModule(llmod); + llvm::LLVMContextDispose(llcx); if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); } @@ -368,6 +389,7 @@ pub mod write { } llvm::LLVMDisposeModule(llmod); + llvm::LLVMContextDispose(llcx); if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); } } } diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index ef5670da455..9a6f48a3257 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -217,7 +217,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)); @@ -340,14 +340,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 = diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 0e9ea982d9f..b18c9e9b4c2 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -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 mod llvm { 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 mod llvm { 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 mod llvm { /** 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] diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 393155ddd7f..f0b57fe37ef 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -3023,7 +3023,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); @@ -3045,9 +3045,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| { @@ -3187,7 +3189,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); } } @@ -3198,8 +3201,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); } diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 9cb98dd8c2d..f8b39d9fbc7 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -476,8 +476,10 @@ mod tests { debug!("regression test for #5784"); run_cmds(["let a = 1;"]); - debug!("regression test for #5803"); - run_cmds(["spawn( || println(\"Please don't segfault\") );", - "do spawn { println(\"Please?\"); }"]); + // XXX: can't spawn new tasks because the JIT code is cleaned up + // after the main function is done. + // debug!("regression test for #5803"); + // run_cmds(["spawn( || println(\"Please don't segfault\") );", + // "do spawn { println(\"Please?\"); }"]); } } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 17eb0f50b9b..30e01b53ab7 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -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 diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index f8c68d798b9..f5397165781 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -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 diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h index 1c8842f7b4a..394146eea20 100644 --- a/src/rustllvm/rustllvm.h +++ b/src/rustllvm/rustllvm.h @@ -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() -- cgit 1.4.1-3-g733a5 From 19adece68b00bd1873499cca6f1537750608d769 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 13 Jun 2013 12:40:22 -0700 Subject: Revert "Have JIT execution take ownership of the LLVMContextRef" This reverts commit 5c5095d25e3652c434c8d4ec178e6844877e3c2d. Conflicts: src/librusti/rusti.rc --- src/librustc/back/link.rs | 62 +++++++++++++-------------------------- src/librustc/driver/driver.rs | 10 +++---- src/librustc/lib/llvm.rs | 14 ++------- src/librustc/middle/trans/base.rs | 23 ++++++--------- src/librusti/rusti.rc | 4 +++ src/rustllvm/RustWrapper.cpp | 30 +++++++++++-------- src/rustllvm/rustllvm.def.in | 4 +-- src/rustllvm/rustllvm.h | 1 - 8 files changed, 60 insertions(+), 88 deletions(-) (limited to 'src/rustllvm/RustWrapper.cpp') diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index f37ef83e770..3c8705b4ee9 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -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, ContextRef}; + use lib::llvm::{ModuleRef, PassManagerRef}; use metadata::cstore; use core::cast; @@ -125,7 +125,6 @@ pub mod jit { pub fn exec(sess: Session, pm: PassManagerRef, - c: ContextRef, m: ModuleRef, opt: c_int, stacks: bool) { @@ -154,43 +153,26 @@ pub mod jit { }); } - // 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"); - } + // 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. - // 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"); - } + let entry = llvm::LLVMRustExecuteJIT(manager, + pm, m, opt, stacks); - // 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); + 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(); + } } } } @@ -207,7 +189,6 @@ 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; @@ -226,7 +207,6 @@ pub mod write { } pub fn run_passes(sess: Session, - llcx: ContextRef, llmod: ModuleRef, output_type: output_type, output: &Path) { @@ -301,7 +281,7 @@ pub mod write { // JIT execution takes ownership of the module, // so don't dispose and return. - jit::exec(sess, pm.llpm, llcx, llmod, CodeGenOptLevel, true); + jit::exec(sess, pm.llpm, llmod, CodeGenOptLevel, true); if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); @@ -369,7 +349,6 @@ pub mod write { // Clean up and return llvm::LLVMDisposeModule(llmod); - llvm::LLVMContextDispose(llcx); if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); } @@ -388,7 +367,6 @@ pub mod write { } llvm::LLVMDisposeModule(llmod); - llvm::LLVMContextDispose(llcx); if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); } } } diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 0447481596a..b72cdd40ecd 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -216,7 +216,7 @@ pub fn compile_rest(sess: Session, let mut crate = crate_opt.unwrap(); - let (llcx, llmod, link_meta) = { + let (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, llcx, llmod, output_type, - &obj_filename)); + link::write::run_passes(sess, 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, llcx, llmod, sess.opts.output_type, - &outputs.obj_filename)); + link::write::run_passes(sess, llmod, sess.opts.output_type, + &outputs.obj_filename)); } let stop_after_codegen = diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index b18c9e9b4c2..0e9ea982d9f 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -205,8 +205,6 @@ 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 {} @@ -225,7 +223,7 @@ pub enum Pass_opaque {} pub type PassRef = *Pass_opaque; pub mod llvm { - use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef, ExecutionEngineRef}; + use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef}; use super::{Bool, BuilderRef, ContextRef, MemoryBufferRef, ModuleRef}; use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef}; use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef}; @@ -365,10 +363,6 @@ pub mod llvm { 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 */ @@ -1009,8 +1003,6 @@ pub mod llvm { Name: *c_char); #[fast_ffi] pub unsafe fn LLVMDisposeBuilder(Builder: BuilderRef); - #[fast_ffi] - pub unsafe fn LLVMDisposeExecutionEngine(EE: ExecutionEngineRef); /* Metadata */ #[fast_ffi] @@ -1827,11 +1819,11 @@ pub mod llvm { /** Execute the JIT engine. */ #[fast_ffi] - pub unsafe fn LLVMRustBuildJIT(MM: *(), + pub unsafe fn LLVMRustExecuteJIT(MM: *(), PM: PassManagerRef, M: ModuleRef, OptLevel: c_int, - EnableSegmentedStacks: bool) -> ExecutionEngineRef; + EnableSegmentedStacks: bool) -> *(); /** Parses the bitcode in the given memory buffer. */ #[fast_ffi] diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 7337b07c402..eefc162d0e3 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -3018,7 +3018,7 @@ pub fn trans_crate(sess: session::Session, tcx: ty::ctxt, output: &Path, emap2: resolve::ExportMap2, - maps: astencode::Maps) -> (ContextRef, ModuleRef, LinkMeta) { + maps: astencode::Maps) -> (ModuleRef, LinkMeta) { let symbol_hasher = @mut hash::default_state(); let link_meta = link::build_link_meta(sess, crate, output, symbol_hasher); @@ -3040,11 +3040,9 @@ pub fn trans_crate(sess: session::Session, let llmod_id = link_meta.name.to_owned() + ".rc"; unsafe { - // 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"); - // } + 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| { @@ -3180,8 +3178,7 @@ pub fn trans_crate(sess: session::Session, io::println(fmt!("%-7u %s", v, k)); } } - unset_task_llcx(); - return (llcx, llmod, link_meta); + return (llmod, link_meta); } } @@ -3192,10 +3189,8 @@ pub fn task_llcx() -> ContextRef { *opt.expect("task-local LLVMContextRef wasn't ever set!") } -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); +fn set_task_llcx(c: ContextRef) { + unsafe { + local_data::local_data_set(task_local_llcx_key, @c); + } } diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 90a5a350b7f..1a97c806027 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -648,5 +648,9 @@ mod tests { fn f() {} f() "); + + debug!("regression test for #5803"); + run_cmds(["spawn( || println(\"Please don't segfault\") );", + "do spawn { println(\"Please?\"); }"]); } } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 30e01b53ab7..17eb0f50b9b 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -329,12 +329,12 @@ LLVMRustLoadCrate(void* mem, const char* crate) { return true; } -extern "C" LLVMExecutionEngineRef -LLVMRustBuildJIT(void* mem, - LLVMPassManagerRef PMR, - LLVMModuleRef M, - CodeGenOpt::Level OptLevel, - bool EnableSegmentedStacks) { +extern "C" void* +LLVMRustExecuteJIT(void* mem, + LLVMPassManagerRef PMR, + LLVMModuleRef M, + CodeGenOpt::Level OptLevel, + bool EnableSegmentedStacks) { InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); @@ -371,15 +371,21 @@ LLVMRustBuildJIT(void* mem, if(!EE || Err != "") { LLVMRustError = Err.c_str(); - // 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; + return 0; } MM->invalidateInstructionCache(); - return wrap(EE); + Function* func = EE->FindFunctionNamed("_rust_main"); + + if(!func || Err != "") { + LLVMRustError = Err.c_str(); + return 0; + } + + void* entry = EE->getPointerToFunction(func); + assert(entry); + + return entry; } extern "C" bool diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index f5397165781..f8c68d798b9 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -6,14 +6,13 @@ LLVMRustConstSmallInt LLVMRustConstInt LLVMRustLoadCrate LLVMRustPrepareJIT -LLVMRustBuildJIT +LLVMRustExecuteJIT LLVMRustParseBitcode LLVMRustParseAssemblyFile LLVMRustPrintPassTimings LLVMRustStartMultithreading LLVMCreateObjectFile LLVMDisposeObjectFile -LLVMDisposeExecutionEngine LLVMGetSections LLVMDisposeSectionIterator LLVMIsSectionIteratorAtEnd @@ -357,7 +356,6 @@ LLVMGetParamParent LLVMGetParamTypes LLVMGetParams LLVMGetPointerAddressSpace -LLVMGetPointerToGlobal LLVMGetPreviousBasicBlock LLVMGetPreviousFunction LLVMGetPreviousGlobal diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h index 394146eea20..1c8842f7b4a 100644 --- a/src/rustllvm/rustllvm.h +++ b/src/rustllvm/rustllvm.h @@ -45,7 +45,6 @@ #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() -- cgit 1.4.1-3-g733a5 From 541c657a738006d78171aa261125a6a46f283b35 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 13 Jun 2013 12:42:02 -0700 Subject: Revert "Remove all usage of the global LLVMContextRef" This reverts commit 779191cd4b8719e8efdf69fb6da93e2a8905ca1d. Conflicts: src/librustc/middle/trans/base.rs src/librustc/middle/trans/common.rs --- src/librustc/lib/llvm.rs | 71 +++++++++++++++++++++++++++++---- src/librustc/middle/trans/base.rs | 42 +++++-------------- src/librustc/middle/trans/build.rs | 3 +- src/librustc/middle/trans/cabi_mips.rs | 3 +- src/librustc/middle/trans/closure.rs | 4 +- src/librustc/middle/trans/common.rs | 73 ++++++++++++---------------------- src/librustc/middle/trans/debuginfo.rs | 9 +---- src/librustc/middle/trans/type_of.rs | 2 +- src/librusti/rusti.rc | 4 -- src/rustllvm/RustWrapper.cpp | 29 +++----------- src/rustllvm/rustllvm.def.in | 3 +- 11 files changed, 113 insertions(+), 130 deletions(-) (limited to 'src/rustllvm/RustWrapper.cpp') diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 0e9ea982d9f..f6beb078e46 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -239,12 +239,16 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMContextCreate() -> ContextRef; #[fast_ffi] + pub unsafe fn LLVMGetGlobalContext() -> ContextRef; + #[fast_ffi] pub unsafe fn LLVMContextDispose(C: ContextRef); #[fast_ffi] pub unsafe fn LLVMGetMDKindIDInContext(C: ContextRef, Name: *c_char, SLen: c_uint) -> c_uint; + #[fast_ffi] + pub unsafe fn LLVMGetMDKindID(Name: *c_char, SLen: c_uint) -> c_uint; /* Create and destroy modules. */ #[fast_ffi] @@ -252,8 +256,6 @@ pub mod llvm { C: ContextRef) -> ModuleRef; #[fast_ffi] - pub unsafe fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef; - #[fast_ffi] pub unsafe fn LLVMDisposeModule(M: ModuleRef); /** Data layout. See Module::getDataLayout. */ @@ -298,6 +300,18 @@ pub mod llvm { pub unsafe fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint) -> TypeRef; + #[fast_ffi] + pub unsafe fn LLVMInt1Type() -> TypeRef; + #[fast_ffi] + pub unsafe fn LLVMInt8Type() -> TypeRef; + #[fast_ffi] + pub unsafe fn LLVMInt16Type() -> TypeRef; + #[fast_ffi] + pub unsafe fn LLVMInt32Type() -> TypeRef; + #[fast_ffi] + pub unsafe fn LLVMInt64Type() -> TypeRef; + #[fast_ffi] + pub unsafe fn LLVMIntType(NumBits: c_uint) -> TypeRef; #[fast_ffi] pub unsafe fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint; @@ -313,6 +327,17 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMPPCFP128TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] + pub unsafe fn LLVMFloatType() -> TypeRef; + #[fast_ffi] + pub unsafe fn LLVMDoubleType() -> TypeRef; + #[fast_ffi] + pub unsafe fn LLVMX86FP80Type() -> TypeRef; + #[fast_ffi] + pub unsafe fn LLVMFP128Type() -> TypeRef; + #[fast_ffi] + pub unsafe fn LLVMPPCFP128Type() -> TypeRef; + /* Operations on function types */ #[fast_ffi] pub unsafe fn LLVMFunctionType(ReturnType: TypeRef, @@ -336,6 +361,11 @@ pub mod llvm { ElementCount: c_uint, Packed: Bool) -> TypeRef; #[fast_ffi] + pub unsafe fn LLVMStructType(ElementTypes: *TypeRef, + ElementCount: c_uint, + Packed: Bool) + -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMCountStructElementTypes(StructTy: TypeRef) -> c_uint; #[fast_ffi] @@ -373,6 +403,13 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMMetadataTypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] + pub unsafe fn LLVMVoidType() -> TypeRef; + #[fast_ffi] + pub unsafe fn LLVMLabelType() -> TypeRef; + #[fast_ffi] + pub unsafe fn LLVMMetadataType() -> TypeRef; + /* Operations on all values */ #[fast_ffi] pub unsafe fn LLVMTypeOf(Val: ValueRef) -> TypeRef; @@ -445,11 +482,15 @@ pub mod llvm { SLen: c_uint) -> ValueRef; #[fast_ffi] + pub unsafe fn LLVMMDString(Str: *c_char, SLen: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMMDNodeInContext(C: ContextRef, Vals: *ValueRef, Count: c_uint) -> ValueRef; #[fast_ffi] + pub unsafe fn LLVMMDNode(Vals: *ValueRef, Count: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMAddNamedMetadataOperand(M: ModuleRef, Str: *c_char, Val: ValueRef); @@ -503,11 +544,20 @@ pub mod llvm { Packed: Bool) -> ValueRef; #[fast_ffi] + pub unsafe fn LLVMConstString(Str: *c_char, + Length: c_uint, + DontNullTerminate: Bool) + -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstArray(ElementTy: TypeRef, ConstantVals: *ValueRef, Length: c_uint) -> ValueRef; #[fast_ffi] + pub unsafe fn LLVMConstStruct(ConstantVals: *ValueRef, + Count: c_uint, + Packed: Bool) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstVector(ScalarConstantVals: *ValueRef, Size: c_uint) -> ValueRef; @@ -920,6 +970,15 @@ pub mod llvm { BB: BasicBlockRef, Name: *c_char) -> BasicBlockRef; + + #[fast_ffi] + pub unsafe fn LLVMAppendBasicBlock(Fn: ValueRef, + Name: *c_char) + -> BasicBlockRef; + #[fast_ffi] + pub unsafe fn LLVMInsertBasicBlock(InsertBeforeBB: BasicBlockRef, + Name: *c_char) + -> BasicBlockRef; #[fast_ffi] pub unsafe fn LLVMDeleteBasicBlock(BB: BasicBlockRef); @@ -980,6 +1039,8 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef; #[fast_ffi] + pub unsafe fn LLVMCreateBuilder() -> BuilderRef; + #[fast_ffi] pub unsafe fn LLVMPositionBuilder(Builder: BuilderRef, Block: BasicBlockRef, Instr: ValueRef); @@ -1832,8 +1893,7 @@ pub mod llvm { /** Parses LLVM asm in the given file */ #[fast_ffi] - pub unsafe fn LLVMRustParseAssemblyFile(Filename: *c_char, - C: ContextRef) + pub unsafe fn LLVMRustParseAssemblyFile(Filename: *c_char) -> ModuleRef; #[fast_ffi] @@ -1849,9 +1909,6 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMRustPrintPassTimings(); - #[fast_ffi] - pub unsafe fn LLVMRustStartMultithreading() -> bool; - #[fast_ffi] pub unsafe fn LLVMStructCreateNamed(C: ContextRef, Name: *c_char) -> TypeRef; diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index eefc162d0e3..20e2e0307dc 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -29,7 +29,7 @@ use back::link::{mangle_exported_name}; use back::{link, abi, upcall}; use driver::session; use driver::session::Session; -use lib::llvm::{ContextRef, ModuleRef, ValueRef, TypeRef, BasicBlockRef}; +use lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef}; use lib::llvm::{True, False}; use lib::llvm::{llvm, mk_target_data, mk_type_names}; use lib; @@ -73,7 +73,6 @@ use core::libc::c_uint; use core::str; use core::uint; use core::vec; -use core::local_data; use extra::time; use syntax::ast::ident; use syntax::ast_map::{path, path_elt_to_str, path_name}; @@ -1188,7 +1187,7 @@ pub fn new_block(cx: fn_ctxt, parent: Option, kind: block_kind, }; unsafe { let llbb = str::as_c_str(cx.ccx.sess.str_of(s), |buf| { - llvm::LLVMAppendBasicBlockInContext(cx.ccx.llcx, cx.llfn, buf) + llvm::LLVMAppendBasicBlock(cx.llfn, buf) }); let bcx = mk_block(llbb, parent, @@ -1555,12 +1554,11 @@ pub struct BasicBlocks { // Creates the standard set of basic blocks for a function pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks { unsafe { - let cx = task_llcx(); BasicBlocks { sa: str::as_c_str("static_allocas", - |buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)), + |buf| llvm::LLVMAppendBasicBlock(llfn, buf)), rt: str::as_c_str("return", - |buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)) + |buf| llvm::LLVMAppendBasicBlock(llfn, buf)) } } } @@ -2343,7 +2341,7 @@ pub fn create_entry_wrapper(ccx: @CrateContext, }; let llbb = str::as_c_str("top", |buf| { unsafe { - llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf) + llvm::LLVMAppendBasicBlock(llfn, buf) } }); let bld = ccx.builder.B; @@ -2661,10 +2659,10 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<&'static str, ValueRef> { T_void())); let memcpy32 = decl_cdecl_fn(llmod, "llvm.memcpy.p0i8.p0i8.i32", - T_fn(T_memcpy32_args, T_void())); + T_fn(copy T_memcpy32_args, T_void())); let memcpy64 = decl_cdecl_fn(llmod, "llvm.memcpy.p0i8.p0i8.i64", - T_fn(T_memcpy64_args, T_void())); + T_fn(copy T_memcpy64_args, T_void())); let memmove32 = decl_cdecl_fn(llmod, "llvm.memmove.p0i8.p0i8.i32", T_fn(T_memcpy32_args, T_void())); @@ -3040,13 +3038,9 @@ 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"); - } - let llcx = llvm::LLVMContextCreate(); - set_task_llcx(llcx); let llmod = str::as_c_str(llmod_id, |buf| { - llvm::LLVMModuleCreateWithNameInContext(buf, llcx) + llvm::LLVMModuleCreateWithNameInContext + (buf, llvm::LLVMGetGlobalContext()) }); let data_layout: &str = sess.targ_cfg.target_strs.data_layout; let targ_triple: &str = sess.targ_cfg.target_strs.target_triple; @@ -3077,7 +3071,6 @@ pub fn trans_crate(sess: session::Session, let ccx = @CrateContext { sess: sess, llmod: llmod, - llcx: llcx, td: td, tn: tn, externs: @mut HashMap::new(), @@ -3131,9 +3124,7 @@ pub fn trans_crate(sess: session::Session, int_type: int_type, float_type: float_type, opaque_vec_type: T_opaque_vec(targ_cfg), - builder: BuilderRef_res(unsafe { - llvm::LLVMCreateBuilderInContext(llcx) - }), + builder: BuilderRef_res(unsafe { llvm::LLVMCreateBuilder() }), shape_cx: mk_ctxt(llmod), crate_map: crate_map, uses_gc: @mut false, @@ -3181,16 +3172,3 @@ pub fn trans_crate(sess: session::Session, return (llmod, link_meta); } } - -fn task_local_llcx_key(_v: @ContextRef) {} - -pub fn task_llcx() -> ContextRef { - let opt = unsafe { local_data::local_data_get(task_local_llcx_key) }; - *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); - } -} diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index af108451810..8ac47ed135a 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -564,8 +564,7 @@ pub fn LoadRangeAssert(cx: block, PointerVal: ValueRef, lo: c_ulonglong, do vec::as_imm_buf([min, max]) |ptr, len| { llvm::LLVMSetMetadata(value, lib::llvm::MD_range as c_uint, - llvm::LLVMMDNodeInContext(cx.fcx.ccx.llcx, - ptr, len as c_uint)); + llvm::LLVMMDNode(ptr, len as c_uint)); } } diff --git a/src/librustc/middle/trans/cabi_mips.rs b/src/librustc/middle/trans/cabi_mips.rs index 366c0a90a4c..6be398c0bb2 100644 --- a/src/librustc/middle/trans/cabi_mips.rs +++ b/src/librustc/middle/trans/cabi_mips.rs @@ -19,7 +19,6 @@ use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double}; use lib::llvm::{Struct, Array, Attribute}; use lib::llvm::{StructRetAttribute}; use lib::llvm::True; -use middle::trans::base::task_llcx; use middle::trans::common::*; use middle::trans::cabi::*; @@ -167,7 +166,7 @@ fn coerce_to_int(size: uint) -> ~[TypeRef] { let r = size % 32; if r > 0 { unsafe { - args.push(llvm::LLVMIntTypeInContext(task_llcx(), r as c_uint)) + args.push(llvm::LLVMIntType(r as c_uint)) } } diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 4804058609a..d5d018c0543 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -327,9 +327,7 @@ pub fn load_environment(fcx: fn_ctxt, str::as_c_str("load_env", |buf| unsafe { - llvm::LLVMAppendBasicBlockInContext(fcx.ccx.llcx, - fcx.llfn, - buf) + llvm::LLVMAppendBasicBlock(fcx.llfn, buf) }); fcx.llloadenv = Some(ll); ll diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 7e47fc47bff..a12ce790d04 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -17,7 +17,7 @@ use back::{abi, upcall}; use driver::session; use driver::session::Session; use lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef, BuilderRef}; -use lib::llvm::{ContextRef, True, False, Bool}; +use lib::llvm::{True, False, Bool}; use lib::llvm::{llvm, TargetData, TypeNames, associate_type, name_has_type}; use lib; use metadata::common::LinkMeta; @@ -161,7 +161,6 @@ pub type ExternMap = @mut HashMap<@str, ValueRef>; pub struct CrateContext { sess: session::Session, llmod: ModuleRef, - llcx: ContextRef, td: TargetData, tn: @TypeNames, externs: ExternMap, @@ -799,44 +798,30 @@ impl block_ { // LLVM type constructors. pub fn T_void() -> TypeRef { - unsafe { return llvm::LLVMVoidTypeInContext(base::task_llcx()); } + unsafe { + return llvm::LLVMVoidType(); + } } pub fn T_nil() -> TypeRef { return T_struct([], false) } -pub fn T_metadata() -> TypeRef { - unsafe { return llvm::LLVMMetadataTypeInContext(base::task_llcx()); } -} +pub fn T_metadata() -> TypeRef { unsafe { return llvm::LLVMMetadataType(); } } -pub fn T_i1() -> TypeRef { - unsafe { return llvm::LLVMInt1TypeInContext(base::task_llcx()); } -} +pub fn T_i1() -> TypeRef { unsafe { return llvm::LLVMInt1Type(); } } -pub fn T_i8() -> TypeRef { - unsafe { return llvm::LLVMInt8TypeInContext(base::task_llcx()); } -} +pub fn T_i8() -> TypeRef { unsafe { return llvm::LLVMInt8Type(); } } -pub fn T_i16() -> TypeRef { - unsafe { return llvm::LLVMInt16TypeInContext(base::task_llcx()); } -} +pub fn T_i16() -> TypeRef { unsafe { return llvm::LLVMInt16Type(); } } -pub fn T_i32() -> TypeRef { - unsafe { return llvm::LLVMInt32TypeInContext(base::task_llcx()); } -} +pub fn T_i32() -> TypeRef { unsafe { return llvm::LLVMInt32Type(); } } -pub fn T_i64() -> TypeRef { - unsafe { return llvm::LLVMInt64TypeInContext(base::task_llcx()); } -} +pub fn T_i64() -> TypeRef { unsafe { return llvm::LLVMInt64Type(); } } -pub fn T_f32() -> TypeRef { - unsafe { return llvm::LLVMFloatTypeInContext(base::task_llcx()); } -} +pub fn T_f32() -> TypeRef { unsafe { return llvm::LLVMFloatType(); } } -pub fn T_f64() -> TypeRef { - unsafe { return llvm::LLVMDoubleTypeInContext(base::task_llcx()); } -} +pub fn T_f64() -> TypeRef { unsafe { return llvm::LLVMDoubleType(); } } pub fn T_bool() -> TypeRef { return T_i8(); } @@ -896,8 +881,8 @@ pub fn T_size_t(targ_cfg: @session::config) -> TypeRef { pub fn T_fn(inputs: &[TypeRef], output: TypeRef) -> TypeRef { unsafe { return llvm::LLVMFunctionType(output, to_ptr(inputs), - inputs.len() as c_uint, - False); + inputs.len() as c_uint, + False); } } @@ -919,18 +904,16 @@ pub fn T_root(t: TypeRef, addrspace: addrspace) -> TypeRef { pub fn T_struct(elts: &[TypeRef], packed: bool) -> TypeRef { unsafe { - return llvm::LLVMStructTypeInContext(base::task_llcx(), - to_ptr(elts), - elts.len() as c_uint, - packed as Bool); + return llvm::LLVMStructType(to_ptr(elts), + elts.len() as c_uint, + packed as Bool); } } pub fn T_named_struct(name: &str) -> TypeRef { unsafe { - return str::as_c_str(name, |buf| { - llvm::LLVMStructCreateNamed(base::task_llcx(), buf) - }); + let c = llvm::LLVMGetGlobalContext(); + return str::as_c_str(name, |buf| llvm::LLVMStructCreateNamed(c, buf)); } } @@ -1184,8 +1167,7 @@ pub fn C_cstr(cx: @CrateContext, s: @str) -> ValueRef { } let sc = do str::as_c_str(s) |buf| { - llvm::LLVMConstStringInContext(cx.llcx, buf, s.len() as c_uint, - False) + llvm::LLVMConstString(buf, s.len() as c_uint, False) }; let g = str::as_c_str(fmt!("str%u", (cx.names)("str").name), @@ -1214,8 +1196,7 @@ pub fn C_estr_slice(cx: @CrateContext, s: @str) -> ValueRef { pub fn C_postr(s: &str) -> ValueRef { unsafe { return do str::as_c_str(s) |buf| { - llvm::LLVMConstStringInContext(base::task_llcx(), - buf, s.len() as c_uint, False) + llvm::LLVMConstString(buf, s.len() as c_uint, False) }; } } @@ -1234,8 +1215,7 @@ pub fn C_zero_byte_arr(size: uint) -> ValueRef { pub fn C_struct(elts: &[ValueRef]) -> ValueRef { unsafe { do vec::as_imm_buf(elts) |ptr, len| { - llvm::LLVMConstStructInContext(base::task_llcx(), - ptr, len as c_uint, False) + llvm::LLVMConstStruct(ptr, len as c_uint, False) } } } @@ -1243,8 +1223,7 @@ pub fn C_struct(elts: &[ValueRef]) -> ValueRef { pub fn C_packed_struct(elts: &[ValueRef]) -> ValueRef { unsafe { do vec::as_imm_buf(elts) |ptr, len| { - llvm::LLVMConstStructInContext(base::task_llcx(), - ptr, len as c_uint, True) + llvm::LLVMConstStruct(ptr, len as c_uint, True) } } } @@ -1260,13 +1239,13 @@ pub fn C_named_struct(T: TypeRef, elts: &[ValueRef]) -> ValueRef { pub fn C_array(ty: TypeRef, elts: &[ValueRef]) -> ValueRef { unsafe { return llvm::LLVMConstArray(ty, vec::raw::to_ptr(elts), - elts.len() as c_uint); + elts.len() as c_uint); } } pub fn C_bytes(bytes: &[u8]) -> ValueRef { unsafe { - return llvm::LLVMConstStringInContext(base::task_llcx(), + return llvm::LLVMConstString( cast::transmute(vec::raw::to_ptr(bytes)), bytes.len() as c_uint, True); } @@ -1274,7 +1253,7 @@ pub fn C_bytes(bytes: &[u8]) -> ValueRef { pub fn C_bytes_plus_null(bytes: &[u8]) -> ValueRef { unsafe { - return llvm::LLVMConstStringInContext(base::task_llcx(), + return llvm::LLVMConstString( cast::transmute(vec::raw::to_ptr(bytes)), bytes.len() as c_uint, False); } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 3bb9d4abab0..83c1bfdb0dd 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -13,7 +13,6 @@ use core::prelude::*; use driver::session; use lib::llvm::ValueRef; use lib::llvm::llvm; -use middle::trans::base::task_llcx; use middle::trans::common::*; use middle::trans::machine; use middle::trans::type_of; @@ -62,9 +61,7 @@ static DW_ATE_unsigned_char: int = 0x08; fn llstr(s: &str) -> ValueRef { do str::as_c_str(s) |sbuf| { unsafe { - llvm::LLVMMDStringInContext(task_llcx(), - sbuf, - s.len() as libc::c_uint) + llvm::LLVMMDString(sbuf, s.len() as libc::c_uint) } } } @@ -82,9 +79,7 @@ fn lli1(bval: bool) -> ValueRef { } fn llmdnode(elems: &[ValueRef]) -> ValueRef { unsafe { - llvm::LLVMMDNodeInContext(task_llcx(), - vec::raw::to_ptr(elems), - elems.len() as libc::c_uint) + llvm::LLVMMDNode(vec::raw::to_ptr(elems), elems.len() as libc::c_uint) } } fn llunused() -> ValueRef { diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index 2fff45678bc..e3c424f8e7e 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -58,7 +58,7 @@ pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::t], output: ty::t) if output_is_immediate { T_fn(atys, lloutputtype) } else { - T_fn(atys, llvm::LLVMVoidTypeInContext(cx.llcx)) + T_fn(atys, llvm::LLVMVoidType()) } } } diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 1a97c806027..90a5a350b7f 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -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?\"); }"]); } } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 17eb0f50b9b..4ee5df28d24 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -447,10 +447,9 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, return true; } -extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(LLVMContextRef C, - const char *Filename) { +extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(const char *Filename) { SMDiagnostic d; - Module *m = ParseAssemblyFile(Filename, d, *unwrap(C)); + Module *m = ParseAssemblyFile(Filename, d, getGlobalContext()); if (m) { return wrap(m); } else { @@ -500,6 +499,9 @@ extern "C" LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M, extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) { return wrap(Type::getMetadataTy(*unwrap(C))); } +extern "C" LLVMTypeRef LLVMMetadataType(void) { + return LLVMMetadataTypeInContext(LLVMGetGlobalContext()); +} extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B, LLVMValueRef source, @@ -559,24 +561,3 @@ extern "C" LLVMValueRef LLVMInlineAsm(LLVMTypeRef Ty, Constraints, HasSideEffects, IsAlignStack, (InlineAsm::AsmDialect) Dialect)); } - -/** - * This function is intended to be a threadsafe interface into enabling a - * multithreaded LLVM. This is invoked at the start of the translation phase of - * compilation to ensure that LLVM is ready. - * - * All of trans properly isolates LLVM with the use of a different - * LLVMContextRef per task, thus allowing parallel compilation of different - * crates in the same process. At the time of this writing, the use case for - * this is unit tests for rusti, but there are possible other applications. - */ -extern "C" bool LLVMRustStartMultithreading() { - static Mutex lock; - bool ret = true; - assert(lock.acquire()); - if (!LLVMIsMultithreaded()) { - ret = LLVMStartMultithreaded(); - } - assert(lock.release()); - return ret; -} diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index f8c68d798b9..8ebdbd0f307 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -10,7 +10,6 @@ LLVMRustExecuteJIT LLVMRustParseBitcode LLVMRustParseAssemblyFile LLVMRustPrintPassTimings -LLVMRustStartMultithreading LLVMCreateObjectFile LLVMDisposeObjectFile LLVMGetSections @@ -320,6 +319,7 @@ LLVMGetFunctionAttr LLVMGetFunctionCallConv LLVMGetGC LLVMGetGlobalContext +LLVMGetGlobalContext LLVMGetGlobalParent LLVMGetGlobalPassRegistry LLVMGetIncomingBlock @@ -500,6 +500,7 @@ LLVMMDNode LLVMMDNodeInContext LLVMMDString LLVMMDStringInContext +LLVMMetadataType LLVMMetadataTypeInContext LLVMModuleCreateWithName LLVMModuleCreateWithNameInContext -- cgit 1.4.1-3-g733a5 From 1a3edecbf21eef7f39bbf3a7bf38fb72fdc6af61 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 13 Jun 2013 21:25:12 -0700 Subject: Revert "Revert "Remove all usage of the global LLVMContextRef"" This reverts commit 541c657a738006d78171aa261125a6a46f283b35. --- src/librustc/lib/llvm.rs | 71 ++++----------------------------- src/librustc/middle/trans/base.rs | 42 ++++++++++++++----- src/librustc/middle/trans/build.rs | 3 +- src/librustc/middle/trans/cabi_mips.rs | 3 +- src/librustc/middle/trans/closure.rs | 4 +- src/librustc/middle/trans/common.rs | 73 ++++++++++++++++++++++------------ src/librustc/middle/trans/debuginfo.rs | 9 ++++- src/librustc/middle/trans/type_of.rs | 2 +- src/librusti/rusti.rc | 4 ++ src/rustllvm/RustWrapper.cpp | 29 +++++++++++--- src/rustllvm/rustllvm.def.in | 3 +- 11 files changed, 130 insertions(+), 113 deletions(-) (limited to 'src/rustllvm/RustWrapper.cpp') diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index f6beb078e46..0e9ea982d9f 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -239,16 +239,12 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMContextCreate() -> ContextRef; #[fast_ffi] - pub unsafe fn LLVMGetGlobalContext() -> ContextRef; - #[fast_ffi] pub unsafe fn LLVMContextDispose(C: ContextRef); #[fast_ffi] pub unsafe fn LLVMGetMDKindIDInContext(C: ContextRef, Name: *c_char, SLen: c_uint) -> c_uint; - #[fast_ffi] - pub unsafe fn LLVMGetMDKindID(Name: *c_char, SLen: c_uint) -> c_uint; /* Create and destroy modules. */ #[fast_ffi] @@ -256,6 +252,8 @@ pub mod llvm { C: ContextRef) -> ModuleRef; #[fast_ffi] + pub unsafe fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef; + #[fast_ffi] pub unsafe fn LLVMDisposeModule(M: ModuleRef); /** Data layout. See Module::getDataLayout. */ @@ -300,18 +298,6 @@ pub mod llvm { pub unsafe fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint) -> TypeRef; - #[fast_ffi] - pub unsafe fn LLVMInt1Type() -> TypeRef; - #[fast_ffi] - pub unsafe fn LLVMInt8Type() -> TypeRef; - #[fast_ffi] - pub unsafe fn LLVMInt16Type() -> TypeRef; - #[fast_ffi] - pub unsafe fn LLVMInt32Type() -> TypeRef; - #[fast_ffi] - pub unsafe fn LLVMInt64Type() -> TypeRef; - #[fast_ffi] - pub unsafe fn LLVMIntType(NumBits: c_uint) -> TypeRef; #[fast_ffi] pub unsafe fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint; @@ -327,17 +313,6 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMPPCFP128TypeInContext(C: ContextRef) -> TypeRef; - #[fast_ffi] - pub unsafe fn LLVMFloatType() -> TypeRef; - #[fast_ffi] - pub unsafe fn LLVMDoubleType() -> TypeRef; - #[fast_ffi] - pub unsafe fn LLVMX86FP80Type() -> TypeRef; - #[fast_ffi] - pub unsafe fn LLVMFP128Type() -> TypeRef; - #[fast_ffi] - pub unsafe fn LLVMPPCFP128Type() -> TypeRef; - /* Operations on function types */ #[fast_ffi] pub unsafe fn LLVMFunctionType(ReturnType: TypeRef, @@ -361,11 +336,6 @@ pub mod llvm { ElementCount: c_uint, Packed: Bool) -> TypeRef; #[fast_ffi] - pub unsafe fn LLVMStructType(ElementTypes: *TypeRef, - ElementCount: c_uint, - Packed: Bool) - -> TypeRef; - #[fast_ffi] pub unsafe fn LLVMCountStructElementTypes(StructTy: TypeRef) -> c_uint; #[fast_ffi] @@ -403,13 +373,6 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMMetadataTypeInContext(C: ContextRef) -> TypeRef; - #[fast_ffi] - pub unsafe fn LLVMVoidType() -> TypeRef; - #[fast_ffi] - pub unsafe fn LLVMLabelType() -> TypeRef; - #[fast_ffi] - pub unsafe fn LLVMMetadataType() -> TypeRef; - /* Operations on all values */ #[fast_ffi] pub unsafe fn LLVMTypeOf(Val: ValueRef) -> TypeRef; @@ -482,15 +445,11 @@ pub mod llvm { SLen: c_uint) -> ValueRef; #[fast_ffi] - pub unsafe fn LLVMMDString(Str: *c_char, SLen: c_uint) -> ValueRef; - #[fast_ffi] pub unsafe fn LLVMMDNodeInContext(C: ContextRef, Vals: *ValueRef, Count: c_uint) -> ValueRef; #[fast_ffi] - pub unsafe fn LLVMMDNode(Vals: *ValueRef, Count: c_uint) -> ValueRef; - #[fast_ffi] pub unsafe fn LLVMAddNamedMetadataOperand(M: ModuleRef, Str: *c_char, Val: ValueRef); @@ -544,20 +503,11 @@ pub mod llvm { Packed: Bool) -> ValueRef; #[fast_ffi] - pub unsafe fn LLVMConstString(Str: *c_char, - Length: c_uint, - DontNullTerminate: Bool) - -> ValueRef; - #[fast_ffi] pub unsafe fn LLVMConstArray(ElementTy: TypeRef, ConstantVals: *ValueRef, Length: c_uint) -> ValueRef; #[fast_ffi] - pub unsafe fn LLVMConstStruct(ConstantVals: *ValueRef, - Count: c_uint, - Packed: Bool) -> ValueRef; - #[fast_ffi] pub unsafe fn LLVMConstVector(ScalarConstantVals: *ValueRef, Size: c_uint) -> ValueRef; @@ -970,15 +920,6 @@ pub mod llvm { BB: BasicBlockRef, Name: *c_char) -> BasicBlockRef; - - #[fast_ffi] - pub unsafe fn LLVMAppendBasicBlock(Fn: ValueRef, - Name: *c_char) - -> BasicBlockRef; - #[fast_ffi] - pub unsafe fn LLVMInsertBasicBlock(InsertBeforeBB: BasicBlockRef, - Name: *c_char) - -> BasicBlockRef; #[fast_ffi] pub unsafe fn LLVMDeleteBasicBlock(BB: BasicBlockRef); @@ -1039,8 +980,6 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef; #[fast_ffi] - pub unsafe fn LLVMCreateBuilder() -> BuilderRef; - #[fast_ffi] pub unsafe fn LLVMPositionBuilder(Builder: BuilderRef, Block: BasicBlockRef, Instr: ValueRef); @@ -1893,7 +1832,8 @@ pub mod llvm { /** Parses LLVM asm in the given file */ #[fast_ffi] - pub unsafe fn LLVMRustParseAssemblyFile(Filename: *c_char) + pub unsafe fn LLVMRustParseAssemblyFile(Filename: *c_char, + C: ContextRef) -> ModuleRef; #[fast_ffi] @@ -1909,6 +1849,9 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMRustPrintPassTimings(); + #[fast_ffi] + pub unsafe fn LLVMRustStartMultithreading() -> bool; + #[fast_ffi] pub unsafe fn LLVMStructCreateNamed(C: ContextRef, Name: *c_char) -> TypeRef; diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 60725fa6b73..3f6a37bf864 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -29,7 +29,7 @@ use back::link::{mangle_exported_name}; use back::{link, abi, upcall}; use driver::session; use driver::session::Session; -use lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef}; +use lib::llvm::{ContextRef, ModuleRef, ValueRef, TypeRef, BasicBlockRef}; use lib::llvm::{True, False}; use lib::llvm::{llvm, mk_target_data, mk_type_names}; use lib; @@ -73,6 +73,7 @@ use core::libc::c_uint; use core::str; use core::uint; use core::vec; +use core::local_data; use extra::time; use syntax::ast::ident; use syntax::ast_map::{path, path_elt_to_str, path_name}; @@ -1187,7 +1188,7 @@ pub fn new_block(cx: fn_ctxt, parent: Option, kind: block_kind, }; unsafe { let llbb = str::as_c_str(cx.ccx.sess.str_of(s), |buf| { - llvm::LLVMAppendBasicBlock(cx.llfn, buf) + llvm::LLVMAppendBasicBlockInContext(cx.ccx.llcx, cx.llfn, buf) }); let bcx = mk_block(llbb, parent, @@ -1554,11 +1555,12 @@ pub struct BasicBlocks { // Creates the standard set of basic blocks for a function pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks { unsafe { + let cx = task_llcx(); BasicBlocks { sa: str::as_c_str("static_allocas", - |buf| llvm::LLVMAppendBasicBlock(llfn, buf)), + |buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)), rt: str::as_c_str("return", - |buf| llvm::LLVMAppendBasicBlock(llfn, buf)) + |buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)) } } } @@ -2341,7 +2343,7 @@ pub fn create_entry_wrapper(ccx: @CrateContext, }; let llbb = str::as_c_str("top", |buf| { unsafe { - llvm::LLVMAppendBasicBlock(llfn, buf) + llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf) } }); let bld = ccx.builder.B; @@ -2659,10 +2661,10 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<&'static str, ValueRef> { T_void())); let memcpy32 = decl_cdecl_fn(llmod, "llvm.memcpy.p0i8.p0i8.i32", - T_fn(copy T_memcpy32_args, T_void())); + T_fn(T_memcpy32_args, T_void())); let memcpy64 = decl_cdecl_fn(llmod, "llvm.memcpy.p0i8.p0i8.i64", - T_fn(copy T_memcpy64_args, T_void())); + T_fn(T_memcpy64_args, T_void())); let memmove32 = decl_cdecl_fn(llmod, "llvm.memmove.p0i8.p0i8.i32", T_fn(T_memcpy32_args, T_void())); @@ -3038,9 +3040,13 @@ 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"); + } + let llcx = llvm::LLVMContextCreate(); + set_task_llcx(llcx); let llmod = str::as_c_str(llmod_id, |buf| { - llvm::LLVMModuleCreateWithNameInContext - (buf, llvm::LLVMGetGlobalContext()) + llvm::LLVMModuleCreateWithNameInContext(buf, llcx) }); let data_layout: &str = sess.targ_cfg.target_strs.data_layout; let targ_triple: &str = sess.targ_cfg.target_strs.target_triple; @@ -3071,6 +3077,7 @@ pub fn trans_crate(sess: session::Session, let ccx = @CrateContext { sess: sess, llmod: llmod, + llcx: llcx, td: td, tn: tn, externs: @mut HashMap::new(), @@ -3124,7 +3131,9 @@ pub fn trans_crate(sess: session::Session, int_type: int_type, float_type: float_type, opaque_vec_type: T_opaque_vec(targ_cfg), - builder: BuilderRef_res(unsafe { llvm::LLVMCreateBuilder() }), + builder: BuilderRef_res(unsafe { + llvm::LLVMCreateBuilderInContext(llcx) + }), shape_cx: mk_ctxt(llmod), crate_map: crate_map, uses_gc: @mut false, @@ -3172,3 +3181,16 @@ pub fn trans_crate(sess: session::Session, return (llmod, link_meta); } } + +fn task_local_llcx_key(_v: @ContextRef) {} + +pub fn task_llcx() -> ContextRef { + let opt = unsafe { local_data::local_data_get(task_local_llcx_key) }; + *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); + } +} diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index 8ac47ed135a..af108451810 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -564,7 +564,8 @@ pub fn LoadRangeAssert(cx: block, PointerVal: ValueRef, lo: c_ulonglong, do vec::as_imm_buf([min, max]) |ptr, len| { llvm::LLVMSetMetadata(value, lib::llvm::MD_range as c_uint, - llvm::LLVMMDNode(ptr, len as c_uint)); + llvm::LLVMMDNodeInContext(cx.fcx.ccx.llcx, + ptr, len as c_uint)); } } diff --git a/src/librustc/middle/trans/cabi_mips.rs b/src/librustc/middle/trans/cabi_mips.rs index 6be398c0bb2..366c0a90a4c 100644 --- a/src/librustc/middle/trans/cabi_mips.rs +++ b/src/librustc/middle/trans/cabi_mips.rs @@ -19,6 +19,7 @@ use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double}; use lib::llvm::{Struct, Array, Attribute}; use lib::llvm::{StructRetAttribute}; use lib::llvm::True; +use middle::trans::base::task_llcx; use middle::trans::common::*; use middle::trans::cabi::*; @@ -166,7 +167,7 @@ fn coerce_to_int(size: uint) -> ~[TypeRef] { let r = size % 32; if r > 0 { unsafe { - args.push(llvm::LLVMIntType(r as c_uint)) + args.push(llvm::LLVMIntTypeInContext(task_llcx(), r as c_uint)) } } diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index d5d018c0543..4804058609a 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -327,7 +327,9 @@ pub fn load_environment(fcx: fn_ctxt, str::as_c_str("load_env", |buf| unsafe { - llvm::LLVMAppendBasicBlock(fcx.llfn, buf) + llvm::LLVMAppendBasicBlockInContext(fcx.ccx.llcx, + fcx.llfn, + buf) }); fcx.llloadenv = Some(ll); ll diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index a12ce790d04..7e47fc47bff 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -17,7 +17,7 @@ use back::{abi, upcall}; use driver::session; use driver::session::Session; use lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef, BuilderRef}; -use lib::llvm::{True, False, Bool}; +use lib::llvm::{ContextRef, True, False, Bool}; use lib::llvm::{llvm, TargetData, TypeNames, associate_type, name_has_type}; use lib; use metadata::common::LinkMeta; @@ -161,6 +161,7 @@ pub type ExternMap = @mut HashMap<@str, ValueRef>; pub struct CrateContext { sess: session::Session, llmod: ModuleRef, + llcx: ContextRef, td: TargetData, tn: @TypeNames, externs: ExternMap, @@ -798,30 +799,44 @@ impl block_ { // LLVM type constructors. pub fn T_void() -> TypeRef { - unsafe { - return llvm::LLVMVoidType(); - } + unsafe { return llvm::LLVMVoidTypeInContext(base::task_llcx()); } } pub fn T_nil() -> TypeRef { return T_struct([], false) } -pub fn T_metadata() -> TypeRef { unsafe { return llvm::LLVMMetadataType(); } } +pub fn T_metadata() -> TypeRef { + unsafe { return llvm::LLVMMetadataTypeInContext(base::task_llcx()); } +} -pub fn T_i1() -> TypeRef { unsafe { return llvm::LLVMInt1Type(); } } +pub fn T_i1() -> TypeRef { + unsafe { return llvm::LLVMInt1TypeInContext(base::task_llcx()); } +} -pub fn T_i8() -> TypeRef { unsafe { return llvm::LLVMInt8Type(); } } +pub fn T_i8() -> TypeRef { + unsafe { return llvm::LLVMInt8TypeInContext(base::task_llcx()); } +} -pub fn T_i16() -> TypeRef { unsafe { return llvm::LLVMInt16Type(); } } +pub fn T_i16() -> TypeRef { + unsafe { return llvm::LLVMInt16TypeInContext(base::task_llcx()); } +} -pub fn T_i32() -> TypeRef { unsafe { return llvm::LLVMInt32Type(); } } +pub fn T_i32() -> TypeRef { + unsafe { return llvm::LLVMInt32TypeInContext(base::task_llcx()); } +} -pub fn T_i64() -> TypeRef { unsafe { return llvm::LLVMInt64Type(); } } +pub fn T_i64() -> TypeRef { + unsafe { return llvm::LLVMInt64TypeInContext(base::task_llcx()); } +} -pub fn T_f32() -> TypeRef { unsafe { return llvm::LLVMFloatType(); } } +pub fn T_f32() -> TypeRef { + unsafe { return llvm::LLVMFloatTypeInContext(base::task_llcx()); } +} -pub fn T_f64() -> TypeRef { unsafe { return llvm::LLVMDoubleType(); } } +pub fn T_f64() -> TypeRef { + unsafe { return llvm::LLVMDoubleTypeInContext(base::task_llcx()); } +} pub fn T_bool() -> TypeRef { return T_i8(); } @@ -881,8 +896,8 @@ pub fn T_size_t(targ_cfg: @session::config) -> TypeRef { pub fn T_fn(inputs: &[TypeRef], output: TypeRef) -> TypeRef { unsafe { return llvm::LLVMFunctionType(output, to_ptr(inputs), - inputs.len() as c_uint, - False); + inputs.len() as c_uint, + False); } } @@ -904,16 +919,18 @@ pub fn T_root(t: TypeRef, addrspace: addrspace) -> TypeRef { pub fn T_struct(elts: &[TypeRef], packed: bool) -> TypeRef { unsafe { - return llvm::LLVMStructType(to_ptr(elts), - elts.len() as c_uint, - packed as Bool); + return llvm::LLVMStructTypeInContext(base::task_llcx(), + to_ptr(elts), + elts.len() as c_uint, + packed as Bool); } } pub fn T_named_struct(name: &str) -> TypeRef { unsafe { - let c = llvm::LLVMGetGlobalContext(); - return str::as_c_str(name, |buf| llvm::LLVMStructCreateNamed(c, buf)); + return str::as_c_str(name, |buf| { + llvm::LLVMStructCreateNamed(base::task_llcx(), buf) + }); } } @@ -1167,7 +1184,8 @@ pub fn C_cstr(cx: @CrateContext, s: @str) -> ValueRef { } let sc = do str::as_c_str(s) |buf| { - llvm::LLVMConstString(buf, s.len() as c_uint, False) + llvm::LLVMConstStringInContext(cx.llcx, buf, s.len() as c_uint, + False) }; let g = str::as_c_str(fmt!("str%u", (cx.names)("str").name), @@ -1196,7 +1214,8 @@ pub fn C_estr_slice(cx: @CrateContext, s: @str) -> ValueRef { pub fn C_postr(s: &str) -> ValueRef { unsafe { return do str::as_c_str(s) |buf| { - llvm::LLVMConstString(buf, s.len() as c_uint, False) + llvm::LLVMConstStringInContext(base::task_llcx(), + buf, s.len() as c_uint, False) }; } } @@ -1215,7 +1234,8 @@ pub fn C_zero_byte_arr(size: uint) -> ValueRef { pub fn C_struct(elts: &[ValueRef]) -> ValueRef { unsafe { do vec::as_imm_buf(elts) |ptr, len| { - llvm::LLVMConstStruct(ptr, len as c_uint, False) + llvm::LLVMConstStructInContext(base::task_llcx(), + ptr, len as c_uint, False) } } } @@ -1223,7 +1243,8 @@ pub fn C_struct(elts: &[ValueRef]) -> ValueRef { pub fn C_packed_struct(elts: &[ValueRef]) -> ValueRef { unsafe { do vec::as_imm_buf(elts) |ptr, len| { - llvm::LLVMConstStruct(ptr, len as c_uint, True) + llvm::LLVMConstStructInContext(base::task_llcx(), + ptr, len as c_uint, True) } } } @@ -1239,13 +1260,13 @@ pub fn C_named_struct(T: TypeRef, elts: &[ValueRef]) -> ValueRef { pub fn C_array(ty: TypeRef, elts: &[ValueRef]) -> ValueRef { unsafe { return llvm::LLVMConstArray(ty, vec::raw::to_ptr(elts), - elts.len() as c_uint); + elts.len() as c_uint); } } pub fn C_bytes(bytes: &[u8]) -> ValueRef { unsafe { - return llvm::LLVMConstString( + return llvm::LLVMConstStringInContext(base::task_llcx(), cast::transmute(vec::raw::to_ptr(bytes)), bytes.len() as c_uint, True); } @@ -1253,7 +1274,7 @@ pub fn C_bytes(bytes: &[u8]) -> ValueRef { pub fn C_bytes_plus_null(bytes: &[u8]) -> ValueRef { unsafe { - return llvm::LLVMConstString( + return llvm::LLVMConstStringInContext(base::task_llcx(), cast::transmute(vec::raw::to_ptr(bytes)), bytes.len() as c_uint, False); } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 83c1bfdb0dd..3bb9d4abab0 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -13,6 +13,7 @@ use core::prelude::*; use driver::session; use lib::llvm::ValueRef; use lib::llvm::llvm; +use middle::trans::base::task_llcx; use middle::trans::common::*; use middle::trans::machine; use middle::trans::type_of; @@ -61,7 +62,9 @@ static DW_ATE_unsigned_char: int = 0x08; fn llstr(s: &str) -> ValueRef { do str::as_c_str(s) |sbuf| { unsafe { - llvm::LLVMMDString(sbuf, s.len() as libc::c_uint) + llvm::LLVMMDStringInContext(task_llcx(), + sbuf, + s.len() as libc::c_uint) } } } @@ -79,7 +82,9 @@ fn lli1(bval: bool) -> ValueRef { } fn llmdnode(elems: &[ValueRef]) -> ValueRef { unsafe { - llvm::LLVMMDNode(vec::raw::to_ptr(elems), elems.len() as libc::c_uint) + llvm::LLVMMDNodeInContext(task_llcx(), + vec::raw::to_ptr(elems), + elems.len() as libc::c_uint) } } fn llunused() -> ValueRef { diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index e3c424f8e7e..2fff45678bc 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -58,7 +58,7 @@ pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::t], output: ty::t) if output_is_immediate { T_fn(atys, lloutputtype) } else { - T_fn(atys, llvm::LLVMVoidType()) + T_fn(atys, llvm::LLVMVoidTypeInContext(cx.llcx)) } } } diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 90a5a350b7f..1a97c806027 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -648,5 +648,9 @@ mod tests { fn f() {} f() "); + + debug!("regression test for #5803"); + run_cmds(["spawn( || println(\"Please don't segfault\") );", + "do spawn { println(\"Please?\"); }"]); } } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 4ee5df28d24..17eb0f50b9b 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -447,9 +447,10 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, return true; } -extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(const char *Filename) { +extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(LLVMContextRef C, + const char *Filename) { SMDiagnostic d; - Module *m = ParseAssemblyFile(Filename, d, getGlobalContext()); + Module *m = ParseAssemblyFile(Filename, d, *unwrap(C)); if (m) { return wrap(m); } else { @@ -499,9 +500,6 @@ extern "C" LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M, extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) { return wrap(Type::getMetadataTy(*unwrap(C))); } -extern "C" LLVMTypeRef LLVMMetadataType(void) { - return LLVMMetadataTypeInContext(LLVMGetGlobalContext()); -} extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B, LLVMValueRef source, @@ -561,3 +559,24 @@ extern "C" LLVMValueRef LLVMInlineAsm(LLVMTypeRef Ty, Constraints, HasSideEffects, IsAlignStack, (InlineAsm::AsmDialect) Dialect)); } + +/** + * This function is intended to be a threadsafe interface into enabling a + * multithreaded LLVM. This is invoked at the start of the translation phase of + * compilation to ensure that LLVM is ready. + * + * All of trans properly isolates LLVM with the use of a different + * LLVMContextRef per task, thus allowing parallel compilation of different + * crates in the same process. At the time of this writing, the use case for + * this is unit tests for rusti, but there are possible other applications. + */ +extern "C" bool LLVMRustStartMultithreading() { + static Mutex lock; + bool ret = true; + assert(lock.acquire()); + if (!LLVMIsMultithreaded()) { + ret = LLVMStartMultithreaded(); + } + assert(lock.release()); + return ret; +} diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index 8ebdbd0f307..f8c68d798b9 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -10,6 +10,7 @@ LLVMRustExecuteJIT LLVMRustParseBitcode LLVMRustParseAssemblyFile LLVMRustPrintPassTimings +LLVMRustStartMultithreading LLVMCreateObjectFile LLVMDisposeObjectFile LLVMGetSections @@ -319,7 +320,6 @@ LLVMGetFunctionAttr LLVMGetFunctionCallConv LLVMGetGC LLVMGetGlobalContext -LLVMGetGlobalContext LLVMGetGlobalParent LLVMGetGlobalPassRegistry LLVMGetIncomingBlock @@ -500,7 +500,6 @@ LLVMMDNode LLVMMDNodeInContext LLVMMDString LLVMMDStringInContext -LLVMMetadataType LLVMMetadataTypeInContext LLVMModuleCreateWithName LLVMModuleCreateWithNameInContext -- cgit 1.4.1-3-g733a5 From a90fffe3671cb70c37d493efe8cebafab2a4705d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 13 Jun 2013 21:25:18 -0700 Subject: Revert "Revert "Have JIT execution take ownership of the LLVMContextRef"" This reverts commit 19adece68b00bd1873499cca6f1537750608d769. --- src/librustc/back/link.rs | 62 ++++++++++++++++++++++++++------------- src/librustc/driver/driver.rs | 10 +++---- src/librustc/lib/llvm.rs | 14 +++++++-- src/librustc/middle/trans/base.rs | 23 +++++++++------ src/librusti/rusti.rc | 4 --- src/rustllvm/RustWrapper.cpp | 30 ++++++++----------- src/rustllvm/rustllvm.def.in | 4 ++- src/rustllvm/rustllvm.h | 1 + 8 files changed, 88 insertions(+), 60 deletions(-) (limited to 'src/rustllvm/RustWrapper.cpp') diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 3c8705b4ee9..f37ef83e770 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -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 mod jit { pub fn exec(sess: Session, pm: PassManagerRef, + c: ContextRef, m: ModuleRef, opt: c_int, stacks: bool) { @@ -153,26 +154,43 @@ pub mod jit { }); } - // 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); + // 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"); + } - func(); + // 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 mod write { } pub fn run_passes(sess: Session, + llcx: ContextRef, llmod: ModuleRef, output_type: output_type, output: &Path) { @@ -281,7 +301,7 @@ pub mod write { // 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 mod write { // Clean up and return llvm::LLVMDisposeModule(llmod); + llvm::LLVMContextDispose(llcx); if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); } @@ -367,6 +388,7 @@ pub mod write { } llvm::LLVMDisposeModule(llmod); + llvm::LLVMContextDispose(llcx); if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); } } } diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index b72cdd40ecd..0447481596a 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -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 = diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 0e9ea982d9f..b18c9e9b4c2 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -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 mod llvm { 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 mod llvm { 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 mod llvm { /** 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] diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 3f6a37bf864..f2cf35f9fc7 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -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); } diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 1a97c806027..90a5a350b7f 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -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?\"); }"]); } } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 17eb0f50b9b..30e01b53ab7 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -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 diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index f8c68d798b9..f5397165781 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -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 diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h index 1c8842f7b4a..394146eea20 100644 --- a/src/rustllvm/rustllvm.h +++ b/src/rustllvm/rustllvm.h @@ -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() -- cgit 1.4.1-3-g733a5 From dc18321ef589711ee0a0e5adc5b7ed412641e73e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 13 Jun 2013 21:46:59 -0700 Subject: Don't run passes again on JIT code These passes are already run beforehand, no need to do them twice. --- src/librustc/back/link.rs | 52 +++++++++++++++----------------------------- src/librustc/lib/llvm.rs | 2 -- src/rustllvm/RustWrapper.cpp | 14 ------------ 3 files changed, 17 insertions(+), 51 deletions(-) (limited to 'src/rustllvm/RustWrapper.cpp') diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index f37ef83e770..32ad07bde93 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -102,35 +102,21 @@ pub mod jit { use back::link::llvm_err; use driver::session::Session; use lib::llvm::llvm; - use lib::llvm::{ModuleRef, PassManagerRef, ContextRef}; + use lib::llvm::{ModuleRef, ContextRef}; use metadata::cstore; use core::cast; - use core::libc::c_int; use core::ptr; use core::str; - - pub mod rusti { - #[nolink] - #[abi = "rust-intrinsic"] - pub extern "rust-intrinsic" { - pub fn morestack_addr() -> *(); - } - } - - pub struct Closure { - code: *(), - env: *(), - } + use core::sys; + use core::unstable::intrinsics; pub fn exec(sess: Session, - pm: PassManagerRef, c: ContextRef, m: ModuleRef, - opt: c_int, stacks: bool) { unsafe { - let manager = llvm::LLVMRustPrepareJIT(rusti::morestack_addr()); + let manager = llvm::LLVMRustPrepareJIT(intrinsics::morestack_addr()); // We need to tell JIT where to resolve all linked // symbols from. The equivalent of -lstd, -lcore, etc. @@ -156,7 +142,7 @@ pub mod jit { // 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); + let ee = llvm::LLVMRustBuildJIT(manager, m, stacks); if ee.is_null() { llvm::LLVMContextDispose(c); llvm_err(sess, ~"Could not create the JIT"); @@ -179,7 +165,7 @@ pub mod jit { // closure let code = llvm::LLVMGetPointerToGlobal(ee, fun); assert!(!code.is_null()); - let closure = Closure { + let closure = sys::Closure { code: code, env: ptr::null() }; @@ -282,7 +268,17 @@ pub mod write { debug!("Running Module Optimization Pass"); mpm.run(llmod); - if is_object_or_assembly_or_exe(output_type) || opts.jit { + if opts.jit { + // If we are using JIT, go ahead and create and execute the + // engine now. JIT execution takes ownership of the module and + // context, so don't dispose and return. + jit::exec(sess, llcx, llmod, true); + + if sess.time_llvm_passes() { + llvm::LLVMRustPrintPassTimings(); + } + return; + } else if is_object_or_assembly_or_exe(output_type) { let LLVMOptNone = 0 as c_int; // -O0 let LLVMOptLess = 1 as c_int; // -O1 let LLVMOptDefault = 2 as c_int; // -O2, -Os @@ -295,20 +291,6 @@ pub mod write { session::Aggressive => LLVMOptAggressive }; - if opts.jit { - // If we are using JIT, go ahead and create and - // execute the engine now. - // JIT execution takes ownership of the module, - // so don't dispose and return. - - jit::exec(sess, pm.llpm, llcx, llmod, CodeGenOptLevel, true); - - if sess.time_llvm_passes() { - llvm::LLVMRustPrintPassTimings(); - } - return; - } - let FileType; if output_type == output_type_object || output_type == output_type_exe { diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index b18c9e9b4c2..289bb4f63f5 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -1828,9 +1828,7 @@ pub mod llvm { /** Execute the JIT engine. */ #[fast_ffi] pub unsafe fn LLVMRustBuildJIT(MM: *(), - PM: PassManagerRef, M: ModuleRef, - OptLevel: c_int, EnableSegmentedStacks: bool) -> ExecutionEngineRef; /** Parses the bitcode in the given memory buffer. */ diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 30e01b53ab7..ba87624e2dd 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -331,9 +331,7 @@ LLVMRustLoadCrate(void* mem, const char* crate) { extern "C" LLVMExecutionEngineRef LLVMRustBuildJIT(void* mem, - LLVMPassManagerRef PMR, LLVMModuleRef M, - CodeGenOpt::Level OptLevel, bool EnableSegmentedStacks) { InitializeNativeTarget(); @@ -346,25 +344,13 @@ LLVMRustBuildJIT(void* mem, Options.JITEmitDebugInfo = true; Options.NoFramePointerElim = true; Options.EnableSegmentedStacks = EnableSegmentedStacks; - PassManager *PM = unwrap(PMR); RustMCJITMemoryManager* MM = (RustMCJITMemoryManager*) mem; - assert(MM); - PM->add(createBasicAliasAnalysisPass()); - PM->add(createInstructionCombiningPass()); - PM->add(createReassociatePass()); - PM->add(createGVNPass()); - PM->add(createCFGSimplificationPass()); - PM->add(createFunctionInliningPass()); - PM->add(createPromoteMemoryToRegisterPass()); - PM->run(*unwrap(M)); - ExecutionEngine* EE = EngineBuilder(unwrap(M)) .setErrorStr(&Err) .setTargetOptions(Options) .setJITMemoryManager(MM) - .setOptLevel(OptLevel) .setUseMCJIT(true) .setAllocateGVsWithCode(false) .create(); -- cgit 1.4.1-3-g733a5