From fc88c8b0f50ad7d19158edf6415eca4bf37885ec Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 14 May 2015 12:10:43 -0700 Subject: [PATCH] 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. * The `LoopVectorize` option of the LLVM optimization passes has been disabled as it causes a divide-by-zero exception to happen in LLVM for zero-sized types. This is reported as https://llvm.org/bugs/show_bug.cgi?id=23763 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`. --- src/librustc_llvm/lib.rs | 11 +- src/librustc_trans/back/write.rs | 91 +++++++------ src/librustc_trans/trans/attributes.rs | 15 ++ src/librustc_trans/trans/base.rs | 20 ++- .../trans/debuginfo/metadata.rs | 2 +- src/librustc_trans/trans/debuginfo/mod.rs | 10 +- src/llvm | 2 +- src/rustllvm/ExecutionEngineWrapper.cpp | 3 - src/rustllvm/PassWrapper.cpp | 63 ++++++++- src/rustllvm/RustWrapper.cpp | 128 ++++++++++++++---- src/rustllvm/llvm-auto-clean-trigger | 2 +- src/rustllvm/rustllvm.h | 7 +- src/test/auxiliary/llvm_pass_plugin.rs | 2 +- src/test/codegen/loads.rs | 8 +- src/test/codegen/stores.rs | 4 +- 15 files changed, 266 insertions(+), 102 deletions(-) diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index a3b9a0e846700..7e6f38dc6eba2 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -979,6 +979,9 @@ extern { 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); @@ -1924,6 +1927,7 @@ extern { VarInfo: DIVariable, AddrOps: *const i64, AddrOpsCount: c_uint, + DL: ValueRef, InsertAtEnd: BasicBlockRef) -> ValueRef; @@ -1932,6 +1936,7 @@ extern { VarInfo: DIVariable, AddrOps: *const i64, AddrOpsCount: c_uint, + DL: ValueRef, InsertBefore: ValueRef) -> ValueRef; @@ -2039,7 +2044,6 @@ extern { Level: CodeGenOptLevel, EnableSegstk: bool, UseSoftFP: bool, - NoFramePointerElim: bool, PositionIndependentExecutable: bool, FunctionSections: bool, DataSections: bool) -> TargetMachineRef; @@ -2050,6 +2054,11 @@ extern { 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); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 5352c61d8c0ad..1b8f049972f21 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -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 @@ impl ModuleConfig { no_prepopulate_passes: false, no_builtins: false, time_passes: false, + vectorize_loop: false, + vectorize_slp: false, + merge_functions: false, } } @@ -309,6 +310,18 @@ impl ModuleConfig { 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 optimize_and_codegen(cgcx: &CodegenContext, 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 optimize_and_codegen(cgcx: &CodegenContext, 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 _); - } - _ => {} - }; } diff --git a/src/librustc_trans/trans/attributes.rs b/src/librustc_trans/trans/attributes.rs index 132947e34d795..f7e9bd4d3d071 100644 --- a/src/librustc_trans/trans/attributes.rs +++ b/src/librustc_trans/trans/attributes.rs @@ -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); diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index c3f614c8cc06a..f368f83048931 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -480,9 +480,23 @@ pub fn iter_structural_ty<'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"); diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs index ab86cd7cdde59..406c8b98bd55e 100644 --- a/src/librustc_trans/trans/debuginfo/metadata.rs +++ b/src/librustc_trans/trans/debuginfo/metadata.rs @@ -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), diff --git a/src/librustc_trans/trans/debuginfo/mod.rs b/src/librustc_trans/trans/debuginfo/mod.rs index f9ad3d1a857f1..ec7bd7a5f8403 100644 --- a/src/librustc_trans/trans/debuginfo/mod.rs +++ b/src/librustc_trans/trans/debuginfo/mod.rs @@ -484,10 +484,10 @@ pub fn create_function_debug_context<'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 @@ pub fn create_function_debug_context<'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); diff --git a/src/llvm b/src/llvm index bff6907697564..5d48133e76293 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit bff69076975642c64e76dbeaa53476bfa7212086 +Subproject commit 5d48133e7629339e6d97d0fc023bc578a09f48af diff --git a/src/rustllvm/ExecutionEngineWrapper.cpp b/src/rustllvm/ExecutionEngineWrapper.cpp index 7e0630fd242d3..2c73de47d6612 100644 --- a/src/rustllvm/ExecutionEngineWrapper.cpp +++ b/src/rustllvm/ExecutionEngineWrapper.cpp @@ -85,9 +85,6 @@ extern "C" LLVMExecutionEngineRef LLVMBuildExecutionEngine( std::string error_str; TargetOptions options; - options.JITEmitDebugInfo = true; - options.NoFramePointerElim = true; - ExecutionEngine *ee = #if LLVM_VERSION_MINOR >= 6 EngineBuilder(std::unique_ptr(unwrap(mod))) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index a2ab8040198ff..aade684d18fa9 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -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 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,37 @@ 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 >= 7 + unwrap(PMB)->MergeFunctions = MergeFunctions; + unwrap(PMB)->SLPVectorize = SLPVectorize; + unwrap(PMB)->OptLevel = OptLevel; + + // For now always set `LoopVectorize` to **false** as our current version of + // LLVM causes a divide-by-zero exception when a loop may contain a + // zero-sized type. More information can be found on the LLVM bug report: + // + // https://llvm.org/bugs/show_bug.cgi?id=23763 + unwrap(PMB)->LoopVectorize = false; +#endif } // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo` @@ -138,7 +167,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 +184,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 +244,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; } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 66db7326d21bf..58799cf3b3aa2 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -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(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(fn); LLVMContext &C = f->getContext(); @@ -228,9 +237,19 @@ inline Metadata **unwrap(LLVMMetadataRef *Vals) { typedef LLVMValueRef LLVMMetadataRef; #endif +#if LLVM_VERSION_MINOR <= 6 +#else +#define DIDescriptor DIScope +#define DIArray DINodeArray +#endif + template -DIT unwrapDI(LLVMMetadataRef ref) { +DIT* unwrapDI(LLVMMetadataRef ref) { +#if LLVM_VERSION_MINOR >= 7 + return ref ? (DIT*) unwrap(ref) : NULL; +#else return DIT(ref ? unwrap(ref) : NULL); +#endif } extern "C" const uint32_t LLVMRustDebugMetadataVersion() { @@ -288,7 +307,9 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateSubroutineType( LLVMMetadataRef ParameterTypes) { return wrap(Builder->createSubroutineType( unwrapDI(File), -#if LLVM_VERSION_MINOR >= 6 +#if LLVM_VERSION_MINOR >= 7 + DITypeRefArray(unwrap(ParameterTypes)))); +#elif LLVM_VERSION_MINOR >= 6 unwrapDI(ParameterTypes))); #else unwrapDI(ParameterTypes))); @@ -314,11 +335,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction( return wrap(Builder->createFunction( unwrapDI(Scope), Name, LinkageName, unwrapDI(File), LineNo, - unwrapDI(Ty), isLocalToUnit, isDefinition, ScopeLine, + unwrapDI(Ty), isLocalToUnit, isDefinition, ScopeLine, Flags, isOptimized, unwrap(Fn), - unwrapDI(TParam), - unwrapDI(Decl))); + unwrapDI(TParam), + unwrapDI(Decl))); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType( @@ -365,7 +386,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateStructType( AlignInBits, Flags, unwrapDI(DerivedFrom), +#if LLVM_VERSION_MINOR >= 7 + DINodeArray(unwrapDI(Elements)), +#else unwrapDI(Elements), +#endif RunTimeLang, unwrapDI(VTableHolder), UniqueId @@ -428,7 +453,7 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateStaticVariable( unwrapDI(Ty), isLocalToUnit, cast(unwrap(Val)), - unwrapDI(Decl))); + unwrapDI(Decl))); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable( @@ -478,7 +503,12 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateArrayType( LLVMMetadataRef Subscripts) { return wrap(Builder->createArrayType(Size, AlignInBits, unwrapDI(Ty), - unwrapDI(Subscripts))); +#if LLVM_VERSION_MINOR >= 7 + DINodeArray(unwrapDI(Subscripts)) +#else + unwrapDI(Subscripts) +#endif + )); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType( @@ -489,7 +519,12 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType( LLVMMetadataRef Subscripts) { return wrap(Builder->createVectorType(Size, AlignInBits, unwrapDI(Ty), - unwrapDI(Subscripts))); +#if LLVM_VERSION_MINOR >= 7 + DINodeArray(unwrapDI(Subscripts)) +#else + unwrapDI(Subscripts) +#endif + )); } extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange( @@ -503,12 +538,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(DataValue, Count)).get()); +#else return wrap(Builder->getOrCreateArray( #if LLVM_VERSION_MINOR >= 6 ArrayRef(unwrap(Ptr), Count))); #else ArrayRef(reinterpret_cast(Ptr), Count))); #endif +#endif } extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd( @@ -517,21 +558,24 @@ 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 addr_ops(AddrOps, AddrOpsCount); - Expr = Builder->createExpression(addr_ops); - } + DIExpression *Expr = Builder->createExpression( + llvm::ArrayRef(AddrOps, AddrOpsCount)); #endif return wrap(Builder->insertDeclare( unwrap(Val), +#if LLVM_VERSION_MINOR >= 7 + unwrap(VarInfo), +#else unwrapDI(VarInfo), +#endif #if LLVM_VERSION_MINOR >= 6 Expr, +#endif +#if LLVM_VERSION_MINOR >= 7 + DebugLoc(cast(unwrap(DL)->getMetadata())), #endif unwrap(InsertAtEnd))); } @@ -542,21 +586,24 @@ 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 addr_ops(AddrOps, AddrOpsCount); - Expr = Builder->createExpression(addr_ops); - } + DIExpression *Expr = Builder->createExpression( + llvm::ArrayRef(AddrOps, AddrOpsCount)); #endif return wrap(Builder->insertDeclare( unwrap(Val), +#if LLVM_VERSION_MINOR >= 7 + unwrap(VarInfo), +#else unwrapDI(VarInfo), +#endif #if LLVM_VERSION_MINOR >= 6 Expr, +#endif +#if LLVM_VERSION_MINOR >= 7 + DebugLoc(cast(unwrap(DL)->getMetadata())), #endif unwrap(InsertBefore))); } @@ -587,7 +634,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerationType( LineNumber, SizeInBits, AlignInBits, +#if LLVM_VERSION_MINOR >= 7 + DINodeArray(unwrapDI(Elements)), +#else unwrapDI(Elements), +#endif unwrapDI(ClassType))); } @@ -612,7 +663,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateUnionType( SizeInBits, AlignInBits, Flags, +#if LLVM_VERSION_MINOR >= 7 + DINodeArray(unwrapDI(Elements)), +#else unwrapDI(Elements), +#endif RunTimeLang, UniqueId )); @@ -630,10 +685,14 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateTemplateTypeParameter( return wrap(Builder->createTemplateTypeParameter( unwrapDI(Scope), Name, - unwrapDI(Ty), - unwrapDI(File), + unwrapDI(Ty) +#if LLVM_VERSION_MINOR <= 6 + , + unwrapDI(File), LineNo, - ColumnNo)); + ColumnNo +#endif + )); } extern "C" int64_t LLVMDIBuilderCreateOpDeref() @@ -665,7 +724,10 @@ extern "C" void LLVMDICompositeTypeSetTypeArray( LLVMMetadataRef CompositeType, LLVMMetadataRef TypeArray) { -#if LLVM_VERSION_MINOR >= 6 +#if LLVM_VERSION_MINOR >= 7 + DICompositeType *tmp = unwrapDI(CompositeType); + Builder->replaceArrays(tmp, DINodeArray(unwrap(TypeArray))); +#elif LLVM_VERSION_MINOR >= 6 DICompositeType tmp = unwrapDI(CompositeType); Builder->replaceArrays(tmp, unwrapDI(TypeArray)); #else @@ -684,11 +746,15 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateDebugLocation( DebugLoc debug_loc = DebugLoc::get(Line, Column, - unwrapDI(Scope), - unwrapDI(InlinedAt)); + unwrapDI(Scope), + unwrapDI(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 @@ -934,7 +1000,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) diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index 1ea40fc46a521..ea74eb23a0c78 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -1,4 +1,4 @@ # 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-03 diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h index 8a4330acf4341..db54e555be143 100644 --- a/src/rustllvm/rustllvm.h +++ b/src/rustllvm/rustllvm.h @@ -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" diff --git a/src/test/auxiliary/llvm_pass_plugin.rs b/src/test/auxiliary/llvm_pass_plugin.rs index d61f47fd7ef27..bacc1acd3c4c3 100644 --- a/src/test/auxiliary/llvm_pass_plugin.rs +++ b/src/test/auxiliary/llvm_pass_plugin.rs @@ -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"); } diff --git a/src/test/codegen/loads.rs b/src/test/codegen/loads.rs index 20a55740bb776..45b8731c3b149 100644 --- a/src/test/codegen/loads.rs +++ b/src/test/codegen/loads.rs @@ -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 { -// CHECK: load i32** %x{{.*}}, !nonnull +// CHECK: load i32*, i32** %x{{.*}}, !nonnull *x } @@ -36,7 +36,7 @@ pub fn _box(x: Box) -> 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 small_array_alignment(x: [i8; 4]) -> [i8; 4] { // 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 } diff --git a/src/test/codegen/stores.rs b/src/test/codegen/stores.rs index 32337b085cd27..15cf76b2ab1de 100644 --- a/src/test/codegen/stores.rs +++ b/src/test/codegen/stores.rs @@ -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 fn small_array_alignment(x: &mut [i8; 4]) { // 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 {