Rollup merge of #111878 - ferrocene:pa-codegen-tests, r=Mark-Simulacrum

Fix codegen test suite for bare-metal-like targets

For Ferrocene I needed to run the test suite for custom target with no unwinding and static relocation. Running the tests uncovered ~20 failures due to the test suite not accounting for these options. This PR fixes them by:

* Fixing `CHECK`s to account for functions having extra LLVM IR attributes (in this case `nounwind`).
* Fixing `CHECK`s to account for the `dso_local` LLVM IR modifier, which is [added to every item when relocation is static](f3d597b31c/compiler/rustc_codegen_llvm/src/mono_item.rs (L139-L142)).
* Fixing `CHECK`s to account for missing `uwtables` attributes.
* Added the `needs-unwind` attributes for tests that are designed to check unwinding.

There is no part of Rust CI that checks this unfortunately, and testing whether the PR works locally is kinda hard because you need a target with std enabled but no unwinding and static relocations. Still, this works in my local testing, and if future PRs accidentally break this Ferrocene will take care of sending followup PRs.
This commit is contained in:
Matthias Krüger 2023-06-03 20:38:11 +02:00 committed by GitHub
commit bdf9ed497a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 64 additions and 55 deletions

View File

@ -31,4 +31,4 @@ pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
// Hide the LLVM 15+ `allocalign` attribute in the declaration of __rust_alloc
// from the CHECK-NOT above. We don't check the attributes here because we can't rely
// on all of them being set until LLVM 15.
// CHECK: declare noalias{{.*}} @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+.*}} noundef)
// CHECK: declare {{(dso_local )?}}noalias{{.*}} @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+.*}} noundef)

View File

@ -28,6 +28,6 @@ pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
// Hide the `allocalign` attribute in the declaration of __rust_alloc
// from the CHECK-NOT above, and also verify the attributes got set reasonably.
// CHECK: declare noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]
// CHECK: declare {{(dso_local )?}}noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]
// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} }
// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) {{(uwtable )?}}"alloc-family"="__rust_alloc" {{.*}} }

View File

@ -6,7 +6,7 @@
#![crate_type = "lib"]
pub fn test() {
// CHECK: call noundef i8 @some_true(), !range [[R0:![0-9]+]]
// CHECK: call noundef i8 @some_true(){{( #[0-9]+)?}}, !range [[R0:![0-9]+]]
// CHECK: [[R0]] = !{i8 0, i8 3}
some_true();
}

View File

