Xiangling_L created this revision.
Xiangling_L added reviewers: jasonliu, hubert.reinterpretcast, sfertile.
Xiangling_L added a project: LLVM.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Address the following aspects of power alignment rules:

- Implemented double/long double alignment when not first struct member
- A double member in union is always treated as the first member, and should 
not use special alignment rule
- Fixed the alignment issue caused by virtual function
- Applied AIX Alignment rule when layout base class
- Fixed AIX layout for zero sized bitfield followed by double


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D78563

Files:
  clang/include/clang/AST/RecordLayout.h
  clang/lib/AST/RecordLayout.cpp
  clang/lib/AST/RecordLayoutBuilder.cpp
  clang/test/Layout/aix-double-struct-member.cpp
  clang/test/Layout/aix-virtual-function-alignment.cpp

Index: clang/test/Layout/aix-virtual-function-alignment.cpp
===================================================================
--- /dev/null
+++ clang/test/Layout/aix-virtual-function-alignment.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple powerpc-ibm-aix-xcoff \
+// RUN: -fdump-record-layouts -fsyntax-only %s 2>/dev/null | FileCheck \
+// RUN: --check-prefix=CHECK32 %s
+
+// RUN: %clang_cc1 -emit-llvm-only -triple powerpc64-ibm-aix-xcoff \
+// RUN: -fdump-record-layouts -fsyntax-only %s 2>/dev/null | FileCheck \
+// RUN: --check-prefix=CHECK64 %s
+
+struct A {
+  virtual void boo() {}
+};
+
+struct B {
+  bool b;
+  A a;
+};
+
+int i = sizeof(B);
+
+// CHECK32:      *** Dumping AST Record Layout
+// CHECK32-NEXT:          0 | struct A
+// CHECK32-NEXT:          0 |   (A vtable pointer)
+// CHECK32-NEXT:            | [sizeof=4, dsize=4, align=4,
+// CHECK32-NEXT:            |  nvsize=4, nvalign=4]
+
+// CHECK32:      *** Dumping AST Record Layout
+// CHECK32-NEXT:          0 | struct B
+// CHECK32-NEXT:          0 |   _Bool b
+// CHECK32-NEXT:          4 |   struct A a
+// CHECK32-NEXT:          4 |     (A vtable pointer)
+// CHECK32-NEXT:            | [sizeof=8, dsize=8, align=4,
+// CHECK32-NEXT:            |  nvsize=8, nvalign=4]
+
+// CHECK64:      *** Dumping AST Record Layout
+// CHECK64-NEXT:          0 | struct A
+// CHECK64-NEXT:          0 |   (A vtable pointer)
+// CHECK64-NEXT:            | [sizeof=8, dsize=8, align=8,
+// CHECK64-NEXT:            |  nvsize=8, nvalign=8]
+
+// CHECK64:      *** Dumping AST Record Layout
+// CHECK64-NEXT:          0 | struct B
+// CHECK64-NEXT:          0 |   _Bool b
+// CHECK64-NEXT:          8 |   struct A a
+// CHECK64-NEXT:          8 |     (A vtable pointer)
+// CHECK64-NEXT:            | [sizeof=16, dsize=16, align=8,
+// CHECK64-NEXT:            |  nvsize=16, nvalign=8]
Index: clang/test/Layout/aix-double-struct-member.cpp
===================================================================
--- /dev/null
+++ clang/test/Layout/aix-double-struct-member.cpp
@@ -0,0 +1,136 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple powerpc-ibm-aix-xcoff \
+// RUN: -fdump-record-layouts -fsyntax-only %s 2>/dev/null | FileCheck %s
+
+// RUN: %clang_cc1 -emit-llvm-only -triple powerpc64-ibm-aix-xcoff \
+// RUN: -fdump-record-layouts -fsyntax-only %s 2>/dev/null | FileCheck %s
+
+namespace test1 {
+// Test double alignment when it is/is not the first struct member.
+struct D {
+  double d1;
+  int i1;
+};
+
+struct DoubleFirst {
+  struct D d2;
+  int i2;
+};
+
+struct IntFirst {
+  int i3;
+  struct D d3;
+};
+
+int a = sizeof(DoubleFirst);
+int b = sizeof(IntFirst);
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:         0 | struct test1::D
+// CHECK-NEXT:         0 |   double d1
+// CHECK-NEXT:         8 |   int i1
+// CHECK-NEXT:           | [sizeof=16, dsize=16, align=8,
+// CHECK-NEXT:           |  nvsize=16, nvalign=8]
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:         0 | struct test1::DoubleFirst
+// CHECK-NEXT:         0 |   struct test1::D d2
+// CHECK-NEXT:         0 |     double d1
+// CHECK-NEXT:         8 |     int i1
+// CHECK-NEXT:        16 |   int i2
+// CHECK-NEXT:           | [sizeof=24, dsize=24, align=8,
+// CHECK-NEXT:           |  nvsize=24, nvalign=8]
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:         0 | struct test1::IntFirst
+// CHECK-NEXT:         0 |   int i3
+// CHECK-NEXT:         4 |   struct test1::D d3
+// CHECK-NEXT:         4 |     double d1
+// CHECK-NEXT:        12 |     int i1
+// CHECK-NEXT:           | [sizeof=20, dsize=20, align=4,
+// CHECK-NEXT:           |  nvsize=20, nvalign=4]
+}; // namespace test1
+
+namespace test2 {
+// Test AIX layout for zero sized bitfield followed by double.
+struct Double {
+  int : 0;
+  double d;
+};
+
+int a = sizeof(Double);
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:         0 | struct test2::Double
+// CHECK-NEXT:       0:- |   int
+// CHECK-NEXT:         0 |   double d
+// CHECK-NEXT:           | [sizeof=8, dsize=8, align=4,
+// CHECK-NEXT:           |  nvsize=8, nvalign=4]
+}; // namespace test2
+
+namespace test3 {
+// Test the alignment of a double member in union.
+union A {
+  int *b;
+  double d;
+};
+
+struct UnionStruct {
+  union A a;
+  int i;
+};
+
+int a = sizeof(UnionStruct);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | union test3::A
+// CHECK-NEXT:          0 |   int * b
+// CHECK-NEXT:          0 |   double d
+// CHECK-NEXT:            | [sizeof=8, dsize=8, align=8,
+// CHECK-NEXT:            |  nvsize=8, nvalign=8]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test3::UnionStruct
+// CHECK-NEXT:          0 |   union test3::A a
+// CHECK-NEXT:          0 |     int * b
+// CHECK-NEXT:          0 |     double d
+// CHECK-NEXT:          8 |   int i
+// CHECK-NEXT:            | [sizeof=16, dsize=16, align=8,
+// CHECK-NEXT:            |  nvsize=16, nvalign=8]
+}; // namespace test3
+
+namespace test4 {
+// Test the AIX Alignment rule when layout base class.
+struct A {
+  int a;
+};
+
+struct B {
+  double d;
+};
+
+class S : A, B {
+};
+
+int a = sizeof(S);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test4::A
+// CHECK-NEXT:          0 |   int a
+// CHECK-NEXT:            | [sizeof=4, dsize=4, align=4,
+// CHECK-NEXT:            |  nvsize=4, nvalign=4]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test4::B
+// CHECK-NEXT:          0 |   double d
+// CHECK-NEXT:            | [sizeof=8, dsize=8, align=8,
+// CHECK-NEXT:            |  nvsize=8, nvalign=8]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | class test4::S
+// CHECK-NEXT:          0 |   struct test4::A (base)
+// CHECK-NEXT:          0 |     int a
+// CHECK-NEXT:          4 |   struct test4::B (base)
+// CHECK-NEXT:          4 |     double d
+// CHECK-NEXT:            | [sizeof=12, dsize=12, align=4,
+// CHECK-NEXT:            |  nvsize=12, nvalign=4]
+}; // namespace test4
Index: clang/lib/AST/RecordLayoutBuilder.cpp
===================================================================
--- clang/lib/AST/RecordLayoutBuilder.cpp
+++ clang/lib/AST/RecordLayoutBuilder.cpp
@@ -6,7 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/AST/RecordLayout.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTDiagnostic.h"
 #include "clang/AST/Attr.h"
