From 2967036f57675dbf3e00713d9d9d27956db068e4 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 25 Jul 2021 21:54:48 +0200 Subject: [PATCH 01/12] Update codegen tests for LLVM 13 --- src/test/codegen/array-equality.rs | 4 ++-- src/test/codegen/repeat-trusted-len.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/codegen/array-equality.rs b/src/test/codegen/array-equality.rs index 4b60fa4b0bff..fefc232b4904 100644 --- a/src/test/codegen/array-equality.rs +++ b/src/test/codegen/array-equality.rs @@ -29,7 +29,7 @@ pub fn array_eq_value_still_passed_by_pointer(a: [u16; 9], b: [u16; 9]) -> bool // CHECK-NEXT: start: // CHECK-NEXT: bitcast // CHECK-NEXT: bitcast - // CHECK-NEXT: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(i8* nonnull dereferenceable(18) %{{.+}}, i8* nonnull dereferenceable(18) %{{.+}}, i64 18) + // CHECK-NEXT: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(i8* {{.*}} dereferenceable(18) %{{.+}}, i8* {{.*}} dereferenceable(18) %{{.+}}, i64 18) // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0 // CHECK-NEXT: ret i1 %[[EQ]] a == b @@ -41,7 +41,7 @@ pub fn array_eq_long(a: &[u16; 1234], b: &[u16; 1234]) -> bool { // CHECK-NEXT: start: // CHECK-NEXT: bitcast // CHECK-NEXT: bitcast - // CHECK-NEXT: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(i8* nonnull dereferenceable(2468) %{{.+}}, i8* nonnull dereferenceable(2468) %{{.+}}, i64 2468) + // CHECK-NEXT: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(i8* {{.*}} dereferenceable(2468) %{{.+}}, i8* {{.*}} dereferenceable(2468) %{{.+}}, i64 2468) // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0 // CHECK-NEXT: ret i1 %[[EQ]] a == b diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs index 9e904fc82ab4..cb2d0ef809af 100644 --- a/src/test/codegen/repeat-trusted-len.rs +++ b/src/test/codegen/repeat-trusted-len.rs @@ -8,6 +8,6 @@ use std::iter; // CHECK-LABEL: @repeat_take_collect #[no_mangle] pub fn repeat_take_collect() -> Vec { -// CHECK: call void @llvm.memset.p0i8.i{{[0-9]+}}(i8* {{(nonnull )?}}align 1{{.*}} %{{[0-9]+}}, i8 42, i{{[0-9]+}} 100000, i1 false) +// CHECK: call void @llvm.memset.p0i8.i{{[0-9]+}}(i8* {{.*}}align 1{{.*}} %{{[0-9]+}}, i8 42, i{{[0-9]+}} 100000, i1 false) iter::repeat(42).take(100000).collect() } From 621f5146c331ada06c6ff581edd0dbc23ffbb763 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 28 Jul 2021 21:31:47 +0200 Subject: [PATCH 02/12] Handle SrcMgr diagnostics This is how InlineAsm diagnostics with source information are reported now. Previously a separate InlineAsm diagnostic handler was used. --- compiler/rustc_codegen_llvm/src/back/write.rs | 43 +-------- .../rustc_codegen_llvm/src/llvm/diagnostic.rs | 96 +++++++++++++++---- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 7 +- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 20 +++- src/test/ui/llvm-asm/issue-69092.rs | 4 +- src/test/ui/llvm-asm/issue-69092.stderr | 4 +- 6 files changed, 108 insertions(+), 66 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 5b4a187a1d56..791604a18273 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -296,39 +296,8 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void } let (cgcx, _) = *(user as *const (&CodegenContext, &Handler)); - // Recover the post-substitution assembly code from LLVM for better - // diagnostics. - let mut have_source = false; - let mut buffer = String::new(); - let mut level = llvm::DiagnosticLevel::Error; - let mut loc = 0; - let mut ranges = [0; 8]; - let mut num_ranges = ranges.len() / 2; - let msg = llvm::build_string(|msg| { - buffer = llvm::build_string(|buffer| { - have_source = llvm::LLVMRustUnpackSMDiagnostic( - diag, - msg, - buffer, - &mut level, - &mut loc, - ranges.as_mut_ptr(), - &mut num_ranges, - ); - }) - .expect("non-UTF8 inline asm"); - }) - .expect("non-UTF8 SMDiagnostic"); - - let source = have_source.then(|| { - let mut spans = vec![InnerSpan::new(loc as usize, loc as usize)]; - for i in 0..num_ranges { - spans.push(InnerSpan::new(ranges[i * 2] as usize, ranges[i * 2 + 1] as usize)); - } - (buffer, spans) - }); - - report_inline_asm(cgcx, msg, level, cookie, source); + let smdiag = llvm::diagnostic::SrcMgrDiagnostic::unpack(diag); + report_inline_asm(cgcx, smdiag.message, smdiag.level, cookie, smdiag.source); } unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) { @@ -339,13 +308,7 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void match llvm::diagnostic::Diagnostic::unpack(info) { llvm::diagnostic::InlineAsm(inline) => { - report_inline_asm( - cgcx, - llvm::twine_to_string(inline.message), - inline.level, - inline.cookie, - None, - ); + report_inline_asm(cgcx, inline.message, inline.level, inline.cookie, inline.source); } llvm::diagnostic::Optimization(opt) => { diff --git a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs index ccd3e42e458f..36aa022d7465 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs @@ -6,7 +6,8 @@ pub use self::OptimizationDiagnosticKind::*; use crate::value::Value; use libc::c_uint; -use super::{DiagnosticInfo, Twine}; +use super::{DiagnosticInfo, SMDiagnostic}; +use rustc_span::InnerSpan; #[derive(Copy, Clone)] pub enum OptimizationDiagnosticKind { @@ -86,36 +87,91 @@ impl OptimizationDiagnostic<'ll> { } } -#[derive(Copy, Clone)] -pub struct InlineAsmDiagnostic<'ll> { +pub struct SrcMgrDiagnostic { pub level: super::DiagnosticLevel, - pub cookie: c_uint, - pub message: &'ll Twine, - pub instruction: Option<&'ll Value>, + pub message: String, + pub source: Option<(String, Vec)>, } -impl InlineAsmDiagnostic<'ll> { - unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self { +impl SrcMgrDiagnostic { + pub unsafe fn unpack(diag: &SMDiagnostic) -> SrcMgrDiagnostic { + // Recover the post-substitution assembly code from LLVM for better + // diagnostics. + let mut have_source = false; + let mut buffer = String::new(); + let mut level = super::DiagnosticLevel::Error; + let mut loc = 0; + let mut ranges = [0; 8]; + let mut num_ranges = ranges.len() / 2; + let message = super::build_string(|message| { + buffer = super::build_string(|buffer| { + have_source = super::LLVMRustUnpackSMDiagnostic( + diag, + message, + buffer, + &mut level, + &mut loc, + ranges.as_mut_ptr(), + &mut num_ranges, + ); + }) + .expect("non-UTF8 inline asm"); + }) + .expect("non-UTF8 SMDiagnostic"); + + SrcMgrDiagnostic { + message, + level, + source: have_source.then(|| { + let mut spans = vec![InnerSpan::new(loc as usize, loc as usize)]; + for i in 0..num_ranges { + spans.push(InnerSpan::new(ranges[i * 2] as usize, ranges[i * 2 + 1] as usize)); + } + (buffer, spans) + }), + } + } +} + +#[derive(Clone)] +pub struct InlineAsmDiagnostic { + pub level: super::DiagnosticLevel, + pub cookie: c_uint, + pub message: String, + pub source: Option<(String, Vec)>, +} + +impl InlineAsmDiagnostic { + unsafe fn unpackInlineAsm(di: &'ll DiagnosticInfo) -> Self { let mut cookie = 0; let mut message = None; - let mut instruction = None; let mut level = super::DiagnosticLevel::Error; - super::LLVMRustUnpackInlineAsmDiagnostic( - di, - &mut level, - &mut cookie, - &mut message, - &mut instruction, - ); + super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut level, &mut cookie, &mut message); - InlineAsmDiagnostic { level, cookie, message: message.unwrap(), instruction } + InlineAsmDiagnostic { + level, + cookie, + message: super::twine_to_string(message.unwrap()), + source: None, + } + } + + unsafe fn unpackSrcMgr(di: &'ll DiagnosticInfo) -> Self { + let mut cookie = 0; + let smdiag = SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie)); + InlineAsmDiagnostic { + level: smdiag.level, + cookie, + message: smdiag.message, + source: smdiag.source, + } } } pub enum Diagnostic<'ll> { Optimization(OptimizationDiagnostic<'ll>), - InlineAsm(InlineAsmDiagnostic<'ll>), + InlineAsm(InlineAsmDiagnostic), PGO(&'ll DiagnosticInfo), Linker(&'ll DiagnosticInfo), Unsupported(&'ll DiagnosticInfo), @@ -130,7 +186,7 @@ impl Diagnostic<'ll> { let kind = super::LLVMRustGetDiagInfoKind(di); match kind { - Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpack(di)), + Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpackInlineAsm(di)), Dk::OptimizationRemark => { Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di)) @@ -162,6 +218,8 @@ impl Diagnostic<'ll> { Dk::Linker => Linker(di), Dk::Unsupported => Unsupported(di), + Dk::SrcMgr => InlineAsm(InlineAsmDiagnostic::unpackSrcMgr(di)), + _ => UnknownDiagnostic(di), } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 57173a49107a..3f2ed02d90df 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -490,6 +490,7 @@ pub enum DiagnosticKind { PGOProfile, Linker, Unsupported, + SrcMgr, } /// LLVMRustDiagnosticLevel @@ -2264,13 +2265,17 @@ extern "C" { level_out: &mut DiagnosticLevel, cookie_out: &mut c_uint, message_out: &mut Option<&'a Twine>, - instruction_out: &mut Option<&'a Value>, ); #[allow(improper_ctypes)] pub fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString); pub fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind; + pub fn LLVMRustGetSMDiagnostic( + DI: &'a DiagnosticInfo, + cookie_out: &mut c_uint, + ) -> &'a SMDiagnostic; + pub fn LLVMRustSetInlineAsmDiagnosticHandler( C: &Context, H: InlineAsmDiagHandler, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 52566b19eca0..4edfed034018 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1114,15 +1114,13 @@ extern "C" void LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, LLVMRustDiagnosticLevel *LevelOut, unsigned *CookieOut, - LLVMTwineRef *MessageOut, - LLVMValueRef *InstructionOut) { + LLVMTwineRef *MessageOut) { // Undefined to call this not on an inline assembly diagnostic! llvm::DiagnosticInfoInlineAsm *IA = static_cast(unwrap(DI)); *CookieOut = IA->getLocCookie(); *MessageOut = wrap(&IA->getMsgStr()); - *InstructionOut = wrap(IA->getInstruction()); switch (IA->getSeverity()) { case DS_Error: @@ -1165,6 +1163,7 @@ enum class LLVMRustDiagnosticKind { PGOProfile, Linker, Unsupported, + SrcMgr, }; static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) { @@ -1193,6 +1192,10 @@ static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) { return LLVMRustDiagnosticKind::Linker; case DK_Unsupported: return LLVMRustDiagnosticKind::Unsupported; +#if LLVM_VERSION_GE(13, 0) + case DK_SrcMgr: + return LLVMRustDiagnosticKind::SrcMgr; +#endif default: return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark) ? LLVMRustDiagnosticKind::OptimizationRemarkOther @@ -1280,6 +1283,17 @@ extern "C" void LLVMRustSetInlineAsmDiagnosticHandler( #endif } +extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic( + LLVMDiagnosticInfoRef DI, unsigned *Cookie) { +#if LLVM_VERSION_GE(13, 0) + llvm::DiagnosticInfoSrcMgr *SM = static_cast(unwrap(DI)); + *Cookie = SM->getLocCookie(); + return wrap(&SM->getSMDiag()); +#else + report_fatal_error("Shouldn't get called on older versions"); +#endif +} + extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, RustStringRef MessageOut, RustStringRef BufferOut, diff --git a/src/test/ui/llvm-asm/issue-69092.rs b/src/test/ui/llvm-asm/issue-69092.rs index 26fccec80f18..ea1b80cc9b06 100644 --- a/src/test/ui/llvm-asm/issue-69092.rs +++ b/src/test/ui/llvm-asm/issue-69092.rs @@ -1,5 +1,7 @@ // build-fail // ignore-emscripten no asm! support +// The error message differs slightly between LLVM versions +// min-llvm-version: 13.0 // Regression test for #69092 #![feature(llvm_asm)] @@ -7,5 +9,5 @@ fn main() { unsafe { llvm_asm!(".ascii \"Xen\0\""); } - //~^ ERROR: expected string in '.ascii' directive + //~^ ERROR: expected string } diff --git a/src/test/ui/llvm-asm/issue-69092.stderr b/src/test/ui/llvm-asm/issue-69092.stderr index 15a35e43c270..28c5fbbca3c6 100644 --- a/src/test/ui/llvm-asm/issue-69092.stderr +++ b/src/test/ui/llvm-asm/issue-69092.stderr @@ -1,5 +1,5 @@ -error: expected string in '.ascii' directive - --> $DIR/issue-69092.rs:9:14 +error: expected string + --> $DIR/issue-69092.rs:11:14 | LL | unsafe { llvm_asm!(".ascii \"Xen\0\""); } | ^ From 335f003b0241ec544bd337afba91c7d447b05dbe Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 28 Jul 2021 22:15:51 +0200 Subject: [PATCH 03/12] Remove codegen/issue-83623-SIMD-PartialEq.rs This has regressed due to https://bugs.llvm.org/show_bug.cgi?id=51211. It's pretty likely that we'll have to eat this regression for this release. --- .../codegen/issue-83623-SIMD-PartialEq.rs | 46 ------------------- 1 file changed, 46 deletions(-) delete mode 100644 src/test/codegen/issue-83623-SIMD-PartialEq.rs diff --git a/src/test/codegen/issue-83623-SIMD-PartialEq.rs b/src/test/codegen/issue-83623-SIMD-PartialEq.rs deleted file mode 100644 index b22b7f52402d..000000000000 --- a/src/test/codegen/issue-83623-SIMD-PartialEq.rs +++ /dev/null @@ -1,46 +0,0 @@ -// This test checks that jumps generated by logical operators can be optimized away - -// compile-flags: -Copt-level=3 -// only-64bit - -#![crate_type="lib"] - -pub struct Blueprint { - pub fuel_tank_size: u32, - pub payload: u32, - pub wheel_diameter: u32, - pub wheel_width: u32, - pub storage: u32, -} - -// && chains should not prevent SIMD optimizations for primitives -impl PartialEq for Blueprint{ - fn eq(&self, other: &Self)->bool{ - // CHECK-NOT: call{{.*}}bcmp - // CHECK-NOT: call{{.*}}memcmp - // CHECK-NOT: br {{.*}} - self.fuel_tank_size == other.fuel_tank_size - && self.payload == other.payload - && self.wheel_diameter == other.wheel_diameter - && self.wheel_width == other.wheel_width - && self.storage == other.storage - } -} - -#[derive(PartialEq)] -pub struct Blueprint2 { - pub fuel_tank_size: u32, - pub payload: u32, - pub wheel_diameter: u32, - pub wheel_width: u32, - pub storage: u32, -} - -// Derived PartialEq should not generate jumps and should use SIMD -#[no_mangle] -pub fn partial_eq_should_not_jump(a: &Blueprint2, b:&Blueprint2)->bool{ - // CHECK-NOT: call{{.*}}bcmp - // CHECK-NOT: call{{.*}}memcmp - // CHECK-NOT: br {{.*}} - a==b -} From 6eaf227ce15c37dedb07696209dab03629990204 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 28 Jul 2021 22:26:14 +0200 Subject: [PATCH 04/12] Update wasm data layout --- compiler/rustc_codegen_llvm/src/context.rs | 8 ++++++++ .../rustc_target/src/spec/wasm32_unknown_emscripten.rs | 2 +- compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs | 2 +- compiler/rustc_target/src/spec/wasm32_wasi.rs | 2 +- compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs | 2 +- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 5d56c93f835d..e204606443ab 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -132,6 +132,14 @@ pub unsafe fn create_module( if llvm_util::get_version() < (12, 0, 0) && sess.target.arch == "powerpc64" { target_data_layout = strip_powerpc64_vectors(target_data_layout); } + if llvm_util::get_version() < (13, 0, 0) { + if sess.target.arch == "wasm32" { + target_data_layout = "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(); + } + if sess.target.arch == "wasm64" { + target_data_layout = "e-m:e-p:64:64-i64:64-n32:64-S128".to_string(); + } + } // Ensure the data-layout values hardcoded remain the defaults. if sess.target.is_builtin { diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs index 302139395d31..86b1a7552335 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs @@ -43,7 +43,7 @@ pub fn target() -> Target { Target { llvm_target: "wasm32-unknown-emscripten".to_string(), pointer_width: 32, - data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-f128:64-n32:64-S128-ni:1:10:20".to_string(), arch: "wasm32".to_string(), options: opts, } diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs index 834c4dbfc05f..134c6803b15d 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs @@ -54,7 +54,7 @@ pub fn target() -> Target { Target { llvm_target: "wasm32-unknown-unknown".to_string(), pointer_width: 32, - data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20".to_string(), arch: "wasm32".to_string(), options, } diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs index a6b12d2ee8f6..2dab206dc760 100644 --- a/compiler/rustc_target/src/spec/wasm32_wasi.rs +++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs @@ -109,7 +109,7 @@ pub fn target() -> Target { Target { llvm_target: "wasm32-wasi".to_string(), pointer_width: 32, - data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20".to_string(), arch: "wasm32".to_string(), options, } diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs index 8bfb229d77f6..fb6526c0e720 100644 --- a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs @@ -32,7 +32,7 @@ pub fn target() -> Target { Target { llvm_target: "wasm64-unknown-unknown".to_string(), pointer_width: 64, - data_layout: "e-m:e-p:64:64-i64:64-n32:64-S128".to_string(), + data_layout: "e-m:e-p:64:64-i64:64-n32:64-S128-ni:1:10:20".to_string(), arch: "wasm64".to_string(), options, } From b5cc03b71ad1c33417ba31f8f2988328e34dac25 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 28 Jul 2021 22:48:45 +0200 Subject: [PATCH 05/12] Update powerpc64 data layout --- compiler/rustc_codegen_llvm/src/context.rs | 9 ++++----- .../rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs | 2 +- .../src/spec/powerpc64_unknown_linux_musl.rs | 2 +- compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs | 2 +- .../src/spec/powerpc64le_unknown_linux_gnu.rs | 2 +- .../src/spec/powerpc64le_unknown_linux_musl.rs | 2 +- 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index e204606443ab..a469a13bc729 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -115,10 +115,6 @@ fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode { } } -fn strip_powerpc64_vectors(data_layout: String) -> String { - data_layout.replace("-v256:256:256-v512:512:512", "") -} - pub unsafe fn create_module( tcx: TyCtxt<'_>, llcx: &'ll llvm::Context, @@ -130,9 +126,12 @@ pub unsafe fn create_module( let mut target_data_layout = sess.target.data_layout.clone(); if llvm_util::get_version() < (12, 0, 0) && sess.target.arch == "powerpc64" { - target_data_layout = strip_powerpc64_vectors(target_data_layout); + target_data_layout = target_data_layout.replace("-v256:256:256-v512:512:512", ""); } if llvm_util::get_version() < (13, 0, 0) { + if sess.target.arch == "powerpc64" { + target_data_layout = target_data_layout.replace("-S128", ""); + } if sess.target.arch == "wasm32" { target_data_layout = "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(); } diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs index 559a1a40868f..f10d4d49bb90 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs @@ -14,7 +14,7 @@ pub fn target() -> Target { Target { llvm_target: "powerpc64-unknown-linux-gnu".to_string(), pointer_width: 64, - data_layout: "E-m:e-i64:64-n32:64-v256:256:256-v512:512:512".to_string(), + data_layout: "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".to_string(), arch: "powerpc64".to_string(), options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs index f1190b159aba..611621727bd1 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs @@ -10,7 +10,7 @@ pub fn target() -> Target { Target { llvm_target: "powerpc64-unknown-linux-musl".to_string(), pointer_width: 64, - data_layout: "E-m:e-i64:64-n32:64-v256:256:256-v512:512:512".to_string(), + data_layout: "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".to_string(), arch: "powerpc64".to_string(), options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs index 3ebc5469e0a8..9c63997ce2f9 100644 --- a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs @@ -10,7 +10,7 @@ pub fn target() -> Target { Target { llvm_target: "powerpc64-unknown-linux-gnu".to_string(), pointer_width: 64, - data_layout: "E-m:e-i64:64-n32:64-v256:256:256-v512:512:512".to_string(), + data_layout: "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".to_string(), arch: "powerpc64".to_string(), options: TargetOptions { endian: Endian::Big, ..base }, } diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs index 76f70e474f07..f645eceadfe3 100644 --- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs @@ -9,7 +9,7 @@ pub fn target() -> Target { Target { llvm_target: "powerpc64le-unknown-linux-gnu".to_string(), pointer_width: 64, - data_layout: "e-m:e-i64:64-n32:64-v256:256:256-v512:512:512".to_string(), + data_layout: "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".to_string(), arch: "powerpc64".to_string(), options: TargetOptions { mcount: "_mcount".to_string(), ..base }, } diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs index 42c49103b3b4..934371fb2211 100644 --- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs @@ -9,7 +9,7 @@ pub fn target() -> Target { Target { llvm_target: "powerpc64le-unknown-linux-musl".to_string(), pointer_width: 64, - data_layout: "e-m:e-i64:64-n32:64-v256:256:256-v512:512:512".to_string(), + data_layout: "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".to_string(), arch: "powerpc64".to_string(), options: TargetOptions { mcount: "_mcount".to_string(), ..base }, } From 154c8408e9f9d90d82aa3060ed13732c955f0c53 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 29 Jul 2021 21:12:45 +0200 Subject: [PATCH 06/12] Update coverage LLVM IR test This uses comdats since LLVM 13, causing various minor changes to the output. --- .../coverage-llvmir/filecheck.testprog.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt b/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt index a312ec48e849..f54d49f7f96b 100644 --- a/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt +++ b/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt @@ -12,18 +12,18 @@ CHECK-SAME: section "[[INSTR_PROF_COVMAP]]", align 8 WINDOWS: @__llvm_profile_runtime = external global i32 CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = [[PRIVATE_GLOBAL]] -CHECK-SAME: section "[[INSTR_PROF_CNTS]]", align 8 +CHECK-SAME: section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8 CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = [[PRIVATE_GLOBAL]] CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called, -CHECK-SAME: section "[[INSTR_PROF_DATA]]", align 8 +CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8 CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main = [[PRIVATE_GLOBAL]] -CHECK-SAME: section "[[INSTR_PROF_CNTS]]", align 8 +CHECK-SAME: section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8 CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog4main = [[PRIVATE_GLOBAL]] CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main, -CHECK-SAME: section "[[INSTR_PROF_DATA]]", align 8 +CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8 CHECK: @__llvm_prf_nm = private constant CHECK-SAME: section "[[INSTR_PROF_NAME]]", align 1 @@ -31,7 +31,6 @@ CHECK-SAME: section "[[INSTR_PROF_NAME]]", align 1 CHECK: @llvm.used = appending global CHECK-SAME: i8* bitcast ({ {{.*}} }* @__llvm_coverage_mapping to i8*) WINDOWS-SAME: i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*) -CHECK-SAME: i8* bitcast ({ {{.*}} }* @__profd__R{{[a-zA-Z0-9_]*}}testprog4main to i8*) CHECK-SAME: i8* getelementptr inbounds ({{.*}}* @__llvm_prf_nm, i32 0, i32 0) CHECK-SAME: section "llvm.metadata" From 7c015648dd78a329920060125378eb52762a728f Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 7 Aug 2021 17:04:32 +0200 Subject: [PATCH 07/12] Use llvm.compiler.used insetad of llvm.used The #[used] attribute explicitly only requires symbols to be retained in object files, but allows the linker to drop them if dead. This corresponds to llvm.compiler.used semantics. The motivation to change this *now* is that https://reviews.llvm.org/D97448 starts emitting #[used] symbols into unique sections with SHF_GNU_RETAIN flag. This triggers a bug in some version of gold, resulting in the ARGV_INIT_ARRAY symbol part of the .init_array section to be incorrectly placed. --- compiler/rustc_codegen_llvm/src/base.rs | 4 ++-- compiler/rustc_codegen_llvm/src/consts.rs | 2 +- compiler/rustc_codegen_llvm/src/context.rs | 12 +++++++++--- compiler/rustc_feature/src/accepted.rs | 2 +- .../coverage-llvmir/filecheck.testprog.txt | 4 +++- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index cc3cbea4def5..a9f43880ef6b 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -157,12 +157,12 @@ pub fn compile_codegen_unit( } // Finalize code coverage by injecting the coverage map. Note, the coverage map will - // also be added to the `llvm.used` variable, created next. + // also be added to the `llvm.compiler.used` variable, created next. if cx.sess().instrument_coverage() { cx.coverageinfo_finalize(); } - // Create the llvm.used variable + // Create the llvm.compiler.used variable // This variable has type [N x i8*] and is stored in the llvm.metadata section if !cx.used_statics().borrow().is_empty() { cx.create_used_variable() diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 3ca295f4a7e8..7b14c1791748 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -479,7 +479,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { } } - /// Add a global value to a list to be stored in the `llvm.used` variable, an array of i8*. + /// Add a global value to a list to be stored in the `llvm.compiler.used` variable, an array of i8*. fn add_used_global(&self, global: &'ll Value) { let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) }; self.used_statics.borrow_mut().push(cast); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index a469a13bc729..9c0220d3448e 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -71,8 +71,8 @@ pub struct CodegenCx<'ll, 'tcx> { /// to constants.) pub statics_to_rauw: RefCell>, - /// Statics that will be placed in the llvm.used variable - /// See for details + /// Statics that will be placed in the llvm.compiler.used variable + /// See for details pub used_statics: RefCell>, /// Mapping of non-scalar types to llvm types and field remapping if needed. @@ -447,7 +447,13 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { } fn create_used_variable(&self) { - let name = cstr!("llvm.used"); + // The semantics of #[used] in Rust only require the symbol to make it into the object + // file. It is explicitly allowed for the linker to strip the symbol if it is dead. + // As such, use llvm.compiler.used instead of llvm.used. + // Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique + // sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs in + // some versions of the gold linker. + let name = cstr!("llvm.compiler.used"); let section = cstr!("llvm.metadata"); let array = self.const_array(&self.type_ptr_to(self.type_i8()), &*self.used_statics.borrow()); diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 9ce5a149697f..ddb11985cd8b 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -178,7 +178,7 @@ declare_features! ( /// Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`. /// This defines the behavior of panics. (accepted, panic_handler, "1.30.0", Some(44489), None), - /// Allows `#[used]` to preserve symbols (see llvm.used). + /// Allows `#[used]` to preserve symbols (see llvm.compiler.used). (accepted, used, "1.30.0", Some(40289), None), /// Allows `crate` in paths. (accepted, crate_in_paths, "1.30.0", Some(45477), None), diff --git a/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt b/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt index f54d49f7f96b..9b1f810500bc 100644 --- a/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt +++ b/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt @@ -28,9 +28,11 @@ CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8 CHECK: @__llvm_prf_nm = private constant CHECK-SAME: section "[[INSTR_PROF_NAME]]", align 1 -CHECK: @llvm.used = appending global +CHECK: @llvm.compiler.used = appending global CHECK-SAME: i8* bitcast ({ {{.*}} }* @__llvm_coverage_mapping to i8*) WINDOWS-SAME: i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*) +CHECK-SAME: section "llvm.metadata" +CHECK: @llvm.used = appending global CHECK-SAME: i8* getelementptr inbounds ({{.*}}* @__llvm_prf_nm, i32 0, i32 0) CHECK-SAME: section "llvm.metadata" From d20e798ad871b25ff5597c837e081fb6b635be57 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 7 Aug 2021 17:23:12 +0200 Subject: [PATCH 08/12] Set LLVM_INCLUDE_TESTS=OFF when building LLVM When LLVM_INCLUDE_TESTS is enabled (by default), LLVM requires Python 3.6 for the lit test runner, otherwise only Python 3.0 is required. As we have many docker images using Ubuntu 16.04, which only has Python 3.5, this avoids the need to install a newer Python version for them. --- src/bootstrap/native.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index b32629af4d3f..d1397394be75 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -180,6 +180,7 @@ impl Step for Llvm { .define("LLVM_INCLUDE_EXAMPLES", "OFF") .define("LLVM_INCLUDE_DOCS", "OFF") .define("LLVM_INCLUDE_BENCHMARKS", "OFF") + .define("LLVM_INCLUDE_TESTS", "OFF") .define("LLVM_ENABLE_TERMINFO", "OFF") .define("LLVM_ENABLE_LIBEDIT", "OFF") .define("LLVM_ENABLE_BINDINGS", "OFF") From 6a454edce908ab2ef204052c4ca5bad29fa9a30e Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 15 Aug 2021 17:46:20 +0200 Subject: [PATCH 09/12] Dispose LLVM context after TargetMachine The TargetMachine may be referencing data in the context. In particular, at least the GlobalISel instruction selector stored in the TM may reference a TrackedMDNode DebugLoc that destruction of the TargetMachine will try to untrack. --- compiler/rustc_codegen_llvm/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index aa4db1622b23..1e6e5252b25d 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -352,8 +352,8 @@ impl ModuleLlvm { impl Drop for ModuleLlvm { fn drop(&mut self) { unsafe { - llvm::LLVMContextDispose(&mut *(self.llcx as *mut _)); llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _)); + llvm::LLVMContextDispose(&mut *(self.llcx as *mut _)); } } } From 3cfb7305ddb7fd73b92c87ae6af1b169068b6b0f Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 16 Aug 2021 18:42:21 +0200 Subject: [PATCH 10/12] Relax internal/private checks in coverage IR test Since https://reviews.llvm.org/D103355 this will usually also use internal rather than private on Windows as well. We don't particularly care about this implementation detail, just accept either. --- src/test/run-make-fulldeps/coverage-llvmir/Makefile | 2 -- .../coverage-llvmir/filecheck.testprog.txt | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/test/run-make-fulldeps/coverage-llvmir/Makefile b/src/test/run-make-fulldeps/coverage-llvmir/Makefile index 7d9121ee2f83..1ff1ffcc4b0b 100644 --- a/src/test/run-make-fulldeps/coverage-llvmir/Makefile +++ b/src/test/run-make-fulldeps/coverage-llvmir/Makefile @@ -22,7 +22,6 @@ DEFINE_INTERNAL=define internal ifdef IS_WINDOWS LLVM_FILECHECK_OPTIONS=\ -check-prefixes=CHECK,WINDOWS \ - -DPRIVATE_GLOBAL='internal global' \ -DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \ -DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \ -DINSTR_PROF_DATA='.lprfd$$M' \ @@ -36,7 +35,6 @@ ifdef IS_WINDOWS else LLVM_FILECHECK_OPTIONS=\ -check-prefixes=CHECK \ - -DPRIVATE_GLOBAL='private global' \ -DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \ -DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \ -DINSTR_PROF_DATA='$(DATA_SECTION_PREFIX)__llvm_prf_data$(INSTR_PROF_DATA_SUFFIX)' \ diff --git a/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt b/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt index 9b1f810500bc..973f695e36dd 100644 --- a/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt +++ b/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt @@ -11,17 +11,17 @@ CHECK-SAME: section "[[INSTR_PROF_COVMAP]]", align 8 WINDOWS: @__llvm_profile_runtime = external global i32 -CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = [[PRIVATE_GLOBAL]] +CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global CHECK-SAME: section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8 -CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = [[PRIVATE_GLOBAL]] +CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called, CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8 -CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main = [[PRIVATE_GLOBAL]] +CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main = {{private|internal}} global CHECK-SAME: section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8 -CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog4main = [[PRIVATE_GLOBAL]] +CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog4main = {{private|internal}} global CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main, CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8 From f3ae726f30401acb1aacf5600f5a2a2883a0c9d4 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 24 Jul 2021 21:14:49 +0200 Subject: [PATCH 11/12] Update to LLVM 13 --- .gitmodules | 2 +- src/llvm-project | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 60ccf9375ee3..e22d57627904 100644 --- a/.gitmodules +++ b/.gitmodules @@ -34,7 +34,7 @@ [submodule "src/llvm-project"] path = src/llvm-project url = https://github.com/rust-lang/llvm-project.git - branch = rustc/12.0-2021-07-10 + branch = rustc/13.0-2021-08-08 [submodule "src/doc/embedded-book"] path = src/doc/embedded-book url = https://github.com/rust-embedded/book.git diff --git a/src/llvm-project b/src/llvm-project index 260e0f868209..e6c5dd473b7d 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 260e0f8682098faab68af9c608534756ad378365 +Subproject commit e6c5dd473b7da567dc20ed3a635ca4dd2c6b7fb6 From 306259c64595807db0632f0a293bd06bf034f97b Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 20 Aug 2021 21:13:18 +0200 Subject: [PATCH 12/12] Always use llvm.used for coverage symbols This follows what clang does in CoverageMappingGen. Using just llvm.compiler.used is insufficient at least for MSVC targets. --- compiler/rustc_codegen_llvm/src/base.rs | 6 ++- compiler/rustc_codegen_llvm/src/consts.rs | 17 ++++++- compiler/rustc_codegen_llvm/src/context.rs | 46 ++++++++++++------- compiler/rustc_codegen_ssa/src/traits/misc.rs | 2 + .../rustc_codegen_ssa/src/traits/statics.rs | 18 ++++---- .../coverage-llvmir/filecheck.testprog.txt | 5 +- 6 files changed, 59 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index a9f43880ef6b..a6bdbd11899d 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -162,11 +162,13 @@ pub fn compile_codegen_unit( cx.coverageinfo_finalize(); } - // Create the llvm.compiler.used variable - // This variable has type [N x i8*] and is stored in the llvm.metadata section + // Create the llvm.used and llvm.compiler.used variables. if !cx.used_statics().borrow().is_empty() { cx.create_used_variable() } + if !cx.compiler_used_statics().borrow().is_empty() { + cx.create_compiler_used_variable() + } // Finalize debuginfo if cx.sess().opts.debuginfo != DebugInfo::None { diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 7b14c1791748..e1baf95e1d9e 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -474,14 +474,27 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { } if attrs.flags.contains(CodegenFnAttrFlags::USED) { - self.add_used_global(g); + // The semantics of #[used] in Rust only require the symbol to make it into the + // object file. It is explicitly allowed for the linker to strip the symbol if it + // is dead. As such, use llvm.compiler.used instead of llvm.used. + // Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique + // sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs + // in some versions of the gold linker. + self.add_compiler_used_global(g); } } } - /// Add a global value to a list to be stored in the `llvm.compiler.used` variable, an array of i8*. + /// Add a global value to a list to be stored in the `llvm.used` variable, an array of i8*. fn add_used_global(&self, global: &'ll Value) { let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) }; self.used_statics.borrow_mut().push(cast); } + + /// Add a global value to a list to be stored in the `llvm.compiler.used` variable, + /// an array of i8*. + fn add_compiler_used_global(&self, global: &'ll Value) { + let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) }; + self.compiler_used_statics.borrow_mut().push(cast); + } } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 9c0220d3448e..35c866d48a41 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -71,9 +71,13 @@ pub struct CodegenCx<'ll, 'tcx> { /// to constants.) pub statics_to_rauw: RefCell>, + /// Statics that will be placed in the llvm.used variable + /// See for details + pub used_statics: RefCell>, + /// Statics that will be placed in the llvm.compiler.used variable /// See for details - pub used_statics: RefCell>, + pub compiler_used_statics: RefCell>, /// Mapping of non-scalar types to llvm types and field remapping if needed. pub type_lowering: RefCell, Option), TypeLowering<'ll>>>, @@ -325,6 +329,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { const_globals: Default::default(), statics_to_rauw: RefCell::new(Vec::new()), used_statics: RefCell::new(Vec::new()), + compiler_used_statics: RefCell::new(Vec::new()), type_lowering: Default::default(), scalar_lltypes: Default::default(), pointee_infos: Default::default(), @@ -347,6 +352,18 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { pub fn coverage_context(&'a self) -> Option<&'a coverageinfo::CrateCoverageContext<'ll, 'tcx>> { self.coverage_cx.as_ref() } + + fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) { + let section = cstr!("llvm.metadata"); + let array = self.const_array(&self.type_ptr_to(self.type_i8()), values); + + unsafe { + let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr()); + llvm::LLVMSetInitializer(g, array); + llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage); + llvm::LLVMSetSection(g, section.as_ptr()); + } + } } impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { @@ -437,6 +454,10 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { &self.used_statics } + fn compiler_used_statics(&self) -> &RefCell> { + &self.compiler_used_statics + } + fn set_frame_pointer_type(&self, llfn: &'ll Value) { attributes::set_frame_pointer_type(self, llfn) } @@ -447,23 +468,14 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { } fn create_used_variable(&self) { - // The semantics of #[used] in Rust only require the symbol to make it into the object - // file. It is explicitly allowed for the linker to strip the symbol if it is dead. - // As such, use llvm.compiler.used instead of llvm.used. - // Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique - // sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs in - // some versions of the gold linker. - let name = cstr!("llvm.compiler.used"); - let section = cstr!("llvm.metadata"); - let array = - self.const_array(&self.type_ptr_to(self.type_i8()), &*self.used_statics.borrow()); + self.create_used_variable_impl(cstr!("llvm.used"), &*self.used_statics.borrow()); + } - unsafe { - let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr()); - llvm::LLVMSetInitializer(g, array); - llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage); - llvm::LLVMSetSection(g, section.as_ptr()); - } + fn create_compiler_used_variable(&self) { + self.create_used_variable_impl( + cstr!("llvm.compiler.used"), + &*self.compiler_used_statics.borrow(), + ); } fn declare_c_main(&self, fn_type: Self::Type) -> Option { diff --git a/compiler/rustc_codegen_ssa/src/traits/misc.rs b/compiler/rustc_codegen_ssa/src/traits/misc.rs index 46f2adbe5520..4266e42ec2b5 100644 --- a/compiler/rustc_codegen_ssa/src/traits/misc.rs +++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs @@ -16,9 +16,11 @@ pub trait MiscMethods<'tcx>: BackendTypes { fn sess(&self) -> &Session; fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx>; fn used_statics(&self) -> &RefCell>; + fn compiler_used_statics(&self) -> &RefCell>; fn set_frame_pointer_type(&self, llfn: Self::Function); fn apply_target_cpu_attr(&self, llfn: Self::Function); fn create_used_variable(&self); + fn create_compiler_used_variable(&self); /// Declares the extern "C" main function for the entry point. Returns None if the symbol already exists. fn declare_c_main(&self, fn_type: Self::Type) -> Option; } diff --git a/compiler/rustc_codegen_ssa/src/traits/statics.rs b/compiler/rustc_codegen_ssa/src/traits/statics.rs index 817fc02d166a..a2a3cb56c780 100644 --- a/compiler/rustc_codegen_ssa/src/traits/statics.rs +++ b/compiler/rustc_codegen_ssa/src/traits/statics.rs @@ -6,17 +6,15 @@ pub trait StaticMethods: BackendTypes { fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value; fn codegen_static(&self, def_id: DefId, is_mutable: bool); - /// Mark the given global value as "used", to prevent a backend from potentially removing a - /// static variable that may otherwise appear unused. - /// - /// Static variables in Rust can be annotated with the `#[used]` attribute to direct the `rustc` - /// compiler to mark the variable as a "used global". - /// - /// ```no_run - /// #[used] - /// static FOO: u32 = 0; - /// ``` + /// Mark the given global value as "used", to prevent the compiler and linker from potentially + /// removing a static variable that may otherwise appear unused. fn add_used_global(&self, global: Self::Value); + + /// Same as add_used_global(), but only prevent the compiler from potentially removing an + /// otherwise unused symbol. The linker is still permitted to drop it. + /// + /// This corresponds to the semantics of the `#[used]` attribute. + fn add_compiler_used_global(&self, global: Self::Value); } pub trait StaticBuilderMethods: BackendTypes { diff --git a/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt b/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt index 973f695e36dd..8e5f21046877 100644 --- a/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt +++ b/src/test/run-make-fulldeps/coverage-llvmir/filecheck.testprog.txt @@ -28,11 +28,8 @@ CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8 CHECK: @__llvm_prf_nm = private constant CHECK-SAME: section "[[INSTR_PROF_NAME]]", align 1 -CHECK: @llvm.compiler.used = appending global -CHECK-SAME: i8* bitcast ({ {{.*}} }* @__llvm_coverage_mapping to i8*) -WINDOWS-SAME: i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*) -CHECK-SAME: section "llvm.metadata" CHECK: @llvm.used = appending global +CHECK-SAME: i8* bitcast ({ {{.*}} }* @__llvm_coverage_mapping to i8*) CHECK-SAME: i8* getelementptr inbounds ({{.*}}* @__llvm_prf_nm, i32 0, i32 0) CHECK-SAME: section "llvm.metadata"