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:
commit
83d44f87e5
15 changed files with 242 additions and 215 deletions
|
@ -101,34 +101,21 @@ pub mod jit {
|
||||||
use back::link::llvm_err;
|
use back::link::llvm_err;
|
||||||
use driver::session::Session;
|
use driver::session::Session;
|
||||||
use lib::llvm::llvm;
|
use lib::llvm::llvm;
|
||||||
use lib::llvm::{ModuleRef, PassManagerRef};
|
use lib::llvm::{ModuleRef, ContextRef};
|
||||||
use metadata::cstore;
|
use metadata::cstore;
|
||||||
|
|
||||||
use core::cast;
|
use core::cast;
|
||||||
use core::libc::c_int;
|
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
use core::str;
|
use core::str;
|
||||||
|
use core::sys;
|
||||||
pub mod rusti {
|
use core::unstable::intrinsics;
|
||||||
#[nolink]
|
|
||||||
#[abi = "rust-intrinsic"]
|
|
||||||
pub extern "rust-intrinsic" {
|
|
||||||
pub fn morestack_addr() -> *();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Closure {
|
|
||||||
code: *(),
|
|
||||||
env: *(),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn exec(sess: Session,
|
pub fn exec(sess: Session,
|
||||||
pm: PassManagerRef,
|
c: ContextRef,
|
||||||
m: ModuleRef,
|
m: ModuleRef,
|
||||||
opt: c_int,
|
|
||||||
stacks: bool) {
|
stacks: bool) {
|
||||||
unsafe {
|
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
|
// We need to tell JIT where to resolve all linked
|
||||||
// symbols from. The equivalent of -lstd, -lcore, etc.
|
// symbols from. The equivalent of -lstd, -lcore, etc.
|
||||||
|
@ -152,26 +139,43 @@ pub mod jit {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// The execute function will return a void pointer
|
// We custom-build a JIT execution engine via some rust wrappers
|
||||||
// to the _rust_main function. We can do closure
|
// first. This wrappers takes ownership of the module passed in.
|
||||||
// magic here to turn it straight into a callable rust
|
let ee = llvm::LLVMRustBuildJIT(manager, m, stacks);
|
||||||
// closure. It will also cleanup the memory manager
|
if ee.is_null() {
|
||||||
// for us.
|
llvm::LLVMContextDispose(c);
|
||||||
|
llvm_err(sess, ~"Could not create the JIT");
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 = 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 driver::session;
|
||||||
use lib::llvm::llvm;
|
use lib::llvm::llvm;
|
||||||
use lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data};
|
use lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data};
|
||||||
|
use lib::llvm::{ContextRef};
|
||||||
use lib;
|
use lib;
|
||||||
|
|
||||||
use back::passes;
|
use back::passes;
|
||||||
|
@ -206,6 +211,7 @@ pub mod write {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_passes(sess: Session,
|
pub fn run_passes(sess: Session,
|
||||||
|
llcx: ContextRef,
|
||||||
llmod: ModuleRef,
|
llmod: ModuleRef,
|
||||||
output_type: output_type,
|
output_type: output_type,
|
||||||
output: &Path) {
|
output: &Path) {
|
||||||
|
@ -261,7 +267,17 @@ pub mod write {
|
||||||
debug!("Running Module Optimization Pass");
|
debug!("Running Module Optimization Pass");
|
||||||
mpm.run(llmod);
|
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 LLVMOptNone = 0 as c_int; // -O0
|
||||||
let LLVMOptLess = 1 as c_int; // -O1
|
let LLVMOptLess = 1 as c_int; // -O1
|
||||||
let LLVMOptDefault = 2 as c_int; // -O2, -Os
|
let LLVMOptDefault = 2 as c_int; // -O2, -Os
|
||||||
|
@ -274,20 +290,6 @@ pub mod write {
|
||||||
session::Aggressive => LLVMOptAggressive
|
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;
|
let FileType;
|
||||||
if output_type == output_type_object ||
|
if output_type == output_type_object ||
|
||||||
output_type == output_type_exe {
|
output_type == output_type_exe {
|
||||||
|
@ -348,6 +350,7 @@ pub mod write {
|
||||||
// Clean up and return
|
// Clean up and return
|
||||||
|
|
||||||
llvm::LLVMDisposeModule(llmod);
|
llvm::LLVMDisposeModule(llmod);
|
||||||
|
llvm::LLVMContextDispose(llcx);
|
||||||
if sess.time_llvm_passes() {
|
if sess.time_llvm_passes() {
|
||||||
llvm::LLVMRustPrintPassTimings();
|
llvm::LLVMRustPrintPassTimings();
|
||||||
}
|
}
|
||||||
|
@ -366,6 +369,7 @@ pub mod write {
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::LLVMDisposeModule(llmod);
|
llvm::LLVMDisposeModule(llmod);
|
||||||
|
llvm::LLVMContextDispose(llcx);
|
||||||
if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
|
if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,7 +215,7 @@ pub fn compile_rest(sess: Session,
|
||||||
|
|
||||||
let mut crate = crate_opt.unwrap();
|
let mut crate = crate_opt.unwrap();
|
||||||
|
|
||||||
let (llmod, link_meta) = {
|
let (llcx, llmod, link_meta) = {
|
||||||
crate = time(time_passes, ~"intrinsic injection", ||
|
crate = time(time_passes, ~"intrinsic injection", ||
|
||||||
front::intrinsic_inject::inject_intrinsic(sess, crate));
|
front::intrinsic_inject::inject_intrinsic(sess, crate));
|
||||||
|
|
||||||
|
@ -338,14 +338,14 @@ pub fn compile_rest(sess: Session,
|
||||||
let obj_filename = outputs.obj_filename.with_filetype("s");
|
let obj_filename = outputs.obj_filename.with_filetype("s");
|
||||||
|
|
||||||
time(time_passes, ~"LLVM passes", ||
|
time(time_passes, ~"LLVM passes", ||
|
||||||
link::write::run_passes(sess, llmod, output_type,
|
link::write::run_passes(sess, llcx, llmod, output_type,
|
||||||
&obj_filename));
|
&obj_filename));
|
||||||
|
|
||||||
link::write::run_ndk(sess, &obj_filename, &outputs.obj_filename);
|
link::write::run_ndk(sess, &obj_filename, &outputs.obj_filename);
|
||||||
} else {
|
} else {
|
||||||
time(time_passes, ~"LLVM passes", ||
|
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));
|
&outputs.obj_filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
let stop_after_codegen =
|
let stop_after_codegen =
|
||||||
|
|
|
@ -205,6 +205,8 @@ pub enum BasicBlock_opaque {}
|
||||||
pub type BasicBlockRef = *BasicBlock_opaque;
|
pub type BasicBlockRef = *BasicBlock_opaque;
|
||||||
pub enum Builder_opaque {}
|
pub enum Builder_opaque {}
|
||||||
pub type BuilderRef = *Builder_opaque;
|
pub type BuilderRef = *Builder_opaque;
|
||||||
|
pub enum ExecutionEngine_opaque {}
|
||||||
|
pub type ExecutionEngineRef = *ExecutionEngine_opaque;
|
||||||
pub enum MemoryBuffer_opaque {}
|
pub enum MemoryBuffer_opaque {}
|
||||||
pub type MemoryBufferRef = *MemoryBuffer_opaque;
|
pub type MemoryBufferRef = *MemoryBuffer_opaque;
|
||||||
pub enum PassManager_opaque {}
|
pub enum PassManager_opaque {}
|
||||||
|
@ -223,7 +225,7 @@ pub enum Pass_opaque {}
|
||||||
pub type PassRef = *Pass_opaque;
|
pub type PassRef = *Pass_opaque;
|
||||||
|
|
||||||
pub mod llvm {
|
pub mod llvm {
|
||||||
use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef};
|
use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef, ExecutionEngineRef};
|
||||||
use super::{Bool, BuilderRef, ContextRef, MemoryBufferRef, ModuleRef};
|
use super::{Bool, BuilderRef, ContextRef, MemoryBufferRef, ModuleRef};
|
||||||
use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef};
|
use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef};
|
||||||
use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef};
|
use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef};
|
||||||
|
@ -239,16 +241,12 @@ pub mod llvm {
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMContextCreate() -> ContextRef;
|
pub unsafe fn LLVMContextCreate() -> ContextRef;
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMGetGlobalContext() -> ContextRef;
|
|
||||||
#[fast_ffi]
|
|
||||||
pub unsafe fn LLVMContextDispose(C: ContextRef);
|
pub unsafe fn LLVMContextDispose(C: ContextRef);
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMGetMDKindIDInContext(C: ContextRef,
|
pub unsafe fn LLVMGetMDKindIDInContext(C: ContextRef,
|
||||||
Name: *c_char,
|
Name: *c_char,
|
||||||
SLen: c_uint)
|
SLen: c_uint)
|
||||||
-> c_uint;
|
-> c_uint;
|
||||||
#[fast_ffi]
|
|
||||||
pub unsafe fn LLVMGetMDKindID(Name: *c_char, SLen: c_uint) -> c_uint;
|
|
||||||
|
|
||||||
/* Create and destroy modules. */
|
/* Create and destroy modules. */
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
|
@ -256,6 +254,8 @@ pub mod llvm {
|
||||||
C: ContextRef)
|
C: ContextRef)
|
||||||
-> ModuleRef;
|
-> ModuleRef;
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
|
pub unsafe fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef;
|
||||||
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMDisposeModule(M: ModuleRef);
|
pub unsafe fn LLVMDisposeModule(M: ModuleRef);
|
||||||
|
|
||||||
/** Data layout. See Module::getDataLayout. */
|
/** Data layout. See Module::getDataLayout. */
|
||||||
|
@ -300,18 +300,6 @@ pub mod llvm {
|
||||||
pub unsafe fn LLVMIntTypeInContext(C: ContextRef,
|
pub unsafe fn LLVMIntTypeInContext(C: ContextRef,
|
||||||
NumBits: c_uint) -> TypeRef;
|
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]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint;
|
pub unsafe fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint;
|
||||||
|
|
||||||
|
@ -327,17 +315,6 @@ pub mod llvm {
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMPPCFP128TypeInContext(C: ContextRef) -> TypeRef;
|
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 */
|
/* Operations on function types */
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMFunctionType(ReturnType: TypeRef,
|
pub unsafe fn LLVMFunctionType(ReturnType: TypeRef,
|
||||||
|
@ -361,11 +338,6 @@ pub mod llvm {
|
||||||
ElementCount: c_uint,
|
ElementCount: c_uint,
|
||||||
Packed: Bool) -> TypeRef;
|
Packed: Bool) -> TypeRef;
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMStructType(ElementTypes: *TypeRef,
|
|
||||||
ElementCount: c_uint,
|
|
||||||
Packed: Bool)
|
|
||||||
-> TypeRef;
|
|
||||||
#[fast_ffi]
|
|
||||||
pub unsafe fn LLVMCountStructElementTypes(StructTy: TypeRef)
|
pub unsafe fn LLVMCountStructElementTypes(StructTy: TypeRef)
|
||||||
-> c_uint;
|
-> c_uint;
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
|
@ -393,6 +365,10 @@ pub mod llvm {
|
||||||
pub unsafe fn LLVMGetPointerAddressSpace(PointerTy: TypeRef)
|
pub unsafe fn LLVMGetPointerAddressSpace(PointerTy: TypeRef)
|
||||||
-> c_uint;
|
-> c_uint;
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
|
pub unsafe fn LLVMGetPointerToGlobal(EE: ExecutionEngineRef,
|
||||||
|
V: ValueRef)
|
||||||
|
-> *();
|
||||||
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint;
|
pub unsafe fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint;
|
||||||
|
|
||||||
/* Operations on other types */
|
/* Operations on other types */
|
||||||
|
@ -403,13 +379,6 @@ pub mod llvm {
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMMetadataTypeInContext(C: ContextRef) -> TypeRef;
|
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 */
|
/* Operations on all values */
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMTypeOf(Val: ValueRef) -> TypeRef;
|
pub unsafe fn LLVMTypeOf(Val: ValueRef) -> TypeRef;
|
||||||
|
@ -482,15 +451,11 @@ pub mod llvm {
|
||||||
SLen: c_uint)
|
SLen: c_uint)
|
||||||
-> ValueRef;
|
-> ValueRef;
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMMDString(Str: *c_char, SLen: c_uint) -> ValueRef;
|
|
||||||
#[fast_ffi]
|
|
||||||
pub unsafe fn LLVMMDNodeInContext(C: ContextRef,
|
pub unsafe fn LLVMMDNodeInContext(C: ContextRef,
|
||||||
Vals: *ValueRef,
|
Vals: *ValueRef,
|
||||||
Count: c_uint)
|
Count: c_uint)
|
||||||
-> ValueRef;
|
-> ValueRef;
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMMDNode(Vals: *ValueRef, Count: c_uint) -> ValueRef;
|
|
||||||
#[fast_ffi]
|
|
||||||
pub unsafe fn LLVMAddNamedMetadataOperand(M: ModuleRef, Str: *c_char,
|
pub unsafe fn LLVMAddNamedMetadataOperand(M: ModuleRef, Str: *c_char,
|
||||||
Val: ValueRef);
|
Val: ValueRef);
|
||||||
|
|
||||||
|
@ -544,20 +509,11 @@ pub mod llvm {
|
||||||
Packed: Bool) -> ValueRef;
|
Packed: Bool) -> ValueRef;
|
||||||
|
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMConstString(Str: *c_char,
|
|
||||||
Length: c_uint,
|
|
||||||
DontNullTerminate: Bool)
|
|
||||||
-> ValueRef;
|
|
||||||
#[fast_ffi]
|
|
||||||
pub unsafe fn LLVMConstArray(ElementTy: TypeRef,
|
pub unsafe fn LLVMConstArray(ElementTy: TypeRef,
|
||||||
ConstantVals: *ValueRef,
|
ConstantVals: *ValueRef,
|
||||||
Length: c_uint)
|
Length: c_uint)
|
||||||
-> ValueRef;
|
-> ValueRef;
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMConstStruct(ConstantVals: *ValueRef,
|
|
||||||
Count: c_uint,
|
|
||||||
Packed: Bool) -> ValueRef;
|
|
||||||
#[fast_ffi]
|
|
||||||
pub unsafe fn LLVMConstVector(ScalarConstantVals: *ValueRef,
|
pub unsafe fn LLVMConstVector(ScalarConstantVals: *ValueRef,
|
||||||
Size: c_uint) -> ValueRef;
|
Size: c_uint) -> ValueRef;
|
||||||
|
|
||||||
|
@ -970,15 +926,6 @@ pub mod llvm {
|
||||||
BB: BasicBlockRef,
|
BB: BasicBlockRef,
|
||||||
Name: *c_char)
|
Name: *c_char)
|
||||||
-> BasicBlockRef;
|
-> 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]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMDeleteBasicBlock(BB: BasicBlockRef);
|
pub unsafe fn LLVMDeleteBasicBlock(BB: BasicBlockRef);
|
||||||
|
|
||||||
|
@ -1039,8 +986,6 @@ pub mod llvm {
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef;
|
pub unsafe fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef;
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMCreateBuilder() -> BuilderRef;
|
|
||||||
#[fast_ffi]
|
|
||||||
pub unsafe fn LLVMPositionBuilder(Builder: BuilderRef,
|
pub unsafe fn LLVMPositionBuilder(Builder: BuilderRef,
|
||||||
Block: BasicBlockRef,
|
Block: BasicBlockRef,
|
||||||
Instr: ValueRef);
|
Instr: ValueRef);
|
||||||
|
@ -1064,6 +1009,8 @@ pub mod llvm {
|
||||||
Name: *c_char);
|
Name: *c_char);
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMDisposeBuilder(Builder: BuilderRef);
|
pub unsafe fn LLVMDisposeBuilder(Builder: BuilderRef);
|
||||||
|
#[fast_ffi]
|
||||||
|
pub unsafe fn LLVMDisposeExecutionEngine(EE: ExecutionEngineRef);
|
||||||
|
|
||||||
/* Metadata */
|
/* Metadata */
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
|
@ -1880,11 +1827,9 @@ pub mod llvm {
|
||||||
|
|
||||||
/** Execute the JIT engine. */
|
/** Execute the JIT engine. */
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMRustExecuteJIT(MM: *(),
|
pub unsafe fn LLVMRustBuildJIT(MM: *(),
|
||||||
PM: PassManagerRef,
|
|
||||||
M: ModuleRef,
|
M: ModuleRef,
|
||||||
OptLevel: c_int,
|
EnableSegmentedStacks: bool) -> ExecutionEngineRef;
|
||||||
EnableSegmentedStacks: bool) -> *();
|
|
||||||
|
|
||||||
/** Parses the bitcode in the given memory buffer. */
|
/** Parses the bitcode in the given memory buffer. */
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
|
@ -1893,7 +1838,8 @@ pub mod llvm {
|
||||||
|
|
||||||
/** Parses LLVM asm in the given file */
|
/** Parses LLVM asm in the given file */
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMRustParseAssemblyFile(Filename: *c_char)
|
pub unsafe fn LLVMRustParseAssemblyFile(Filename: *c_char,
|
||||||
|
C: ContextRef)
|
||||||
-> ModuleRef;
|
-> ModuleRef;
|
||||||
|
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
|
@ -1909,6 +1855,9 @@ pub mod llvm {
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMRustPrintPassTimings();
|
pub unsafe fn LLVMRustPrintPassTimings();
|
||||||
|
|
||||||
|
#[fast_ffi]
|
||||||
|
pub unsafe fn LLVMRustStartMultithreading() -> bool;
|
||||||
|
|
||||||
#[fast_ffi]
|
#[fast_ffi]
|
||||||
pub unsafe fn LLVMStructCreateNamed(C: ContextRef, Name: *c_char)
|
pub unsafe fn LLVMStructCreateNamed(C: ContextRef, Name: *c_char)
|
||||||
-> TypeRef;
|
-> TypeRef;
|
||||||
|
|
|
@ -29,7 +29,7 @@ use back::link::{mangle_exported_name};
|
||||||
use back::{link, abi, upcall};
|
use back::{link, abi, upcall};
|
||||||
use driver::session;
|
use driver::session;
|
||||||
use driver::session::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::{True, False};
|
||||||
use lib::llvm::{llvm, mk_target_data, mk_type_names};
|
use lib::llvm::{llvm, mk_target_data, mk_type_names};
|
||||||
use lib;
|
use lib;
|
||||||
|
@ -72,6 +72,7 @@ use core::libc::c_uint;
|
||||||
use core::str;
|
use core::str;
|
||||||
use core::uint;
|
use core::uint;
|
||||||
use core::vec;
|
use core::vec;
|
||||||
|
use core::local_data;
|
||||||
use extra::time;
|
use extra::time;
|
||||||
use syntax::ast::ident;
|
use syntax::ast::ident;
|
||||||
use syntax::ast_map::{path, path_elt_to_str, path_name};
|
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 {
|
unsafe {
|
||||||
let llbb = str::as_c_str(cx.ccx.sess.str_of(s), |buf| {
|
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,
|
let bcx = mk_block(llbb,
|
||||||
parent,
|
parent,
|
||||||
|
@ -1553,11 +1554,12 @@ pub struct BasicBlocks {
|
||||||
// Creates the standard set of basic blocks for a function
|
// Creates the standard set of basic blocks for a function
|
||||||
pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks {
|
pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let cx = task_llcx();
|
||||||
BasicBlocks {
|
BasicBlocks {
|
||||||
sa: str::as_c_str("static_allocas",
|
sa: str::as_c_str("static_allocas",
|
||||||
|buf| llvm::LLVMAppendBasicBlock(llfn, buf)),
|
|buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)),
|
||||||
rt: str::as_c_str("return",
|
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| {
|
let llbb = str::as_c_str("top", |buf| {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMAppendBasicBlock(llfn, buf)
|
llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let bld = ccx.builder.B;
|
let bld = ccx.builder.B;
|
||||||
|
@ -2658,10 +2660,10 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<&'static str, ValueRef> {
|
||||||
T_void()));
|
T_void()));
|
||||||
let memcpy32 =
|
let memcpy32 =
|
||||||
decl_cdecl_fn(llmod, "llvm.memcpy.p0i8.p0i8.i32",
|
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 =
|
let memcpy64 =
|
||||||
decl_cdecl_fn(llmod, "llvm.memcpy.p0i8.p0i8.i64",
|
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 =
|
let memmove32 =
|
||||||
decl_cdecl_fn(llmod, "llvm.memmove.p0i8.p0i8.i32",
|
decl_cdecl_fn(llmod, "llvm.memmove.p0i8.p0i8.i32",
|
||||||
T_fn(T_memcpy32_args, T_void()));
|
T_fn(T_memcpy32_args, T_void()));
|
||||||
|
@ -3015,7 +3017,7 @@ pub fn trans_crate(sess: session::Session,
|
||||||
tcx: ty::ctxt,
|
tcx: ty::ctxt,
|
||||||
output: &Path,
|
output: &Path,
|
||||||
emap2: resolve::ExportMap2,
|
emap2: resolve::ExportMap2,
|
||||||
maps: astencode::Maps) -> (ModuleRef, LinkMeta) {
|
maps: astencode::Maps) -> (ContextRef, ModuleRef, LinkMeta) {
|
||||||
|
|
||||||
let symbol_hasher = @mut hash::default_state();
|
let symbol_hasher = @mut hash::default_state();
|
||||||
let link_meta = link::build_link_meta(sess, crate, output, symbol_hasher);
|
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";
|
let llmod_id = link_meta.name.to_owned() + ".rc";
|
||||||
|
|
||||||
unsafe {
|
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| {
|
let llmod = str::as_c_str(llmod_id, |buf| {
|
||||||
llvm::LLVMModuleCreateWithNameInContext
|
llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
|
||||||
(buf, llvm::LLVMGetGlobalContext())
|
|
||||||
});
|
});
|
||||||
let data_layout: &str = sess.targ_cfg.target_strs.data_layout;
|
let data_layout: &str = sess.targ_cfg.target_strs.data_layout;
|
||||||
let targ_triple: &str = sess.targ_cfg.target_strs.target_triple;
|
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 {
|
let ccx = @CrateContext {
|
||||||
sess: sess,
|
sess: sess,
|
||||||
llmod: llmod,
|
llmod: llmod,
|
||||||
|
llcx: llcx,
|
||||||
td: td,
|
td: td,
|
||||||
tn: tn,
|
tn: tn,
|
||||||
externs: @mut HashMap::new(),
|
externs: @mut HashMap::new(),
|
||||||
|
@ -3124,7 +3133,9 @@ pub fn trans_crate(sess: session::Session,
|
||||||
int_type: int_type,
|
int_type: int_type,
|
||||||
float_type: float_type,
|
float_type: float_type,
|
||||||
opaque_vec_type: T_opaque_vec(targ_cfg),
|
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),
|
shape_cx: mk_ctxt(llmod),
|
||||||
crate_map: crate_map,
|
crate_map: crate_map,
|
||||||
uses_gc: @mut false,
|
uses_gc: @mut false,
|
||||||
|
@ -3169,6 +3180,22 @@ pub fn trans_crate(sess: session::Session,
|
||||||
io::println(fmt!("%-7u %s", v, k));
|
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| {
|
do vec::as_imm_buf([min, max]) |ptr, len| {
|
||||||
llvm::LLVMSetMetadata(value, lib::llvm::MD_range as c_uint,
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double};
|
||||||
use lib::llvm::{Struct, Array, Attribute};
|
use lib::llvm::{Struct, Array, Attribute};
|
||||||
use lib::llvm::{StructRetAttribute};
|
use lib::llvm::{StructRetAttribute};
|
||||||
use lib::llvm::True;
|
use lib::llvm::True;
|
||||||
|
use middle::trans::base::task_llcx;
|
||||||
use middle::trans::common::*;
|
use middle::trans::common::*;
|
||||||
use middle::trans::cabi::*;
|
use middle::trans::cabi::*;
|
||||||
|
|
||||||
|
@ -165,7 +166,7 @@ fn coerce_to_int(size: uint) -> ~[TypeRef] {
|
||||||
let r = size % 32;
|
let r = size % 32;
|
||||||
if r > 0 {
|
if r > 0 {
|
||||||
unsafe {
|
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",
|
str::as_c_str("load_env",
|
||||||
|buf|
|
|buf|
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMAppendBasicBlock(fcx.llfn, buf)
|
llvm::LLVMAppendBasicBlockInContext(fcx.ccx.llcx,
|
||||||
|
fcx.llfn,
|
||||||
|
buf)
|
||||||
});
|
});
|
||||||
fcx.llloadenv = Some(ll);
|
fcx.llloadenv = Some(ll);
|
||||||
ll
|
ll
|
||||||
|
|
|
@ -16,7 +16,7 @@ use back::{abi, upcall};
|
||||||
use driver::session;
|
use driver::session;
|
||||||
use driver::session::Session;
|
use driver::session::Session;
|
||||||
use lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef, BuilderRef};
|
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::llvm::{llvm, TargetData, TypeNames, associate_type, name_has_type};
|
||||||
use lib;
|
use lib;
|
||||||
use metadata::common::LinkMeta;
|
use metadata::common::LinkMeta;
|
||||||
|
@ -160,6 +160,7 @@ pub type ExternMap = @mut HashMap<@str, ValueRef>;
|
||||||
pub struct CrateContext {
|
pub struct CrateContext {
|
||||||
sess: session::Session,
|
sess: session::Session,
|
||||||
llmod: ModuleRef,
|
llmod: ModuleRef,
|
||||||
|
llcx: ContextRef,
|
||||||
td: TargetData,
|
td: TargetData,
|
||||||
tn: @TypeNames,
|
tn: @TypeNames,
|
||||||
externs: ExternMap,
|
externs: ExternMap,
|
||||||
|
@ -799,30 +800,44 @@ impl block_ {
|
||||||
|
|
||||||
// LLVM type constructors.
|
// LLVM type constructors.
|
||||||
pub fn T_void() -> TypeRef {
|
pub fn T_void() -> TypeRef {
|
||||||
unsafe {
|
unsafe { return llvm::LLVMVoidTypeInContext(base::task_llcx()); }
|
||||||
return llvm::LLVMVoidType();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_nil() -> TypeRef {
|
pub fn T_nil() -> TypeRef {
|
||||||
return T_struct([], false)
|
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(); }
|
pub fn T_bool() -> TypeRef { return T_i8(); }
|
||||||
|
|
||||||
|
@ -882,8 +897,8 @@ pub fn T_size_t(targ_cfg: @session::config) -> TypeRef {
|
||||||
pub fn T_fn(inputs: &[TypeRef], output: TypeRef) -> TypeRef {
|
pub fn T_fn(inputs: &[TypeRef], output: TypeRef) -> TypeRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
return llvm::LLVMFunctionType(output, to_ptr(inputs),
|
return llvm::LLVMFunctionType(output, to_ptr(inputs),
|
||||||
inputs.len() as c_uint,
|
inputs.len() as c_uint,
|
||||||
False);
|
False);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -905,16 +920,18 @@ pub fn T_root(t: TypeRef, addrspace: addrspace) -> TypeRef {
|
||||||
|
|
||||||
pub fn T_struct(elts: &[TypeRef], packed: bool) -> TypeRef {
|
pub fn T_struct(elts: &[TypeRef], packed: bool) -> TypeRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
return llvm::LLVMStructType(to_ptr(elts),
|
return llvm::LLVMStructTypeInContext(base::task_llcx(),
|
||||||
elts.len() as c_uint,
|
to_ptr(elts),
|
||||||
packed as Bool);
|
elts.len() as c_uint,
|
||||||
|
packed as Bool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_named_struct(name: &str) -> TypeRef {
|
pub fn T_named_struct(name: &str) -> TypeRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
let c = llvm::LLVMGetGlobalContext();
|
return str::as_c_str(name, |buf| {
|
||||||
return str::as_c_str(name, |buf| llvm::LLVMStructCreateNamed(c, 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| {
|
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 =
|
let g =
|
||||||
str::as_c_str(fmt!("str%u", (cx.names)("str").name),
|
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 {
|
pub fn C_postr(s: &str) -> ValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
return do str::as_c_str(s) |buf| {
|
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 {
|
pub fn C_struct(elts: &[ValueRef]) -> ValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
do vec::as_imm_buf(elts) |ptr, len| {
|
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 {
|
pub fn C_packed_struct(elts: &[ValueRef]) -> ValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
do vec::as_imm_buf(elts) |ptr, len| {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1240,13 +1261,13 @@ pub fn C_named_struct(T: TypeRef, elts: &[ValueRef]) -> ValueRef {
|
||||||
pub fn C_array(ty: TypeRef, elts: &[ValueRef]) -> ValueRef {
|
pub fn C_array(ty: TypeRef, elts: &[ValueRef]) -> ValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
return llvm::LLVMConstArray(ty, vec::raw::to_ptr(elts),
|
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 {
|
pub fn C_bytes(bytes: &[u8]) -> ValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
return llvm::LLVMConstString(
|
return llvm::LLVMConstStringInContext(base::task_llcx(),
|
||||||
cast::transmute(vec::raw::to_ptr(bytes)),
|
cast::transmute(vec::raw::to_ptr(bytes)),
|
||||||
bytes.len() as c_uint, True);
|
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 {
|
pub fn C_bytes_plus_null(bytes: &[u8]) -> ValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
return llvm::LLVMConstString(
|
return llvm::LLVMConstStringInContext(base::task_llcx(),
|
||||||
cast::transmute(vec::raw::to_ptr(bytes)),
|
cast::transmute(vec::raw::to_ptr(bytes)),
|
||||||
bytes.len() as c_uint, False);
|
bytes.len() as c_uint, False);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ use core::prelude::*;
|
||||||
use driver::session;
|
use driver::session;
|
||||||
use lib::llvm::ValueRef;
|
use lib::llvm::ValueRef;
|
||||||
use lib::llvm::llvm;
|
use lib::llvm::llvm;
|
||||||
|
use middle::trans::base::task_llcx;
|
||||||
use middle::trans::common::*;
|
use middle::trans::common::*;
|
||||||
use middle::trans::machine;
|
use middle::trans::machine;
|
||||||
use middle::trans::type_of;
|
use middle::trans::type_of;
|
||||||
|
@ -61,7 +62,9 @@ static DW_ATE_unsigned_char: int = 0x08;
|
||||||
fn llstr(s: &str) -> ValueRef {
|
fn llstr(s: &str) -> ValueRef {
|
||||||
do str::as_c_str(s) |sbuf| {
|
do str::as_c_str(s) |sbuf| {
|
||||||
unsafe {
|
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 {
|
fn llmdnode(elems: &[ValueRef]) -> ValueRef {
|
||||||
unsafe {
|
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 {
|
fn llunused() -> ValueRef {
|
||||||
|
|
|
@ -58,7 +58,7 @@ pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::t], output: ty::t)
|
||||||
if output_is_immediate {
|
if output_is_immediate {
|
||||||
T_fn(atys, lloutputtype)
|
T_fn(atys, lloutputtype)
|
||||||
} else {
|
} else {
|
||||||
T_fn(atys, llvm::LLVMVoidType())
|
T_fn(atys, llvm::LLVMVoidTypeInContext(cx.llcx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -421,7 +421,7 @@ pub fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str,
|
||||||
-> Option<Repl> {
|
-> Option<Repl> {
|
||||||
if line.starts_with(":") {
|
if line.starts_with(":") {
|
||||||
// drop the : and the \n (one byte each)
|
// 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 split: ~[~str] = full.word_iter().transform(|s| s.to_owned()).collect();
|
||||||
let len = split.len();
|
let len = split.len();
|
||||||
|
|
||||||
|
@ -538,7 +538,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn run_all() {
|
fn run_all() {
|
||||||
// FIXME(#6511):
|
// FIXME(#7071):
|
||||||
// By default, unit tests are run in parallel. Rusti, on the other hand,
|
// 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
|
// does not enjoy doing this. I suspect that it is because the LLVM
|
||||||
// bindings are not thread-safe (when running parallel tests, some tests
|
// bindings are not thread-safe (when running parallel tests, some tests
|
||||||
|
@ -646,4 +646,14 @@ mod tests {
|
||||||
f()
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,6 +114,17 @@ fn test_sysroot() -> Path {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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() {
|
fn test_make_dir_rwx() {
|
||||||
let temp = &os::tmpdir();
|
let temp = &os::tmpdir();
|
||||||
let dir = temp.push("quux");
|
let dir = temp.push("quux");
|
||||||
|
@ -126,7 +137,6 @@ fn test_make_dir_rwx() {
|
||||||
assert!(os::remove_dir_recursive(&dir));
|
assert!(os::remove_dir_recursive(&dir));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_install_valid() {
|
fn test_install_valid() {
|
||||||
use path_util::installed_library_in_workspace;
|
use path_util::installed_library_in_workspace;
|
||||||
|
|
||||||
|
@ -155,7 +165,6 @@ fn test_install_valid() {
|
||||||
assert!(!os::path_exists(&bench));
|
assert!(!os::path_exists(&bench));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_install_invalid() {
|
fn test_install_invalid() {
|
||||||
use conditions::nonexistent_package::cond;
|
use conditions::nonexistent_package::cond;
|
||||||
use cond1 = conditions::missing_pkg_files::cond;
|
use cond1 = conditions::missing_pkg_files::cond;
|
||||||
|
@ -178,7 +187,6 @@ fn test_install_invalid() {
|
||||||
assert!(error_occurred && error1_occurred);
|
assert!(error_occurred && error1_occurred);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_install_url() {
|
fn test_install_url() {
|
||||||
let workspace = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
|
let workspace = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
|
||||||
let sysroot = test_sysroot();
|
let sysroot = test_sysroot();
|
||||||
|
@ -214,7 +222,6 @@ fn test_install_url() {
|
||||||
assert!(!os::path_exists(&bench));
|
assert!(!os::path_exists(&bench));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_package_ids_must_be_relative_path_like() {
|
fn test_package_ids_must_be_relative_path_like() {
|
||||||
use conditions::bad_pkg_id::cond;
|
use conditions::bad_pkg_id::cond;
|
||||||
|
|
||||||
|
@ -255,7 +262,6 @@ fn test_package_ids_must_be_relative_path_like() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_package_version() {
|
fn test_package_version() {
|
||||||
let temp_pkg_id = PkgId::new("github.com/catamorphism/test_pkg_version");
|
let temp_pkg_id = PkgId::new("github.com/catamorphism/test_pkg_version");
|
||||||
match temp_pkg_id.version {
|
match temp_pkg_id.version {
|
||||||
|
|
|
@ -329,12 +329,10 @@ LLVMRustLoadCrate(void* mem, const char* crate) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void*
|
extern "C" LLVMExecutionEngineRef
|
||||||
LLVMRustExecuteJIT(void* mem,
|
LLVMRustBuildJIT(void* mem,
|
||||||
LLVMPassManagerRef PMR,
|
LLVMModuleRef M,
|
||||||
LLVMModuleRef M,
|
bool EnableSegmentedStacks) {
|
||||||
CodeGenOpt::Level OptLevel,
|
|
||||||
bool EnableSegmentedStacks) {
|
|
||||||
|
|
||||||
InitializeNativeTarget();
|
InitializeNativeTarget();
|
||||||
InitializeNativeTargetAsmPrinter();
|
InitializeNativeTargetAsmPrinter();
|
||||||
|
@ -346,46 +344,28 @@ LLVMRustExecuteJIT(void* mem,
|
||||||
Options.JITEmitDebugInfo = true;
|
Options.JITEmitDebugInfo = true;
|
||||||
Options.NoFramePointerElim = true;
|
Options.NoFramePointerElim = true;
|
||||||
Options.EnableSegmentedStacks = EnableSegmentedStacks;
|
Options.EnableSegmentedStacks = EnableSegmentedStacks;
|
||||||
PassManager *PM = unwrap<PassManager>(PMR);
|
|
||||||
RustMCJITMemoryManager* MM = (RustMCJITMemoryManager*) mem;
|
RustMCJITMemoryManager* MM = (RustMCJITMemoryManager*) mem;
|
||||||
|
|
||||||
assert(MM);
|
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))
|
ExecutionEngine* EE = EngineBuilder(unwrap(M))
|
||||||
.setErrorStr(&Err)
|
.setErrorStr(&Err)
|
||||||
.setTargetOptions(Options)
|
.setTargetOptions(Options)
|
||||||
.setJITMemoryManager(MM)
|
.setJITMemoryManager(MM)
|
||||||
.setOptLevel(OptLevel)
|
|
||||||
.setUseMCJIT(true)
|
.setUseMCJIT(true)
|
||||||
.setAllocateGVsWithCode(false)
|
.setAllocateGVsWithCode(false)
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
if(!EE || Err != "") {
|
if(!EE || Err != "") {
|
||||||
LLVMRustError = Err.c_str();
|
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();
|
MM->invalidateInstructionCache();
|
||||||
Function* func = EE->FindFunctionNamed("_rust_main");
|
return wrap(EE);
|
||||||
|
|
||||||
if(!func || Err != "") {
|
|
||||||
LLVMRustError = Err.c_str();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* entry = EE->getPointerToFunction(func);
|
|
||||||
assert(entry);
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" bool
|
extern "C" bool
|
||||||
|
@ -447,9 +427,10 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(const char *Filename) {
|
extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(LLVMContextRef C,
|
||||||
|
const char *Filename) {
|
||||||
SMDiagnostic d;
|
SMDiagnostic d;
|
||||||
Module *m = ParseAssemblyFile(Filename, d, getGlobalContext());
|
Module *m = ParseAssemblyFile(Filename, d, *unwrap(C));
|
||||||
if (m) {
|
if (m) {
|
||||||
return wrap(m);
|
return wrap(m);
|
||||||
} else {
|
} else {
|
||||||
|
@ -499,9 +480,6 @@ extern "C" LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M,
|
||||||
extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) {
|
extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) {
|
||||||
return wrap(Type::getMetadataTy(*unwrap(C)));
|
return wrap(Type::getMetadataTy(*unwrap(C)));
|
||||||
}
|
}
|
||||||
extern "C" LLVMTypeRef LLVMMetadataType(void) {
|
|
||||||
return LLVMMetadataTypeInContext(LLVMGetGlobalContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B,
|
extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B,
|
||||||
LLVMValueRef source,
|
LLVMValueRef source,
|
||||||
|
@ -561,3 +539,24 @@ extern "C" LLVMValueRef LLVMInlineAsm(LLVMTypeRef Ty,
|
||||||
Constraints, HasSideEffects,
|
Constraints, HasSideEffects,
|
||||||
IsAlignStack, (InlineAsm::AsmDialect) Dialect));
|
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
|
LLVMRustConstInt
|
||||||
LLVMRustLoadCrate
|
LLVMRustLoadCrate
|
||||||
LLVMRustPrepareJIT
|
LLVMRustPrepareJIT
|
||||||
LLVMRustExecuteJIT
|
LLVMRustBuildJIT
|
||||||
LLVMRustParseBitcode
|
LLVMRustParseBitcode
|
||||||
LLVMRustParseAssemblyFile
|
LLVMRustParseAssemblyFile
|
||||||
LLVMRustPrintPassTimings
|
LLVMRustPrintPassTimings
|
||||||
|
LLVMRustStartMultithreading
|
||||||
LLVMCreateObjectFile
|
LLVMCreateObjectFile
|
||||||
LLVMDisposeObjectFile
|
LLVMDisposeObjectFile
|
||||||
|
LLVMDisposeExecutionEngine
|
||||||
LLVMGetSections
|
LLVMGetSections
|
||||||
LLVMDisposeSectionIterator
|
LLVMDisposeSectionIterator
|
||||||
LLVMIsSectionIteratorAtEnd
|
LLVMIsSectionIteratorAtEnd
|
||||||
|
@ -319,7 +321,6 @@ LLVMGetFunctionAttr
|
||||||
LLVMGetFunctionCallConv
|
LLVMGetFunctionCallConv
|
||||||
LLVMGetGC
|
LLVMGetGC
|
||||||
LLVMGetGlobalContext
|
LLVMGetGlobalContext
|
||||||
LLVMGetGlobalContext
|
|
||||||
LLVMGetGlobalParent
|
LLVMGetGlobalParent
|
||||||
LLVMGetGlobalPassRegistry
|
LLVMGetGlobalPassRegistry
|
||||||
LLVMGetIncomingBlock
|
LLVMGetIncomingBlock
|
||||||
|
@ -356,6 +357,7 @@ LLVMGetParamParent
|
||||||
LLVMGetParamTypes
|
LLVMGetParamTypes
|
||||||
LLVMGetParams
|
LLVMGetParams
|
||||||
LLVMGetPointerAddressSpace
|
LLVMGetPointerAddressSpace
|
||||||
|
LLVMGetPointerToGlobal
|
||||||
LLVMGetPreviousBasicBlock
|
LLVMGetPreviousBasicBlock
|
||||||
LLVMGetPreviousFunction
|
LLVMGetPreviousFunction
|
||||||
LLVMGetPreviousGlobal
|
LLVMGetPreviousGlobal
|
||||||
|
@ -500,7 +502,6 @@ LLVMMDNode
|
||||||
LLVMMDNodeInContext
|
LLVMMDNodeInContext
|
||||||
LLVMMDString
|
LLVMMDString
|
||||||
LLVMMDStringInContext
|
LLVMMDStringInContext
|
||||||
LLVMMetadataType
|
|
||||||
LLVMMetadataTypeInContext
|
LLVMMetadataTypeInContext
|
||||||
LLVMModuleCreateWithName
|
LLVMModuleCreateWithName
|
||||||
LLVMModuleCreateWithNameInContext
|
LLVMModuleCreateWithNameInContext
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include "llvm/Transforms/Vectorize.h"
|
#include "llvm/Transforms/Vectorize.h"
|
||||||
#include "llvm-c/Core.h"
|
#include "llvm-c/Core.h"
|
||||||
#include "llvm-c/BitReader.h"
|
#include "llvm-c/BitReader.h"
|
||||||
|
#include "llvm-c/ExecutionEngine.h"
|
||||||
#include "llvm-c/Object.h"
|
#include "llvm-c/Object.h"
|
||||||
|
|
||||||
// Used by RustMCJITMemoryManager::getPointerToNamedFunction()
|
// Used by RustMCJITMemoryManager::getPointerToNamedFunction()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue