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