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 %arg0)
19 pub extern fn test_F32(_
: F32
) -> F32 { loop {}
}
22 pub struct Ptr(*mut u8);
24 // CHECK: define i8* @test_Ptr(i8* %arg0)
26 pub extern fn test_Ptr(_
: Ptr
) -> Ptr { loop {}
}
29 pub struct WithZst(u64, Zst1
);
31 // CHECK: define i64 @test_WithZst(i64 %arg0)
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* %arg0)
41 pub extern fn test_WithZeroSizedArray(_
: WithZeroSizedArray
) -> WithZeroSizedArray { loop {}
}
44 pub struct Generic
<T
>(T
);
46 // CHECK: define double @test_Generic(double %arg0)
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)?}} %arg0)
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* %arg0)
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 %arg0)
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)?}} %arg0)
82 pub extern fn test_TwoZsts(_
: TwoZsts
) -> TwoZsts { loop {}
}
85 pub struct Nested1(Zst2
, Generic
<f64>);
87 // CHECK: define double @test_Nested1(double %arg0)
89 pub extern fn test_Nested1(_
: Nested1
) -> Nested1 { loop {}
}
92 pub struct Nested2(Nested1
, Zst1
);
94 // CHECK: define double @test_Nested2(double %arg0)
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> %arg0)
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 %arg0)
116 pub extern fn test_Projection(_
: StructWithProjection
) -> StructWithProjection { loop {}
}
123 // CHECK: define float @test_EnumF32(float %arg0)
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 %arg0)
134 pub extern fn test_EnumF32WithZsts(_
: EnumF32WithZsts
) -> EnumF32WithZsts { loop {}
}
141 // CHECK: define float @test_UnionF32(float %arg0)
143 pub extern fn test_UnionF32(_
: UnionF32
) -> UnionF32 { loop {}
}
146 pub union UnionF32WithZsts
{
152 // CHECK: define float @test_UnionF32WithZsts(float %arg0)
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