auto merge of #7125 : alexcrichton/rust/rusti-issues, r=brson

This un-reverts the reverts of the rusti commits made awhile back. These were reverted for an LLVM failure in rustpkg. I believe that this is not a problem with these commits, but rather that rustc is being used in parallel for rustpkg tests (in-process). This is not working yet (almost! see #7011), so I serialized all the tests to run one after another.

@brson, I'm mainly just guessing as to the cause of the LLVM failures in rustpkg tests. I'm confident that running tests in parallel is more likely to be the problem than those commits I made.

Additionally, this fixes two recently reported issues with rusti.
This commit is contained in:
bors 2013-06-15 01:04:05 -07:00
commit 83d44f87e5
15 changed files with 242 additions and 215 deletions

View File

@ -101,34 +101,21 @@ 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, 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.
@ -152,26 +139,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.
// 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, m, stacks);
if ee.is_null() {
llvm::LLVMContextDispose(c);
llvm_err(sess, ~"Could not create the JIT");
}
let entry = llvm::LLVMRustExecuteJIT(manager,
pm, m, opt, stacks);
// 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");
}
if ptr::is_null(entry) {
llvm_err(sess, ~"Could not JIT");
} else {
let closure = Closure {
code: entry,
// 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 = sys::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);
}
}
}
@ -188,6 +192,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;
@ -206,6 +211,7 @@ pub mod write {
}
pub fn run_passes(sess: Session,
llcx: ContextRef,
llmod: ModuleRef,
output_type: output_type,
output: &Path) {
@ -261,7 +267,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
@ -274,20 +290,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, llmod, CodeGenOptLevel, true);
if sess.time_llvm_passes() {
llvm::LLVMRustPrintPassTimings();
}
return;
}
let FileType;
if output_type == output_type_object ||
output_type == output_type_exe {
@ -348,6 +350,7 @@ pub mod write {
// Clean up and return
llvm::LLVMDisposeModule(llmod);
llvm::LLVMContextDispose(llcx);
if sess.time_llvm_passes() {
llvm::LLVMRustPrintPassTimings();
}
@ -366,6 +369,7 @@ pub mod write {
}
llvm::LLVMDisposeModule(llmod);
llvm::LLVMContextDispose(llcx);
if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
}
}

View File

@ -215,7 +215,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));
@ -338,13 +338,13 @@ 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,
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,
link::write::run_passes(sess, llcx, llmod, sess.opts.output_type,
&outputs.obj_filename));
}

View File

@ -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,9 @@ pub mod llvm {
/** Execute the JIT engine. */
#[fast_ffi]
pub unsafe fn LLVMRustExecuteJIT(MM: *(),
PM: PassManagerRef,
pub unsafe fn LLVMRustBuildJIT(MM: *(),
M: ModuleRef,
OptLevel: c_int,
EnableSegmentedStacks: bool) -> *();
EnableSegmentedStacks: bool) -> ExecutionEngineRef;
/** Parses the bitcode in the given memory buffer. */
#[fast_ffi]
@ -1893,7 +1838,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 +1855,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;

View File

@ -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;
@ -72,6 +72,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,
@ -1553,11 +1554,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))
}
}
}
@ -2340,7 +2342,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;
@ -2658,10 +2660,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()));
@ -3015,7 +3017,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);
@ -3037,9 +3039,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;
@ -3070,6 +3078,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 +3133,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,
@ -3169,6 +3180,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);
}

View File

@ -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));
}
}

View File

@ -18,6 +18,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::*;
@ -165,7 +166,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))
}
}

View File

@ -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

View File

@ -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,
@ -799,30 +800,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(); }
@ -905,7 +920,8 @@ 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),
return llvm::LLVMStructTypeInContext(base::task_llcx(),
to_ptr(elts),
elts.len() as c_uint,
packed as Bool);
}
@ -913,8 +929,9 @@ pub fn T_struct(elts: &[TypeRef], packed: bool) -> TypeRef {
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)
});
}
}
@ -1168,7 +1185,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),
@ -1197,7 +1215,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)
};
}
}
@ -1216,7 +1235,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)
}
}
}
@ -1224,7 +1244,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)
}
}
}
@ -1246,7 +1267,7 @@ pub fn C_array(ty: TypeRef, elts: &[ValueRef]) -> ValueRef {
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);
}
@ -1254,7 +1275,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);
}

