提交 f9d4149c 编写于 作者: A Alex Crichton

rustc: Update LLVM

This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:

* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
  significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
  ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
  `PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
  `no-frame-pointer-elim` function attribute instead.

Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
上级 71a8d313
......@@ -976,6 +976,9 @@ pub fn LLVMGetOrInsertFunction(M: ModuleRef,
pub fn LLVMAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: uint64_t);
pub fn LLVMAddFunctionAttribute(Fn: ValueRef, index: c_uint, PA: uint64_t);
pub fn LLVMAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
pub fn LLVMAddFunctionAttrStringValue(Fn: ValueRef, index: c_uint,
Name: *const c_char,
Value: *const c_char);
pub fn LLVMRemoveFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_ulonglong;
pub fn LLVMRemoveFunctionAttr(Fn: ValueRef, val: c_ulonglong);
......@@ -1920,6 +1923,7 @@ pub fn LLVMDIBuilderInsertDeclareAtEnd(Builder: DIBuilderRef,
VarInfo: DIVariable,
AddrOps: *const i64,
AddrOpsCount: c_uint,
DL: ValueRef,
InsertAtEnd: BasicBlockRef)
-> ValueRef;
......@@ -1928,6 +1932,7 @@ pub fn LLVMDIBuilderInsertDeclareBefore(Builder: DIBuilderRef,
VarInfo: DIVariable,
AddrOps: *const i64,
AddrOpsCount: c_uint,
DL: ValueRef,
InsertBefore: ValueRef)
-> ValueRef;
......@@ -2035,7 +2040,6 @@ pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
Level: CodeGenOptLevel,
EnableSegstk: bool,
UseSoftFP: bool,
NoFramePointerElim: bool,
PositionIndependentExecutable: bool,
FunctionSections: bool,
DataSections: bool) -> TargetMachineRef;
......@@ -2046,6 +2050,11 @@ pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef,
pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef,
M: ModuleRef,
DisableSimplifyLibCalls: bool);
pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef,
OptLevel: CodeGenOptLevel,
MergeFunctions: bool,
SLPVectorize: bool,
LoopVectorize: bool);
pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef,
DisableSimplifyLibCalls: bool);
pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef);
......@@ -2116,6 +2125,12 @@ pub fn LLVMSetInlineAsmDiagnosticHandler(C: ContextRef,
pub fn LLVMWriteSMDiagnosticToString(d: SMDiagnosticRef, s: RustStringRef);
}
// LLVM requires symbols from this library, but apparently they're not printed
// during llvm-config?
#[cfg(windows)]
#[link(name = "ole32")]
extern {}
pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {
unsafe {
LLVMSetInstructionCallConv(instr, cc as c_uint);
......
......@@ -10,7 +10,7 @@
use back::lto;
use back::link::{get_cc_prog, remove};
use session::config::{OutputFilenames, NoDebugInfo, Passes, SomePasses, AllPasses};
use session::config::{OutputFilenames, Passes, SomePasses, AllPasses};
use session::Session;
use session::config;
use llvm;
......@@ -188,10 +188,6 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
let opt_level = get_llvm_opt_level(sess.opts.optimize);
let use_softfp = sess.opts.cg.soft_float;
// FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter.
let no_fp_elim = (sess.opts.debuginfo != NoDebugInfo) ||
!sess.target.target.options.eliminate_frame_pointer;
let any_library = sess.crate_types.borrow().iter().any(|ty| {
*ty != config::CrateTypeExecutable
});
......@@ -237,7 +233,6 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
opt_level,
true /* EnableSegstk */,
use_softfp,
no_fp_elim,
!any_library && reloc_model == llvm::RelocPIC,
ffunction_sections,
fdata_sections,
......@@ -279,6 +274,9 @@ struct ModuleConfig {
no_prepopulate_passes: bool,
no_builtins: bool,
time_passes: bool,
vectorize_loop: bool,
vectorize_slp: bool,
merge_functions: bool,
}
unsafe impl Send for ModuleConfig { }
......@@ -301,6 +299,9 @@ fn new(tm: TargetMachineRef, passes: Vec<String>) -> ModuleConfig {
no_prepopulate_passes: false,
no_builtins: false,
time_passes: false,
vectorize_loop: false,
vectorize_slp: false,
merge_functions: false,
}
}
......@@ -309,6 +310,18 @@ fn set_flags(&mut self, sess: &Session, trans: &CrateTranslation) {
self.no_prepopulate_passes = sess.opts.cg.no_prepopulate_passes;
self.no_builtins = trans.no_builtins;
self.time_passes = sess.time_passes();
// Copy what clang does by turning on loop vectorization at O2 and
// slp vectorization at O3. Otherwise configure other optimization aspects
// of this pass manager builder.
self.vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
(sess.opts.optimize == config::Default ||
sess.opts.optimize == config::Aggressive);
self.vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
sess.opts.optimize == config::Aggressive;
self.merge_functions = sess.opts.optimize == config::Default ||
sess.opts.optimize == config::Aggressive;
}
}
......@@ -448,27 +461,26 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
let pass = CString::new(pass).unwrap();
llvm::LLVMRustAddPass(fpm, pass.as_ptr())
};
if !config.no_verify { assert!(addpass("verify")); }
if !config.no_verify { assert!(addpass("verify")); }
if !config.no_prepopulate_passes {
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
populate_llvm_passes(fpm, mpm, llmod, opt_level,
config.no_builtins);
populate_llvm_passes(fpm, mpm, llmod, opt_level, &config);
}
for pass in &config.passes {
let pass = CString::new(pass.clone()).unwrap();
if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
cgcx.handler.warn(&format!("unknown pass {:?}, ignoring", pass));
if !addpass(pass) {
cgcx.handler.warn(&format!("unknown pass `{}`, ignoring",
pass));
}
}
for pass in &cgcx.plugin_passes {
let pass = CString::new(pass.clone()).unwrap();
if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
cgcx.handler.err(&format!("a plugin asked for LLVM pass {:?} but LLVM \
does not recognize it", pass));
if !addpass(pass) {
cgcx.handler.err(&format!("a plugin asked for LLVM pass \
`{}` but LLVM does not \
recognize it", pass));
}
}
......@@ -520,7 +532,6 @@ unsafe fn with_codegen<F>(tm: TargetMachineRef,
llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
f(cpm);
llvm::LLVMDisposePassManager(cpm);
}
if config.emit_bc {
......@@ -537,13 +548,15 @@ unsafe fn with_codegen<F>(tm: TargetMachineRef,
let out = path2cstr(&out);
with_codegen(tm, llmod, config.no_builtins, |cpm| {
llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
llvm::LLVMDisposePassManager(cpm);
})
}
if config.emit_asm {
let path = output_names.with_extension(&format!("{}.s", name_extra));
with_codegen(tm, llmod, config.no_builtins, |cpm| {
write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::AssemblyFileType);
write_output_file(cgcx.handler, tm, cpm, llmod, &path,
llvm::AssemblyFileType);
});
}
......@@ -1008,16 +1021,9 @@ unsafe fn configure_llvm(sess: &Session) {
use std::sync::Once;
static INIT: Once = Once::new();
// Copy what clang does by turning on loop vectorization at O2 and
// slp vectorization at O3
let vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
(sess.opts.optimize == config::Default ||
sess.opts.optimize == config::Aggressive);
let vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
sess.opts.optimize == config::Aggressive;
let mut llvm_c_strs = Vec::new();
let mut llvm_args = Vec::new();
{
let mut add = |arg: &str| {
let s = CString::new(arg).unwrap();
......@@ -1025,8 +1031,6 @@ unsafe fn configure_llvm(sess: &Session) {
llvm_c_strs.push(s);
};
add("rustc"); // fake program name
if vectorize_loop { add("-vectorize-loops"); }
if vectorize_slp { add("-vectorize-slp"); }
if sess.time_llvm_passes() { add("-time-passes"); }
if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
......@@ -1084,41 +1088,40 @@ unsafe fn populate_llvm_passes(fpm: llvm::PassManagerRef,
mpm: llvm::PassManagerRef,
llmod: ModuleRef,
opt: llvm::CodeGenOptLevel,
no_builtins: bool) {
config: &ModuleConfig) {
// Create the PassManagerBuilder for LLVM. We configure it with
// reasonable defaults and prepare it to actually populate the pass
// manager.
let builder = llvm::LLVMPassManagerBuilderCreate();
llvm::LLVMRustConfigurePassManagerBuilder(builder, opt,
config.merge_functions,
config.vectorize_slp,
config.vectorize_loop);
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins);
// Here we match what clang does (kinda). For O0 we only inline
// always-inline functions (but don't add lifetime intrinsics), at O1 we
// inline with lifetime intrinsics, and O2+ we add an inliner with a
// thresholds copied from clang.
match opt {
llvm::CodeGenLevelNone => {
// Don't add lifetime intrinsics at O0
llvm::LLVMRustAddAlwaysInlinePass(builder, false);
}
llvm::CodeGenLevelLess => {
llvm::LLVMRustAddAlwaysInlinePass(builder, true);
}
// numeric values copied from clang
llvm::CodeGenLevelDefault => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
225);
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
}
llvm::CodeGenLevelAggressive => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
275);
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
}
}
llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt as c_uint);
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, no_builtins);
// Use the builder to populate the function/module pass managers.
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm);
llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm);
llvm::LLVMPassManagerBuilderDispose(builder);
match opt {
llvm::CodeGenLevelDefault | llvm::CodeGenLevelAggressive => {
llvm::LLVMRustAddPass(mpm, "mergefunc\0".as_ptr() as *const _);
}
_ => {}
};
}
......@@ -1029,11 +1029,26 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
}
General(ity, ref cases, _) => {
let ccx = bcx.ccx();
let unr_cx = fcx.new_temp_block("enum-variant-iter-unr");
Unreachable(unr_cx);
// See the comments in trans/base.rs for more information (inside
// iter_structural_ty), but the gist here is that if the enum's
// discriminant is *not* in the range that we're expecting (in which
// case we'll take the fall-through branch on the switch
// instruction) then we can't just optimize this to an Unreachable
// block.
//
// Currently we still have filling drop, so this means that the drop
// glue for enums may be called when the enum has been paved over
// with the "I've been dropped" value. In this case the default
// branch of the switch instruction will actually be taken at
// runtime, so the basic block isn't actually unreachable, so we
// need to make it do something with defined behavior. In this case
// we just return early from the function.
let ret_void_cx = fcx.new_temp_block("enum-variant-iter-ret-void");
RetVoid(ret_void_cx, DebugLoc::None);
let discr_val = trans_get_discr(bcx, r, value, None);
let llswitch = Switch(bcx, discr_val, unr_cx.llbb, cases.len());
let llswitch = Switch(bcx, discr_val, ret_void_cx.llbb, cases.len());
let bcx_next = fcx.new_temp_block("enum-variant-iter-next");
for (discr, case) in cases.iter().enumerate() {
......
......@@ -12,6 +12,7 @@
use libc::{c_uint, c_ulonglong};
use llvm::{self, ValueRef, AttrHelper};
use middle::ty::{self, ClosureTyper};
use session::config::NoDebugInfo;
use syntax::abi;
use syntax::ast;
pub use syntax::attr::InlineAttr;
......@@ -106,6 +107,20 @@ pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRe
use syntax::attr::*;
inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), attrs));
// FIXME: #11906: Omitting frame pointers breaks retrieving the value of a
// parameter.
let no_fp_elim = (ccx.sess().opts.debuginfo != NoDebugInfo) ||
!ccx.sess().target.target.options.eliminate_frame_pointer;
if no_fp_elim {
unsafe {
let attr = "no-frame-pointer-elim\0".as_ptr() as *const _;
let val = "true\0".as_ptr() as *const _;
llvm::LLVMAddFunctionAttrStringValue(llfn,
llvm::FunctionIndex as c_uint,
attr, val);
}
}
for attr in attrs {
if attr.check_name("no_stack_check") {
split_stack(llfn, false);
......
......@@ -480,9 +480,23 @@ fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
}
(_match::Switch, Some(lldiscrim_a)) => {
cx = f(cx, lldiscrim_a, cx.tcx().types.isize);
let unr_cx = fcx.new_temp_block("enum-iter-unr");
Unreachable(unr_cx);
let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb,
// Create a fall-through basic block for the "else" case of
// the switch instruction we're about to generate. Note that
// we do **not** use an Unreachable instruction here, even
// though most of the time this basic block will never be hit.
//
// When an enum is dropped it's contents are currently
// overwritten to DTOR_DONE, which means the discriminant
// could have changed value to something not within the actual
// range of the discriminant. Currently this function is only
// used for drop glue so in this case we just return quickly
// from the outer function, and any other use case will only
// call this for an already-valid enum in which case the `ret
// void` will never be hit.
let ret_void_cx = fcx.new_temp_block("enum-iter-ret-void");
RetVoid(ret_void_cx, DebugLoc::None);
let llswitch = Switch(cx, lldiscrim_a, ret_void_cx.llbb,
n_variants);
let next_cx = fcx.new_temp_block("enum-iter-next");
......
......@@ -1673,7 +1673,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
DIB(cx),
containing_scope,
enum_name.as_ptr(),
UNKNOWN_FILE_METADATA,
file_metadata,
UNKNOWN_LINE_NUMBER,
bytes_to_bits(enum_type_size),
bytes_to_bits(enum_type_align),
......
......@@ -484,10 +484,10 @@ fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let param_metadata = unsafe {
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
DIB(cx),
file_metadata,
ptr::null_mut(),
name.as_ptr(),
actual_self_type_metadata,
ptr::null_mut(),
file_metadata,
0,
0)
};
......@@ -518,10 +518,10 @@ fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let param_metadata = unsafe {
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
DIB(cx),
file_metadata,
ptr::null_mut(),
name.as_ptr(),
actual_type_metadata,
ptr::null_mut(),
file_metadata,
0,
0)
};
......@@ -580,12 +580,14 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
loc.line,
loc.col.to_usize()));
unsafe {
let debug_loc = llvm::LLVMGetCurrentDebugLocation(cx.raw_builder());
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
DIB(cx),
alloca,
metadata,
address_operations.as_ptr(),
address_operations.len() as c_uint,
debug_loc,
bcx.llbb);
llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
......
Subproject commit bff69076975642c64e76dbeaa53476bfa7212086
Subproject commit 8cbcdf1b72e1b23679646f6faca265f76b20d379
......@@ -103,9 +103,6 @@ extern "C" LLVMExecutionEngineRef LLVMBuildExecutionEngine(LLVMModuleRef mod)
std::string error_str;
TargetOptions options;
options.JITEmitDebugInfo = true;
options.NoFramePointerElim = true;
RustJITMemoryManager *mm = new RustJITMemoryManager;
ExecutionEngine *ee =
......
......@@ -15,12 +15,19 @@
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#if LLVM_VERSION_MINOR >= 7
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#else
#include "llvm/Target/TargetLibraryInfo.h"
#endif
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm-c/Transforms/PassManagerBuilder.h"
using namespace llvm;
using namespace llvm::legacy;
extern cl::opt<bool> EnableARMEHABI;
......@@ -71,7 +78,6 @@ LLVMRustCreateTargetMachine(const char *triple,
CodeGenOpt::Level OptLevel,
bool EnableSegmentedStacks,
bool UseSoftFloat,
bool NoFramePointerElim,
bool PositionIndependentExecutable,
bool FunctionSections,
bool DataSections) {
......@@ -91,12 +97,12 @@ LLVMRustCreateTargetMachine(const char *triple,
TargetOptions Options;
Options.PositionIndependentExecutable = PositionIndependentExecutable;
Options.NoFramePointerElim = NoFramePointerElim;
Options.FloatABIType = FloatABI::Default;
Options.UseSoftFloat = UseSoftFloat;
if (UseSoftFloat) {
Options.FloatABIType = FloatABI::Soft;
}
Options.DataSections = DataSections;
Options.FunctionSections = FunctionSections;
TargetMachine *TM = TheTarget->createTargetMachine(Trip.getTriple(),
real_cpu,
......@@ -105,8 +111,6 @@ LLVMRustCreateTargetMachine(const char *triple,
RM,
CM,
OptLevel);
TM->setDataSections(DataSections);
TM->setFunctionSections(FunctionSections);
return wrap(TM);
}
......@@ -123,12 +127,32 @@ LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
LLVMPassManagerRef PMR,
LLVMModuleRef M) {
PassManagerBase *PM = unwrap(PMR);
#if LLVM_VERSION_MINOR >= 6
#if LLVM_VERSION_MINOR >= 7
PM->add(createTargetTransformInfoWrapperPass(
unwrap(TM)->getTargetIRAnalysis()));
#else
#if LLVM_VERSION_MINOR == 6
PM->add(new DataLayoutPass());
#else
PM->add(new DataLayoutPass(unwrap(M)));
#endif
unwrap(TM)->addAnalysisPasses(*PM);
#endif
}
extern "C" void
LLVMRustConfigurePassManagerBuilder(LLVMPassManagerBuilderRef PMB,
CodeGenOpt::Level OptLevel,
bool MergeFunctions,
bool SLPVectorize,
bool LoopVectorize) {
#if LLVM_VERSION_MINOR >= 6
// Ignore mergefunc for now as enabling it causes crashes.
//unwrap(PMB)->MergeFunctions = MergeFunctions;
#endif
unwrap(PMB)->SLPVectorize = SLPVectorize;
unwrap(PMB)->OptLevel = OptLevel;
unwrap(PMB)->LoopVectorize = LoopVectorize;
}
// Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
......@@ -138,7 +162,11 @@ LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMB,
LLVMModuleRef M,
bool DisableSimplifyLibCalls) {
Triple TargetTriple(unwrap(M)->getTargetTriple());
#if LLVM_VERSION_MINOR >= 7
TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
#else
TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple);
#endif
if (DisableSimplifyLibCalls)
TLI->disableAllFunctions();
unwrap(PMB)->LibraryInfo = TLI;
......@@ -151,10 +179,17 @@ LLVMRustAddLibraryInfo(LLVMPassManagerRef PMB,
LLVMModuleRef M,
bool DisableSimplifyLibCalls) {
Triple TargetTriple(unwrap(M)->getTargetTriple());
#if LLVM_VERSION_MINOR >= 7
TargetLibraryInfoImpl TLII(TargetTriple);
if (DisableSimplifyLibCalls)
TLII.disableAllFunctions();
unwrap(PMB)->add(new TargetLibraryInfoWrapperPass(TLII));
#else
TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple);
if (DisableSimplifyLibCalls)
TLI->disableAllFunctions();
unwrap(PMB)->add(TLI);
#endif
}
// Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
......@@ -204,10 +239,19 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
LLVMRustSetLastError(ErrorInfo.c_str());
return false;
}
formatted_raw_ostream FOS(OS);
#if LLVM_VERSION_MINOR >= 7
unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
#else
formatted_raw_ostream FOS(OS);
unwrap(Target)->addPassesToEmitFile(*PM, FOS, FileType, false);
#endif
PM->run(*unwrap(M));
// Apparently `addPassesToEmitFile` adds an pointer to our on-the-stack output
// stream (OS), so the only real safe place to delete this is here? Don't we
// wish this was written in Rust?
delete PM;
return true;
}
......
......@@ -141,6 +141,15 @@ extern "C" void LLVMAddFunctionAttrString(LLVMValueRef Fn, unsigned index, const
F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
}
extern "C" void LLVMAddFunctionAttrStringValue(LLVMValueRef Fn, unsigned index,
const char *Name,
const char *Value) {
Function *F = unwrap<Function>(Fn);
AttrBuilder B;
B.addAttribute(Name, Value);
F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
}
extern "C" void LLVMRemoveFunctionAttrString(LLVMValueRef fn, unsigned index, const char *Name) {
Function *f = unwrap<Function>(fn);
LLVMContext &C = f->getContext();
......@@ -228,10 +237,25 @@ inline Metadata **unwrap(LLVMMetadataRef *Vals) {
typedef LLVMValueRef LLVMMetadataRef;
#endif
template<typename DIT>
DIT* unwrapDIptr(LLVMMetadataRef ref) {
return (DIT*) (ref ? unwrap<MDNode>(ref) : NULL);
}
#if LLVM_VERSION_MINOR <= 6
template<typename DIT>
DIT unwrapDI(LLVMMetadataRef ref) {
return DIT(ref ? unwrap<MDNode>(ref) : NULL);
}
#else
#define DIDescriptor DIScope
#define DIArray DINodeArray
#define unwrapDI unwrapDIptr
#endif
#if LLVM_VERSION_MINOR <= 5
#define DISubroutineType DICompositeType
#endif
extern "C" uint32_t LLVMRustDebugMetadataVersion() {
return DEBUG_METADATA_VERSION;
......@@ -296,7 +320,9 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateSubroutineType(
LLVMMetadataRef ParameterTypes) {
return wrap(Builder->createSubroutineType(
unwrapDI<DIFile>(File),
#if LLVM_VERSION_MINOR >= 6
#if LLVM_VERSION_MINOR >= 7
DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
#elif LLVM_VERSION_MINOR >= 6
unwrapDI<DITypeArray>(ParameterTypes)));
#else
unwrapDI<DIArray>(ParameterTypes)));
......@@ -322,11 +348,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction(
return wrap(Builder->createFunction(
unwrapDI<DIScope>(Scope), Name, LinkageName,
unwrapDI<DIFile>(File), LineNo,
unwrapDI<DICompositeType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
unwrapDI<DISubroutineType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
Flags, isOptimized,
unwrap<Function>(Fn),
unwrapDI<MDNode*>(TParam),
unwrapDI<MDNode*>(Decl)));
unwrapDIptr<MDNode>(TParam),
unwrapDIptr<MDNode>(Decl)));
}
extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType(
......@@ -373,7 +399,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateStructType(
AlignInBits,
Flags,
unwrapDI<DIType>(DerivedFrom),
#if LLVM_VERSION_MINOR >= 7
DINodeArray(unwrapDI<MDTuple>(Elements)),
#else
unwrapDI<DIArray>(Elements),
#endif
RunTimeLang,
unwrapDI<DIType>(VTableHolder),
UniqueId
......@@ -436,7 +466,7 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateStaticVariable(
unwrapDI<DIType>(Ty),
isLocalToUnit,
cast<Constant>(unwrap(Val)),
unwrapDI<MDNode*>(Decl)));
unwrapDIptr<MDNode>(Decl)));
}
extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable(
......@@ -486,7 +516,12 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateArrayType(
LLVMMetadataRef Subscripts) {
return wrap(Builder->createArrayType(Size, AlignInBits,
unwrapDI<DIType>(Ty),
unwrapDI<DIArray>(Subscripts)));
#if LLVM_VERSION_MINOR >= 7
DINodeArray(unwrapDI<MDTuple>(Subscripts))
#else
unwrapDI<DIArray>(Subscripts)
#endif
));
}
extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType(
......@@ -497,7 +532,12 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType(
LLVMMetadataRef Subscripts) {
return wrap(Builder->createVectorType(Size, AlignInBits,
unwrapDI<DIType>(Ty),
unwrapDI<DIArray>(Subscripts)));
#if LLVM_VERSION_MINOR >= 7
DINodeArray(unwrapDI<MDTuple>(Subscripts))
#else
unwrapDI<DIArray>(Subscripts)
#endif
));
}
extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(
......@@ -511,12 +551,18 @@ extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(
DIBuilderRef Builder,
LLVMMetadataRef* Ptr,
unsigned Count) {
#if LLVM_VERSION_MINOR >= 7
Metadata **DataValue = unwrap(Ptr);
return wrap(Builder->getOrCreateArray(
ArrayRef<Metadata*>(DataValue, Count)).get());
#else
return wrap(Builder->getOrCreateArray(
#if LLVM_VERSION_MINOR >= 6
ArrayRef<Metadata*>(unwrap(Ptr), Count)));
#else
ArrayRef<Value*>(reinterpret_cast<Value**>(Ptr), Count)));
#endif
#endif
}
extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
......@@ -525,21 +571,21 @@ extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
LLVMMetadataRef VarInfo,
int64_t* AddrOps,
unsigned AddrOpsCount,
LLVMValueRef DL,
LLVMBasicBlockRef InsertAtEnd) {
#if LLVM_VERSION_MINOR >= 6
DIExpression Expr;
if (AddrOpsCount == 0) {
Expr = Builder->createExpression();
} else {
llvm::ArrayRef<int64_t> addr_ops(AddrOps, AddrOpsCount);
Expr = Builder->createExpression(addr_ops);
}
#endif
return wrap(Builder->insertDeclare(
unwrap(Val),
#if LLVM_VERSION_MINOR >= 7
unwrap<DILocalVariable>(VarInfo),
#else
unwrapDI<DIVariable>(VarInfo),
#endif
#if LLVM_VERSION_MINOR >= 6
Expr,
Builder->createExpression(
llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
#endif
#if LLVM_VERSION_MINOR >= 7
DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
#endif
unwrap(InsertAtEnd)));
}
......@@ -550,21 +596,23 @@ extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore(
LLVMMetadataRef VarInfo,
int64_t* AddrOps,
unsigned AddrOpsCount,
LLVMValueRef DL,
LLVMValueRef InsertBefore) {
#if LLVM_VERSION_MINOR >= 6
DIExpression Expr;
if (AddrOpsCount == 0) {
Expr = Builder->createExpression();
} else {
llvm::ArrayRef<int64_t> addr_ops(AddrOps, AddrOpsCount);
Expr = Builder->createExpression(addr_ops);
}
#endif
return wrap(Builder->insertDeclare(
unwrap(Val),
#if LLVM_VERSION_MINOR >= 7
unwrap<DILocalVariable>(VarInfo),
#else
unwrapDI<DIVariable>(VarInfo),
#endif
#if LLVM_VERSION_MINOR >= 6
Expr,
Builder->createExpression(
llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
#endif
#if LLVM_VERSION_MINOR >= 7
DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
#endif
unwrap<Instruction>(InsertBefore)));
}
......@@ -595,7 +643,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerationType(
LineNumber,
SizeInBits,
AlignInBits,
#if LLVM_VERSION_MINOR >= 7
DINodeArray(unwrapDI<MDTuple>(Elements)),
#else
unwrapDI<DIArray>(Elements),
#endif
unwrapDI<DIType>(ClassType)));
}
......@@ -620,7 +672,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateUnionType(
SizeInBits,
AlignInBits,
Flags,
#if LLVM_VERSION_MINOR >= 7
DINodeArray(unwrapDI<MDTuple>(Elements)),
#else
unwrapDI<DIArray>(Elements),
#endif
RunTimeLang,
UniqueId
));
......@@ -638,10 +694,14 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateTemplateTypeParameter(
return wrap(Builder->createTemplateTypeParameter(
unwrapDI<DIDescriptor>(Scope),
Name,
unwrapDI<DIType>(Ty),
unwrapDI<DIType>(Ty)
#if LLVM_VERSION_MINOR <= 6
,
unwrapDI<MDNode*>(File),
LineNo,
ColumnNo));
ColumnNo
#endif
));
}
extern "C" int64_t LLVMDIBuilderCreateOpDeref()
......@@ -673,7 +733,10 @@ extern "C" void LLVMDICompositeTypeSetTypeArray(
LLVMMetadataRef CompositeType,
LLVMMetadataRef TypeArray)
{
#if LLVM_VERSION_MINOR >= 6
#if LLVM_VERSION_MINOR >= 7
DICompositeType *tmp = unwrapDI<DICompositeType>(CompositeType);
Builder->replaceArrays(tmp, DINodeArray(unwrap<MDTuple>(TypeArray)));
#elif LLVM_VERSION_MINOR >= 6
DICompositeType tmp = unwrapDI<DICompositeType>(CompositeType);
Builder->replaceArrays(tmp, unwrapDI<DIArray>(TypeArray));
#else
......@@ -692,11 +755,15 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateDebugLocation(
DebugLoc debug_loc = DebugLoc::get(Line,
Column,
unwrapDI<MDNode*>(Scope),
unwrapDI<MDNode*>(InlinedAt));
unwrapDIptr<MDNode>(Scope),
unwrapDIptr<MDNode>(InlinedAt));
#if LLVM_VERSION_MINOR >= 6
return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode(context)));
return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode(
#if LLVM_VERSION_MINOR <= 6
context
#endif
)));
#else
return wrap(debug_loc.getAsMDNode(context));
#endif
......@@ -721,7 +788,12 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
Module *Dst = unwrap(dst);
#if LLVM_VERSION_MINOR >= 6
std::unique_ptr<MemoryBuffer> buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
#if LLVM_VERSION_MINOR >= 7
ErrorOr<std::unique_ptr<Module>> Src =
llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext());
#else
ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext());
#endif
#else
MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(buf, Dst->getContext());
......@@ -739,7 +811,11 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
#if LLVM_VERSION_MINOR >= 6
raw_string_ostream Stream(Err);
DiagnosticPrinterRawOStream DP(Stream);
#if LLVM_VERSION_MINOR >= 7
if (Linker::LinkModules(Dst, Src->get(), [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
#else
if (Linker::LinkModules(Dst, *Src, [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
#endif
#else
if (Linker::LinkModules(Dst, *Src, Linker::DestroySource, &Err)) {
#endif
......@@ -813,8 +889,12 @@ extern "C" const Archive::Child*
LLVMRustArchiveIteratorCurrent(RustArchiveIterator *rai) {
if (rai->cur == rai->end)
return NULL;
#if LLVM_VERSION_MINOR >= 6
const Archive::Child &ret = *rai->cur;
return &ret;
#else
return rai->cur.operator->();
#endif
}
extern "C" void
......@@ -942,7 +1022,11 @@ extern "C" void LLVMWriteDebugLocToString(
RustStringRef str)
{
raw_rust_string_ostream os(str);
#if LLVM_VERSION_MINOR >= 7
unwrap(dl)->print(os);
#else
unwrap(dl)->print(*unwrap(C), os);
#endif
}
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
......
# If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
# The actual contents of this file do not matter, but to trigger a change on the
# build bots then the contents should be changed so git updates the mtime.
2015-03-04
2015-06-16
......@@ -12,7 +12,6 @@
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Analysis/Passes.h"
......@@ -46,6 +45,12 @@
#include "llvm-c/ExecutionEngine.h"
#include "llvm-c/Object.h"
#if LLVM_VERSION_MINOR >= 7
#include "llvm/IR/LegacyPassManager.h"
#else
#include "llvm/PassManager.h"
#endif
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DIBuilder.h"
......
......@@ -24,5 +24,5 @@ pub fn plugin_registrar(reg: &mut Registry) {
// Normally, we would name a pass that was registered through
// C++ static object constructors in the same .so file as the
// plugin registrar.
reg.register_llvm_pass("inline");
reg.register_llvm_pass("gvn");
}
......@@ -20,14 +20,14 @@ pub struct Bytes {
// CHECK-LABEL: @borrow
#[no_mangle]
pub fn borrow(x: &i32) -> &i32 {
// CHECK: load i32** %x{{.*}}, !nonnull
// CHECK: load i32*, i32** %x{{.*}}, !nonnull
x
}
// CHECK-LABEL: @_box
#[no_mangle]
pub fn _box(x: Box<i32>) -> i32 {
// CHECK: load i32** %x{{.*}}, !nonnull
// CHECK: load i32*, i32** %x{{.*}}, !nonnull
*x
}
......@@ -36,7 +36,7 @@ pub fn _box(x: Box<i32>) -> i32 {
// dependent alignment
#[no_mangle]
pub fn small_array_alignment(x: [i8; 4]) -> [i8; 4] {
// CHECK: [[VAR:%[0-9]+]] = load i32* %{{.*}}, align 1
// CHECK: [[VAR:%[0-9]+]] = load i32, i32* %{{.*}}, align 1
// CHECK: ret i32 [[VAR]]
x
}
......@@ -46,7 +46,7 @@ pub fn _box(x: Box<i32>) -> i32 {
// dependent alignment
#[no_mangle]
pub fn small_struct_alignment(x: Bytes) -> Bytes {
// CHECK: [[VAR:%[0-9]+]] = load i32* %{{.*}}, align 1
// CHECK: [[VAR:%[0-9]+]] = load i32, i32* %{{.*}}, align 1
// CHECK: ret i32 [[VAR]]
x
}
......@@ -22,7 +22,7 @@ pub struct Bytes {
// dependent alignment
#[no_mangle]
pub fn small_array_alignment(x: &mut [i8; 4]) {
// CHECK: [[VAR:%[0-9]+]] = load [4 x i8]** %x
// CHECK: [[VAR:%[0-9]+]] = load [4 x i8]*, [4 x i8]** %x
// CHECK: [[VAR2:%[0-9]+]] = bitcast [4 x i8]* [[VAR]] to i32*
// CHECK: store i32 %{{.*}}, i32* [[VAR2]], align 1
*x = [0; 4];
......@@ -33,7 +33,7 @@ pub struct Bytes {
// dependent alignment
#[no_mangle]
pub fn small_struct_alignment(x: &mut Bytes) {
// CHECK: [[VAR:%[0-9]+]] = load %Bytes** %x
// CHECK: [[VAR:%[0-9]+]] = load %Bytes*, %Bytes** %x
// CHECK: [[VAR2:%[0-9]+]] = bitcast %Bytes* [[VAR]] to i32*
// CHECK: store i32 %{{.*}}, i32* [[VAR2]], align 1
*x = Bytes {
......
......@@ -8,14 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(asm)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
unsafe fn next_power_of_2(n: u32) -> u32 {
let mut tmp = n;
asm!("dec $0" : "+rm"(tmp) :: "cc");
let mut shift = 1_usize;
let mut shift = 1_u32;
while shift <= 16 {
asm!(
"shr %cl, $2
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册