[clang] e092165 - [AIX] Implement AIX special bitfield related alignment rules

Xiangling Liao via cfe-commits cfe-commits at lists.llvm.org
Mon May 17 08:31:03 PDT 2021


Author: Xiangling Liao
Date: 2021-05-17T11:30:29-04:00
New Revision: e0921655b1ff8d4ba7c14be59252fe05b705920e

URL: https://github.com/llvm/llvm-project/commit/e0921655b1ff8d4ba7c14be59252fe05b705920e
DIFF: https://github.com/llvm/llvm-project/commit/e0921655b1ff8d4ba7c14be59252fe05b705920e.diff

LOG: [AIX] Implement AIX special bitfield related alignment rules

1.[bool, char, short] bitfields have the same alignment as unsigned int
2.Adjust alignment on typedef field decls/honor align attribute
3.Fix alignment for scoped enum class
4.Long long bitfield has 4bytes alignment and StorageUnitSize under 32 bit
  compile mode

Differential Revision: https://reviews.llvm.org/D87029

Added: 
    clang/test/Layout/aix-bitfield-alignment.c
    clang/test/Layout/aix-bitfield-alignment.cpp

Modified: 
    clang/lib/AST/RecordLayoutBuilder.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index 8a25b5cbd84a..beb111e2e971 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -1528,12 +1528,17 @@ void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
   UpdateAlignment(TypeAlign);
 }
 
+static bool isAIXLayout(const ASTContext &Context) {
+  return Context.getTargetInfo().getTriple().getOS() == llvm::Triple::AIX;
+}
+
 void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
   bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
   uint64_t FieldSize = D->getBitWidthValue(Context);
   TypeInfo FieldInfo = Context.getTypeInfo(D->getType());
   uint64_t StorageUnitSize = FieldInfo.Width;
   unsigned FieldAlign = FieldInfo.Align;
+  bool AlignIsRequired = FieldInfo.AlignIsRequired;
 
   // UnfilledBitsInLastUnit is the 
diff erence between the end of the
   // last allocated bitfield (i.e. the first bit offset available for
@@ -1611,9 +1616,33 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
     }
   }
 
+  if (isAIXLayout(Context)) {
+    if (StorageUnitSize < Context.getTypeSize(Context.UnsignedIntTy)) {
+      // On AIX, [bool, char, short] bitfields have the same alignment
+      // as [unsigned].
+      StorageUnitSize = Context.getTypeSize(Context.UnsignedIntTy);
+    } else if (StorageUnitSize > Context.getTypeSize(Context.UnsignedIntTy) &&
+               Context.getTargetInfo().getTriple().isArch32Bit() &&
+               FieldSize <= 32) {
+      // Under 32-bit compile mode, the bitcontainer is 32 bits if a single
+      // long long bitfield has length no greater than 32 bits.
+      StorageUnitSize = 32;
+
+      if (!AlignIsRequired)
+        FieldAlign = 32;
+    }
+
+    if (FieldAlign < StorageUnitSize) {
+      // The bitfield alignment should always be greater than or equal to
+      // bitcontainer size.
+      FieldAlign = StorageUnitSize;
+    }
+  }
+
   // If the field is wider than its declared type, it follows