@@ -15,6 +14,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/RecordLayout.h"
 #include "clang/Basic/TargetInfo.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/Support/Format.h"
@@ -594,6 +594,10 @@
   /// \brief The maximum of the alignments of top-level members.
   CharUnits UnadjustedAlignment;
 
+  /// \breif The AIX special alignment for object contains floating-point
+  /// member or sub-members
+  CharUnits AIXOffsetAlignment;
+
   SmallVector<uint64_t, 16> FieldOffsets;
 
   /// Whether the external AST source has provided a layout for this
@@ -679,15 +683,15 @@
       : Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
         Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()),
         UnadjustedAlignment(CharUnits::One()),
-        UseExternalLayout(false), InferAlignment(false), Packed(false),
-        IsUnion(false), IsMac68kAlign(false), IsMsStruct(false),
-        UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0),
-        MaxFieldAlignment(CharUnits::Zero()), DataSize(0),
-        NonVirtualSize(CharUnits::Zero()),
+        AIXOffsetAlignment(CharUnits::One()), UseExternalLayout(false),
+        InferAlignment(false), Packed(false), IsUnion(false),
+        IsMac68kAlign(false), IsMsStruct(false), UnfilledBitsInLastUnit(0),
+        LastBitfieldTypeSize(0), MaxFieldAlignment(CharUnits::Zero()),
+        DataSize(0), NonVirtualSize(CharUnits::Zero()),
         NonVirtualAlignment(CharUnits::One()),
         PaddedFieldSize(CharUnits::Zero()), PrimaryBase(nullptr),