View File

@ -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 {

View File

@ -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))
}
}
}

View File

@ -421,7 +421,7 @@ pub fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str,
-> Option<Repl> {
if line.starts_with(":") {
// drop the : and the \n (one byte each)
let full = line.slice(1, line.len() - 1);
let full = line.slice(1, line.len());
let split: ~[~str] = full.word_iter().transform(|s| s.to_owned()).collect();
let len = split.len();
@ -538,7 +538,7 @@ mod tests {
#[test]
fn run_all() {
// FIXME(#6511):
// FIXME(#7071):
// By default, unit tests are run in parallel. Rusti, on the other hand,
// does not enjoy doing this. I suspect that it is because the LLVM
// bindings are not thread-safe (when running parallel tests, some tests
@ -646,4 +646,14 @@ mod tests {
f()
");
}
#[test]
fn exit_quits() {
let mut r = repl();
assert!(r.running);
let result = run_line(&mut r, io::stdin(), io::stdout(),
~":exit", false);
assert!(result.is_none());
assert!(!r.running);
}
}

View File

@ -114,6 +114,17 @@ fn test_sysroot() -> Path {
}
#[test]
fn test_all() {
// FIXME(#7071): these tests use rustc, so they can't be run in parallel
// until this issue is resolved
test_make_dir_rwx();
test_install_valid();
test_install_invalid();
test_install_url();
test_package_ids_must_be_relative_path_like();
test_package_version();
}
fn test_make_dir_rwx() {
let temp = &os::tmpdir();
let dir = temp.push("quux");
@ -126,7 +137,6 @@ fn test_make_dir_rwx() {
assert!(os::remove_dir_recursive(&dir));
}
#[test]
fn test_install_valid() {
use path_util::installed_library_in_workspace;
@ -155,7 +165,6 @@ fn test_install_valid() {
assert!(!os::path_exists(&bench));
}
#[test]
fn test_install_invalid() {
use conditions::nonexistent_package::cond;
use cond1 = conditions::missing_pkg_files::cond;
@ -178,7 +187,6 @@ fn test_install_invalid() {
assert!(error_occurred && error1_occurred);
}
#[test]
fn test_install_url() {
let workspace = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
let sysroot = test_sysroot();
@ -214,7 +222,6 @@ fn test_install_url() {
assert!(!os::path_exists(&bench));
}
#[test]
fn test_package_ids_must_be_relative_path_like() {
use conditions::bad_pkg_id::cond;
@ -255,7 +262,6 @@ fn test_package_ids_must_be_relative_path_like() {
}
#[test]
fn test_package_version() {
let temp_pkg_id = PkgId::new("github.com/catamorphism/test_pkg_version");
match temp_pkg_id.version {

View File

@ -329,11 +329,9 @@ LLVMRustLoadCrate(void* mem, const char* crate) {
return true;
}
extern "C" void*
LLVMRustExecuteJIT(void* mem,
LLVMPassManagerRef PMR,
extern "C" LLVMExecutionEngineRef
LLVMRustBuildJIT(void* mem,
LLVMModuleRef M,
CodeGenOpt::Level OptLevel,
bool EnableSegmentedStacks) {
InitializeNativeTarget();
@ -346,46 +344,28 @@ LLVMRustExecuteJIT(void* mem,
Options.JITEmitDebugInfo = true;
Options.NoFramePointerElim = true;
Options.EnableSegmentedStacks = EnableSegmentedStacks;
PassManager *PM = unwrap<PassManager>(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();
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 +427,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 +480,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 +539,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;
}

View File

@ -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

View File

@ -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()