From 58d80150442eb2fab0044b2aa46472120605ddd5 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Sun, 14 Dec 2025 02:37:21 +0800 Subject: [PATCH] Compat fixes for llvm-7 Revert b97a33b1cb90326ccfa1c8a9882e50cd9e6de80f Revert 7d872f538efc5cb3786c3aa0a6654bae7a67ec63 See also 6e17a5c5fd086ebe6f57216fb3ce5d1d8d6c83e5 Revert b51bcc72d9fce469ccdcd75676d8bd35f41e5614 attributes.rs part is skipped, since llvm_target_features was removed in 72fb4379d56b93b9bd0149649a74fb4b5465ec18 and 7e443c4282df6daa9c92be7d1008c974cc5ede00 Revert 8b8e706008111fa3865e8da76eeddabfbf9851f0 Revert 8506bb006040cf8e8cb004202706c81e62ddacee --- compiler/rustc_codegen_llvm/src/attributes.rs | 21 +- compiler/rustc_codegen_llvm/src/back/write.rs | 4 + compiler/rustc_codegen_llvm/src/context.rs | 17 ++ .../src/debuginfo/metadata.rs | 18 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 49 +++- compiler/rustc_codegen_llvm/src/llvm_util.rs | 18 +- compiler/rustc_llvm/build.rs | 26 ++- .../llvm-wrapper/ArchiveWrapper.cpp | 4 + .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 120 +++++++++- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 210 +++++++++++++++++- compiler/rustc_llvm/src/lib.rs | 5 +- library/core/src/num/dec2flt/algorithm.rs | 10 +- library/profiler_builtins/build.rs | 4 +- library/std/src/os/fortanix_sgx/arch.rs | 6 +- library/std/src/sys/sgx/abi/mem.rs | 5 +- src/bootstrap/native.rs | 4 +- src/test/codegen/abi-efiapi.rs | 1 + src/test/codegen/enum-debug-clike.rs | 12 +- src/test/codegen/enum-debug-niche-2.rs | 7 +- src/test/codegen/enum-debug-niche.rs | 6 +- src/test/codegen/enum-debug-tagged.rs | 6 +- src/test/codegen/force-frame-pointers.rs | 1 + src/test/codegen/force-unwind-tables.rs | 1 + src/test/codegen/instrument-mcount.rs | 3 +- .../simd-intrinsic-transmute-array.rs | 1 + src/test/debuginfo/borrowed-enum.rs | 3 +- src/test/debuginfo/enum-thinlto.rs | 3 +- src/test/debuginfo/generator-objects.rs | 3 +- .../generic-enum-with-different-disr-sizes.rs | 3 +- .../debuginfo/generic-struct-style-enum.rs | 3 +- .../debuginfo/generic-tuple-style-enum.rs | 3 +- src/test/debuginfo/issue-57822.rs | 3 +- src/test/debuginfo/recursive-struct.rs | 3 +- src/test/debuginfo/struct-style-enum.rs | 3 +- src/test/debuginfo/tuple-style-enum.rs | 3 +- src/test/debuginfo/unique-enum.rs | 3 +- .../new-llvm-pass-manager-thin-lto.rs | 1 + ...intrinsic-generic-arithmetic-saturating.rs | 1 + .../simd/simd-intrinsic-generic-reduction.rs | 1 + 39 files changed, 528 insertions(+), 67 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index f1c45d8dc36..65db02d85d1 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -71,12 +71,21 @@ fn naked(val: &'ll Value, is_naked: bool) { pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { if cx.sess().must_not_eliminate_frame_pointers() { - llvm::AddFunctionAttrStringValue( - llfn, - llvm::AttributePlace::Function, - cstr!("frame-pointer"), - cstr!("all"), - ); + if llvm_util::get_version() >= (8, 0, 0) { + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + cstr!("frame-pointer"), + cstr!("all"), + ); + } else { + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + cstr!("no-frame-pointer-elim"), + cstr!("true"), + ); + } } } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 5b4a187a1d5..8e1a7c0e5e1 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -407,6 +407,10 @@ fn get_pgo_use_path(config: &ModuleConfig) -> Option { } pub(crate) fn should_use_new_llvm_pass_manager(config: &ModuleConfig) -> bool { + // We only support the new pass manager starting with LLVM 9. + if llvm_util::get_version() < (9, 0, 0) { + return false; + } // The new pass manager is disabled by default. config.new_llvm_pass_manager.unwrap_or(false) } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 6aa952462fa..5b69d42c03e 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -101,6 +101,15 @@ fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode { } } +fn strip_function_ptr_alignment(data_layout: String) -> String { + // FIXME: Make this more general. + data_layout.replace("-Fi8-", "-") +} + +fn strip_x86_address_spaces(data_layout: String) -> String { + data_layout.replace("-p270:32:32-p271:32:32-p272:64:64-", "-") +} + fn strip_powerpc64_vectors(data_layout: String) -> String { data_layout.replace("-v256:256:256-v512:512:512", "") } @@ -115,6 +124,14 @@ pub unsafe fn create_module( let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx); let mut target_data_layout = sess.target.data_layout.clone(); + if llvm_util::get_version() < (9, 0, 0) { + target_data_layout = strip_function_ptr_alignment(target_data_layout); + } + if llvm_util::get_version() < (10, 0, 0) + && (sess.target.arch == "x86" || sess.target.arch == "x86_64") + { + target_data_layout = strip_x86_address_spaces(target_data_layout); + } if llvm_util::get_version() < (12, 0, 0) && sess.target.arch == "powerpc64" { target_data_layout = strip_powerpc64_vectors(target_data_layout); } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 1e70664e64d..a51acaa6161 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -16,6 +16,7 @@ DIArray, DICompositeType, DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind, }; +use crate::llvm_util; use crate::value::Value; use cstr::cstr; @@ -1402,11 +1403,22 @@ fn prepare_union_metadata( // Enums //=----------------------------------------------------------------------------- -/// DWARF variant support is only available starting in LLVM 8, but -/// on MSVC we have to use the fallback mode, because LLVM doesn't -/// lower variant parts to PDB. +/// DWARF variant support is only available starting in LLVM 8. +/// Although the earlier enum debug info output did not work properly +/// in all situations, it is better for the time being to continue to +/// sometimes emit the old style rather than emit something completely +/// useless when rust is compiled against LLVM 6 or older. LLVM 7 +/// contains an early version of the DWARF variant support, and will +/// crash when handling the new debug info format. This function +/// decides which representation will be emitted. fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool { + // On MSVC we have to use the fallback mode, because LLVM doesn't + // lower variant parts to PDB. cx.sess().target.is_like_msvc + // LLVM version 7 did not release with an important bug fix; + // but the required patch is in the LLVM 8. Rust LLVM reports + // 8 as well. + || llvm_util::get_version() < (8, 0, 0) } // FIXME(eddyb) maybe precompute this? Right now it's computed once diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 22d513d66d1..b3e1d405d7e 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -2,6 +2,7 @@ use crate::builder::Builder; use crate::context::CodegenCx; use crate::llvm; +use crate::llvm_util; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::va_arg::emit_va_arg; @@ -270,14 +271,46 @@ fn codegen_intrinsic_call( let is_add = name == sym::saturating_add; let lhs = args[0].immediate(); let rhs = args[1].immediate(); - let llvm_name = &format!( - "llvm.{}{}.sat.i{}", - if signed { 's' } else { 'u' }, - if is_add { "add" } else { "sub" }, - width - ); - let llfn = self.get_intrinsic(llvm_name); - self.call(llfn, &[lhs, rhs], None) + if llvm_util::get_version() >= (8, 0, 0) { + let llvm_name = &format!( + "llvm.{}{}.sat.i{}", + if signed { 's' } else { 'u' }, + if is_add { "add" } else { "sub" }, + width + ); + let llfn = self.get_intrinsic(llvm_name); + self.call(llfn, &[lhs, rhs], None) + } else { + let llvm_name = &format!( + "llvm.{}{}.with.overflow.i{}", + if signed { 's' } else { 'u' }, + if is_add { "add" } else { "sub" }, + width + ); + let llfn = self.get_intrinsic(llvm_name); + let pair = self.call(llfn, &[lhs, rhs], None); + let val = self.extract_value(pair, 0); + let overflow = self.extract_value(pair, 1); + let llty = self.type_ix(width); + + let limit = if signed { + let limit_lo = self + .const_uint_big(llty, (i128::MIN >> (128 - width)) as u128); + let limit_hi = self + .const_uint_big(llty, (i128::MAX >> (128 - width)) as u128); + let neg = self.icmp( + IntPredicate::IntSLT, + val, + self.const_uint(llty, 0), + ); + self.select(neg, limit_hi, limit_lo) + } else if is_add { + self.const_uint_big(llty, u128::MAX >> (128 - width)) + } else { + self.const_uint(llty, 0) + }; + self.select(overflow, limit, val) + } } _ => bug!(), }, diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 0dd3d2ae15b..6d2ddd50c7d 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -95,10 +95,12 @@ fn llvm_arg_to_arg_name(full_arg: &str) -> &str { add("-enable-machine-outliner=never", false); } - match sess.opts.debugging_opts.merge_functions.unwrap_or(sess.target.merge_functions) { - MergeFunctions::Disabled | MergeFunctions::Trampolines => {} - MergeFunctions::Aliases => { - add("-mergefunc-use-aliases", false); + if llvm_util::get_version() >= (8, 0, 0) { + match sess.opts.debugging_opts.merge_functions.unwrap_or(sess.target.merge_functions) { + MergeFunctions::Disabled | MergeFunctions::Trampolines => {} + MergeFunctions::Aliases => { + add("-mergefunc-use-aliases", false); + } } } @@ -118,7 +120,7 @@ fn llvm_arg_to_arg_name(full_arg: &str) -> &str { } } - if sess.opts.debugging_opts.llvm_time_trace { + if sess.opts.debugging_opts.llvm_time_trace && llvm_util::get_version() >= (9, 0, 0) { // time-trace is not thread safe and running it in parallel will cause seg faults. if !sess.opts.debugging_opts.no_parallel_llvm { bug!("`-Z llvm-time-trace` requires `-Z no-parallel-llvm") @@ -136,8 +138,10 @@ fn llvm_arg_to_arg_name(full_arg: &str) -> &str { pub fn time_trace_profiler_finish(file_name: &str) { unsafe { - let file_name = CString::new(file_name).unwrap(); - llvm::LLVMTimeTraceProfilerFinish(file_name.as_ptr()); + if llvm_util::get_version() >= (9, 0, 0) { + let file_name = CString::new(file_name).unwrap(); + llvm::LLVMTimeTraceProfilerFinish(file_name.as_ptr()); + } } } diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 452d1b19a18..a4c7747381e 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -70,7 +70,7 @@ fn main() { let host = env::var("HOST").expect("HOST was not set"); let is_crossed = target != host; - let optional_components = &[ + let mut optional_components = vec![ "x86", "arm", "aarch64", @@ -85,10 +85,26 @@ fn main() { "sparc", "nvptx", "hexagon", - "riscv", - "bpf", ]; + let mut version_cmd = Command::new(&llvm_config); + version_cmd.arg("--version"); + let version_output = output(&mut version_cmd); + let mut parts = version_output.split('.').take(2).filter_map(|s| s.parse::().ok()); + let (major, _minor) = if let (Some(major), Some(minor)) = (parts.next(), parts.next()) { + (major, minor) + } else { + (7, 0) + }; + + if major > 6 { + optional_components.push("riscv"); + } + + if major > 9 { + optional_components.push("bpf"); + } + let required_components = &[ "ipo", "bitreader", @@ -114,6 +130,10 @@ fn main() { println!("cargo:rustc-cfg=llvm_component=\"{}\"", component); } + if major >= 9 { + println!("cargo:rustc-cfg=llvm_has_msp430_asm_parser"); + } + // Link in our own LLVM shims, compiled with the same flags as LLVM let mut cmd = Command::new(&llvm_config); cmd.arg("--cxxflags"); diff --git a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp index 97541e615da..2797fe8df4a 100644 --- a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp @@ -91,7 +91,11 @@ extern "C" void LLVMRustDestroyArchive(LLVMRustArchiveRef RustArchive) { extern "C" LLVMRustArchiveIteratorRef LLVMRustArchiveIteratorNew(LLVMRustArchiveRef RustArchive) { Archive *Archive = RustArchive->getBinary(); +#if LLVM_VERSION_GE(10, 0) std::unique_ptr Err = std::make_unique(Error::success()); +#else + std::unique_ptr Err = llvm::make_unique(Error::success()); +#endif auto Cur = Archive->child_begin(*Err); if (*Err) { LLVMRustSetLastError(toString(std::move(*Err)).c_str()); diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 3595e37cf96..9e3e9e35ee4 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -17,7 +17,9 @@ #include "llvm/Object/ObjectFile.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Passes/PassBuilder.h" +#if LLVM_VERSION_GE(9, 0) #include "llvm/Passes/StandardInstrumentations.h" +#endif #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -30,14 +32,20 @@ #include "llvm-c/Transforms/PassManagerBuilder.h" #include "llvm/Transforms/Instrumentation.h" +#if LLVM_VERSION_GE(9, 0) #include "llvm/Transforms/Instrumentation/AddressSanitizer.h" #include "llvm/Support/TimeProfiler.h" +#endif #include "llvm/Transforms/Instrumentation/GCOVProfiler.h" #include "llvm/Transforms/Instrumentation/InstrProfiling.h" +#if LLVM_VERSION_GE(8, 0) #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" #include "llvm/Transforms/Instrumentation/MemorySanitizer.h" #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h" +#endif +#if LLVM_VERSION_GE(9, 0) #include "llvm/Transforms/Utils/CanonicalizeAliases.h" +#endif #include "llvm/Transforms/Utils/NameAnonGlobals.h" using namespace llvm; @@ -67,18 +75,24 @@ extern "C" void LLVMInitializePasses() { } extern "C" void LLVMTimeTraceProfilerInitialize() { +#if LLVM_VERSION_GE(10, 0) timeTraceProfilerInitialize( /* TimeTraceGranularity */ 0, /* ProcName */ "rustc"); +#elif LLVM_VERSION_GE(9, 0) + timeTraceProfilerInitialize(); +#endif } extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { +#if LLVM_VERSION_GE(9, 0) StringRef FN(FileName); std::error_code EC; raw_fd_ostream OS(FN, EC, sys::fs::CD_CreateAlways); timeTraceProfilerWrite(OS); timeTraceProfilerCleanup(); +#endif } enum class LLVMRustPassKind { @@ -119,25 +133,41 @@ extern "C" LLVMPassRef LLVMRustCreateAddressSanitizerFunctionPass(bool Recover) extern "C" LLVMPassRef LLVMRustCreateModuleAddressSanitizerPass(bool Recover) { const bool CompileKernel = false; +#if LLVM_VERSION_GE(9, 0) return wrap(createModuleAddressSanitizerLegacyPassPass(CompileKernel, Recover)); +#else + return wrap(createAddressSanitizerModulePass(CompileKernel, Recover)); +#endif } extern "C" LLVMPassRef LLVMRustCreateMemorySanitizerPass(int TrackOrigins, bool Recover) { +#if LLVM_VERSION_GE(9, 0) const bool CompileKernel = false; return wrap(createMemorySanitizerLegacyPassPass( MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel})); +#elif LLVM_VERSION_GE(8, 0) + return wrap(createMemorySanitizerLegacyPassPass(TrackOrigins, Recover)); +#else + return wrap(createMemorySanitizerPass(TrackOrigins, Recover)); +#endif } extern "C" LLVMPassRef LLVMRustCreateThreadSanitizerPass() { +#if LLVM_VERSION_GE(8, 0) return wrap(createThreadSanitizerLegacyPassPass()); +#else + return wrap(createThreadSanitizerPass()); +#endif } +#if LLVM_VERSION_GE(8, 0) extern "C" LLVMPassRef LLVMRustCreateHWAddressSanitizerPass(bool Recover) { const bool CompileKernel = false; return wrap(createHWAddressSanitizerLegacyPassPass(CompileKernel, Recover)); } +#endif extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) { assert(RustPass); @@ -173,8 +203,10 @@ void LLVMRustAddLastExtensionPasses( // so they are run for optimized and non-optimized builds. unwrap(PMBR)->addExtension(PassManagerBuilder::EP_OptimizerLast, AddExtensionPasses); +#if LLVM_VERSION_GE(9, 0) unwrap(PMBR)->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, AddExtensionPasses); +#endif } #ifdef LLVM_COMPONENT_X86 @@ -284,7 +316,11 @@ enum class LLVMRustCodeModel { static Optional fromRust(LLVMRustCodeModel Model) { switch (Model) { case LLVMRustCodeModel::Tiny: +#if LLVM_VERSION_GE(9, 0) return CodeModel::Tiny; +#else + return CodeModel::Small; +#endif case LLVMRustCodeModel::Small: return CodeModel::Small; case LLVMRustCodeModel::Kernel: @@ -392,7 +428,11 @@ extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) { const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); const Triple::ArchType HostArch = Triple(sys::getProcessTriple()).getArch(); const Triple::ArchType TargetArch = Target->getTargetTriple().getArch(); +#if LLVM_VERSION_GE(9, 0) const ArrayRef CPUTable = MCInfo->getCPUTable(); +#else + const ArrayRef CPUTable = MCInfo->getCPUTable(); +#endif unsigned MaxCPULen = getLongestEntryLength(CPUTable); printf("Available CPUs for this target:\n"); @@ -591,6 +631,7 @@ enum class LLVMRustFileType { ObjectFile, }; +#if LLVM_VERSION_GE(10, 0) static CodeGenFileType fromRust(LLVMRustFileType Type) { switch (Type) { case LLVMRustFileType::AssemblyFile: @@ -601,6 +642,18 @@ static CodeGenFileType fromRust(LLVMRustFileType Type) { report_fatal_error("Bad FileType."); } } +#else +static TargetMachine::CodeGenFileType fromRust(LLVMRustFileType Type) { + switch (Type) { + case LLVMRustFileType::AssemblyFile: + return TargetMachine::CGFT_AssemblyFile; + case LLVMRustFileType::ObjectFile: + return TargetMachine::CGFT_ObjectFile; + default: + report_fatal_error("Bad FileType."); + } +} +#endif extern "C" LLVMRustResult LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, @@ -649,6 +702,8 @@ extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)(void*, // LlvmS const char*); // IR name extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)(void*); // LlvmSelfProfiler +#if LLVM_VERSION_GE(9, 0) + std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) { if (any_isa(WrappedIr)) return any_cast(WrappedIr)->getName().str(); @@ -717,6 +772,8 @@ void LLVMSelfProfileInitializeCallbacks( }); } +#endif + enum class LLVMRustOptStage { PreLinkNoLTO, PreLinkThinLTO, @@ -732,8 +789,10 @@ struct LLVMRustSanitizerOptions { bool SanitizeMemoryRecover; int SanitizeMemoryTrackOrigins; bool SanitizeThread; +#if LLVM_VERSION_GE(8, 0) bool SanitizeHWAddress; bool SanitizeHWAddressRecover; +#endif }; extern "C" LLVMRustResult @@ -752,6 +811,7 @@ LLVMRustOptimizeWithNewPassManager( LLVMRustSelfProfileBeforePassCallback BeforePassCallback, LLVMRustSelfProfileAfterPassCallback AfterPassCallback, const char *ExtraPasses, size_t ExtraPassesLen) { +#if LLVM_VERSION_GE(9, 0) Module *TheModule = unwrap(ModuleRef); TargetMachine *TM = unwrap(TMRef); PassBuilder::OptimizationLevel OptLevel = fromRust(OptLevelRust); @@ -876,11 +936,13 @@ LLVMRustOptimizeWithNewPassManager( } ); #else +#if LLVM_VERSION_GE(10, 0) PipelineStartEPCallbacks.push_back( [Options](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { MPM.addPass(MemorySanitizerPass(Options)); } ); +#endif OptimizerLastEPCallbacks.push_back( [Options](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { FPM.addPass(MemorySanitizerPass(Options)); @@ -898,11 +960,13 @@ LLVMRustOptimizeWithNewPassManager( } ); #else +#if LLVM_VERSION_GE(10, 0) PipelineStartEPCallbacks.push_back( [](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { MPM.addPass(ThreadSanitizerPass()); } ); +#endif OptimizerLastEPCallbacks.push_back( [](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { FPM.addPass(ThreadSanitizerPass()); @@ -944,6 +1008,7 @@ LLVMRustOptimizeWithNewPassManager( ); #endif } +#if LLVM_VERSION_GE(8, 0) if (SanitizerOptions->SanitizeHWAddress) { #if LLVM_VERSION_GE(11, 0) OptimizerLastEPCallbacks.push_back( @@ -961,6 +1026,7 @@ LLVMRustOptimizeWithNewPassManager( ); #endif } +#endif } #if LLVM_VERSION_GE(13, 0) @@ -997,11 +1063,13 @@ LLVMRustOptimizeWithNewPassManager( MPM.addPass(AlwaysInlinerPass(EmitLifetimeMarkers)); +# if LLVM_VERSION_GE(10, 0) if (PGOOpt) { PB.addPGOInstrPassesForO0( MPM, DebugPassManager, PGOOpt->Action == PGOOptions::IRInstr, /*IsCS=*/false, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile); } +# endif #endif } else { #if LLVM_VERSION_GE(12, 0) @@ -1093,6 +1161,11 @@ LLVMRustOptimizeWithNewPassManager( MPM.run(*TheModule, MAM); return LLVMRustResult::Success; +#else + // The new pass manager has been available for a long time, + // but we don't bother supporting it on old LLVM versions. + report_fatal_error("New pass manager only supported since LLVM 9"); +#endif } // Callback to demangle function name @@ -1158,10 +1231,18 @@ public: const Value *Value; if (const CallInst *CI = dyn_cast(I)) { Name = "call"; +#if LLVM_VERSION_GE(8, 0) Value = CI->getCalledOperand(); +#else + Value = CI->getCalledValue(); +#endif } else if (const InvokeInst* II = dyn_cast(I)) { Name = "invoke"; +#if LLVM_VERSION_GE(8, 0) Value = II->getCalledOperand(); +#else + Value = II->getCalledValue(); +#endif } else { // Could demangle more operations, e. g. // `store %place, @function`. @@ -1284,7 +1365,9 @@ extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M, auto CM = fromRust(Model); if (!CM.hasValue()) return; +#if LLVM_VERSION_GE(9, 0) unwrap(M)->setCodeModel(*CM); +#endif } // Here you'll find an implementation of ThinLTO as used by the Rust compiler @@ -1381,7 +1464,11 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, int num_modules, const char **preserved_symbols, int num_symbols) { +#if LLVM_VERSION_GE(10, 0) auto Ret = std::make_unique(); +#else + auto Ret = llvm::make_unique(); +#endif // Load each module's summary and merge it into one combined index for (int i = 0; i < num_modules; i++) { @@ -1414,11 +1501,15 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, auto deadIsPrevailing = [&](GlobalValue::GUID G) { return PrevailingType::Unknown; }; +#if LLVM_VERSION_GE(8, 0) // We don't have a complete picture in our use of ThinLTO, just our immediate // crate, so we need `ImportEnabled = false` to limit internalization. // Otherwise, we sometimes lose `static` values -- see #60184. computeDeadSymbolsWithConstProp(Ret->Index, Ret->GUIDPreservedSymbols, deadIsPrevailing, /* ImportEnabled = */ false); +#else + computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols, deadIsPrevailing); +#endif ComputeCrossModuleImport( Ret->Index, Ret->ModuleToDefinedGVSummaries, @@ -1455,9 +1546,13 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, lto::Config conf; thinLTOResolvePrevailingInIndex(conf, Ret->Index, isPrevailing, recordNewLinkage, Ret->GUIDPreservedSymbols); -#else +#elif LLVM_VERSION_GE(9, 0) thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage, Ret->GUIDPreservedSymbols); +#elif LLVM_VERSION_GE(8, 0) + thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage); +#else + thinLTOResolveWeakForLinkerInIndex(Ret->Index, isPrevailing, recordNewLinkage); #endif // Here we calculate an `ExportedGUIDs` set for use in the `isExported` // callback below. This callback below will dictate the linkage for all @@ -1474,6 +1569,7 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, ExportedGUIDs.insert(GUID); } } +#if LLVM_VERSION_GE(10, 0) auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) { const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier); return (ExportList != Ret->ExportLists.end() && @@ -1481,6 +1577,15 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, ExportedGUIDs.count(VI.getGUID()); }; thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing); +#else + auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) { + const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier); + return (ExportList != Ret->ExportLists.end() && + ExportList->second.count(GUID)) || + ExportedGUIDs.count(GUID); + }; + thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported); +#endif return Ret.release(); } @@ -1535,7 +1640,11 @@ extern "C" bool LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { Module &Mod = *unwrap(M); const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier()); +#if LLVM_VERSION_GE(8, 0) thinLTOResolvePrevailingInModule(Mod, DefinedGlobals); +#else + thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals); +#endif return true; } @@ -1637,7 +1746,11 @@ struct LLVMRustThinLTOBuffer { extern "C" LLVMRustThinLTOBuffer* LLVMRustThinLTOBufferCreate(LLVMModuleRef M) { +#if LLVM_VERSION_GE(10, 0) auto Ret = std::make_unique(); +#else + auto Ret = llvm::make_unique(); +#endif { raw_string_ostream OS(Ret->data); { @@ -1776,6 +1889,7 @@ LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) { // used during the normal linker-plugin incremental thin-LTO process. extern "C" void LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const char *ModId, LLVMRustThinLTOData *Data) { +#if LLVM_VERSION_GE(9, 0) SmallString<40> Key; llvm::lto::Config conf; const auto &ImportList = Data->ImportLists.lookup(ModId); @@ -1798,4 +1912,8 @@ LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const char *ModId, LLVMRustThin ); LLVMRustStringWriteImpl(KeyOut, Key.c_str(), Key.size()); +#else + // computeLTOCacheKey doesn't exist in LLVM 7 + LLVMRustStringWriteImpl(KeyOut, "", 0); +#endif } diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 9b757eb40c1..a62ce96d9bd 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -114,7 +114,9 @@ extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M, return wrap(unwrap(M) ->getOrInsertFunction(StringRef(Name, NameLen), unwrap(FunctionTy)) +#if LLVM_VERSION_GE(9, 0) .getCallee() +#endif ); } @@ -196,74 +198,175 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { case InaccessibleMemOnly: return Attribute::InaccessibleMemOnly; case SanitizeHWAddress: +#if LLVM_VERSION_GE(8, 0) return Attribute::SanitizeHWAddress; +#else + report_fatal_error("SanitizeHWAddress not supported in LLVM < 8"); +#endif case WillReturn: +#if LLVM_VERSION_GE(9, 0) return Attribute::WillReturn; +#else + report_fatal_error("WillReturn not supported in LLVM < 9"); +#endif } report_fatal_error("bad AttributeKind"); } +#if LLVM_VERSION_GE(9, 0) + #define LLVM_CALL_INST_OR_INVOKE_BASE CallBase +#else + // For LLVM < 9, we need to handle CallInst and InvokeInst separately + #define LLVM_CALL_INST_OR_INVOKE_BASE Instruction +#endif + extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index, LLVMRustAttribute RustAttr) { +#if LLVM_VERSION_GE(9, 0) CallBase *Call = unwrap(Instr); Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr)); Call->addAttribute(Index, Attr); +#else + Instruction *I = unwrap(Instr); + Attribute Attr = Attribute::get(I->getContext(), fromRust(RustAttr)); + if (CallInst *CI = dyn_cast(I)) { + CI->addAttribute(Index, Attr); + } else if (InvokeInst *II = dyn_cast(I)) { + II->addAttribute(Index, Attr); + } +#endif } extern "C" void LLVMRustAddCallSiteAttrString(LLVMValueRef Instr, unsigned Index, const char *Name) { +#if LLVM_VERSION_GE(9, 0) CallBase *Call = unwrap(Instr); Attribute Attr = Attribute::get(Call->getContext(), Name); Call->addAttribute(Index, Attr); +#else + Instruction *I = unwrap(Instr); + Attribute Attr = Attribute::get(I->getContext(), Name); + if (CallInst *CI = dyn_cast(I)) { + CI->addAttribute(Index, Attr); + } else if (InvokeInst *II = dyn_cast(I)) { + II->addAttribute(Index, Attr); + } +#endif } - extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr, unsigned Index, uint32_t Bytes) { +#if LLVM_VERSION_GE(9, 0) CallBase *Call = unwrap(Instr); AttrBuilder B; B.addAlignmentAttr(Bytes); Call->setAttributes(Call->getAttributes().addAttributes( Call->getContext(), Index, B)); +#else + Instruction *I = unwrap(Instr); + AttrBuilder B; + B.addAlignmentAttr(Bytes); + if (CallInst *CI = dyn_cast(I)) { + CI->setAttributes(CI->getAttributes().addAttributes( + CI->getContext(), Index, B)); + } else if (InvokeInst *II = dyn_cast(I)) { + II->setAttributes(II->getAttributes().addAttributes( + II->getContext(), Index, B)); + } +#endif } extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr, unsigned Index, uint64_t Bytes) { +#if LLVM_VERSION_GE(9, 0) CallBase *Call = unwrap(Instr); AttrBuilder B; B.addDereferenceableAttr(Bytes); Call->setAttributes(Call->getAttributes().addAttributes( Call->getContext(), Index, B)); +#else + Instruction *I = unwrap(Instr); + AttrBuilder B; + B.addDereferenceableAttr(Bytes); + if (CallInst *CI = dyn_cast(I)) { + CI->setAttributes(CI->getAttributes().addAttributes( + CI->getContext(), Index, B)); + } else if (InvokeInst *II = dyn_cast(I)) { + II->setAttributes(II->getAttributes().addAttributes( + II->getContext(), Index, B)); + } +#endif } extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr, unsigned Index, uint64_t Bytes) { +#if LLVM_VERSION_GE(9, 0) CallBase *Call = unwrap(Instr); AttrBuilder B; B.addDereferenceableOrNullAttr(Bytes); Call->setAttributes(Call->getAttributes().addAttributes( Call->getContext(), Index, B)); +#else + Instruction *I = unwrap(Instr); + AttrBuilder B; + B.addDereferenceableOrNullAttr(Bytes); + if (CallInst *CI = dyn_cast(I)) { + CI->setAttributes(CI->getAttributes().addAttributes( + CI->getContext(), Index, B)); + } else if (InvokeInst *II = dyn_cast(I)) { + II->setAttributes(II->getAttributes().addAttributes( + II->getContext(), Index, B)); + } +#endif } extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index, LLVMTypeRef Ty) { +#if LLVM_VERSION_GE(9, 0) CallBase *Call = unwrap(Instr); Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty)); Call->addAttribute(Index, Attr); +#elif LLVM_VERSION_GE(8, 0) + Instruction *I = unwrap(Instr); + Attribute Attr = Attribute::get(I->getContext(), Attribute::ByVal); + if (CallInst *CI = dyn_cast(I)) { + CI->addAttribute(Index, Attr); + } else if (InvokeInst *II = dyn_cast(I)) { + II->addAttribute(Index, Attr); + } +#else + Instruction *I = unwrap(Instr); + Attribute Attr = Attribute::get(I->getContext(), Attribute::ByVal); + if (CallInst *CI = dyn_cast(I)) { + CI->addAttribute(Index, Attr); + } else if (InvokeInst *II = dyn_cast(I)) { + II->addAttribute(Index, Attr); + } +#endif } extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned Index, LLVMTypeRef Ty) { - CallBase *Call = unwrap(Instr); #if LLVM_VERSION_GE(12, 0) + CallBase *Call = unwrap(Instr); Attribute Attr = Attribute::getWithStructRetType(Call->getContext(), unwrap(Ty)); -#else + Call->addAttribute(Index, Attr); +#elif LLVM_VERSION_GE(9, 0) + CallBase *Call = unwrap(Instr); Attribute Attr = Attribute::get(Call->getContext(), Attribute::StructRet); -#endif Call->addAttribute(Index, Attr); +#else + Instruction *I = unwrap(Instr); + Attribute Attr = Attribute::get(I->getContext(), Attribute::StructRet); + if (CallInst *CI = dyn_cast(I)) { + CI->addAttribute(Index, Attr); + } else if (InvokeInst *II = dyn_cast(I)) { + II->addAttribute(Index, Attr); + } +#endif } extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index, @@ -303,7 +406,11 @@ extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn, extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index, LLVMTypeRef Ty) { Function *F = unwrap(Fn); +#if LLVM_VERSION_GE(9, 0) Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty)); +#else + Attribute Attr = Attribute::get(F->getContext(), Attribute::ByVal); +#endif F->addAttribute(Index, Attr); } @@ -533,6 +640,11 @@ static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) { if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) { Result |= DINode::DIFlags::FlagAppleBlock; } +#if LLVM_VERSION_LT(10, 0) + if (isSet(Flags & LLVMRustDIFlags::FlagBlockByrefStruct)) { + Result |= DINode::DIFlags::FlagBlockByrefStruct; + } +#endif if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) { Result |= DINode::DIFlags::FlagVirtual; } @@ -612,6 +724,7 @@ inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) { return static_cast(static_cast(F) & 0x3); } +#if LLVM_VERSION_GE(8, 0) static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) { DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero; @@ -636,12 +749,15 @@ static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) { if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) { Result |= DISubprogram::DISPFlags::SPFlagOptimized; } +#if LLVM_VERSION_GE(9, 0) if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) { Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram; } +#endif return Result; } +#endif enum class LLVMRustDebugEmissionKind { NoDebug, @@ -763,8 +879,13 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction( LLVMMetadataRef Decl) { DITemplateParameterArray TParams = DITemplateParameterArray(unwrap(TParam)); +#if LLVM_VERSION_GE(8, 0) DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags); DINode::DIFlags llvmFlags = fromRust(Flags); +#if LLVM_VERSION_LT(9, 0) + if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) + llvmFlags |= DINode::DIFlags::FlagMainSubprogram; +#endif DISubprogram *Sub = Builder->createFunction( unwrapDI(Scope), StringRef(Name, NameLen), @@ -772,6 +893,22 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction( unwrapDI(File), LineNo, unwrapDI(Ty), ScopeLine, llvmFlags, llvmSPFlags, TParams, unwrapDIPtr(Decl)); +#else + bool IsLocalToUnit = isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit); + bool IsDefinition = isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition); + bool IsOptimized = isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized); + DINode::DIFlags llvmFlags = fromRust(Flags); + if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) + llvmFlags |= DINode::DIFlags::FlagMainSubprogram; + DISubprogram *Sub = Builder->createFunction( + unwrapDI(Scope), + StringRef(Name, NameLen), + StringRef(LinkageName, LinkageNameLen), + unwrapDI(File), LineNo, + unwrapDI(Ty), IsLocalToUnit, IsDefinition, + ScopeLine, llvmFlags, IsOptimized, TParams, + unwrapDIPtr(Decl)); +#endif if (MaybeFn) unwrap(MaybeFn)->setSubprogram(Sub); return wrap(Sub); @@ -897,9 +1034,13 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( unwrapDI(Context), StringRef(Name, NameLen), StringRef(LinkageName, LinkageNameLen), unwrapDI(File), LineNo, unwrapDI(Ty), IsLocalToUnit, +#if LLVM_VERSION_GE(10, 0) /* isDefined */ true, +#endif InitExpr, unwrapDIPtr(Decl), +#if LLVM_VERSION_GE(8, 0) /* templateParams */ nullptr, +#endif AlignInBits); InitVal->setMetadata("dbg", VarExpr); @@ -1097,7 +1238,11 @@ extern "C" void LLVMRustUnpackOptimizationDiagnostic( if (loc.isValid()) { *Line = loc.getLine(); *Column = loc.getColumn(); +#if LLVM_VERSION_GE(8, 0) FilenameOS << loc.getAbsolutePath(); +#else + FilenameOS << loc.getFilename(); +#endif } RawRustStringOstream MessageOS(MessageOut); @@ -1400,8 +1545,18 @@ extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, FunctionType *FTy = cast(Callee->getType()->getPointerElementType()); unsigned Len = Bundle ? 1 : 0; ArrayRef Bundles = makeArrayRef(Bundle, Len); +#if LLVM_VERSION_GE(8, 0) return wrap(unwrap(B)->CreateCall( FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles)); +#else + if (Len > 0) { + return wrap(unwrap(B)->CreateCall( + Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles)); + } else { + return wrap(unwrap(B)->CreateCall( + Callee, makeArrayRef(unwrap(Args), NumArgs))); + } +#endif } extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) { @@ -1413,28 +1568,47 @@ extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool IsVolatile) { +#if LLVM_VERSION_GE(10, 0) return wrap(unwrap(B)->CreateMemCpy( unwrap(Dst), MaybeAlign(DstAlign), unwrap(Src), MaybeAlign(SrcAlign), unwrap(Size), IsVolatile)); +#else + return wrap(unwrap(B)->CreateMemCpy( + unwrap(Dst), DstAlign, + unwrap(Src), SrcAlign, + unwrap(Size), IsVolatile)); +#endif } extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool IsVolatile) { +#if LLVM_VERSION_GE(10, 0) return wrap(unwrap(B)->CreateMemMove( unwrap(Dst), MaybeAlign(DstAlign), unwrap(Src), MaybeAlign(SrcAlign), unwrap(Size), IsVolatile)); +#else + return wrap(unwrap(B)->CreateMemMove( + unwrap(Dst), DstAlign, + unwrap(Src), SrcAlign, + unwrap(Size), IsVolatile)); +#endif } extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Val, LLVMValueRef Size, bool IsVolatile) { +#if LLVM_VERSION_GE(10, 0) return wrap(unwrap(B)->CreateMemSet( unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile)); +#else + return wrap(unwrap(B)->CreateMemSet( + unwrap(Dst), unwrap(Val), unwrap(Size), DstAlign, IsVolatile)); +#endif } extern "C" LLVMValueRef @@ -1446,9 +1620,21 @@ LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, FunctionType *FTy = cast(Callee->getType()->getPointerElementType()); unsigned Len = Bundle ? 1 : 0; ArrayRef Bundles = makeArrayRef(Bundle, Len); +#if LLVM_VERSION_GE(8, 0) return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch), makeArrayRef(unwrap(Args), NumArgs), Bundles, Name)); +#else + if (Len > 0) { + return wrap(unwrap(B)->CreateInvoke(Callee, unwrap(Then), unwrap(Catch), + makeArrayRef(unwrap(Args), NumArgs), + Bundles, Name)); + } else { + return wrap(unwrap(B)->CreateInvoke(Callee, unwrap(Then), unwrap(Catch), + makeArrayRef(unwrap(Args), NumArgs), + Name)); + } +#endif } extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, @@ -1624,7 +1810,11 @@ struct LLVMRustModuleBuffer { extern "C" LLVMRustModuleBuffer* LLVMRustModuleBufferCreate(LLVMModuleRef M) { +#if LLVM_VERSION_GE(10, 0) auto Ret = std::make_unique(); +#else + auto Ret = llvm::make_unique(); +#endif { raw_string_ostream OS(Ret->data); { @@ -1744,6 +1934,7 @@ extern "C" LLVMRustResult LLVMRustWriteImportLibrary( ConvertedExports.reserve(NumExports); for (size_t i = 0; i < NumExports; ++i) { +#if LLVM_VERSION_GE(8, 0) ConvertedExports.push_back(llvm::object::COFFShortExport{ Exports[i].name, // Name std::string{}, // ExtName @@ -1755,6 +1946,17 @@ extern "C" LLVMRustResult LLVMRustWriteImportLibrary( false, // Private false // Constant }); +#else + llvm::object::COFFShortExport exp; + exp.Name = Exports[i].name; + exp.ExtName = ""; + exp.Ordinal = 0; + exp.Noname = false; + exp.Data = false; + exp.Private = false; + exp.Constant = false; + ConvertedExports.push_back(exp); +#endif } auto Error = llvm::object::writeImportLibrary( diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index 122627eb500..dc21f75ec80 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -125,7 +125,10 @@ fn init() { } LLVMInitializeMSP430TargetInfo, LLVMInitializeMSP430Target, LLVMInitializeMSP430TargetMC, - LLVMInitializeMSP430AsmPrinter, + LLVMInitializeMSP430AsmPrinter + ); + init_target!( + all(llvm_component = "msp430", llvm_has_msp430_asm_parser), LLVMInitializeMSP430AsmParser ); init_target!( diff --git a/library/core/src/num/dec2flt/algorithm.rs b/library/core/src/num/dec2flt/algorithm.rs index 313b6870ac9..38554b460cd 100644 --- a/library/core/src/num/dec2flt/algorithm.rs +++ b/library/core/src/num/dec2flt/algorithm.rs @@ -62,9 +62,10 @@ fn set_cw(cw: u16) { // any `u16` unsafe { asm!( - "fldcw word ptr [{}]", + "fldcw ({})", in(reg) &cw, - options(nostack), + // We are using ATT syntax to support LLVM 8 and LLVM 9. + options(att_syntax, nostack), ) } } @@ -86,9 +87,10 @@ pub fn set_precision() -> FPUControlWord { // any `u16` unsafe { asm!( - "fnstcw word ptr [{}]", + "fnstcw ({})", in(reg) &mut cw, - options(nostack), + // We are using ATT syntax to support LLVM 8 and LLVM 9. + options(att_syntax, nostack), ) } diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs index 1b1f11798d7..2de6db762b2 100644 --- a/library/profiler_builtins/build.rs +++ b/library/profiler_builtins/build.rs @@ -24,11 +24,13 @@ fn main() { "InstrProfilingPlatformLinux.c", "InstrProfilingPlatformOther.c", "InstrProfilingPlatformWindows.c", - "InstrProfilingRuntime.cpp", "InstrProfilingUtil.c", "InstrProfilingValue.c", "InstrProfilingVersionVar.c", "InstrProfilingWriter.c", + // This file was renamed in LLVM 10. + "InstrProfilingRuntime.cc", + "InstrProfilingRuntime.cpp", // These files were added in LLVM 11. "InstrProfilingInternal.c", "InstrProfilingBiasVar.c", diff --git a/library/std/src/os/fortanix_sgx/arch.rs b/library/std/src/os/fortanix_sgx/arch.rs index b0170e67446..971cf1ee726 100644 --- a/library/std/src/os/fortanix_sgx/arch.rs +++ b/library/std/src/os/fortanix_sgx/arch.rs @@ -39,7 +39,8 @@ inout(reg) request => _, inlateout("eax") ENCLU_EGETKEY => error, in("rcx") out.as_mut_ptr(), - options(nostack), + // NOTE(#76738): ATT syntax is used to support LLVM 8 and 9. + options(att_syntax, nostack), ); match error { @@ -71,7 +72,8 @@ pub fn ereport( in("eax") ENCLU_EREPORT, in("rcx") reportdata, in("rdx") report.as_mut_ptr(), - options(preserves_flags, nostack), + // NOTE(#76738): ATT syntax is used to support LLVM 8 and 9. + options(att_syntax, preserves_flags, nostack), ); report.assume_init() diff --git a/library/std/src/sys/sgx/abi/mem.rs b/library/std/src/sys/sgx/abi/mem.rs index 1e743894a9f..3753fdd3536 100644 --- a/library/std/src/sys/sgx/abi/mem.rs +++ b/library/std/src/sys/sgx/abi/mem.rs @@ -36,9 +36,10 @@ pub fn image_base() -> u64 { let base: u64; unsafe { asm!( - "lea {}, qword ptr [rip + IMAGE_BASE]", + "lea IMAGE_BASE(%rip), {}", lateout(reg) base, - options(nostack, preserves_flags, nomem, pure), + // NOTE(#76738): ATT syntax is used to support LLVM 8 and 9. + options(att_syntax, nostack, preserves_flags, nomem, pure), ) }; base diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 449fdb87b02..d4b3f8b7831 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -347,11 +347,11 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) { let version = output(cmd.arg("--version")); let mut parts = version.split('.').take(2).filter_map(|s| s.parse::().ok()); if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) { - if major >= 10 { + if major >= 7 { return; } } - panic!("\n\nbad LLVM version: {}, need >=10.0\n\n", version) + panic!("\n\nbad LLVM version: {}, need >=7.0\n\n", version) } fn configure_cmake( diff --git a/src/test/codegen/abi-efiapi.rs b/src/test/codegen/abi-efiapi.rs index 613b0bf50e5..19bbf840045 100644 --- a/src/test/codegen/abi-efiapi.rs +++ b/src/test/codegen/abi-efiapi.rs @@ -1,6 +1,7 @@ // Checks if the correct annotation for the efiapi ABI is passed to llvm. // revisions:x86_64 i686 aarch64 arm riscv +// min-llvm-version: 9.0 // needs-llvm-components: aarch64 arm riscv //[x86_64] compile-flags: --target x86_64-unknown-uefi diff --git a/src/test/codegen/enum-debug-clike.rs b/src/test/codegen/enum-debug-clike.rs index 1e369a2c4e6..6ac01d05603 100644 --- a/src/test/codegen/enum-debug-clike.rs +++ b/src/test/codegen/enum-debug-clike.rs @@ -1,13 +1,17 @@ -// This tests that debug info for "c-like" enums is properly emitted. -// This is ignored for the fallback mode on MSVC due to problems with PDB. +// This test depends on a patch that was committed to upstream LLVM +// before 7.0, then backported to the Rust LLVM fork. It tests that +// debug info for "c-like" enums is properly emitted. -// // ignore-msvc +// min-system-llvm-version 8.0 // compile-flags: -g -C no-prepopulate-passes +// DIFlagFixedEnum was deprecated in 8.0, renamed to DIFlagEnumClass. +// We match either for compatibility. + // CHECK-LABEL: @main -// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_enumeration_type,{{.*}}name: "E",{{.*}}flags: DIFlagEnumClass,{{.*}} +// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_enumeration_type,{{.*}}name: "E",{{.*}}flags: {{(DIFlagEnumClass|DIFlagFixedEnum)}},{{.*}} // CHECK: {{.*}}DIEnumerator{{.*}}name: "A",{{.*}}value: {{[0-9].*}} // CHECK: {{.*}}DIEnumerator{{.*}}name: "B",{{.*}}value: {{[0-9].*}} // CHECK: {{.*}}DIEnumerator{{.*}}name: "C",{{.*}}value: {{[0-9].*}} diff --git a/src/test/codegen/enum-debug-niche-2.rs b/src/test/codegen/enum-debug-niche-2.rs index 9c72ad9d248..6143ba7f556 100644 --- a/src/test/codegen/enum-debug-niche-2.rs +++ b/src/test/codegen/enum-debug-niche-2.rs @@ -1,8 +1,9 @@ -// This tests that optimized enum debug info accurately reflects the enum layout. -// This is ignored for the fallback mode on MSVC due to problems with PDB. +// This test depends on a patch that was committed to upstream LLVM +// before 7.0, then backported to the Rust LLVM fork. It tests that +// optimized enum debug info accurately reflects the enum layout. -// // ignore-msvc +// min-system-llvm-version 8.0 // compile-flags: -g -C no-prepopulate-passes diff --git a/src/test/codegen/enum-debug-niche.rs b/src/test/codegen/enum-debug-niche.rs index b718a6854dd..737335a5081 100644 --- a/src/test/codegen/enum-debug-niche.rs +++ b/src/test/codegen/enum-debug-niche.rs @@ -1,7 +1,9 @@ -// This tests that optimized enum debug info accurately reflects the enum layout. -// This is ignored for the fallback mode on MSVC due to problems with PDB. +// This test depends on a patch that was committed to upstream LLVM +// before 7.0, then backported to the Rust LLVM fork. It tests that +// optimized enum debug info accurately reflects the enum layout. // ignore-msvc +// min-system-llvm-version 8.0 // compile-flags: -g -C no-prepopulate-passes diff --git a/src/test/codegen/enum-debug-tagged.rs b/src/test/codegen/enum-debug-tagged.rs index 095c49ac3ac..e3b5e62d4ba 100644 --- a/src/test/codegen/enum-debug-tagged.rs +++ b/src/test/codegen/enum-debug-tagged.rs @@ -1,6 +1,8 @@ -// This tests that debug info for tagged (ordinary) enums is properly emitted. -// This is ignored for the fallback mode on MSVC due to problems with PDB. +// This test depends on a patch that was committed to upstream LLVM +// before 7.0, then backported to the Rust LLVM fork. It tests that +// debug info for tagged (ordinary) enums is properly emitted. +// min-system-llvm-version 8.0 // ignore-msvc // compile-flags: -g -C no-prepopulate-passes diff --git a/src/test/codegen/force-frame-pointers.rs b/src/test/codegen/force-frame-pointers.rs index 637c4234654..4c94a601f33 100644 --- a/src/test/codegen/force-frame-pointers.rs +++ b/src/test/codegen/force-frame-pointers.rs @@ -1,3 +1,4 @@ +// min-llvm-version 8.0 // compile-flags: -C no-prepopulate-passes -C force-frame-pointers=y #![crate_type="lib"] diff --git a/src/test/codegen/force-unwind-tables.rs b/src/test/codegen/force-unwind-tables.rs index 4c0a5602c6d..eba4a7469f9 100644 --- a/src/test/codegen/force-unwind-tables.rs +++ b/src/test/codegen/force-unwind-tables.rs @@ -1,3 +1,4 @@ +// min-llvm-version: 8.0 // compile-flags: -C no-prepopulate-passes -C force-unwind-tables=y #![crate_type="lib"] diff --git a/src/test/codegen/instrument-mcount.rs b/src/test/codegen/instrument-mcount.rs index b26076e7a7b..e4e6d5ca2b8 100644 --- a/src/test/codegen/instrument-mcount.rs +++ b/src/test/codegen/instrument-mcount.rs @@ -1,4 +1,5 @@ -// +// min-llvm-version 8.0 +// ignore-tidy-linelength // compile-flags: -Z instrument-mcount #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs index 7d9b0d2a77b..63b1ebdad9e 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs @@ -1,5 +1,6 @@ // // compile-flags: -C no-prepopulate-passes +// min-llvm-version 8.0 #![crate_type = "lib"] diff --git a/src/test/debuginfo/borrowed-enum.rs b/src/test/debuginfo/borrowed-enum.rs index f3e465dc652..273e6b9b977 100644 --- a/src/test/debuginfo/borrowed-enum.rs +++ b/src/test/debuginfo/borrowed-enum.rs @@ -1,4 +1,5 @@ -// Require a gdb or lldb that can read DW_TAG_variant_part. +// Require LLVM with DW_TAG_variant_part and a gdb or lldb that can read it. +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // rust-lldb diff --git a/src/test/debuginfo/enum-thinlto.rs b/src/test/debuginfo/enum-thinlto.rs index b10e04a4a9e..de8dfb12dc4 100644 --- a/src/test/debuginfo/enum-thinlto.rs +++ b/src/test/debuginfo/enum-thinlto.rs @@ -1,4 +1,5 @@ -// Require a gdb that can read DW_TAG_variant_part. +// Require LLVM with DW_TAG_variant_part and a gdb that can read it. +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // compile-flags:-g -Z thinlto diff --git a/src/test/debuginfo/generator-objects.rs b/src/test/debuginfo/generator-objects.rs index 1beed1c835d..2c36adc1621 100644 --- a/src/test/debuginfo/generator-objects.rs +++ b/src/test/debuginfo/generator-objects.rs @@ -1,4 +1,5 @@ -// Require a gdb that can read DW_TAG_variant_part. +// Require LLVM with DW_TAG_variant_part and a gdb that can read it. +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // LLDB without native Rust support cannot read DW_TAG_variant_part, diff --git a/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs b/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs index adcb04da30d..72d38a6f045 100644 --- a/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs +++ b/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs @@ -1,7 +1,8 @@ // ignore-lldb: FIXME(#27089) // min-lldb-version: 310 -// Require a gdb that can read DW_TAG_variant_part. +// Require LLVM with DW_TAG_variant_part and a gdb that can read it. +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // compile-flags:-g diff --git a/src/test/debuginfo/generic-struct-style-enum.rs b/src/test/debuginfo/generic-struct-style-enum.rs index 764330ae27f..3fae6a239a4 100644 --- a/src/test/debuginfo/generic-struct-style-enum.rs +++ b/src/test/debuginfo/generic-struct-style-enum.rs @@ -1,6 +1,7 @@ // min-lldb-version: 310 -// Require a gdb that can read DW_TAG_variant_part. +// Require LLVM with DW_TAG_variant_part and a gdb that can read it. +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // compile-flags:-g diff --git a/src/test/debuginfo/generic-tuple-style-enum.rs b/src/test/debuginfo/generic-tuple-style-enum.rs index 60362e54e7d..5b57750718d 100644 --- a/src/test/debuginfo/generic-tuple-style-enum.rs +++ b/src/test/debuginfo/generic-tuple-style-enum.rs @@ -1,4 +1,5 @@ -// Require a gdb or lldb that can read DW_TAG_variant_part. +// Require LLVM with DW_TAG_variant_part and a gdb and lldb that can read it. +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // rust-lldb diff --git a/src/test/debuginfo/issue-57822.rs b/src/test/debuginfo/issue-57822.rs index 6b2b12edda5..59985db1c3d 100644 --- a/src/test/debuginfo/issue-57822.rs +++ b/src/test/debuginfo/issue-57822.rs @@ -1,7 +1,8 @@ // This test makes sure that the LLDB pretty printer does not throw an exception // for nested closures and generators. -// Require a gdb that can read DW_TAG_variant_part. +// Require LLVM with DW_TAG_variant_part and a gdb that can read it. +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // compile-flags:-g diff --git a/src/test/debuginfo/recursive-struct.rs b/src/test/debuginfo/recursive-struct.rs index c0bd6736701..4f75ef4fa9b 100644 --- a/src/test/debuginfo/recursive-struct.rs +++ b/src/test/debuginfo/recursive-struct.rs @@ -1,6 +1,7 @@ // ignore-lldb -// Require a gdb that can read DW_TAG_variant_part. +// Require LLVM with DW_TAG_variant_part and a gdb that can read it. +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // compile-flags:-g diff --git a/src/test/debuginfo/struct-style-enum.rs b/src/test/debuginfo/struct-style-enum.rs index 3d819e36898..465471010ba 100644 --- a/src/test/debuginfo/struct-style-enum.rs +++ b/src/test/debuginfo/struct-style-enum.rs @@ -1,4 +1,5 @@ -// Require a gdb or lldb that can read DW_TAG_variant_part. +// Require LLVM with DW_TAG_variant_part and a gdb and lldb that can read it. +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // rust-lldb diff --git a/src/test/debuginfo/tuple-style-enum.rs b/src/test/debuginfo/tuple-style-enum.rs index 39ead172e65..d26fc08f202 100644 --- a/src/test/debuginfo/tuple-style-enum.rs +++ b/src/test/debuginfo/tuple-style-enum.rs @@ -1,4 +1,5 @@ -// Require a gdb or lldb that can read DW_TAG_variant_part. +// Require LLVM with DW_TAG_variant_part and a gdb and lldb that can read it. +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // rust-lldb diff --git a/src/test/debuginfo/unique-enum.rs b/src/test/debuginfo/unique-enum.rs index 9d938b6e369..2be94574943 100644 --- a/src/test/debuginfo/unique-enum.rs +++ b/src/test/debuginfo/unique-enum.rs @@ -1,4 +1,5 @@ -// Require a gdb or lldb that can read DW_TAG_variant_part. +// Require LLVM with DW_TAG_variant_part and a gdb and lldb that can read it. +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // rust-lldb diff --git a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs index 1542c7f3118..9439df266d5 100644 --- a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs +++ b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs @@ -2,6 +2,7 @@ // being run when compiling with new LLVM pass manager and ThinLTO. // Note: The issue occurred only on non-zero opt-level. // +// min-llvm-version: 9.0 // needs-sanitizer-support // needs-sanitizer-address // diff --git a/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs b/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs index c11d14b99d4..f4627028cfa 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs @@ -1,5 +1,6 @@ // run-pass // ignore-emscripten +// min-llvm-version 8.0 #![allow(non_camel_case_types)] #![feature(repr_simd, platform_intrinsics)] diff --git a/src/test/ui/simd/simd-intrinsic-generic-reduction.rs b/src/test/ui/simd/simd-intrinsic-generic-reduction.rs index 7193fb3527f..8b5afeac0bc 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-reduction.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-reduction.rs @@ -2,6 +2,7 @@ #![allow(non_camel_case_types)] // ignore-emscripten +// min-system-llvm-version: 9.0 // Test that the simd_reduce_{op} intrinsics produce the correct results.