-        PrimaryBaseIsVirtual(false), HasOwnVFPtr(false),
-        HasPackedField(false), FirstNearlyEmptyVBase(nullptr) {}
+        PrimaryBaseIsVirtual(false), HasOwnVFPtr(false), HasPackedField(false),
+        FirstNearlyEmptyVBase(nullptr) {}
 
   void Layout(const RecordDecl *D);
   void Layout(const CXXRecordDecl *D);
@@ -762,9 +766,13 @@
   /// alignment.
   void FinishLayout(const NamedDecl *D);
 
-  void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment);
+  void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment,
+                       CharUnits AIXOffsetNewAlignment);
+  void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment) {
+    UpdateAlignment(NewAlignment, UnpackedNewAlignment, UnpackedNewAlignment);
+  }
   void UpdateAlignment(CharUnits NewAlignment) {
-    UpdateAlignment(NewAlignment, NewAlignment);
+    UpdateAlignment(NewAlignment, NewAlignment, NewAlignment);
   }
 
   /// Retrieve the externally-supplied field offset for the given
@@ -806,6 +814,10 @@
 };
 } // end anonymous namespace
 
+static bool isAIXLayout(const ASTContext &Context) {
+  return Context.getTargetInfo().getTriple().getOS() == llvm::Triple::AIX;
+}
+
 void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
   for (const auto &I : RD->bases()) {
     assert(!I.getType()->isDependentType() &&
@@ -997,7 +1009,9 @@
   setSize(getSize().alignTo(BaseAlign));
 
   // Update the alignment.
-  UpdateAlignment(BaseAlign, UnpackedBaseAlign);
+  UpdateAlignment(BaseAlign, UnpackedBaseAlign,
+                  /*AIXOffsetAlignment : used by AIX-ABI*/
+                  BaseAlign);
 }
 
 void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
@@ -1196,6 +1210,7 @@
   // Clang <= 6 incorrectly applied the 'packed' attribute to base classes.
   // Per GCC's documentation, it only applies to non-static data members.
   CharUnits UnpackedBaseAlign = Layout.getNonVirtualAlignment();
+  CharUnits AIXOffsetBaseAlign = Layout.getAIXOffsetAlignment();
   CharUnits BaseAlign =
       (Packed && ((Context.getLangOpts().getClangABICompat() <=
                    LangOptions::ClangABI::Ver6) ||
@@ -1208,11 +1223,17 @@
       (!HasExternalLayout || Offset == CharUnits::Zero()) &&
       EmptySubobjects->CanPlaceBaseAtOffset(Base, CharUnits::Zero())) {
     setSize(std::max(getSize(), Layout.getSize()));
-    UpdateAlignment(BaseAlign, UnpackedBaseAlign);
+    UpdateAlignment(BaseAlign, UnpackedBaseAlign, AIXOffsetBaseAlign);
 
     return CharUnits::Zero();
   }
 
+  // Use AIX special alignment if current base is not the first member
+  // and the struct is not a union
+  if (isAIXLayout(Context) && !getDataSize().isZero() && !IsUnion) {
+    BaseAlign = AIXOffsetBaseAlign;
+  }
+
   // The maximum field alignment overrides base align.
   if (!MaxFieldAlignment.isZero()) {
     BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
@@ -1248,7 +1269,7 @@
     setSize(std::max(getSize(), Offset + Layout.getSize()));
 
   // Remember max struct/class alignment.
-  UpdateAlignment(BaseAlign, UnpackedBaseAlign);
+  UpdateAlignment(BaseAlign, UnpackedBaseAlign, AIXOffsetBaseAlign);
 
   return Offset;
 }
@@ -1829,22 +1850,54 @@
     }
   }
 
