1 // compile-flags: -C no-prepopulate-passes
4 #![feature(repr_simd, transparent_enums, transparent_unions)]
6 use std::marker::PhantomData;
10 #[derive(Copy, Clone)]
13 #[derive(Copy, Clone)]
17 // CHECK: define float @test_F32(float %_1)
19 pub extern fn test_F32(_: F32) -> F32 { loop {} }
22 pub struct Ptr(*mut u8);
24 // CHECK: define i8* @test_Ptr(i8* %_1)
26 pub extern fn test_Ptr(_: Ptr) -> Ptr { loop {} }
29 pub struct WithZst(u64, Zst1);
31 // CHECK: define i64 @test_WithZst(i64 %_1)
33 pub extern fn test_WithZst(_: WithZst) -> WithZst { loop {} }
36 pub struct WithZeroSizedArray(*const f32, [i8; 0]);
38 // Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever.
39 // CHECK: define i32* @test_WithZeroSizedArray(i32* %_1)
41 pub extern fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} }
44 pub struct Generic<T>(T);
46 // CHECK: define double @test_Generic(double %_1)
48 pub extern fn test_Generic(_: Generic<f64>) -> Generic<f64> { loop {} }
51 pub struct GenericPlusZst<T>(T, Zst2);
54 pub enum Bool { True, False, FileNotFound }
56 // CHECK: define{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %_1)
58 pub extern fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { loop {} }
61 pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>);
63 // CHECK: define i16* @test_LifetimePhantom(i16* %_1)
65 pub extern fn test_LifetimePhantom(_: LifetimePhantom<i16>) -> LifetimePhantom<i16> { loop {} }
67 // This works despite current alignment resrictions because PhantomData is always align(1)
69 pub struct UnitPhantom<T, U> { val: T, unit: PhantomData<U> }
73 // CHECK: define float @test_UnitPhantom(float %_1)
75 pub extern fn test_UnitPhantom(_: UnitPhantom<f32, Px>) -> UnitPhantom<f32, Px> { loop {} }
78 pub struct TwoZsts(Zst1, i8, Zst2);
80 // CHECK: define{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %_1)
82 pub extern fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} }
85 pub struct Nested1(Zst2, Generic<f64>);
87 // CHECK: define double @test_Nested1(double %_1)
89 pub extern fn test_Nested1(_: Nested1) -> Nested1 { loop {} }
92 pub struct Nested2(Nested1, Zst1);
94 // CHECK: define double @test_Nested2(double %_1)
96 pub extern fn test_Nested2(_: Nested2) -> Nested2 { loop {} }
99 struct f32x4(f32, f32, f32, f32);
102 pub struct Vector(f32x4);
104 // CHECK: define <4 x float> @test_Vector(<4 x float> %_1)
106 pub extern fn test_Vector(_: Vector) -> Vector { loop {} }
108 trait Mirror { type It: ?Sized; }
109 impl<T: ?Sized> Mirror for T { type It = Self; }
112 pub struct StructWithProjection(<f32 as Mirror>::It);
114 // CHECK: define float @test_Projection(float %_1)
116 pub extern fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} }
123 // CHECK: define float @test_EnumF32(float %_1)
125 pub extern fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} }
128 pub enum EnumF32WithZsts {
129 Variant(Zst1, F32, Zst2)
132 // CHECK: define float @test_EnumF32WithZsts(float %_1)
134 pub extern fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} }
141 // CHECK: define float @test_UnionF32(float %_1)
143 pub extern fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }
146 pub union UnionF32WithZsts {
152 // CHECK: define float @test_UnionF32WithZsts(float %_1)
154 pub extern fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} }
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.
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