about summary refs log tree commit diff
path: root/tests/codegen/repr
diff options
context:
space:
mode:
authorJubilee Young <workingjubilee@gmail.com>2023-07-29 15:15:23 -0700
committerJubilee Young <workingjubilee@gmail.com>2023-07-29 15:35:36 -0700
commit040bc3447e3d43ce79dee8420f4ab05d6aa3a8c7 (patch)
treeef7cfb3cae9fa06ab4907091fb6fb16c1a561b13 /tests/codegen/repr
parentb2375fb9e2616e5f600752672c9b34d4df703348 (diff)
downloadrust-040bc3447e3d43ce79dee8420f4ab05d6aa3a8c7.tar.gz
rust-040bc3447e3d43ce79dee8420f4ab05d6aa3a8c7.zip
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
Diffstat (limited to 'tests/codegen/repr')
-rw-r--r--tests/codegen/repr/transparent-imm-array.rs90
-rw-r--r--tests/codegen/repr/transparent-mips64.rs79
-rw-r--r--tests/codegen/repr/transparent-struct-ptr.rs89
-rw-r--r--tests/codegen/repr/transparent-sysv64.rs28
-rw-r--r--tests/codegen/repr/transparent.rs171
5 files changed, 457 insertions, 0 deletions
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>(T);
+
+// CHECK: define{{.*}}double @test_Generic(double noundef %_1)
+#[no_mangle]
+pub extern "C" fn test_Generic(_: Generic<f64>) -> Generic<f64> { loop {} }
+
+#[repr(transparent)]
+pub struct GenericPlusZst<T>(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<Bool>) -> GenericPlusZst<Bool> { 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<i16>) -> LifetimePhantom<i16> { loop {} }
+
+// This works despite current alignment resrictions because PhantomData is always align(1)
+#[repr(transparent)]
+pub struct UnitPhantom<T, U> { val: T, unit: PhantomData<U> }
+
+pub struct Px;
+
+// CHECK: define{{.*}}float @test_UnitPhantom(float noundef %_1)
+#[no_mangle]
+pub extern "C" fn test_UnitPhantom(_: UnitPhantom<f32, Px>) -> UnitPhantom<f32, Px> { 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<f64>);
+
+// 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<T: ?Sized> Mirror for T { type It = Self; }
+
+#[repr(transparent)]
+pub struct StructWithProjection(<f32 as Mirror>::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*).