+  // AIX abi has this special rule that in aggregates, the first member of
+  // floating point data type(or aggregate type contains floating point data
+  // type) is aligned according to its natural alignment value, subsequent
+  // of such data type members of the aggregate are aligned on 4-byte
+  // boundaries.
+  CharUnits AIXOffsetFieldAlign = FieldAlign;
+  if (isAIXLayout(Context)) {
+    if (const BuiltinType *BTy =
+            Context.getBaseElementType(D->getType())->getAs<BuiltinType>()) {
+      if (BTy->isFloatingPoint()) {
+        AIXOffsetFieldAlign = CharUnits::fromQuantity(4);
+      }
+    } else if (const RecordType *RT = D->getType()
+                                          ->getBaseElementTypeUnsafe()
+                                          ->getAs<RecordType>()) {
+      if (const RecordDecl *RD = RT->getDecl()) {
+        const ASTRecordLayout &FieldRecord = Context.getASTRecordLayout(RD);
+        AIXOffsetFieldAlign = FieldRecord.getAIXOffsetAlignment();
+      }
+    }
+    // Field offset could still be 0 if we have 0 size bitfield as first member
+    // So if field index is not 0 and the struct is not a union, we should use
+    // AIX special alignment as well.
+    if (FieldOffset != CharUnits::Zero() ||
+        (D->getFieldIndex() != 0 && !IsUnion))
+      FieldAlign = AIXOffsetFieldAlign;
+  }
+
   // The align if the field is not packed. This is to check if the attribute
   // was unnecessary (-Wpacked).
   CharUnits UnpackedFieldAlign = FieldAlign;
   CharUnits UnpackedFieldOffset = FieldOffset;
 
-  if (FieldPacked)
+  if (FieldPacked) {
     FieldAlign = CharUnits::One();
+    AIXOffsetFieldAlign = CharUnits::One();
+  }
   CharUnits MaxAlignmentInChars =
     Context.toCharUnitsFromBits(D->getMaxAlignment());
   FieldAlign = std::max(FieldAlign, MaxAlignmentInChars);
   UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
+  AIXOffsetFieldAlign = std::max(AIXOffsetFieldAlign, MaxAlignmentInChars);
 
   // The maximum field alignment overrides the aligned attribute.
   if (!MaxFieldAlignment.isZero()) {
     FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
     UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
+    AIXOffsetFieldAlign = std::min(AIXOffsetFieldAlign, MaxFieldAlignment);
   }
 
   // Round up the current record size to the field's alignment boundary.
@@ -1910,7 +1963,7 @@
 
   // Remember max struct/class alignment.
   UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
-  UpdateAlignment(FieldAlign, UnpackedFieldAlign);
+  UpdateAlignment(FieldAlign, UnpackedFieldAlign, AIXOffsetFieldAlign);
 }
 
 void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
