Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare to use LLVM in a threadsafe fashion #6570

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -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));

Expand Down Expand Up @@ -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 =
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