/src/test/codegen/packed.rs

https://gitlab.com/rust-lang/rust · Rust · 153 lines · 90 code · 21 blank · 42 comment · 0 complexity · 1e3ad1897d87dd01d88e47c7b88e5192 MD5 · raw file

  1. //
  2. // compile-flags: -O -C no-prepopulate-passes
  3. #![crate_type = "lib"]
  4. #[repr(packed)]
  5. pub struct Packed1 {
  6. dealign: u8,
  7. data: u32
  8. }
  9. #[repr(packed(2))]
  10. pub struct Packed2 {
  11. dealign: u8,
  12. data: u32
  13. }
  14. // CHECK-LABEL: @write_pkd1
  15. #[no_mangle]
  16. pub fn write_pkd1(pkd: &mut Packed1) -> u32 {
  17. // CHECK: %{{.*}} = load i32, {{i32\*|ptr}} %{{.*}}, align 1
  18. // CHECK: store i32 42, {{i32\*|ptr}} %{{.*}}, align 1
  19. let result = pkd.data;
  20. pkd.data = 42;
  21. result
  22. }
  23. // CHECK-LABEL: @write_pkd2
  24. #[no_mangle]
  25. pub fn write_pkd2(pkd: &mut Packed2) -> u32 {
  26. // CHECK: %{{.*}} = load i32, {{i32\*|ptr}} %{{.*}}, align 2
  27. // CHECK: store i32 42, {{i32\*|ptr}} %{{.*}}, align 2
  28. let result = pkd.data;
  29. pkd.data = 42;
  30. result
  31. }
  32. pub struct Array([i32; 8]);
  33. #[repr(packed)]
  34. pub struct BigPacked1 {
  35. dealign: u8,
  36. data: Array
  37. }
  38. #[repr(packed(2))]
  39. pub struct BigPacked2 {
  40. dealign: u8,
  41. data: Array
  42. }
  43. // CHECK-LABEL: @call_pkd1
  44. #[no_mangle]
  45. pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
  46. // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
  47. // CHECK: call void %{{.*}}({{%Array\*|ptr}} noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
  48. // CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
  49. // check that calls whose destination is a field of a packed struct
  50. // go through an alloca rather than calling the function with an
  51. // unaligned destination.
  52. BigPacked1 { dealign: 0, data: f() }
  53. }
  54. // CHECK-LABEL: @call_pkd2
  55. #[no_mangle]
  56. pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
  57. // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
  58. // CHECK: call void %{{.*}}({{%Array\*|ptr}} noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
  59. // CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 2 %{{.*}}, {{i8\*|ptr}} align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
  60. // check that calls whose destination is a field of a packed struct
  61. // go through an alloca rather than calling the function with an
  62. // unaligned destination.
  63. BigPacked2 { dealign: 0, data: f() }
  64. }
  65. // CHECK-LABEL: @write_packed_array1
  66. // CHECK: store i32 0, {{i32\*|ptr}} %{{.+}}, align 1
  67. // CHECK: store i32 1, {{i32\*|ptr}} %{{.+}}, align 1
  68. // CHECK: store i32 2, {{i32\*|ptr}} %{{.+}}, align 1
  69. #[no_mangle]
  70. pub fn write_packed_array1(p: &mut BigPacked1) {
  71. p.data.0[0] = 0;
  72. p.data.0[1] = 1;
  73. p.data.0[2] = 2;
  74. }
  75. // CHECK-LABEL: @write_packed_array2
  76. // CHECK: store i32 0, {{i32\*|ptr}} %{{.+}}, align 2
  77. // CHECK: store i32 1, {{i32\*|ptr}} %{{.+}}, align 2
  78. // CHECK: store i32 2, {{i32\*|ptr}} %{{.+}}, align 2
  79. #[no_mangle]
  80. pub fn write_packed_array2(p: &mut BigPacked2) {
  81. p.data.0[0] = 0;
  82. p.data.0[1] = 1;
  83. p.data.0[2] = 2;
  84. }
  85. // CHECK-LABEL: @repeat_packed_array1
  86. // CHECK: store i32 42, {{i32\*|ptr}} %{{.+}}, align 1
  87. #[no_mangle]
  88. pub fn repeat_packed_array1(p: &mut BigPacked1) {
  89. p.data.0 = [42; 8];
  90. }
  91. // CHECK-LABEL: @repeat_packed_array2
  92. // CHECK: store i32 42, {{i32\*|ptr}} %{{.+}}, align 2
  93. #[no_mangle]
  94. pub fn repeat_packed_array2(p: &mut BigPacked2) {
  95. p.data.0 = [42; 8];
  96. }
  97. #[repr(packed)]
  98. #[derive(Copy, Clone)]
  99. pub struct Packed1Pair(u8, u32);
  100. #[repr(packed(2))]
  101. #[derive(Copy, Clone)]
  102. pub struct Packed2Pair(u8, u32);
  103. // CHECK-LABEL: @pkd1_pair
  104. #[no_mangle]
  105. pub fn pkd1_pair(pair1: &mut Packed1Pair, pair2: &mut Packed1Pair) {
  106. // CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{[0-9]+}} 5, i1 false)
  107. *pair2 = *pair1;
  108. }
  109. // CHECK-LABEL: @pkd2_pair
  110. #[no_mangle]
  111. pub fn pkd2_pair(pair1: &mut Packed2Pair, pair2: &mut Packed2Pair) {
  112. // CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 2 %{{.*}}, {{i8\*|ptr}} align 2 %{{.*}}, i{{[0-9]+}} 6, i1 false)
  113. *pair2 = *pair1;
  114. }
  115. #[repr(packed)]
  116. #[derive(Copy, Clone)]
  117. pub struct Packed1NestedPair((u32, u32));
  118. #[repr(packed(2))]
  119. #[derive(Copy, Clone)]
  120. pub struct Packed2NestedPair((u32, u32));
  121. // CHECK-LABEL: @pkd1_nested_pair
  122. #[no_mangle]
  123. pub fn pkd1_nested_pair(pair1: &mut Packed1NestedPair, pair2: &mut Packed1NestedPair) {
  124. // CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{[0-9]+}} 8, i1 false)
  125. *pair2 = *pair1;
  126. }
  127. // CHECK-LABEL: @pkd2_nested_pair
  128. #[no_mangle]
  129. pub fn pkd2_nested_pair(pair1: &mut Packed2NestedPair, pair2: &mut Packed2NestedPair) {
  130. // CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 2 %{{.*}}, {{i8\*|ptr}} align 2 %{{.*}}, i{{[0-9]+}} 8, i1 false)
  131. *pair2 = *pair1;
  132. }