@@ -1981,7 +2034,8 @@
 }
 
 void ItaniumRecordLayoutBuilder::UpdateAlignment(
-    CharUnits NewAlignment, CharUnits UnpackedNewAlignment) {
+    CharUnits NewAlignment, CharUnits UnpackedNewAlignment,
+    CharUnits AIXOffsetNewAlignment) {
   // The alignment is not modified when using 'mac68k' alignment or when
   // we have an externally-supplied layout that also provides overall alignment.
   if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
@@ -1998,6 +2052,12 @@
            "Alignment not a power of 2");
     UnpackedAlignment = UnpackedNewAlignment;
   }
+
+  if (AIXOffsetNewAlignment > AIXOffsetAlignment) {
+    assert(llvm::isPowerOf2_64(AIXOffsetNewAlignment.getQuantity()) &&
+           "Alignment not a power of 2");
+    AIXOffsetAlignment = AIXOffsetNewAlignment;
+  }
 }
 
 uint64_t
@@ -3049,6 +3109,7 @@
       NewEntry = new (*this) ASTRecordLayout(
           *this, Builder.Size, Builder.Alignment, Builder.Alignment,
           Builder.RequiredAlignment,
+          /*AIXOffsetAlignment : used by AIX-ABI*/ Builder.Alignment,
           Builder.HasOwnVFPtr, Builder.HasOwnVFPtr || Builder.PrimaryBase,
           Builder.VBPtrOffset, Builder.DataSize, Builder.FieldOffsets,
           Builder.NonVirtualSize, Builder.Alignment, CharUnits::Zero(),
@@ -3060,6 +3121,7 @@
       NewEntry = new (*this) ASTRecordLayout(
           *this, Builder.Size, Builder.Alignment, Builder.Alignment,
           Builder.RequiredAlignment,
+          /*AIXOffsetAlignment : used by AIX-ABI*/ Builder.Alignment,
           Builder.Size, Builder.FieldOffsets);
     }
   } else {
@@ -3080,9 +3142,12 @@
       CharUnits NonVirtualSize =
           skipTailPadding ? DataSize : Builder.NonVirtualSize;
       NewEntry = new (*this) ASTRecordLayout(
-          *this, Builder.getSize(), Builder.Alignment, Builder.UnadjustedAlignment,
+          *this, Builder.getSize(), Builder.Alignment,
+          Builder.UnadjustedAlignment,
           /*RequiredAlignment : used by MS-ABI)*/
-          Builder.Alignment, Builder.HasOwnVFPtr, RD->isDynamicClass(),
+          Builder.Alignment,
+          /*AIXOffsetAlignment : used by AIX-ABI)*/
+          Builder.AIXOffsetAlignment, Builder.HasOwnVFPtr, RD->isDynamicClass(),
           CharUnits::fromQuantity(-1), DataSize, Builder.FieldOffsets,
           NonVirtualSize, Builder.NonVirtualAlignment,
           EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
@@ -3093,9 +3158,12 @@
       Builder.Layout(D);
 
       NewEntry = new (*this) ASTRecordLayout(
-          *this, Builder.getSize(), Builder.Alignment, Builder.UnadjustedAlignment,
+          *this, Builder.getSize(), Builder.Alignment,
+          Builder.UnadjustedAlignment,
           /*RequiredAlignment : used by MS-ABI)*/
-          Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
+          Builder.Alignment,
+          /*AIXOffsetAlignment : used by AIX-ABI)*/
+          Builder.AIXOffsetAlignment, Builder.getSize(), Builder.FieldOffsets);
     }
   }
 
@@ -3245,14 +3313,12 @@
   ItaniumRecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr);
   Builder.Layout(D);
 
