/src/test/codegen/repr-transparent.rs

https://gitlab.com/rust-lang/rust · Rust · 169 lines · 93 code · 44 blank · 32 comment · 1 complexity · 3373df78bcb1fb89ee8e938551211ce3 MD5 · raw file

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