[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
Thu Sep 10 12:49:46 PDT 2026


================
@@ -1664,27 +1666,62 @@ fir::getTypeSizeAndAlignment(mlir::Location loc, mlir::Type ty,
   if (auto recTy = mlir::dyn_cast<fir::RecordType>(ty)) {
     std::uint64_t size = 0;
     unsigned short align = 1;
+    if (recTy.isPacked()) {
+      // LLVM packed structs (<{ ... }>) place fields back-to-back with no
+      // inter-field alignment padding and no tail padding.  Each component
+      // still occupies its allocation size (llvm::alignTo(storeSize, ABI
+      // alignment)), because LLVM's packed StructLayout advances by
+      // getTypeAllocSize, not getTypeStoreSize.  For example, x86 f80 has
+      // store size 10 bytes but ABI alignment 16 bytes, so its allocation
+      // size is 16 bytes; a packed {f80, i8} therefore occupies 17 bytes,
+      // not 11.  The packed struct's own ABI alignment is always 1.
+      for (auto component : recTy.getTypeList()) {
+        // Use the component's allocation size (storeSizeOnly=false) regardless
+        // of the outer storeSizeOnly flag.  LLVM's packed StructLayout advances
+        // by getTypeAllocSize per field, so we need the allocation size of each
+        // component to reproduce the correct packed layout.  The outer
+        // storeSizeOnly flag is irrelevant here because packed structs have no
+        // tail padding; the struct's total size is the same whether or not tail
+        // rounding is requested.
+        auto result =
+            getTypeSizeAndAlignmentImpl(loc, component.second, dl, kindMap,
+                                        /*storeSizeOnly=*/false);
+        if (!result)
+          return result;
+        auto [compSize, compAlign] = *result;
+        size += llvm::alignTo(compSize, compAlign); // alloc size per field
+      }
+      // Packed structs have no tail padding regardless of storeSizeOnly.
+      return std::pair{size, static_cast<unsigned short>(1)};
+    }
     for (auto component : recTy.getTypeList()) {
-      auto result = getTypeSizeAndAlignment(loc, component.second, dl, kindMap);
+      auto result = getTypeSizeAndAlignmentImpl(loc, component.second, dl,
+                                                kindMap, storeSizeOnly);
       if (!result)
         return result;
       auto [compSize, compAlign] = *result;
       size =
           llvm::alignTo(size, compAlign) + llvm::alignTo(compSize, compAlign);
       align = std::max(align, compAlign);
     }
+    // Round up to the record's alignment to include outermost tail padding.
+    // storeSizeOnly suppresses only this final rounding; inter-field padding
+    // within the record is always included.
+    if (!storeSizeOnly)
+      size = llvm::alignTo(size, align);
----------------
MattPD wrote:

Confirmed: The test now checks the correct 16-byte element stride.

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


More information about the flang-commits mailing list