Skip to content

Commit

Permalink
auto merge of #7040 : alexcrichton/rust/issue-6511-threadsafe-llvm, r…
Browse files Browse the repository at this point in the history
…=graydon

This is a reopening of #6570, and almost fixes #6511.

Note that this doesn't actually enable building a threadsafe LLVM, because that will require an LLVM rebuild which will be bundled with the upgrades in #6713.

What this does do, however, is removes all thread-unsafe usage of LLVM from the compiler.
  • Loading branch information
bors committed Jun 11, 2013
2 parents bf41586 + 5c5095d commit 443a48e
Show file tree
Hide file tree
Showing 14 changed files with 212 additions and 165 deletions.
62 changes: 42 additions & 20 deletions src/librustc/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -126,6 +126,7 @@ pub mod jit {

pub fn exec(sess: Session,
pm: PassManagerRef,
c: ContextRef,
m: ModuleRef,
opt: c_int,
stacks: bool) {
Expand Down Expand Up @@ -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);
}
}
}
Expand All @@ -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;
Expand All @@ -208,6 +227,7 @@ pub mod write {
}

pub fn run_passes(sess: Session,
llcx: ContextRef,
llmod: ModuleRef,
output_type: output_type,
output: &Path) {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -350,6 +370,7 @@ pub mod write {
// Clean up and return

llvm::LLVMDisposeModule(llmod);
llvm::LLVMContextDispose(llcx);
if sess.time_llvm_passes() {
llvm::LLVMRustPrintPassTimings();
}
Expand All @@ -368,6 +389,7 @@ pub mod write {
}

llvm::LLVMDisposeModule(llmod);
llvm::LLVMContextDispose(llcx);
if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down Expand Up @@ -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 =
Expand Down
85 changes: 18 additions & 67 deletions src/librustc/lib/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand All @@ -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};
Expand All @@ -239,23 +241,21 @@ 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]
pub unsafe fn LLVMModuleCreateWithNameInContext(ModuleID: *c_char,
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. */
Expand Down Expand Up @@ -300,18 +300,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;

Expand All @@ -327,17 +315,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,
Expand All @@ -361,11 +338,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]
Expand Down Expand Up @@ -393,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 */
Expand All @@ -403,13 +379,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;
Expand Down Expand Up @@ -482,15 +451,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);

Expand Down Expand Up @@ -544,20 +509,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;

Expand Down Expand Up @@ -970,15 +926,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);

Expand Down Expand Up @@ -1039,8 +986,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);
Expand All @@ -1064,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]
Expand Down Expand Up @@ -1880,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]
Expand All @@ -1893,7 +1840,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]
Expand All @@ -1909,6 +1857,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;
Expand Down
Loading

0 comments on commit 443a48e

Please sign in to comment.