-  const ASTRecordLayout *NewEntry =
-    new (*this) ASTRecordLayout(*this, Builder.getSize(),
-                                Builder.Alignment,
-                                Builder.UnadjustedAlignment,
-                                /*RequiredAlignment : used by MS-ABI)*/
-                                Builder.Alignment,
-                                Builder.getDataSize(),
-                                Builder.FieldOffsets);
+  const ASTRecordLayout *NewEntry = new (*this) ASTRecordLayout(
+      *this, Builder.getSize(), Builder.Alignment, Builder.UnadjustedAlignment,
+      /*RequiredAlignment : used by MS-ABI)*/
+      Builder.Alignment,
+      /*AIXOffsetAlignment : used by AIX-ABI)*/
+      Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);
 
   ObjCLayouts[Key] = NewEntry;
 
Index: clang/lib/AST/RecordLayout.cpp
===================================================================
--- clang/lib/AST/RecordLayout.cpp
+++ clang/lib/AST/RecordLayout.cpp
@@ -31,37 +31,32 @@
                                  CharUnits alignment,
                                  CharUnits unadjustedAlignment,
                                  CharUnits requiredAlignment,
+                                 CharUnits aixOffsetAlignment,
                                  CharUnits datasize,
                                  ArrayRef<uint64_t> fieldoffsets)
     : Size(size), DataSize(datasize), Alignment(alignment),
       UnadjustedAlignment(unadjustedAlignment),
-      RequiredAlignment(requiredAlignment) {
+      RequiredAlignment(requiredAlignment),
+      AIXOffsetAlignment(aixOffsetAlignment) {
   FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end());
 }
 
 // Constructor for C++ records.
-ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
-                                 CharUnits size, CharUnits alignment,
-                                 CharUnits unadjustedAlignment,
-                                 CharUnits requiredAlignment,
-                                 bool hasOwnVFPtr, bool hasExtendableVFPtr,
-                                 CharUnits vbptroffset,
-                                 CharUnits datasize,
-                                 ArrayRef<uint64_t> fieldoffsets,
-                                 CharUnits nonvirtualsize,
-                                 CharUnits nonvirtualalignment,
-                                 CharUnits SizeOfLargestEmptySubobject,
-                                 const CXXRecordDecl *PrimaryBase,
-                                 bool IsPrimaryBaseVirtual,
-                                 const CXXRecordDecl *BaseSharingVBPtr,
-                                 bool EndsWithZeroSizedObject,
-                                 bool LeadsWithZeroSizedBase,
-                                 const BaseOffsetsMapTy& BaseOffsets,
-                                 const VBaseOffsetsMapTy& VBaseOffsets)
-  : Size(size), DataSize(datasize), Alignment(alignment),
-    UnadjustedAlignment(unadjustedAlignment),
-    RequiredAlignment(requiredAlignment), CXXInfo(new (Ctx) CXXRecordLayoutInfo)
-{
+ASTRecordLayout::ASTRecordLayout(
+    const ASTContext &Ctx, CharUnits size, CharUnits alignment,
+    CharUnits unadjustedAlignment, CharUnits requiredAlignment,
+    CharUnits aixOffsetAlignment, bool hasOwnVFPtr, bool hasExtendableVFPtr,
+    CharUnits vbptroffset, CharUnits datasize, ArrayRef<uint64_t> fieldoffsets,
+    CharUnits nonvirtualsize, CharUnits nonvirtualalignment,
+    CharUnits SizeOfLargestEmptySubobject, const CXXRecordDecl *PrimaryBase,
+    bool IsPrimaryBaseVirtual, const CXXRecordDecl *BaseSharingVBPtr,
+    bool EndsWithZeroSizedObject, bool LeadsWithZeroSizedBase,
+    const BaseOffsetsMapTy &BaseOffsets, const VBaseOffsetsMapTy &VBaseOffsets)
+    : Size(size), DataSize(datasize), Alignment(alignment),
+      UnadjustedAlignment(unadjustedAlignment),
+      RequiredAlignment(requiredAlignment),
+      AIXOffsetAlignment(aixOffsetAlignment),
+      CXXInfo(new (Ctx) CXXRecordLayoutInfo) {
   FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end());
 
   CXXInfo->PrimaryBase.setPointer(PrimaryBase);
Index: clang/include/clang/AST/RecordLayout.h
===================================================================
--- clang/include/clang/AST/RecordLayout.h
+++ clang/include/clang/AST/RecordLayout.h
@@ -78,6 +78,10 @@
   /// the __declspec(align()) trumps #pramga pack and must always be obeyed.
   CharUnits RequiredAlignment;
 
+  /// AIXOffsetAlignment - The special AIX Alignment for the object that
+  /// contains floating-point member or sub-member. This is for AIX-abi only.
+  CharUnits AIXOffsetAlignment;
+
   /// FieldOffsets - Array of field offsets in bits.
   ASTVector<uint64_t> FieldOffsets;
 
@@ -139,30 +143,25 @@
   CXXRecordLayoutInfo *CXXInfo = nullptr;
 
   ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
-                  CharUnits unadjustedAlignment,
-                  CharUnits requiredAlignment, CharUnits datasize,
+                  CharUnits unadjustedAlignment, CharUnits requiredAlignment,
+                  CharUnits aixOffsetAlignment, CharUnits datasize,
                   ArrayRef<uint64_t> fieldoffsets);
 
   using BaseOffsetsMapTy = CXXRecordLayoutInfo::BaseOffsetsMapTy;
 
   // Constructor for C++ records.
