[flang-commits] [flang] [flang] Fix RecordType sizes, TRANSFER lowering, and BIND(C) ABI on SystemZ/PPC64le (PR #220377)

via flang-commits flang-commits at lists.llvm.org
Fri Sep 4 23:33:10 PDT 2026


================
@@ -102,4 +102,67 @@ module attributes { dlti.dl_spec = #dlti.dl_spec< i1 = dense<8> : vector<2xi64>,
   // CHECK:         %[[C:.*]] = arith.constant 16 : index
   // CHECK:         return %[[C]]
   // CHECK-NOT:     fir.box_elesize
+
+  // Fold: packed derived type -- fir.type<tp<{i:i32,d:f64}>>.
+  // This is the exact example from MattPD's review: on x86-64
+  // (f64 ABI align=8B) the non-packed size is 16B and the packed
+  // size is 12B (i32 allocSize=4B + f64 allocSize=alignTo(8,8)=8B,
+  // no inter-field gap, no tail padding).
+  // The element distance must be 12, not 16.
+  func.func @fold_packed_record(%arg0: !fir.box<!fir.type<tp<{i:i32,d:f64}>>>) -> index {
+    %0 = fir.box_elesize %arg0 : (!fir.box<!fir.type<tp<{i:i32,d:f64}>>>) -> index
+    return %0 : index
+  }
+  // CHECK-LABEL: func.func @fold_packed_record(
+  // CHECK:         %[[C:.*]] = arith.constant 12 : index
+  // CHECK:         return %[[C]]
+  // CHECK-NOT:     fir.box_elesize
+
+  // Fold: packed derived type with a wider alignment gap.
+  // On x86-64: i32 store=4B, complex<f64> store=16B.
+  // Non-packed: alignTo(4,4)=4 + alignTo(4,8)+alignTo(16,8)=24, tail=24 -> 24B.
+  // Packed:     4 + 16 = 20B, align=1.
+  // The element distance must be 20, not 24.
+  func.func @fold_packed_record2(%arg0: !fir.box<!fir.type<tp2<{i:i32,z:complex<f64>}>>>) -> index {
+    %0 = fir.box_elesize %arg0 : (!fir.box<!fir.type<tp2<{i:i32,z:complex<f64>}>>>) -> index
+    return %0 : index
+  }
+  // CHECK-LABEL: func.func @fold_packed_record2(
+  // CHECK:         %[[C:.*]] = arith.constant 20 : index
+  // CHECK:         return %[[C]]
+  // CHECK-NOT:     fir.box_elesize
+
+  // Fold: tail-padded record type -- fir.type<tpad{a:i32,b:i8}>.
+  // The field loop gives size=5, align=4; getTypeSizeAndAlignment returns
+  // {8, 4} (alignTo(5,4)=8).  FoldBoxEleSize also rounded 5 to 8 before
+  // this fix, so both revisions fold to 8.  This check verifies that the
+  // correct 8-byte element stride is produced; the distinction between
+  // allocation size and raw store size is covered by
+  // flang/test/Fir/CUDA/cuda-constructor-2.f90 and
+  // flang/test/Fir/CUDA/cuda-shared-offset.mlir.
+  // Use a distinct type name (tpad) to avoid redefining the packed type (tp)
+  // used above.
+  func.func @fold_tail_padded_record(%arg0: !fir.box<!fir.array<?x!fir.type<tpad{a:i32,b:i8}>>>) -> index {
+    %0 = fir.box_elesize %arg0 : (!fir.box<!fir.array<?x!fir.type<tpad{a:i32,b:i8}>>>) -> index
+    return %0 : index
+  }
+  // CHECK-LABEL: func.func @fold_tail_padded_record(
+  // CHECK:         %[[C:.*]] = arith.constant 8 : index
+  // CHECK:         return %[[C]]
+  // CHECK-NOT:     fir.box_elesize
+
+  // Fold: packed derived type with f80 component.
+  // f80 on x86-64: store size = 10B, ABI alignment = 16B,
+  //   allocation size = alignTo(10, 16) = 16B.
+  // i8:  store size = 1B, ABI alignment = 1B, allocation size = 1B.
+  // Packed size = 16 + 1 = 17B (not 10 + 1 = 11B).
+  // This case distinguishes allocation-size from store-size in the packed path.
+  func.func @fold_packed_f80_i8(%arg0: !fir.box<!fir.type<tp3<{x:f80,b:i8}>>>) -> index {
+    %0 = fir.box_elesize %arg0 : (!fir.box<!fir.type<tp3<{x:f80,b:i8}>>>) -> index
+    return %0 : index
+  }
+  // CHECK-LABEL: func.func @fold_packed_f80_i8(
+  // CHECK:         %[[C:.*]] = arith.constant 17 : index
----------------
MattPD wrote:

I am flagging a separate FIR-to-LLVM heap-allocation gap so it is tracked. At `de5ef3bc48d6`, `fir.allocmem !fir.type<tp3<{x:f80,b:i8}>>` lowers to `malloc(11)`, although LLVM places `b` at byte 16. Could the PR link an issue that tracks the allocation gap?

https://github.com/llvm/llvm-project/pull/220377


More information about the flang-commits mailing list