[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