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