-  ASTRecordLayout(const ASTContext &Ctx,
-                  CharUnits size, CharUnits alignment,
-                  CharUnits unadjustedAlignment,
-                  CharUnits requiredAlignment,
-                  bool hasOwnVFPtr, bool hasExtendableVFPtr,
-                  CharUnits vbptroffset,
-                  CharUnits datasize,
-                  ArrayRef<uint64_t> fieldoffsets,
+  ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
+                  CharUnits unadjustedAlignment, CharUnits requiredAlignment,
+                  CharUnits aixOffsetAlignment, bool hasOwnVFPtr,
+                  bool hasExtendableVFPtr, CharUnits vbptroffset,
+                  CharUnits datasize, ArrayRef<uint64_t> fieldoffsets,
                   CharUnits nonvirtualsize, CharUnits nonvirtualalignment,
                   CharUnits SizeOfLargestEmptySubobject,
-                  const CXXRecordDecl *PrimaryBase,
-                  bool IsPrimaryBaseVirtual,
+                  const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual,
                   const CXXRecordDecl *BaseSharingVBPtr,
-                  bool EndsWithZeroSizedObject,
-                  bool LeadsWithZeroSizedBase,
-                  const BaseOffsetsMapTy& BaseOffsets,
-                  const VBaseOffsetsMapTy& VBaseOffsets);
+                  bool EndsWithZeroSizedObject, bool LeadsWithZeroSizedBase,
+                  const BaseOffsetsMapTy &BaseOffsets,
+                  const VBaseOffsetsMapTy &VBaseOffsets);
 
   ~ASTRecordLayout() = default;
 
@@ -175,6 +174,10 @@
   /// getAlignment - Get the record alignment in characters.
   CharUnits getAlignment() const { return Alignment; }
 
+  /// getAIXOffsetAlignment - Get the record of aixOffset alignment in
+  /// characters.
+  CharUnits getAIXOffsetAlignment() const { return AIXOffsetAlignment; }
+
   /// getUnadjustedAlignment - Get the record alignment in characters, before
   /// alignment adjustement.
   CharUnits getUnadjustedAlignment() const { return UnadjustedAlignment; }
@@ -193,9 +196,7 @@
 
   /// getDataSize() - Get the record data size, which is the record size
   /// without tail padding, in characters.
-  CharUnits getDataSize() const {
-    return DataSize;
-  }
+  CharUnits getDataSize() const { return DataSize; }
 
   /// getNonVirtualSize - Get the non-virtual size (in chars) of an object,
   /// which is the size of the object without virtual bases.
@@ -287,9 +288,7 @@
     return !CXXInfo->VBPtrOffset.isNegative();
   }
 
-  CharUnits getRequiredAlignment() const {
-    return RequiredAlignment;
-  }
+  CharUnits getRequiredAlignment() const { return RequiredAlignment; }
 
   bool endsWithZeroSizedObject() const {
     return CXXInfo && CXXInfo->EndsWithZeroSizedObject;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to