auto merge of #7040 : alexcrichton/rust/issue-6511-threadsafe-llvm, r=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.
This commit is contained in:
commit
da9172af60
14 changed files with 213 additions and 166 deletions
|
|
@ -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);
|
||||
|
||||
func();
|
||||
// We custom-build a JIT execution engine via some rust wrappers
|
||||
// first. This wrappers takes ownership of the module passed in.
|
||||
let ee = llvm::LLVMRustBuildJIT(manager, pm, m, opt, stacks);
|
||||
if ee.is_null() {
|
||||
llvm::LLVMContextDispose(c);
|
||||
llvm_err(sess, ~"Could not create the JIT");
|
||||
}
|
||||
|
||||
// Next, we need to get a handle on the _rust_main function by
|
||||
// looking up it's corresponding ValueRef and then requesting that
|
||||
// the execution engine compiles the function.
|
||||
let fun = do str::as_c_str("_rust_main") |entry| {
|
||||
llvm::LLVMGetNamedFunction(m, entry)
|
||||
};
|
||||
if fun.is_null() {
|
||||
llvm::LLVMDisposeExecutionEngine(ee);
|
||||
llvm::LLVMContextDispose(c);
|
||||
llvm_err(sess, ~"Could not find _rust_main in the JIT");
|
||||
}
|
||||
|
||||
// Finally, once we have the pointer to the code, we can do some
|
||||
// closure magic here to turn it straight into a callable rust
|
||||
// closure
|
||||
let code = llvm::LLVMGetPointerToGlobal(ee, fun);
|
||||
assert!(!code.is_null());
|
||||
let closure = Closure {
|
||||
code: code,
|
||||
env: ptr::null()
|
||||
};
|
||||
let func: &fn() = cast::transmute(closure);
|
||||
func();
|
||||
|
||||
// Sadly, there currently is no interface to re-use this execution
|
||||
// engine, so it's disposed of here along with the context to
|
||||
// prevent leaks.
|
||||
llvm::LLVMDisposeExecutionEngine(ee);
|
||||
llvm::LLVMContextDispose(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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(); }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
@ -239,16 +241,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 +254,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 +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;
|
||||
|
||||
|
|
@ -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,
|
||||
|
|
@ -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]
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
@ -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]
|
||||
|
|
@ -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]
|
||||
|
|
@ -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]
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
@ -1186,7 +1187,7 @@ pub fn new_block(cx: fn_ctxt, parent: Option<block>, 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,
|
||||
|
|
@ -1560,11 +1561,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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2347,7 +2349,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;
|
||||
|
|
@ -2665,10 +2667,10 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~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()));
|
||||
|
|
@ -3021,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);
|
||||
|
|
@ -3043,9 +3045,15 @@ 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");
|
||||
// }
|
||||
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;
|
||||
|
|
@ -3079,6 +3087,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(),
|
||||
|
|
@ -3133,7 +3142,9 @@ pub fn trans_crate(sess: session::Session,
|
|||
float_type: float_type,
|
||||
task_type: task_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,
|
||||
|
|
@ -3178,6 +3189,22 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
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!")
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -326,7 +326,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
|
||||
|
|
|
|||
|
|
@ -16,7 +16,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;
|
||||
|
|
@ -160,6 +160,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)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1191,7 +1208,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),
|
||||
|
|
@ -1220,7 +1238,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)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1239,7 +1258,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1247,7 +1267,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1263,13 +1284,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);
|
||||
}
|
||||
|
|
@ -1277,7 +1298,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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?\"); }"]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -447,9 +441,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 +494,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 +553,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,14 @@ LLVMRustConstSmallInt
|
|||
LLVMRustConstInt
|
||||
LLVMRustLoadCrate
|
||||
LLVMRustPrepareJIT
|
||||
LLVMRustExecuteJIT
|
||||
LLVMRustBuildJIT
|
||||
LLVMRustParseBitcode
|
||||
LLVMRustParseAssemblyFile
|
||||
LLVMRustPrintPassTimings
|
||||
LLVMRustStartMultithreading
|
||||
LLVMCreateObjectFile
|
||||
LLVMDisposeObjectFile
|
||||
LLVMDisposeExecutionEngine
|
||||
LLVMGetSections
|
||||
LLVMDisposeSectionIterator
|
||||
LLVMIsSectionIteratorAtEnd
|
||||
|
|
@ -319,7 +321,6 @@ LLVMGetFunctionAttr
|
|||
LLVMGetFunctionCallConv
|
||||
LLVMGetGC
|
||||
LLVMGetGlobalContext
|
||||
LLVMGetGlobalContext
|
||||
LLVMGetGlobalParent
|
||||
LLVMGetGlobalPassRegistry
|
||||
LLVMGetIncomingBlock
|
||||
|
|
@ -356,6 +357,7 @@ LLVMGetParamParent
|
|||
LLVMGetParamTypes
|
||||
LLVMGetParams
|
||||
LLVMGetPointerAddressSpace
|
||||
LLVMGetPointerToGlobal
|
||||
LLVMGetPreviousBasicBlock
|
||||
LLVMGetPreviousFunction
|
||||
LLVMGetPreviousGlobal
|
||||
|
|
@ -500,7 +502,6 @@ LLVMMDNode
|
|||
LLVMMDNodeInContext
|
||||
LLVMMDString
|
||||
LLVMMDStringInContext
|
||||
LLVMMetadataType
|
||||
LLVMMetadataTypeInContext
|
||||
LLVMModuleCreateWithName
|
||||
LLVMModuleCreateWithNameInContext
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "llvm/Transforms/Vectorize.h"
|
||||
#include "llvm-c/Core.h"
|
||||
#include "llvm-c/BitReader.h"
|
||||
#include "llvm-c/ExecutionEngine.h"
|
||||
#include "llvm-c/Object.h"
|
||||
|
||||
// Used by RustMCJITMemoryManager::getPointerToNamedFunction()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue