Xiangling_L updated this revision to Diff 296497.
Xiangling_L marked 4 inline comments as done.
Xiangling_L added a comment.

- Fixed the bug of getting underlying type of enum;
- Fixed the bug to respect align attribute;
- Add more testcases;


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87029/new/

https://reviews.llvm.org/D87029

Files:
  clang/lib/AST/RecordLayoutBuilder.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/Layout/aix-bitfield-alignment.cpp
  clang/test/Layout/aix-oversized-bitfield.cpp

Index: clang/test/Layout/aix-oversized-bitfield.cpp
===================================================================
--- /dev/null
+++ clang/test/Layout/aix-oversized-bitfield.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fsyntax-only -verify -x c++ %s
+
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \
+// RUN:     -fsyntax-only %s | \
+// RUN:   FileCheck --check-prefix=CHECK64 %s
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \
+// RUN:     -fsyntax-only -x c++ %s | \
+// RUN:   FileCheck --check-prefix=CHECK64 %s
+
+struct A {
+  long long l : 64; // expected-error{{width of bit-field 'l' (64 bits) exceeds size of its type (32 bits)}}
+};
+
+int a = sizeof(A);
+
+// CHECK64:      *** Dumping AST Record Layout
+// CHECK64-NEXT:          0 | struct A
+// CHECK64-NEXT:     0:0-63 |   long long l
+// CHECK64-NEXT:            | [sizeof=8, dsize=8, align=8, preferredalign=8,
+// CHECK64-NEXT:            |  nvsize=8, nvalign=8, preferrednvalign=8]
Index: clang/test/Layout/aix-bitfield-alignment.cpp
===================================================================
--- /dev/null
+++ clang/test/Layout/aix-bitfield-alignment.cpp
@@ -0,0 +1,217 @@
+// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \
+// RUN:     -fsyntax-only -faix-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 -faix-pragma-pack -x c++ %s | \
+// RUN:   FileCheck --check-prefixes=CHECK,CHECK64 %s
+
+struct A {
+  bool b : 3;
+  unsigned char c : 2;
+  unsigned short s : 6;
+};
+
+int a = sizeof(A);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct A
+// CHECK-NEXT:      0:0-2 |   _Bool b
+// CHECK-NEXT:      0:3-4 |   unsigned char c
+// CHECK-NEXT:     0:5-10 |   unsigned short s
+// CHECK-NEXT:            | [sizeof=4, dsize=4, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=4, nvalign=4, preferrednvalign=4]
+
+struct B {
+  char c;
+  int : 0;
+};
+
+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,
+// CHECK-NEXT:            |  nvsize=4, nvalign=4, preferrednvalign=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;
+};
+
+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,
+// CHECK32:               |  nvsize=8, nvalign=4, preferrednvalign=4]
+// CHECK64:         3:1-8 |   unsigned long a7
+// CHECK64:               | [sizeof=8, dsize=8, align=8, preferredalign=8,
+// CHECK64:               |  nvsize=8, nvalign=8, preferrednvalign=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;
+};
+#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,
+// CHECK-NEXT:            |  nvsize=5, nvalign=1, preferrednvalign=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;
+};
+#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,
+// CHECK-NEXT:            |  nvsize=8, nvalign=4, preferrednvalign=4]
+
+typedef __attribute__((aligned(32))) short mySHORT;
+struct D {
+  char c : 8;
+  mySHORT : 0;
+};
+
+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,
+// CHECK-NEXT:            |  nvsize=32, nvalign=32, preferrednvalign=32]
+
+typedef __attribute__((aligned(32))) long myLONG;
+struct D1 {
+  char c : 8;
+  myLONG : 0;
+};
+
+int d1 = sizeof(D1);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct D1
+// CHECK-NEXT:      0:0-7 |   char c
+// CHECK-NEXT:       32:- |   myLONG
+// CHECK-NEXT:            | [sizeof=32, dsize=32, align=32, preferredalign=32,
+// CHECK-NEXT:            |  nvsize=32, nvalign=32, preferrednvalign=32]
+
+typedef __attribute__((aligned(32))) long long myLONGLONG;
+struct D2 {
+  char c : 8;
+  myLONGLONG : 0;
+};
+
+int d2 = sizeof(D2);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct D2
+// CHECK-NEXT:      0:0-7 |   char c
+// CHECK-NEXT:       32:- |   myLONGLONG
+// CHECK-NEXT:            | [sizeof=32, dsize=32, align=32, preferredalign=32,
+// CHECK-NEXT:            |  nvsize=32, nvalign=32, preferrednvalign=32]
+
+enum class Bool : bool { False = 0,
+                         True = 1 };
+
+struct E {
+  Bool b : 1;
+};
+
+int e = sizeof(E);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct E
+// 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 };
+
+struct F {
+  enum LL e : 32;
+};
+
+int f = sizeof(F);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct F
+// CHECK-NEXT:     0:0-31 |   enum LL e
+// CHECK32-NEXT:            | [sizeof=4, dsize=4, align=4, preferredalign=4,
+// CHECK32-NEXT:            |  nvsize=4, nvalign=4, preferrednvalign=4]
+// CHECK64-NEXT:            | [sizeof=8, dsize=8, align=8, preferredalign=8,
+// CHECK64-NEXT:            |  nvsize=8, nvalign=8, preferrednvalign=8]
+
+enum LL1 : unsigned long long { val1 = 1 } __attribute__((aligned(16)));
+struct F1 {
+  enum LL1 e : 32;
+};
+
+int f1 = sizeof(F1);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct F1
+// CHECK-NEXT:     0:0-31 |   enum LL1 e
+// CHECK-NEXT:            | [sizeof=16, dsize=16, align=16, preferredalign=16,
+// CHECK-NEXT:            |  nvsize=16, nvalign=16, preferrednvalign=16]
+
+struct G {
+  long long l : 32 __attribute__((aligned(16)));
+};
+
+int g = sizeof(G);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct G
+// CHECK-NEXT:     0:0-31 |   long long l
+// CHECK-NEXT:            | [sizeof=16, dsize=16, align=16, preferredalign=16,
+// CHECK-NEXT:            |  nvsize=16, nvalign=16, preferrednvalign=16]
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -16443,7 +16443,22 @@
     bool MSBitfieldViolation =
         Value.ugt(TypeStorageSize) &&
         (IsMsStruct || Context.getTargetInfo().getCXXABI().isMicrosoft());
-    if (CStdConstraintViolation || MSBitfieldViolation) {
+
+    bool AIXBitfieldViolation = false;
+    if (const BuiltinType *BTy = FieldTy.getTypePtr()->getAs<BuiltinType>()) {
+      if ((BTy->getKind() == BuiltinType::ULongLong ||
+           BTy->getKind() == BuiltinType::LongLong) &&
+          (unsigned)Value.getZExtValue() > 32 &&
+          Context.getTargetInfo().getTriple().isArch32Bit() &&
+          Context.getTargetInfo().getTriple().getOS() == llvm::Triple::AIX) {
+        AIXBitfieldViolation = true;
+        TypeStorageSize = 32;
+        TypeWidth = 32;
+      }
+    }
+
+    if (CStdConstraintViolation || MSBitfieldViolation ||
+        AIXBitfieldViolation) {
       unsigned DiagWidth =
           CStdConstraintViolation ? TypeWidth : TypeStorageSize;
       if (FieldName)
Index: clang/lib/AST/RecordLayoutBuilder.cpp
===================================================================
--- clang/lib/AST/RecordLayoutBuilder.cpp
+++ clang/lib/AST/RecordLayoutBuilder.cpp
@@ -1526,12 +1526,17 @@
   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 difference between the end of the
   // last allocated bitfield (i.e. the first bit offset available for
@@ -1609,9 +1614,49 @@
     }
   }
 
+  // On AIX, [bool, char, short] bitfields have the same alignment
+  // as [unsigned].
+  if (isAIXLayout(Context)) {
+    const BuiltinType *BTy = nullptr;
+
+    // Get the underlying type from EnumDecl.
+    if (const EnumType *ET = dyn_cast<EnumType>(
+            D->getType().getDesugaredType(Context).getTypePtr())) {
+      const EnumDecl *ED = ET->getDecl();
+      if (const BuiltinType *BT =
+              dyn_cast<BuiltinType>(ED->getPromotionType().getTypePtr()))
+        BTy = BT;
+    } else {
+      BTy = Context.getBaseElementType(D->getType())->getAs<BuiltinType>();
+    }
+
+    if (BTy) {
+      BuiltinType::Kind BTyKind = BTy->getKind();
+      if (BTyKind != BuiltinType::ULong && BTyKind != BuiltinType::Long &&
+          BTyKind != BuiltinType::ULongLong &&
+          BTyKind != BuiltinType::LongLong) {
+        // Only set bitfields alignment to unsigned when it does
+        // not have attribute align specified or is less than
+        // unsigned alignment.
+        if (FieldAlign < Context.getTypeSize(Context.UnsignedIntTy))
+          FieldAlign = Context.getTypeSize(Context.UnsignedIntTy);
+        StorageUnitSize = Context.getTypeSize(Context.UnsignedIntTy);
+      } else {
+        // Handle AIX oversized Long Long bitfield under 32 bit compile mode.
+        if (StorageUnitSize > 32 &&
+            Context.getTargetInfo().getTriple().isArch32Bit()) {
+          StorageUnitSize = 32;
+          if (!AlignIsRequired)
+            FieldAlign = 32;
+        }
+      }
+    }
+  }
+
   // If the field is wider than its declared type, it follows
-  // different rules in all cases.
-  if (FieldSize > StorageUnitSize) {
+  // different 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;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to