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 4b60fa4b0bffa..fefc232b49040 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 9e904fc82ab41..cb2d0ef809af4 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 | 94 +++++++++++++++---- 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, 107 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 5b4a187a1d56f..791604a18273d 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 ccd3e42e458fd..36aa022d74658 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 message: String, + pub source: Option<(String, Vec)>, +} + +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: &'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 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 57173a49107a5..3f2ed02d90df3 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 52566b19eca04..4edfed0340187 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 26fccec80f182..ea1b80cc9b06b 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 15a35e43c2705..28c5fbbca3c60 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 b22b7f52402dd..0000000000000 --- 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 5d56c93f835d6..e204606443abf 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 302139395d317..86b1a75523359 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 834c4dbfc05f6..134c6803b15d1 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 a6b12d2ee8f65..2dab206dc7602 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 8bfb229d77f67..fb6526c0e7203 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 e204606443abf..a469a13bc7295 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 559a1a40868ff..f10d4d49bb909 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 f1190b159aba4..611621727bd19 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 3ebc5469e0a8b..9c63997ce2f95 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 76f70e474f073..f645eceadfe3a 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 42c49103b3b4e..934371fb2211c 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 a312ec48e8498..f54d49f7f96b1 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 cc3cbea4def5e..a9f43880ef6b8 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 3ca295f4a7e89..7b14c1791748f 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 a469a13bc7295..9c0220d3448e6 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 9ce5a149697f7..ddb11985cd8b4 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 f54d49f7f96b1..9b1f810500bcf 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 b32629af4d3ff..d1397394be75f 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 aa4db1622b233..1e6e5252b25de 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 7d9121ee2f834..1ff1ffcc4b0b8 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 9b1f810500bcf..973f695e36dd6 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 60ccf9375ee3e..e22d576279042 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 260e0f8682098..e6c5dd473b7da 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 a9f43880ef6b8..a6bdbd11899de 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 7b14c1791748f..e1baf95e1d9e5 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 9c0220d3448e6..35c866d48a41b 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 46f2adbe55209..4266e42ec2b50 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 817fc02d166a3..a2a3cb56c7806 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 973f695e36dd6..8e5f210468773 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"