@ -6,11 +6,11 @@
fn main() {
unsafe {
// Column numbers are 1-based. Regression test for #65437.
// CHECK: call void @giraffe(), !dbg [[A:!.*]]
// CHECK: call void @giraffe(){{( #[0-9]+)?}}, !dbg [[A:!.*]]
giraffe();
// Column numbers use byte offests. Regression test for #67360
// CHECK: call void @turtle(), !dbg [[B:!.*]]
// CHECK: call void @turtle(){{( #[0-9]+)?}}, !dbg [[B:!.*]]
/* ż */ turtle();
// CHECK: [[A]] = !DILocation(line: 10, column: 9,

View File

@ -1,4 +1,5 @@
// ignore-wasm32-bare compiled with panic=abort by default
// needs-unwind - this test verifies the amount of drop calls when unwinding is used
// compile-flags: -C no-prepopulate-passes
#![crate_type = "lib"]

View File

@ -6,72 +6,72 @@
// `#[no_mangle]`d static variables always have external linkage, i.e., no `internal` in their
// definitions
// CHECK: @A = local_unnamed_addr constant
// CHECK: @A = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
static A: u8 = 0;
// CHECK: @B = local_unnamed_addr global
// CHECK: @B = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
static mut B: u8 = 0;
// CHECK: @C = local_unnamed_addr constant
// CHECK: @C = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
pub static C: u8 = 0;
// CHECK: @D = local_unnamed_addr global
// CHECK: @D = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
pub static mut D: u8 = 0;
mod private {
// CHECK: @E = local_unnamed_addr constant
// CHECK: @E = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
static E: u8 = 0;
// CHECK: @F = local_unnamed_addr global
// CHECK: @F = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
static mut F: u8 = 0;
// CHECK: @G = local_unnamed_addr constant
// CHECK: @G = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
pub static G: u8 = 0;
// CHECK: @H = local_unnamed_addr global
// CHECK: @H = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
pub static mut H: u8 = 0;
}
const HIDDEN: () = {
// CHECK: @I = local_unnamed_addr constant
// CHECK: @I = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
static I: u8 = 0;
// CHECK: @J = local_unnamed_addr global
// CHECK: @J = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
static mut J: u8 = 0;
// CHECK: @K = local_unnamed_addr constant
// CHECK: @K = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
pub static K: u8 = 0;
// CHECK: @L = local_unnamed_addr global
// CHECK: @L = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
pub static mut L: u8 = 0;
};
fn x() {
// CHECK: @M = local_unnamed_addr constant
// CHECK: @M = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
static M: fn() = x;
// CHECK: @N = local_unnamed_addr global
// CHECK: @N = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
static mut N: u8 = 0;
// CHECK: @O = local_unnamed_addr constant
// CHECK: @O = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
pub static O: u8 = 0;
// CHECK: @P = local_unnamed_addr global
// CHECK: @P = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
pub static mut P: u8 = 0;
}

View File

@ -7,7 +7,7 @@
#![crate_type = "lib"]
// CHECK-LABEL: define void @string_new
// CHECK-LABEL: define {{(dso_local )?}}void @string_new
#[no_mangle]
pub fn string_new() -> String {
// CHECK: store ptr inttoptr
@ -17,7 +17,7 @@ pub fn string_new() -> String {
String::new()
}
// CHECK-LABEL: define void @empty_to_string
// CHECK-LABEL: define {{(dso_local )?}}void @empty_to_string
#[no_mangle]
pub fn empty_to_string() -> String {
// CHECK: store ptr inttoptr

View File

@ -3,7 +3,7 @@
#![crate_type = "lib"]
// CHECK: @VAR1 = constant <{ [4 x i8] }> <{ [4 x i8] c"\01\00\00\00" }>, section ".test_one"
// CHECK: @VAR1 = {{(dso_local )?}}constant <{ [4 x i8] }> <{ [4 x i8] c"\01\00\00\00" }>, section ".test_one"
#[no_mangle]
#[link_section = ".test_one"]
#[cfg(target_endian = "little")]
@ -19,17 +19,17 @@ pub enum E {
B(f32)
}
// CHECK: @VAR2 = constant {{.*}}, section ".test_two"
// CHECK: @VAR2 = {{(dso_local )?}}constant {{.*}}, section ".test_two"
#[no_mangle]
#[link_section = ".test_two"]
pub static VAR2: E = E::A(666);
// CHECK: @VAR3 = constant {{.*}}, section ".test_three"
// CHECK: @VAR3 = {{(dso_local )?}}constant {{.*}}, section ".test_three"
#[no_mangle]
#[link_section = ".test_three"]
pub static VAR3: E = E::B(1.);
// CHECK: define void @fn1() {{.*}} section ".test_four" {
// CHECK: define {{(dso_local )?}}void @fn1() {{.*}} section ".test_four" {
#[no_mangle]
#[link_section = ".test_four"]
pub fn fn1() {}

View File

@ -19,7 +19,7 @@ pub fn example() {
}
// CHECK-LABEL: @example
// CHECK: tail call void @bar(), !dbg [[DBG_ID:![0-9]+]]
// CHECK: tail call void @bar(){{( #[0-9]+)?}}, !dbg [[DBG_ID:![0-9]+]]
// CHECK: [[DBG_ID]] = !DILocation(line: 7,
// CHECK-SAME: inlinedAt: [[INLINE_ID:![0-9]+]])
// CHECK: [[INLINE_ID]] = !DILocation(line: 18,

View File

@ -12,7 +12,7 @@ use std::arch::asm;
pub unsafe extern "C" fn f() {
// Check that f has naked and noinline attributes.
//
// CHECK: define void @f() unnamed_addr [[ATTR:#[0-9]+]]
// CHECK: define {{(dso_local )?}}void @f() unnamed_addr [[ATTR:#[0-9]+]]
// CHECK-NEXT: start:
// CHECK-NEXT: call void asm
asm!("", options(noreturn));
@ -22,7 +22,7 @@ pub unsafe extern "C" fn f() {
pub unsafe fn g() {
// Check that call to f is not inlined.
//
// CHECK-LABEL: define void @g()
// CHECK-LABEL: define {{(dso_local )?}}void @g()
// CHECK-NEXT: start:
// CHECK-NEXT: call void @f()
f();

View File

@ -1,5 +1,6 @@
// ignore-msvc
// ignore-wasm32-bare compiled with panic=abort by default
// needs-unwind
// compile-flags: -O -C no-prepopulate-passes

View File

@ -9,7 +9,7 @@
use std::mem::MaybeUninit;
// CHECK-LABEL: define noundef i8 @copy_byte(
// CHECK-LABEL: define {{(dso_local )?}}noundef i8 @copy_byte(
#[no_mangle]
pub unsafe fn copy_byte(p: *const u8) -> u8 {
// CHECK-NOT: load
@ -19,7 +19,7 @@ pub unsafe fn copy_byte(p: *const u8) -> u8 {
*p
}
// CHECK-LABEL: define noundef i8 @read_byte(
// CHECK-LABEL: define {{(dso_local )?}}noundef i8 @read_byte(
#[no_mangle]
pub unsafe fn read_byte(p: *const u8) -> u8 {
// CHECK-NOT: load
@ -29,7 +29,7 @@ pub unsafe fn read_byte(p: *const u8) -> u8 {
p.read()
}
// CHECK-LABEL: define i8 @read_byte_maybe_uninit(
// CHECK-LABEL: define {{(dso_local )?}}i8 @read_byte_maybe_uninit(
#[no_mangle]
pub unsafe fn read_byte_maybe_uninit(p: *const MaybeUninit<u8>) -> MaybeUninit<u8> {
// CHECK-NOT: load
@ -39,7 +39,7 @@ pub unsafe fn read_byte_maybe_uninit(p: *const MaybeUninit<u8>) -> MaybeUninit<u
p.read()
}
// CHECK-LABEL: define noundef i8 @read_byte_assume_init(
// CHECK-LABEL: define {{(dso_local )?}}noundef i8 @read_byte_assume_init(
#[no_mangle]
pub unsafe fn read_byte_assume_init(p: &MaybeUninit<u8>) -> u8 {
// CHECK-NOT: load
@ -49,7 +49,7 @@ pub unsafe fn read_byte_assume_init(p: &MaybeUninit<u8>) -> u8 {
p.assume_init_read()
}
// CHECK-LABEL: define noundef i32 @copy_char(
// CHECK-LABEL: define {{(dso_local )?}}noundef i32 @copy_char(
#[no_mangle]
pub unsafe fn copy_char(p: *const char) -> char {
// CHECK-NOT: load
@ -60,7 +60,7 @@ pub unsafe fn copy_char(p: *const char) -> char {
*p
}
// CHECK-LABEL: define noundef i32 @read_char(
// CHECK-LABEL: define {{(dso_local )?}}noundef i32 @read_char(
#[no_mangle]
pub unsafe fn read_char(p: *const char) -> char {
// CHECK-NOT: load
@ -71,7 +71,7 @@ pub unsafe fn read_char(p: *const char) -> char {
p.read()
}
// CHECK-LABEL: define i32 @read_char_maybe_uninit(
// CHECK-LABEL: define {{(dso_local )?}}i32 @read_char_maybe_uninit(
#[no_mangle]
pub unsafe fn read_char_maybe_uninit(p: *const MaybeUninit<char>) -> MaybeUninit<char> {
// CHECK-NOT: load
@ -82,7 +82,7 @@ pub unsafe fn read_char_maybe_uninit(p: *const MaybeUninit<char>) -> MaybeUninit
p.read()
}
// CHECK-LABEL: define noundef i32 @read_char_assume_init(
// CHECK-LABEL: define {{(dso_local )?}}noundef i32 @read_char_assume_init(
#[no_mangle]
pub unsafe fn read_char_assume_init(p: &MaybeUninit<char>) -> char {
// CHECK-NOT: load

View File

@ -6,31 +6,31 @@
#![crate_type="lib"]
type ScalarZstLast = (u128, ());
// CHECK: define i128 @test_ScalarZstLast(i128 %_1)
// CHECK: define {{(dso_local )?}}i128 @test_ScalarZstLast(i128 %_1)
#[no_mangle]
pub fn test_ScalarZstLast(_: ScalarZstLast) -> ScalarZstLast { loop {} }
type ScalarZstFirst = ((), u128);
// CHECK: define i128 @test_ScalarZstFirst(i128 %_1)
// CHECK: define {{(dso_local )?}}i128 @test_ScalarZstFirst(i128 %_1)
#[no_mangle]
pub fn test_ScalarZstFirst(_: ScalarZstFirst) -> ScalarZstFirst { loop {} }
type ScalarPairZstLast = (u8, u128, ());
// CHECK: define { i128, i8 } @test_ScalarPairZstLast(i128 %_1.0, i8 %_1.1)
// CHECK: define {{(dso_local )?}}{ i128, i8 } @test_ScalarPairZstLast(i128 %_1.0, i8 %_1.1)
#[no_mangle]
pub fn test_ScalarPairZstLast(_: ScalarPairZstLast) -> ScalarPairZstLast { loop {} }
type ScalarPairZstFirst = ((), u8, u128);
// CHECK: define { i8, i128 } @test_ScalarPairZstFirst(i8 %_1.0, i128 %_1.1)
// CHECK: define {{(dso_local )?}}{ i8, i128 } @test_ScalarPairZstFirst(i8 %_1.0, i128 %_1.1)
#[no_mangle]
pub fn test_ScalarPairZstFirst(_: ScalarPairZstFirst) -> ScalarPairZstFirst { loop {} }
type ScalarPairLotsOfZsts = ((), u8, (), u128, ());
// CHECK: define { i128, i8 } @test_ScalarPairLotsOfZsts(i128 %_1.0, i8 %_1.1)
// CHECK: define {{(dso_local )?}}{ i128, i8 } @test_ScalarPairLotsOfZsts(i128 %_1.0, i8 %_1.1)
#[no_mangle]
pub fn test_ScalarPairLotsOfZsts(_: ScalarPairLotsOfZsts) -> ScalarPairLotsOfZsts { loop {} }
type ScalarPairLottaNesting = (((), ((), u8, (), u128, ())), ());
// CHECK: define { i128, i8 } @test_ScalarPairLottaNesting(i128 %_1.0, i8 %_1.1)
// CHECK: define {{(dso_local )?}}{ i128, i8 } @test_ScalarPairLottaNesting(i128 %_1.0, i8 %_1.1)
#[no_mangle]
pub fn test_ScalarPairLottaNesting(_: ScalarPairLottaNesting) -> ScalarPairLottaNesting { loop {} }

View File

@ -17,60 +17,60 @@ pub struct i64x4(i64, i64, i64, i64);
#[derive(Copy, Clone)]
pub union UnionI64x4{ a:(), b: i64x4 }
// CHECK: define void @test_UnionI64x4({{<4 x i64>\*|ptr}} {{.*}} %_1)
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4({{<4 x i64>\*|ptr}} {{.*}} %_1)
#[no_mangle]
pub fn test_UnionI64x4(_: UnionI64x4) { loop {} }
pub union UnionI64x4_{ a: i64x4, b: (), c:i64x4, d: Unhab, e: ((),()), f: UnionI64x4 }
// CHECK: define void @test_UnionI64x4_({{<4 x i64>\*|ptr}} {{.*}} %_1)
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4_({{<4 x i64>\*|ptr}} {{.*}} %_1)
#[no_mangle]
pub fn test_UnionI64x4_(_: UnionI64x4_) { loop {} }
pub union UnionI64x4I64{ a: i64x4, b: i64 }
// CHECK: define void @test_UnionI64x4I64({{%UnionI64x4I64\*|ptr}} {{.*}} %_1)
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4I64({{%UnionI64x4I64\*|ptr}} {{.*}} %_1)
#[no_mangle]
pub fn test_UnionI64x4I64(_: UnionI64x4I64) { loop {} }
pub union UnionI64x4Tuple{ a: i64x4, b: (i64, i64, i64, i64) }
// CHECK: define void @test_UnionI64x4Tuple({{%UnionI64x4Tuple\*|ptr}} {{.*}} %_1)
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4Tuple({{%UnionI64x4Tuple\*|ptr}} {{.*}} %_1)
#[no_mangle]
pub fn test_UnionI64x4Tuple(_: UnionI64x4Tuple) { loop {} }
pub union UnionF32{a:f32}
// CHECK: define float @test_UnionF32(float %_1)
// CHECK: define {{(dso_local )?}}float @test_UnionF32(float %_1)
#[no_mangle]
pub fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }
pub union UnionF32F32{a:f32, b:f32}
// CHECK: define float @test_UnionF32F32(float %_1)
// CHECK: define {{(dso_local )?}}float @test_UnionF32F32(float %_1)
#[no_mangle]
pub fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 { loop {} }
pub union UnionF32U32{a:f32, b:u32}
// CHECK: define i32 @test_UnionF32U32(i32{{( %0)?}})
// CHECK: define {{(dso_local )?}}i32 @test_UnionF32U32(i32{{( %0)?}})
#[no_mangle]
pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} }
pub union UnionU128{a:u128}
// CHECK: define i128 @test_UnionU128(i128 %_1)
// CHECK: define {{(dso_local )?}}i128 @test_UnionU128(i128 %_1)
#[no_mangle]
pub fn test_UnionU128(_: UnionU128) -> UnionU128 { loop {} }
#[repr(C)]
pub union CUnionU128{a:u128}
// CHECK: define void @test_CUnionU128({{%CUnionU128\*|ptr}} {{.*}} %_1)
// CHECK: define {{(dso_local )?}}void @test_CUnionU128({{%CUnionU128\*|ptr}} {{.*}} %_1)
#[no_mangle]
pub fn test_CUnionU128(_: CUnionU128) { loop {} }
pub union UnionBool { b:bool }
// CHECK: define noundef zeroext i1 @test_UnionBool(i8 %b)
// CHECK: define {{(dso_local )?}}noundef zeroext i1 @test_UnionBool(i8 %b)
#[no_mangle]
pub fn test_UnionBool(b: UnionBool) -> bool { unsafe { b.b } }
// CHECK: %0 = trunc i8 %b to i1

View File

@ -1,4 +1,5 @@
// compile-flags: -C opt-level=0
// needs-unwind
// Test that `nounwind` attributes are correctly applied to exported `C` and `C-unwind` extern
// functions. `C-unwind` functions MUST NOT have this attribute. We disable optimizations above

View File

@ -1,4 +1,5 @@
// compile-flags: -C opt-level=0
// needs-unwind
// Test that `nounwind` attributes are correctly applied to exported `cdecl` and
// `cdecl-unwind` extern functions. `cdecl-unwind` functions MUST NOT have this attribute. We

View File

@ -1,5 +1,6 @@
// compile-flags: -C opt-level=0
// ignore-wasm32-bare compiled with panic=abort by default
// needs-unwind
#![crate_type = "lib"]

View File

@ -1,4 +1,5 @@
// compile-flags: -C opt-level=0
// needs-unwind
// Test that `nounwind` attributes are correctly applied to exported `system` and `system-unwind`
// extern functions. `system-unwind` functions MUST NOT have this attribute. We disable

View File

@ -1,5 +1,6 @@
// compile-flags: -C opt-level=0
// ignore-wasm32-bare compiled with panic=abort by default
// needs-unwind
#![crate_type = "lib"]
#![feature(c_unwind)]

View File

@ -1,5 +1,6 @@
// compile-flags: -C no-prepopulate-passes
// ignore-wasm32-bare compiled with panic=abort by default
// needs-unwind
#![crate_type = "lib"]
#![feature(c_unwind)]

View File

@ -5,6 +5,7 @@
// [new]min-llvm-version: 17
// compile-flags: -O
// ignore-debug: the debug assertions get in the way
// needs-unwind
#![crate_type = "lib"]
#![feature(shrink_to)]