From 040bc3447e3d43ce79dee8420f4ab05d6aa3a8c7 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 29 Jul 2023 15:15:23 -0700 Subject: mv tests/codegen/repr-* tests/codegen/repr Slightly more complicated: also give them appropriate names that somewhat describe the cases they are trying to cover, using information from PR chatter in rust-lang/rust#47158 --- tests/codegen/repr-transparent-aggregates-1.rs | 89 ------------- tests/codegen/repr-transparent-aggregates-2.rs | 90 ------------- tests/codegen/repr-transparent-aggregates-3.rs | 79 ------------ tests/codegen/repr-transparent-sysv64.rs | 28 ---- tests/codegen/repr-transparent.rs | 171 ------------------------- tests/codegen/repr/transparent-imm-array.rs | 90 +++++++++++++ tests/codegen/repr/transparent-mips64.rs | 79 ++++++++++++ tests/codegen/repr/transparent-struct-ptr.rs | 89 +++++++++++++ tests/codegen/repr/transparent-sysv64.rs | 28 ++++ tests/codegen/repr/transparent.rs | 171 +++++++++++++++++++++++++ 10 files changed, 457 insertions(+), 457 deletions(-) delete mode 100644 tests/codegen/repr-transparent-aggregates-1.rs delete mode 100644 tests/codegen/repr-transparent-aggregates-2.rs delete mode 100644 tests/codegen/repr-transparent-aggregates-3.rs delete mode 100644 tests/codegen/repr-transparent-sysv64.rs delete mode 100644 tests/codegen/repr-transparent.rs create mode 100644 tests/codegen/repr/transparent-imm-array.rs create mode 100644 tests/codegen/repr/transparent-mips64.rs create mode 100644 tests/codegen/repr/transparent-struct-ptr.rs create mode 100644 tests/codegen/repr/transparent-sysv64.rs create mode 100644 tests/codegen/repr/transparent.rs (limited to 'tests/codegen') diff --git a/tests/codegen/repr-transparent-aggregates-1.rs b/tests/codegen/repr-transparent-aggregates-1.rs deleted file mode 100644 index c783a75a400..00000000000 --- a/tests/codegen/repr-transparent-aggregates-1.rs +++ /dev/null @@ -1,89 +0,0 @@ -// compile-flags: -O -C no-prepopulate-passes -// - -// ignore-arm -// ignore-aarch64 -// ignore-mips -// ignore-mips64 -// ignore-powerpc -// ignore-powerpc64 -// ignore-riscv64 see codegen/riscv-abi -// ignore-s390x -// ignore-windows -// ignore-loongarch64 -// ignore-wasm32-bare -// See repr-transparent.rs - -#![feature(transparent_unions)] - -#![crate_type="lib"] - - -#[derive(Clone, Copy)] -#[repr(C)] -pub struct BigS([u32; 16]); - -#[repr(transparent)] -pub struct TsBigS(BigS); - -#[repr(transparent)] -pub union TuBigS { - field: BigS, -} - -#[repr(transparent)] -pub enum TeBigS { - Variant(BigS), -} - -// CHECK: define{{.*}}void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], ptr [[BIGS_ARG_ATTRS1:.*]] byval(%BigS) [[BIGS_ARG_ATTRS2:.*]]) -#[no_mangle] -pub extern "C" fn test_BigS(_: BigS) -> BigS { loop {} } - -// CHECK: define{{.*}}void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%TsBigS) [[BIGS_ARG_ATTRS2:.*]]) -#[no_mangle] -pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} } - -// CHECK: define{{.*}}void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%TuBigS) [[BIGS_ARG_ATTRS2:.*]]) -#[no_mangle] -pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} } - -// CHECK: define{{.*}}void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%"TeBigS::Variant") [[BIGS_ARG_ATTRS2]]) -#[no_mangle] -pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} } - - -#[derive(Clone, Copy)] -#[repr(C)] -pub union BigU { - foo: [u32; 16], -} - -#[repr(transparent)] -pub struct TsBigU(BigU); - -#[repr(transparent)] -pub union TuBigU { - field: BigU, -} - -#[repr(transparent)] -pub enum TeBigU { - Variant(BigU), -} - -// CHECK: define{{.*}}void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1:.*]] byval(%BigU) [[BIGU_ARG_ATTRS2:.*]]) -#[no_mangle] -pub extern "C" fn test_BigU(_: BigU) -> BigU { loop {} } - -// CHECK: define{{.*}}void @test_TsBigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%TsBigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%TsBigU) [[BIGU_ARG_ATTRS2]]) -#[no_mangle] -pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} } - -// CHECK: define{{.*}}void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%TuBigU) [[BIGU_ARG_ATTRS2]]) -#[no_mangle] -pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} } - -// CHECK: define{{.*}}void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%"TeBigU::Variant") [[BIGU_ARG_ATTRS2]]) -#[no_mangle] -pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} } diff --git a/tests/codegen/repr-transparent-aggregates-2.rs b/tests/codegen/repr-transparent-aggregates-2.rs deleted file mode 100644 index 33f4f222b0a..00000000000 --- a/tests/codegen/repr-transparent-aggregates-2.rs +++ /dev/null @@ -1,90 +0,0 @@ -// compile-flags: -C no-prepopulate-passes -// - -// ignore-aarch64 -// ignore-emscripten -// ignore-mips64 -// ignore-powerpc -// ignore-powerpc64 -// ignore-riscv64 see codegen/riscv-abi -// ignore-s390x -// ignore-sparc -// ignore-sparc64 -// ignore-x86 -// ignore-x86_64 -// ignore-loongarch64 -// See repr-transparent.rs - -#![feature(transparent_unions)] - -#![crate_type="lib"] - - -#[derive(Clone, Copy)] -#[repr(C)] -pub struct BigS([u32; 16]); - -#[repr(transparent)] -pub struct TsBigS(BigS); - -#[repr(transparent)] -pub union TuBigS { - field: BigS, -} - -#[repr(transparent)] -pub enum TeBigS { - Variant(BigS), -} - -// CHECK: define void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], [16 x i32] -#[no_mangle] -pub extern fn test_BigS(_: BigS) -> BigS { loop {} } - -// CHECK: define void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], [16 x i32] -#[no_mangle] -pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} } - -// CHECK: define void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], [16 x i32] -#[no_mangle] -pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} } - -// CHECK: define void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], [16 x i32] -#[no_mangle] -pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} } - - -#[derive(Clone, Copy)] -#[repr(C)] -pub union BigU { - foo: [u32; 16], -} - -#[repr(transparent)] -pub struct TsBigU(BigU); - -#[repr(transparent)] -pub union TuBigU { - field: BigU, -} - -#[repr(transparent)] -pub enum TeBigU { - Variant(BigU), -} - -// CHECK: define void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], [16 x i32] -#[no_mangle] -pub extern fn test_BigU(_: BigU) -> BigU { loop {} } - -// CHECK: define void @test_TsBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TsBigU) [[BIGU_RET_ATTRS2]], [16 x i32] -#[no_mangle] -pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} } - -// CHECK: define void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2]], [16 x i32] -#[no_mangle] -pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} } - -// CHECK: define void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2]], [16 x i32] -#[no_mangle] -pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} } diff --git a/tests/codegen/repr-transparent-aggregates-3.rs b/tests/codegen/repr-transparent-aggregates-3.rs deleted file mode 100644 index 0db17e6b13a..00000000000 --- a/tests/codegen/repr-transparent-aggregates-3.rs +++ /dev/null @@ -1,79 +0,0 @@ -// compile-flags: -C no-prepopulate-passes -// - -// only-mips64 -// See repr-transparent.rs - -#![feature(transparent_unions)] - -#![crate_type="lib"] - - -#[derive(Clone, Copy)] -#[repr(C)] -pub struct BigS([u32; 16]); - -#[repr(transparent)] -pub struct TsBigS(BigS); - -#[repr(transparent)] -pub union TuBigS { - field: BigS, -} - -#[repr(transparent)] -pub enum TeBigS { - Variant(BigS), -} - -// CHECK: define void @test_BigS(%BigS* [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], [8 x i64] -#[no_mangle] -pub extern fn test_BigS(_: BigS) -> BigS { loop {} } - -// CHECK: define void @test_TsBigS(%TsBigS* [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], [8 x i64] -#[no_mangle] -pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} } - -// CHECK: define void @test_TuBigS(%TuBigS* [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], [8 x i64] -#[no_mangle] -pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} } - -// CHECK: define void @test_TeBigS(%"TeBigS::Variant"* [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], [8 x i64] -#[no_mangle] -pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} } - - -#[derive(Clone, Copy)] -#[repr(C)] -pub union BigU { - foo: [u32; 16], -} - -#[repr(transparent)] -pub struct TsBigU(BigU); - -#[repr(transparent)] -pub union TuBigU { - field: BigU, -} - -#[repr(transparent)] -pub enum TeBigU { - Variant(BigU), -} - -// CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], [8 x i64] -#[no_mangle] -pub extern fn test_BigU(_: BigU) -> BigU { loop {} } - -// CHECK: define void @test_TsBigU(%TsBigU* [[BIGU_RET_ATTRS1]] sret(%TsBigU) [[BIGU_RET_ATTRS2]], [8 x i64] -#[no_mangle] -pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} } - -// CHECK: define void @test_TuBigU(%TuBigU* [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2]], [8 x i64] -#[no_mangle] -pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} } - -// CHECK: define void @test_TeBigU(%"TeBigU::Variant"* [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2]], [8 x i64] -#[no_mangle] -pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} } diff --git a/tests/codegen/repr-transparent-sysv64.rs b/tests/codegen/repr-transparent-sysv64.rs deleted file mode 100644 index 886b0dd9e7b..00000000000 --- a/tests/codegen/repr-transparent-sysv64.rs +++ /dev/null @@ -1,28 +0,0 @@ -// only-x86_64 - -// compile-flags: -C no-prepopulate-passes - -#![crate_type="lib"] - -#[repr(C)] -pub struct Rgb8 { r: u8, g: u8, b: u8 } - -#[repr(transparent)] -pub struct Rgb8Wrap(Rgb8); - -// CHECK: i24 @test_Rgb8Wrap(i24{{( %0)?}}) -#[no_mangle] -pub extern "sysv64" fn test_Rgb8Wrap(_: Rgb8Wrap) -> Rgb8Wrap { loop {} } - -#[repr(C)] -pub union FloatBits { - float: f32, - bits: u32, -} - -#[repr(transparent)] -pub struct SmallUnion(FloatBits); - -// CHECK: i32 @test_SmallUnion(i32{{( %0)?}}) -#[no_mangle] -pub extern "sysv64" fn test_SmallUnion(_: SmallUnion) -> SmallUnion { loop {} } diff --git a/tests/codegen/repr-transparent.rs b/tests/codegen/repr-transparent.rs deleted file mode 100644 index 64f3ce5a43c..00000000000 --- a/tests/codegen/repr-transparent.rs +++ /dev/null @@ -1,171 +0,0 @@ -// compile-flags: -O -C no-prepopulate-passes - -// ignore-riscv64 riscv64 has an i128 type used with test_Vector -// see codegen/riscv-abi for riscv functiona call tests -// ignore-s390x s390x with default march passes vector types per reference -// ignore-loongarch64 see codegen/loongarch-abi for loongarch function call tests - -#![crate_type="lib"] -#![feature(repr_simd, transparent_unions)] - -use std::marker::PhantomData; - -#[derive(Copy, Clone)] -pub struct Zst1; -#[derive(Copy, Clone)] -pub struct Zst2(()); - -#[derive(Copy, Clone)] -#[repr(transparent)] -pub struct F32(f32); - -// CHECK: define{{.*}}float @test_F32(float noundef %_1) -#[no_mangle] -pub extern "C" fn test_F32(_: F32) -> F32 { loop {} } - -#[repr(transparent)] -pub struct Ptr(*mut u8); - -// CHECK: define{{.*}}ptr @test_Ptr(ptr noundef %_1) -#[no_mangle] -pub extern "C" fn test_Ptr(_: Ptr) -> Ptr { loop {} } - -#[repr(transparent)] -pub struct WithZst(u64, Zst1); - -// CHECK: define{{.*}}i64 @test_WithZst(i64 noundef %_1) -#[no_mangle] -pub extern "C" fn test_WithZst(_: WithZst) -> WithZst { loop {} } - -#[repr(transparent)] -pub struct WithZeroSizedArray(*const f32, [i8; 0]); - -// Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever. -// CHECK: define{{.*}}ptr @test_WithZeroSizedArray(ptr noundef %_1) -#[no_mangle] -pub extern "C" fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} } - -#[repr(transparent)] -pub struct Generic(T); - -// CHECK: define{{.*}}double @test_Generic(double noundef %_1) -#[no_mangle] -pub extern "C" fn test_Generic(_: Generic) -> Generic { loop {} } - -#[repr(transparent)] -pub struct GenericPlusZst(T, Zst2); - -#[repr(u8)] -pub enum Bool { True, False, FileNotFound } - -// CHECK: define{{( dso_local)?}} noundef{{( zeroext)?}} i8 @test_Gpz(i8 noundef{{( zeroext)?}} %_1) -#[no_mangle] -pub extern "C" fn test_Gpz(_: GenericPlusZst) -> GenericPlusZst { loop {} } - -#[repr(transparent)] -pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>); - -// CHECK: define{{.*}}ptr @test_LifetimePhantom(ptr noundef %_1) -#[no_mangle] -pub extern "C" fn test_LifetimePhantom(_: LifetimePhantom) -> LifetimePhantom { loop {} } - -// This works despite current alignment resrictions because PhantomData is always align(1) -#[repr(transparent)] -pub struct UnitPhantom { val: T, unit: PhantomData } - -pub struct Px; - -// CHECK: define{{.*}}float @test_UnitPhantom(float noundef %_1) -#[no_mangle] -pub extern "C" fn test_UnitPhantom(_: UnitPhantom) -> UnitPhantom { loop {} } - -#[repr(transparent)] -pub struct TwoZsts(Zst1, i8, Zst2); - -// CHECK: define{{( dso_local)?}} noundef{{( signext)?}} i8 @test_TwoZsts(i8 noundef{{( signext)?}} %_1) -#[no_mangle] -pub extern "C" fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} } - -#[repr(transparent)] -pub struct Nested1(Zst2, Generic); - -// CHECK: define{{.*}}double @test_Nested1(double noundef %_1) -#[no_mangle] -pub extern "C" fn test_Nested1(_: Nested1) -> Nested1 { loop {} } - -#[repr(transparent)] -pub struct Nested2(Nested1, Zst1); - -// CHECK: define{{.*}}double @test_Nested2(double noundef %_1) -#[no_mangle] -pub extern "C" fn test_Nested2(_: Nested2) -> Nested2 { loop {} } - -#[repr(simd)] -struct f32x4(f32, f32, f32, f32); - -#[repr(transparent)] -pub struct Vector(f32x4); - -// CHECK: define{{.*}}<4 x float> @test_Vector(<4 x float> %_1) -#[no_mangle] -pub extern "C" fn test_Vector(_: Vector) -> Vector { loop {} } - -trait Mirror { type It: ?Sized; } -impl Mirror for T { type It = Self; } - -#[repr(transparent)] -pub struct StructWithProjection(::It); - -// CHECK: define{{.*}}float @test_Projection(float noundef %_1) -#[no_mangle] -pub extern "C" fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} } - -#[repr(transparent)] -pub enum EnumF32 { - Variant(F32) -} - -// CHECK: define{{.*}}float @test_EnumF32(float noundef %_1) -#[no_mangle] -pub extern "C" fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} } - -#[repr(transparent)] -pub enum EnumF32WithZsts { - Variant(Zst1, F32, Zst2) -} - -// CHECK: define{{.*}}float @test_EnumF32WithZsts(float noundef %_1) -#[no_mangle] -pub extern "C" fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} } - -#[repr(transparent)] -pub union UnionF32 { - field: F32, -} - -// CHECK: define{{.*}} float @test_UnionF32(float %_1) -#[no_mangle] -pub extern "C" fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} } - -#[repr(transparent)] -pub union UnionF32WithZsts { - zst1: Zst1, - field: F32, - zst2: Zst2, -} - -// CHECK: define{{.*}}float @test_UnionF32WithZsts(float %_1) -#[no_mangle] -pub extern "C" fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} } - - -// All that remains to be tested are aggregates. They are tested in separate files called repr- -// transparent-*.rs with `only-*` or `ignore-*` directives, because the expected LLVM IR -// function signatures vary so much that it's not reasonably possible to cover all of them with a -// single CHECK line. -// -// You may be wondering why we don't just compare the return types and argument types for equality -// with FileCheck regex captures. Well, rustc doesn't perform newtype unwrapping on newtypes -// containing aggregates. This is OK on all ABIs we support, but because LLVM has not gotten rid of -// pointee types yet, the IR function signature will be syntactically different (%Foo* vs -// %FooWrapper*). diff --git a/tests/codegen/repr/transparent-imm-array.rs b/tests/codegen/repr/transparent-imm-array.rs new file mode 100644 index 00000000000..33f4f222b0a --- /dev/null +++ b/tests/codegen/repr/transparent-imm-array.rs @@ -0,0 +1,90 @@ +// compile-flags: -C no-prepopulate-passes +// + +// ignore-aarch64 +// ignore-emscripten +// ignore-mips64 +// ignore-powerpc +// ignore-powerpc64 +// ignore-riscv64 see codegen/riscv-abi +// ignore-s390x +// ignore-sparc +// ignore-sparc64 +// ignore-x86 +// ignore-x86_64 +// ignore-loongarch64 +// See repr-transparent.rs + +#![feature(transparent_unions)] + +#![crate_type="lib"] + + +#[derive(Clone, Copy)] +#[repr(C)] +pub struct BigS([u32; 16]); + +#[repr(transparent)] +pub struct TsBigS(BigS); + +#[repr(transparent)] +pub union TuBigS { + field: BigS, +} + +#[repr(transparent)] +pub enum TeBigS { + Variant(BigS), +} + +// CHECK: define void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], [16 x i32] +#[no_mangle] +pub extern fn test_BigS(_: BigS) -> BigS { loop {} } + +// CHECK: define void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], [16 x i32] +#[no_mangle] +pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} } + +// CHECK: define void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], [16 x i32] +#[no_mangle] +pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} } + +// CHECK: define void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], [16 x i32] +#[no_mangle] +pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} } + + +#[derive(Clone, Copy)] +#[repr(C)] +pub union BigU { + foo: [u32; 16], +} + +#[repr(transparent)] +pub struct TsBigU(BigU); + +#[repr(transparent)] +pub union TuBigU { + field: BigU, +} + +#[repr(transparent)] +pub enum TeBigU { + Variant(BigU), +} + +// CHECK: define void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], [16 x i32] +#[no_mangle] +pub extern fn test_BigU(_: BigU) -> BigU { loop {} } + +// CHECK: define void @test_TsBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TsBigU) [[BIGU_RET_ATTRS2]], [16 x i32] +#[no_mangle] +pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} } + +// CHECK: define void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2]], [16 x i32] +#[no_mangle] +pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} } + +// CHECK: define void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2]], [16 x i32] +#[no_mangle] +pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} } diff --git a/tests/codegen/repr/transparent-mips64.rs b/tests/codegen/repr/transparent-mips64.rs new file mode 100644 index 00000000000..0db17e6b13a --- /dev/null +++ b/tests/codegen/repr/transparent-mips64.rs @@ -0,0 +1,79 @@ +// compile-flags: -C no-prepopulate-passes +// + +// only-mips64 +// See repr-transparent.rs + +#![feature(transparent_unions)] + +#![crate_type="lib"] + + +#[derive(Clone, Copy)] +#[repr(C)] +pub struct BigS([u32; 16]); + +#[repr(transparent)] +pub struct TsBigS(BigS); + +#[repr(transparent)] +pub union TuBigS { + field: BigS, +} + +#[repr(transparent)] +pub enum TeBigS { + Variant(BigS), +} + +// CHECK: define void @test_BigS(%BigS* [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], [8 x i64] +#[no_mangle] +pub extern fn test_BigS(_: BigS) -> BigS { loop {} } + +// CHECK: define void @test_TsBigS(%TsBigS* [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], [8 x i64] +#[no_mangle] +pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} } + +// CHECK: define void @test_TuBigS(%TuBigS* [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], [8 x i64] +#[no_mangle] +pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} } + +// CHECK: define void @test_TeBigS(%"TeBigS::Variant"* [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], [8 x i64] +#[no_mangle] +pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} } + + +#[derive(Clone, Copy)] +#[repr(C)] +pub union BigU { + foo: [u32; 16], +} + +#[repr(transparent)] +pub struct TsBigU(BigU); + +#[repr(transparent)] +pub union TuBigU { + field: BigU, +} + +#[repr(transparent)] +pub enum TeBigU { + Variant(BigU), +} + +// CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], [8 x i64] +#[no_mangle] +pub extern fn test_BigU(_: BigU) -> BigU { loop {} } + +// CHECK: define void @test_TsBigU(%TsBigU* [[BIGU_RET_ATTRS1]] sret(%TsBigU) [[BIGU_RET_ATTRS2]], [8 x i64] +#[no_mangle] +pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} } + +// CHECK: define void @test_TuBigU(%TuBigU* [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2]], [8 x i64] +#[no_mangle] +pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} } + +// CHECK: define void @test_TeBigU(%"TeBigU::Variant"* [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2]], [8 x i64] +#[no_mangle] +pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} } diff --git a/tests/codegen/repr/transparent-struct-ptr.rs b/tests/codegen/repr/transparent-struct-ptr.rs new file mode 100644 index 00000000000..c783a75a400 --- /dev/null +++ b/tests/codegen/repr/transparent-struct-ptr.rs @@ -0,0 +1,89 @@ +// compile-flags: -O -C no-prepopulate-passes +// + +// ignore-arm +// ignore-aarch64 +// ignore-mips +// ignore-mips64 +// ignore-powerpc +// ignore-powerpc64 +// ignore-riscv64 see codegen/riscv-abi +// ignore-s390x +// ignore-windows +// ignore-loongarch64 +// ignore-wasm32-bare +// See repr-transparent.rs + +#![feature(transparent_unions)] + +#![crate_type="lib"] + + +#[derive(Clone, Copy)] +#[repr(C)] +pub struct BigS([u32; 16]); + +#[repr(transparent)] +pub struct TsBigS(BigS); + +#[repr(transparent)] +pub union TuBigS { + field: BigS, +} + +#[repr(transparent)] +pub enum TeBigS { + Variant(BigS), +} + +// CHECK: define{{.*}}void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], ptr [[BIGS_ARG_ATTRS1:.*]] byval(%BigS) [[BIGS_ARG_ATTRS2:.*]]) +#[no_mangle] +pub extern "C" fn test_BigS(_: BigS) -> BigS { loop {} } + +// CHECK: define{{.*}}void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%TsBigS) [[BIGS_ARG_ATTRS2:.*]]) +#[no_mangle] +pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} } + +// CHECK: define{{.*}}void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%TuBigS) [[BIGS_ARG_ATTRS2:.*]]) +#[no_mangle] +pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} } + +// CHECK: define{{.*}}void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%"TeBigS::Variant") [[BIGS_ARG_ATTRS2]]) +#[no_mangle] +pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} } + + +#[derive(Clone, Copy)] +#[repr(C)] +pub union BigU { + foo: [u32; 16], +} + +#[repr(transparent)] +pub struct TsBigU(BigU); + +#[repr(transparent)] +pub union TuBigU { + field: BigU, +} + +#[repr(transparent)] +pub enum TeBigU { + Variant(BigU), +} + +// CHECK: define{{.*}}void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1:.*]] byval(%BigU) [[BIGU_ARG_ATTRS2:.*]]) +#[no_mangle] +pub extern "C" fn test_BigU(_: BigU) -> BigU { loop {} } + +// CHECK: define{{.*}}void @test_TsBigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%TsBigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%TsBigU) [[BIGU_ARG_ATTRS2]]) +#[no_mangle] +pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} } + +// CHECK: define{{.*}}void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%TuBigU) [[BIGU_ARG_ATTRS2]]) +#[no_mangle] +pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} } + +// CHECK: define{{.*}}void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%"TeBigU::Variant") [[BIGU_ARG_ATTRS2]]) +#[no_mangle] +pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} } diff --git a/tests/codegen/repr/transparent-sysv64.rs b/tests/codegen/repr/transparent-sysv64.rs new file mode 100644 index 00000000000..886b0dd9e7b --- /dev/null +++ b/tests/codegen/repr/transparent-sysv64.rs @@ -0,0 +1,28 @@ +// only-x86_64 + +// compile-flags: -C no-prepopulate-passes + +#![crate_type="lib"] + +#[repr(C)] +pub struct Rgb8 { r: u8, g: u8, b: u8 } + +#[repr(transparent)] +pub struct Rgb8Wrap(Rgb8); + +// CHECK: i24 @test_Rgb8Wrap(i24{{( %0)?}}) +#[no_mangle] +pub extern "sysv64" fn test_Rgb8Wrap(_: Rgb8Wrap) -> Rgb8Wrap { loop {} } + +#[repr(C)] +pub union FloatBits { + float: f32, + bits: u32, +} + +#[repr(transparent)] +pub struct SmallUnion(FloatBits); + +// CHECK: i32 @test_SmallUnion(i32{{( %0)?}}) +#[no_mangle] +pub extern "sysv64" fn test_SmallUnion(_: SmallUnion) -> SmallUnion { loop {} } diff --git a/tests/codegen/repr/transparent.rs b/tests/codegen/repr/transparent.rs new file mode 100644 index 00000000000..64f3ce5a43c --- /dev/null +++ b/tests/codegen/repr/transparent.rs @@ -0,0 +1,171 @@ +// compile-flags: -O -C no-prepopulate-passes + +// ignore-riscv64 riscv64 has an i128 type used with test_Vector +// see codegen/riscv-abi for riscv functiona call tests +// ignore-s390x s390x with default march passes vector types per reference +// ignore-loongarch64 see codegen/loongarch-abi for loongarch function call tests + +#![crate_type="lib"] +#![feature(repr_simd, transparent_unions)] + +use std::marker::PhantomData; + +#[derive(Copy, Clone)] +pub struct Zst1; +#[derive(Copy, Clone)] +pub struct Zst2(()); + +#[derive(Copy, Clone)] +#[repr(transparent)] +pub struct F32(f32); + +// CHECK: define{{.*}}float @test_F32(float noundef %_1) +#[no_mangle] +pub extern "C" fn test_F32(_: F32) -> F32 { loop {} } + +#[repr(transparent)] +pub struct Ptr(*mut u8); + +// CHECK: define{{.*}}ptr @test_Ptr(ptr noundef %_1) +#[no_mangle] +pub extern "C" fn test_Ptr(_: Ptr) -> Ptr { loop {} } + +#[repr(transparent)] +pub struct WithZst(u64, Zst1); + +// CHECK: define{{.*}}i64 @test_WithZst(i64 noundef %_1) +#[no_mangle] +pub extern "C" fn test_WithZst(_: WithZst) -> WithZst { loop {} } + +#[repr(transparent)] +pub struct WithZeroSizedArray(*const f32, [i8; 0]); + +// Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever. +// CHECK: define{{.*}}ptr @test_WithZeroSizedArray(ptr noundef %_1) +#[no_mangle] +pub extern "C" fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} } + +#[repr(transparent)] +pub struct Generic(T); + +// CHECK: define{{.*}}double @test_Generic(double noundef %_1) +#[no_mangle] +pub extern "C" fn test_Generic(_: Generic) -> Generic { loop {} } + +#[repr(transparent)] +pub struct GenericPlusZst(T, Zst2); + +#[repr(u8)] +pub enum Bool { True, False, FileNotFound } + +// CHECK: define{{( dso_local)?}} noundef{{( zeroext)?}} i8 @test_Gpz(i8 noundef{{( zeroext)?}} %_1) +#[no_mangle] +pub extern "C" fn test_Gpz(_: GenericPlusZst) -> GenericPlusZst { loop {} } + +#[repr(transparent)] +pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>); + +// CHECK: define{{.*}}ptr @test_LifetimePhantom(ptr noundef %_1) +#[no_mangle] +pub extern "C" fn test_LifetimePhantom(_: LifetimePhantom) -> LifetimePhantom { loop {} } + +// This works despite current alignment resrictions because PhantomData is always align(1) +#[repr(transparent)] +pub struct UnitPhantom { val: T, unit: PhantomData } + +pub struct Px; + +// CHECK: define{{.*}}float @test_UnitPhantom(float noundef %_1) +#[no_mangle] +pub extern "C" fn test_UnitPhantom(_: UnitPhantom) -> UnitPhantom { loop {} } + +#[repr(transparent)] +pub struct TwoZsts(Zst1, i8, Zst2); + +// CHECK: define{{( dso_local)?}} noundef{{( signext)?}} i8 @test_TwoZsts(i8 noundef{{( signext)?}} %_1) +#[no_mangle] +pub extern "C" fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} } + +#[repr(transparent)] +pub struct Nested1(Zst2, Generic); + +// CHECK: define{{.*}}double @test_Nested1(double noundef %_1) +#[no_mangle] +pub extern "C" fn test_Nested1(_: Nested1) -> Nested1 { loop {} } + +#[repr(transparent)] +pub struct Nested2(Nested1, Zst1); + +// CHECK: define{{.*}}double @test_Nested2(double noundef %_1) +#[no_mangle] +pub extern "C" fn test_Nested2(_: Nested2) -> Nested2 { loop {} } + +#[repr(simd)] +struct f32x4(f32, f32, f32, f32); + +#[repr(transparent)] +pub struct Vector(f32x4); + +// CHECK: define{{.*}}<4 x float> @test_Vector(<4 x float> %_1) +#[no_mangle] +pub extern "C" fn test_Vector(_: Vector) -> Vector { loop {} } + +trait Mirror { type It: ?Sized; } +impl Mirror for T { type It = Self; } + +#[repr(transparent)] +pub struct StructWithProjection(::It); + +// CHECK: define{{.*}}float @test_Projection(float noundef %_1) +#[no_mangle] +pub extern "C" fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} } + +#[repr(transparent)] +pub enum EnumF32 { + Variant(F32) +} + +// CHECK: define{{.*}}float @test_EnumF32(float noundef %_1) +#[no_mangle] +pub extern "C" fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} } + +#[repr(transparent)] +pub enum EnumF32WithZsts { + Variant(Zst1, F32, Zst2) +} + +// CHECK: define{{.*}}float @test_EnumF32WithZsts(float noundef %_1) +#[no_mangle] +pub extern "C" fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} } + +#[repr(transparent)] +pub union UnionF32 { + field: F32, +} + +// CHECK: define{{.*}} float @test_UnionF32(float %_1) +#[no_mangle] +pub extern "C" fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} } + +#[repr(transparent)] +pub union UnionF32WithZsts { + zst1: Zst1, + field: F32, + zst2: Zst2, +} + +// CHECK: define{{.*}}float @test_UnionF32WithZsts(float %_1) +#[no_mangle] +pub extern "C" fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} } + + +// All that remains to be tested are aggregates. They are tested in separate files called repr- +// transparent-*.rs with `only-*` or `ignore-*` directives, because the expected LLVM IR +// function signatures vary so much that it's not reasonably possible to cover all of them with a +// single CHECK line. +// +// You may be wondering why we don't just compare the return types and argument types for equality +// with FileCheck regex captures. Well, rustc doesn't perform newtype unwrapping on newtypes +// containing aggregates. This is OK on all ABIs we support, but because LLVM has not gotten rid of +// pointee types yet, the IR function signature will be syntactically different (%Foo* vs +// %FooWrapper*). -- cgit 1.4.1-3-g733a5