]>
Commit | Line | Data |
---|---|---|
5e7ed085 | 1 | // compile-flags: -O -C no-prepopulate-passes |
2c00a5a8 | 2 | |
f035d41b XL |
3 | // ignore-riscv64 riscv64 has an i128 type used with test_Vector |
4 | // see codegen/riscv-abi for riscv functiona call tests | |
9c376795 | 5 | // ignore-s390x s390x with default march passes vector types per reference |
f035d41b | 6 | |
2c00a5a8 | 7 | #![crate_type="lib"] |
dfeec247 | 8 | #![feature(repr_simd, transparent_unions)] |
2c00a5a8 XL |
9 | |
10 | use std::marker::PhantomData; | |
11 | ||
dc9dc135 | 12 | #[derive(Copy, Clone)] |
2c00a5a8 | 13 | pub struct Zst1; |
dc9dc135 | 14 | #[derive(Copy, Clone)] |
2c00a5a8 XL |
15 | pub struct Zst2(()); |
16 | ||
dc9dc135 | 17 | #[derive(Copy, Clone)] |
2c00a5a8 XL |
18 | #[repr(transparent)] |
19 | pub struct F32(f32); | |
20 | ||
9c376795 | 21 | // CHECK: define{{.*}}float @test_F32(float noundef %_1) |
2c00a5a8 | 22 | #[no_mangle] |
5869c6ff | 23 | pub extern "C" fn test_F32(_: F32) -> F32 { loop {} } |
2c00a5a8 XL |
24 | |
25 | #[repr(transparent)] | |
26 | pub struct Ptr(*mut u8); | |
27 | ||
9c376795 | 28 | // CHECK: define{{.*}}{{i8\*|ptr}} @test_Ptr({{i8\*|ptr}} noundef %_1) |
2c00a5a8 | 29 | #[no_mangle] |
5869c6ff | 30 | pub extern "C" fn test_Ptr(_: Ptr) -> Ptr { loop {} } |
2c00a5a8 XL |
31 | |
32 | #[repr(transparent)] | |
33 | pub struct WithZst(u64, Zst1); | |
34 | ||
9c376795 | 35 | // CHECK: define{{.*}}i64 @test_WithZst(i64 noundef %_1) |
2c00a5a8 | 36 | #[no_mangle] |
5869c6ff | 37 | pub extern "C" fn test_WithZst(_: WithZst) -> WithZst { loop {} } |
2c00a5a8 XL |
38 | |
39 | #[repr(transparent)] | |
40 | pub struct WithZeroSizedArray(*const f32, [i8; 0]); | |
41 | ||
42 | // Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever. | |
9c376795 | 43 | // CHECK: define{{.*}}{{i32\*|ptr}} @test_WithZeroSizedArray({{i32\*|ptr}} noundef %_1) |
2c00a5a8 | 44 | #[no_mangle] |
5869c6ff | 45 | pub extern "C" fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} } |
2c00a5a8 XL |
46 | |
47 | #[repr(transparent)] | |
48 | pub struct Generic<T>(T); | |
49 | ||
9c376795 | 50 | // CHECK: define{{.*}}double @test_Generic(double noundef %_1) |
2c00a5a8 | 51 | #[no_mangle] |
5869c6ff | 52 | pub extern "C" fn test_Generic(_: Generic<f64>) -> Generic<f64> { loop {} } |
2c00a5a8 XL |
53 | |
54 | #[repr(transparent)] | |
55 | pub struct GenericPlusZst<T>(T, Zst2); | |
56 | ||
57 | #[repr(u8)] | |
58 | pub enum Bool { True, False, FileNotFound } | |
59 | ||
5e7ed085 | 60 | // CHECK: define{{( dso_local)?}} noundef{{( zeroext)?}} i8 @test_Gpz(i8 noundef{{( zeroext)?}} %_1) |
2c00a5a8 | 61 | #[no_mangle] |
5869c6ff | 62 | pub extern "C" fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { loop {} } |
2c00a5a8 XL |
63 | |
64 | #[repr(transparent)] | |
65 | pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>); | |
66 | ||
9c376795 | 67 | // CHECK: define{{.*}}{{i16\*|ptr}} @test_LifetimePhantom({{i16\*|ptr}} noundef %_1) |
2c00a5a8 | 68 | #[no_mangle] |
5869c6ff | 69 | pub extern "C" fn test_LifetimePhantom(_: LifetimePhantom<i16>) -> LifetimePhantom<i16> { loop {} } |
2c00a5a8 XL |
70 | |
71 | // This works despite current alignment resrictions because PhantomData is always align(1) | |
72 | #[repr(transparent)] | |
73 | pub struct UnitPhantom<T, U> { val: T, unit: PhantomData<U> } | |
74 | ||
75 | pub struct Px; | |
76 | ||
9c376795 | 77 | // CHECK: define{{.*}}float @test_UnitPhantom(float noundef %_1) |
2c00a5a8 | 78 | #[no_mangle] |
5869c6ff | 79 | pub extern "C" fn test_UnitPhantom(_: UnitPhantom<f32, Px>) -> UnitPhantom<f32, Px> { loop {} } |
2c00a5a8 XL |
80 | |
81 | #[repr(transparent)] | |
82 | pub struct TwoZsts(Zst1, i8, Zst2); | |
83 | ||
9c376795 | 84 | // CHECK: define{{( dso_local)?}} noundef{{( signext)?}} i8 @test_TwoZsts(i8 noundef{{( signext)?}} %_1) |
2c00a5a8 | 85 | #[no_mangle] |
5869c6ff | 86 | pub extern "C" fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} } |
2c00a5a8 XL |
87 | |
88 | #[repr(transparent)] | |
89 | pub struct Nested1(Zst2, Generic<f64>); | |
90 | ||
9c376795 | 91 | // CHECK: define{{.*}}double @test_Nested1(double noundef %_1) |
2c00a5a8 | 92 | #[no_mangle] |
5869c6ff | 93 | pub extern "C" fn test_Nested1(_: Nested1) -> Nested1 { loop {} } |
2c00a5a8 XL |
94 | |
95 | #[repr(transparent)] | |
96 | pub struct Nested2(Nested1, Zst1); | |
97 | ||
9c376795 | 98 | // CHECK: define{{.*}}double @test_Nested2(double noundef %_1) |
2c00a5a8 | 99 | #[no_mangle] |
5869c6ff | 100 | pub extern "C" fn test_Nested2(_: Nested2) -> Nested2 { loop {} } |
2c00a5a8 XL |
101 | |
102 | #[repr(simd)] | |
103 | struct f32x4(f32, f32, f32, f32); | |
104 | ||
105 | #[repr(transparent)] | |
106 | pub struct Vector(f32x4); | |
107 | ||
cdc7bbd5 | 108 | // CHECK: define{{.*}}<4 x float> @test_Vector(<4 x float> %_1) |
2c00a5a8 | 109 | #[no_mangle] |
5869c6ff | 110 | pub extern "C" fn test_Vector(_: Vector) -> Vector { loop {} } |
2c00a5a8 XL |
111 | |
112 | trait Mirror { type It: ?Sized; } | |
113 | impl<T: ?Sized> Mirror for T { type It = Self; } | |
114 | ||
115 | #[repr(transparent)] | |
116 | pub struct StructWithProjection(<f32 as Mirror>::It); | |
117 | ||
9c376795 | 118 | // CHECK: define{{.*}}float @test_Projection(float noundef %_1) |
2c00a5a8 | 119 | #[no_mangle] |
5869c6ff | 120 | pub extern "C" fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} } |
2c00a5a8 | 121 | |
dc9dc135 XL |
122 | #[repr(transparent)] |
123 | pub enum EnumF32 { | |
124 | Variant(F32) | |
125 | } | |
126 | ||
9c376795 | 127 | // CHECK: define{{.*}}float @test_EnumF32(float noundef %_1) |
dc9dc135 | 128 | #[no_mangle] |
5869c6ff | 129 | pub extern "C" fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} } |
dc9dc135 XL |
130 | |
131 | #[repr(transparent)] | |
132 | pub enum EnumF32WithZsts { | |
133 | Variant(Zst1, F32, Zst2) | |
134 | } | |
135 | ||
9c376795 | 136 | // CHECK: define{{.*}}float @test_EnumF32WithZsts(float noundef %_1) |
dc9dc135 | 137 | #[no_mangle] |
5869c6ff | 138 | pub extern "C" fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} } |
dc9dc135 XL |
139 | |
140 | #[repr(transparent)] | |
141 | pub union UnionF32 { | |
142 | field: F32, | |
143 | } | |
144 | ||
9c376795 | 145 | // CHECK: define{{.*}} float @test_UnionF32(float %_1) |
dc9dc135 | 146 | #[no_mangle] |
5869c6ff | 147 | pub extern "C" fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} } |
dc9dc135 XL |
148 | |
149 | #[repr(transparent)] | |
150 | pub union UnionF32WithZsts { | |
151 | zst1: Zst1, | |
152 | field: F32, | |
153 | zst2: Zst2, | |
154 | } | |
155 | ||
cdc7bbd5 | 156 | // CHECK: define{{.*}}float @test_UnionF32WithZsts(float %_1) |
dc9dc135 | 157 | #[no_mangle] |
5869c6ff | 158 | pub extern "C" fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} } |
dc9dc135 | 159 | |
2c00a5a8 XL |
160 | |
161 | // All that remains to be tested are aggregates. They are tested in separate files called repr- | |
162 | // transparent-*.rs with `only-*` or `ignore-*` directives, because the expected LLVM IR | |
163 | // function signatures vary so much that it's not reasonably possible to cover all of them with a | |
164 | // single CHECK line. | |
165 | // | |
166 | // You may be wondering why we don't just compare the return types and argument types for equality | |
167 | // with FileCheck regex captures. Well, rustc doesn't perform newtype unwrapping on newtypes | |
168 | // containing aggregates. This is OK on all ABIs we support, but because LLVM has not gotten rid of | |
169 | // pointee types yet, the IR function signature will be syntactically different (%Foo* vs | |
170 | // %FooWrapper*). |