[PowerPC][AIX] Fix Zero-width bit fields wrt MaxFieldAlign.

On AIX when there is a pragma pack, or pragma align in effect then zero-width bitfields should pad out to the end of the bitfield container but not increase the alignment requirements of the struct greater then the max field align.

Reviewed By: ZarkoCA

Differential Revision: https://reviews.llvm.org/D105635
This commit is contained in:
Steven Wan 2021-07-12 15:31:15 -04:00
parent 363e12ae6f
commit 798fe3c774
3 changed files with 117 additions and 0 deletions

View File

@ -1775,6 +1775,12 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
!D->getIdentifier())
FieldAlign = UnpackedFieldAlign = 1;
// On AIX, zero-width bitfields pad out to the alignment boundary, but then
// do not affect overall record alignment if there is a pragma pack or
// pragma align(packed).
if (isAIXLayout(Context) && !MaxFieldAlignment.isZero() && !FieldSize)
FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
// Diagnose differences in layout due to padding or packing.
if (!UseExternalLayout)
CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,

View File

@ -232,3 +232,37 @@ int s = sizeof(G);
// CHECK-NEXT: 0 | struct G
// CHECK-NEXT: 0:0-44 | long long ll
// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=8, preferredalign=8
#pragma align(packed)
struct H {
char c;
int : 0;
int i;
} H;
#pragma align(reset)
int h = sizeof(H);
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct H
// CHECK-NEXT: 0 | char c
// CHECK-NEXT: 4:- | int
// CHECK-NEXT: 4 | int i
// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=1, preferredalign=1
#pragma pack(2)
struct I {
char c;
int : 0;
int i;
} I;
#pragma pack(pop)
int i = sizeof(I);
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct I
// CHECK-NEXT: 0 | char c
// CHECK-NEXT: 4:- | int
// CHECK-NEXT: 4 | int i
// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=2, preferredalign=2

View File

@ -0,0 +1,77 @@
// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \
// RUN: -fsyntax-only -fxl-pragma-pack -x c %s | FileCheck %s
// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \
// RUN: -fsyntax-only -fxl-pragma-pack -x c++ %s | FileCheck %s
//
// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \
// RUN: -fsyntax-only -fxl-pragma-pack -x c %s | FileCheck %s
//
// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \
// RUN: -fsyntax-only -fxl-pragma-pack -x c++ %s | FileCheck %s
struct A {
int a1 : 30;
int a2 : 30;
int a3 : 4;
};
int a = sizeof(struct A);
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct A
// CHECK-NEXT: 0:0-29 | int a1
// CHECK-NEXT: 4:0-29 | int a2
// CHECK-NEXT: 8:0-3 | int a3
// CHECK-NEXT: sizeof=12, {{(dsize=12, )?}}align=4, preferredalign=4
#pragma align(packed)
struct AlignPacked {
int a1 : 30;
int a2 : 30;
int a3 : 4;
};
#pragma align(reset)
int b = sizeof(struct AlignPacked);
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct AlignPacked
// CHECK-NEXT: 0:0-29 | int a1
// CHECK-NEXT: 3:6-35 | int a2
// CHECK-NEXT: 7:4-7 | int a3
// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=1, preferredalign=1
#pragma pack(1)
struct Pack1 {
int a1 : 30;
int a2 : 30;
int a3 : 4;
};
#pragma pack(pop)
int c = sizeof(struct Pack1);
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct Pack1
// CHECK-NEXT: 0:0-29 | int a1
// CHECK-NEXT: 3:6-35 | int a2
// CHECK-NEXT: 7:4-7 | int a3
// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=1, preferredalign=1
#pragma pack(2)
struct Pack2 {
int a1 : 30;
int a2 : 30;
int a3 : 4;
};
#pragma pack(pop)
int d = sizeof(struct Pack2);
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct Pack2
// CHECK-NEXT: 0:0-29 | int a1
// CHECK-NEXT: 3:6-35 | int a2
// CHECK-NEXT: 7:4-7 | int a3
// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=2, preferredalign=2