-  // 
diff erent rules in all cases.
-  if (FieldSize > StorageUnitSize) {
+  // 
diff erent rules in all cases, except on AIX.
+  // On AIX, wide bitfield follows the same rules as normal bitfield.
+  if (FieldSize > StorageUnitSize && !isAIXLayout(Context)) {
     LayoutWideBitField(FieldSize, StorageUnitSize, FieldPacked, D);
     return;
   }

diff  --git a/clang/test/Layout/aix-bitfield-alignment.c b/clang/test/Layout/aix-bitfield-alignment.c
new file mode 100644
index 000000000000..a736695cc603
--- /dev/null
+++ b/clang/test/Layout/aix-bitfield-alignment.c
@@ -0,0 +1,234 @@
+// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \
+// RUN:     -fsyntax-only -fxl-pragma-pack -x c %s | \
+// RUN:   FileCheck --check-prefixes=CHECK,CHECK32 %s
+// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \
+// RUN:     -fsyntax-only -fxl-pragma-pack -x c++ %s | \
+// RUN:   FileCheck --check-prefixes=CHECK,CHECK32 %s
+
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \
+// RUN:     -fsyntax-only -fxl-pragma-pack -x c %s | \
+// RUN:   FileCheck --check-prefixes=CHECK,CHECK64 %s
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \
+// RUN:     -fsyntax-only -fxl-pragma-pack -x c++ %s | \
+// RUN:   FileCheck --check-prefixes=CHECK,CHECK64 %s
+
+struct A {
+  unsigned char c : 2;
+} A;
+
+int a = sizeof(A);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct A
+// CHECK-NEXT:      0:0-1 |   unsigned char c
+// CHECK-NEXT:               sizeof=4, {{(dsize=4, )?}}align=4, preferredalign=4
+
+struct B {
+  char c;
+  int : 0;
+} B;
+
+int b = sizeof(B);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct B
+// CHECK-NEXT:          0 |   char c
+// CHECK-NEXT:        4:- |   int
+// CHECK-NEXT:               sizeof=4, {{(dsize=4, )?}}align=4, preferredalign=4
+
+struct C {
+  signed int a1 : 6;
+  signed char a2 : 4;
+  short int a3 : 2;
+  int a4 : 2;
+  signed long a5 : 5;
+  long long int a6 : 6;
+  unsigned long a7 : 8;
+} C;
+
+int c = sizeof(C);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct C
+// CHECK-NEXT:      0:0-5 |   int a1
+// CHECK-NEXT:      0:6-9 |   signed char a2
+// CHECK-NEXT:      1:2-3 |   short a3
+// CHECK-NEXT:      1:4-5 |   int a4
+// CHECK-NEXT:     1:6-10 |   long a5
+// CHECK-NEXT:      2:3-8 |   long long a6
+// CHECK32:         4:0-7 |   unsigned long a7
+// CHECK32:                  sizeof=8, {{(dsize=8, )?}}align=4, preferredalign=4
+// CHECK64:         3:1-8 |   unsigned long a7
+// CHECK64:                  sizeof=8, {{(dsize=8, )?}}align=8, preferredalign=8
+
+#pragma align(packed)
+struct C1 {
+  signed int a1 : 6;
+  signed char a2 : 4;
+  short int a3 : 2;
+  int a4 : 2;
+  signed long a5 : 5;
+  long long int a6 : 6;
+  unsigned long a7 : 8;
+} C1;
+#pragma align(reset)
+
+int c1 = sizeof(C1);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct C1
+// CHECK-NEXT:      0:0-5 |   int a1
+// CHECK-NEXT:      0:6-9 |   signed char a2
+// CHECK-NEXT:      1:2-3 |   short a3
+// CHECK-NEXT:      1:4-5 |   int a4
+// CHECK-NEXT:     1:6-10 |   long a5
+// CHECK-NEXT:      2:3-8 |   long long a6
+// CHECK-NEXT:      3:1-8 |   unsigned long a7
+// CHECK-NEXT:               sizeof=5, {{(dsize=5, )?}}align=1, preferredalign=1
+
+#pragma pack(4)
+struct C2 {
+  signed int a1 : 6;
+  signed char a2 : 4;
+  short int a3 : 2;
+  int a4 : 2;
+  signed long a5 : 5;
+  long long int a6 : 6;
+  unsigned long a7 : 8;
+} C2;
+#pragma pack(pop)
+
+int c2 = sizeof(C2);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct C2
+// CHECK-NEXT:      0:0-5 |   int a1
+// CHECK-NEXT:      0:6-9 |   signed char a2
+// CHECK-NEXT:      1:2-3 |   short a3
+// CHECK-NEXT:      1:4-5 |   int a4
+// CHECK-NEXT:     1:6-10 |   long a5
+// CHECK-NEXT:      2:3-8 |   long long a6
+// CHECK-NEXT:      3:1-8 |   unsigned long a7
+// CHECK-NEXT:               sizeof=8, {{(dsize=8, )?}}align=4, preferredalign=4
+
+typedef __attribute__((aligned(32))) short mySHORT;
+struct D {
+  char c : 8;
+  mySHORT : 0;
+} D;
+
+int d = sizeof(D);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct D
+// CHECK-NEXT:      0:0-7 |   char c
+// CHECK-NEXT:       32:- |   mySHORT
+// CHECK-NEXT:               sizeof=32, {{(dsize=32, )?}}align=32, preferredalign=32
+
+typedef __attribute__((aligned(32))) long myLONG;
+struct D11 {
+  char c : 8;
+  myLONG : 0;
+} D11;
+
+int d11 = sizeof(D11);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct D11
+// CHECK-NEXT:      0:0-7 |   char c
+// CHECK-NEXT:       32:- |   myLONG
+// CHECK-NEXT:               sizeof=32, {{(dsize=32, )?}}align=32, preferredalign=32
+
+typedef __attribute__((aligned(2))) long myLONG2;
+struct D12 {
+  char c : 8;
+  myLONG2 : 0;
+} D12;
+
+int d12 = sizeof(D12);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct D12
+// CHECK-NEXT:      0:0-7 |   char c
+// CHECK32:           4:- |   myLONG2
+// CHECK32:                  sizeof=4, {{(dsize=4, )?}}align=4, preferredalign=4
+// CHECK64:           8:- |   myLONG2
+// CHECK64:                  sizeof=8, {{(dsize=8, )?}}align=8, preferredalign=8
+
+typedef __attribute__((aligned(32))) long long myLONGLONG;
+struct D21 {
+  char c : 8;
+  myLONGLONG : 0;
+} D21;
+
+int d21 = sizeof(D21);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct D21
+// CHECK-NEXT:      0:0-7 |   char c
+// CHECK-NEXT:       32:- |   myLONGLONG
+// CHECK-NEXT:               sizeof=32, {{(dsize=32, )?}}align=32, preferredalign=32
+
+typedef __attribute__((aligned(2))) long long myLONGLONG2;
+struct D22 {
+  char c : 8;
+  myLONGLONG2 : 0;
+} D22;
+
+int d22 = sizeof(D22);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct D22
+// CHECK-NEXT:      0:0-7 |   char c
+// CHECK32:           4:- |   myLONGLONG2
+// CHECK32:                  sizeof=4, {{(dsize=4, )?}}align=4, preferredalign=4
+// CHECK64:           8:- |   myLONGLONG2
+// CHECK64:                  sizeof=8, {{(dsize=8, )?}}align=8, preferredalign=8
+
+enum LL : unsigned long long { val = 1 };
+
+struct E {
+  enum LL e : 32;
+} E;
+
+int e = sizeof(E);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct E
+// CHECK-NEXT:     0:0-31 |   enum LL e
+// CHECK32-NEXT:             sizeof=4, {{(dsize=4, )?}}align=4, preferredalign=4
+// CHECK64-NEXT:             sizeof=8, {{(dsize=8, )?}}align=8, preferredalign=8
+
+enum LL1 : unsigned long long { val1 = 1 } __attribute__((aligned(16)));
+struct E1 {
+  enum LL1 e : 32;
+} E1;
+
+int e1 = sizeof(E1);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct E1
+// CHECK-NEXT:     0:0-31 |   enum LL1 e
+// CHECK-NEXT:               sizeof=16, {{(dsize=16, )?}}align=16, preferredalign=16
+
+struct F {
+  long long l : 32 __attribute__((aligned(16)));
+} F;
+
+int f = sizeof(F);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct F
+// CHECK-NEXT:     0:0-31 |   long long l
+// CHECK-NEXT:               sizeof=16, {{(dsize=16, )?}}align=16, preferredalign=16
+
+struct G {
+  long long ll : 45;
+} G;
+
+int s = sizeof(G);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct G
+// CHECK-NEXT:     0:0-44 |   long long ll
+// CHECK-NEXT:               sizeof=8, {{(dsize=8, )?}}align=8, preferredalign=8

diff  --git a/clang/test/Layout/aix-bitfield-alignment.cpp b/clang/test/Layout/aix-bitfield-alignment.cpp
new file mode 100644
index 000000000000..00f00c8ee986
--- /dev/null
+++ b/clang/test/Layout/aix-bitfield-alignment.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \
+// RUN:     -fsyntax-only -fxl-pragma-pack -x c++ %s | \
+// RUN:   FileCheck --check-prefixes=CHECK %s
+
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \
+// RUN:     -fsyntax-only -fxl-pragma-pack -x c++ %s | \
+// RUN:   FileCheck --check-prefixes=CHECK %s
+
+struct A {
+  bool b : 3;
+};
+
+int a = sizeof(A);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct A
+// CHECK-NEXT:      0:0-2 |   _Bool b
+// CHECK-NEXT:            | [sizeof=4, dsize=4, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=4, nvalign=4, preferrednvalign=4]
+
+enum class Bool : bool { False = 0,
+                         True = 1 };
+
+struct B {
+  Bool b : 1;
+};
+
+int b = sizeof(B);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct B
+// CHECK-NEXT:      0:0-0 |   enum Bool b
+// CHECK-NEXT:            | [sizeof=4, dsize=4, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=4, nvalign=4, preferrednvalign=4]
+
+enum LL : unsigned long long { val = 1 };


        


More information about the cfe-commits mailing list