Skip to content

Commit 05ad8e9

Browse files
committed
[AIX] Implement AIX special alignment rule about double/long double
Implement AIX default `power` alignment rule by adding `PreferredAlignment` and `PreferredNVAlignment` in ASTRecordLayout class. The patchh aims at returning correct value for `__alignof(x)` and `alignof(x)` under `power` alignment rules. Differential Revision: https://reviews.llvm.org/D79719
1 parent bef19ab commit 05ad8e9

15 files changed

+1148
-136
lines changed

clang/include/clang/AST/RecordLayout.h

+38-23
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ class ASTRecordLayout {
7070
// Alignment - Alignment of record in characters.
7171
CharUnits Alignment;
7272

73+
// PreferredAlignment - Preferred alignment of record in characters. This
74+
// can be different than Alignment in cases where it is beneficial for
75+
// performance or backwards compatibility preserving (e.g. AIX-ABI).
76+
CharUnits PreferredAlignment;
77+
7378
// UnadjustedAlignment - Maximum of the alignments of the record members in
7479
// characters.
7580
CharUnits UnadjustedAlignment;
@@ -91,6 +96,11 @@ class ASTRecordLayout {
9196
/// which is the alignment of the object without virtual bases.
9297
CharUnits NonVirtualAlignment;
9398

99+
/// PreferredNVAlignment - The preferred non-virtual alignment (in chars) of
100+
/// an object, which is the preferred alignment of the object without
101+
/// virtual bases.
102+
CharUnits PreferredNVAlignment;
103+
94104
/// SizeOfLargestEmptySubobject - The size of the largest empty subobject
95105
/// (either a base or a member). Will be zero if the class doesn't contain
96106
/// any empty subobjects.
@@ -139,30 +149,26 @@ class ASTRecordLayout {
139149
CXXRecordLayoutInfo *CXXInfo = nullptr;
140150

141151
ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
142-
CharUnits unadjustedAlignment,
152+
CharUnits preferredAlignment, CharUnits unadjustedAlignment,
143153
CharUnits requiredAlignment, CharUnits datasize,
144154
ArrayRef<uint64_t> fieldoffsets);
145155

146156
using BaseOffsetsMapTy = CXXRecordLayoutInfo::BaseOffsetsMapTy;
147157

148158
// Constructor for C++ records.
149-
ASTRecordLayout(const ASTContext &Ctx,
150-
CharUnits size, CharUnits alignment,
151-
CharUnits unadjustedAlignment,
152-
CharUnits requiredAlignment,
153-
bool hasOwnVFPtr, bool hasExtendableVFPtr,
154-
CharUnits vbptroffset,
155-
CharUnits datasize,
156-
ArrayRef<uint64_t> fieldoffsets,
159+
ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
160+
CharUnits preferredAlignment, CharUnits unadjustedAlignment,
161+
CharUnits requiredAlignment, bool hasOwnVFPtr,
162+
bool hasExtendableVFPtr, CharUnits vbptroffset,
163+
CharUnits datasize, ArrayRef<uint64_t> fieldoffsets,
157164
CharUnits nonvirtualsize, CharUnits nonvirtualalignment,
165+
CharUnits preferrednvalignment,
158166
CharUnits SizeOfLargestEmptySubobject,
159-
const CXXRecordDecl *PrimaryBase,
160-
bool IsPrimaryBaseVirtual,
167+
const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual,
161168
const CXXRecordDecl *BaseSharingVBPtr,
162-
bool EndsWithZeroSizedObject,
163-
bool LeadsWithZeroSizedBase,
164-
const BaseOffsetsMapTy& BaseOffsets,
165-
const VBaseOffsetsMapTy& VBaseOffsets);
169+
bool EndsWithZeroSizedObject, bool LeadsWithZeroSizedBase,
170+
const BaseOffsetsMapTy &BaseOffsets,
171+
const VBaseOffsetsMapTy &VBaseOffsets);
166172

167173
~ASTRecordLayout() = default;
168174

@@ -175,6 +181,10 @@ class ASTRecordLayout {
175181
/// getAlignment - Get the record alignment in characters.
176182
CharUnits getAlignment() const { return Alignment; }
177183

184+
/// getPreferredFieldAlignment - Get the record preferred alignment in
185+
/// characters.
186+
CharUnits getPreferredAlignment() const { return PreferredAlignment; }
187+
178188
/// getUnadjustedAlignment - Get the record alignment in characters, before
179189
/// alignment adjustement.
180190
CharUnits getUnadjustedAlignment() const { return UnadjustedAlignment; }
@@ -193,9 +203,7 @@ class ASTRecordLayout {
193203

194204
/// getDataSize() - Get the record data size, which is the record size
195205
/// without tail padding, in characters.
196-
CharUnits getDataSize() const {
197-
return DataSize;
198-
}
206+
CharUnits getDataSize() const { return DataSize; }
199207

200208
/// getNonVirtualSize - Get the non-virtual size (in chars) of an object,
201209
/// which is the size of the object without virtual bases.
@@ -205,14 +213,23 @@ class ASTRecordLayout {
205213
return CXXInfo->NonVirtualSize;
206214
}
207215

208-
/// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object,
209-
/// which is the alignment of the object without virtual bases.
216+
/// getNonVirtualAlignment - Get the non-virtual alignment (in chars) of an
217+
/// object, which is the alignment of the object without virtual bases.
210218
CharUnits getNonVirtualAlignment() const {
211219
assert(CXXInfo && "Record layout does not have C++ specific info!");
212220

213221
return CXXInfo->NonVirtualAlignment;
214222
}
215223

224+
/// getPreferredNVAlignment - Get the preferred non-virtual alignment (in
225+
/// chars) of an object, which is the preferred alignment of the object
226+
/// without virtual bases.
227+
CharUnits getPreferredNVAlignment() const {
228+
assert(CXXInfo && "Record layout does not have C++ specific info!");
229+
230+
return CXXInfo->PreferredNVAlignment;
231+
}
232+
216233
/// getPrimaryBase - Get the primary base for this record.
217234
const CXXRecordDecl *getPrimaryBase() const {
218235
assert(CXXInfo && "Record layout does not have C++ specific info!");
@@ -287,9 +304,7 @@ class ASTRecordLayout {
287304
return !CXXInfo->VBPtrOffset.isNegative();
288305
}
289306

290-
CharUnits getRequiredAlignment() const {
291-
return RequiredAlignment;
292-
}
307+
CharUnits getRequiredAlignment() const { return RequiredAlignment; }
293308

294309
bool endsWithZeroSizedObject() const {
295310
return CXXInfo && CXXInfo->EndsWithZeroSizedObject;

clang/include/clang/Basic/TargetInfo.h

+3
Original file line numberDiff line numberDiff line change
@@ -1401,6 +1401,9 @@ class TargetInfo : public virtual TransferrableTargetInfo,
14011401
/// Whether target allows to overalign ABI-specified preferred alignment
14021402
virtual bool allowsLargerPreferedTypeAlignment() const { return true; }
14031403

1404+
/// Whether target defaults to the `power` alignment rules of AIX.
1405+
virtual bool defaultsToAIXPowerAlignment() const { return false; }
1406+
14041407
/// Set supported OpenCL extensions and optional core features.
14051408
virtual void setSupportedOpenCLOpts() {}
14061409

clang/lib/AST/ASTContext.cpp

+20-5
Original file line numberDiff line numberDiff line change
@@ -2439,8 +2439,8 @@ CharUnits ASTContext::getTypeUnadjustedAlignInChars(const Type *T) const {
24392439

24402440
/// getPreferredTypeAlign - Return the "preferred" alignment of the specified
24412441
/// type for the current target in bits. This can be different than the ABI
2442-
/// alignment in cases where it is beneficial for performance to overalign
2443-
/// a data type.
2442+
/// alignment in cases where it is beneficial for performance or backwards
2443+
/// compatibility preserving to overalign a data type.
24442444
unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
24452445
TypeInfo TI = getTypeInfo(T);
24462446
unsigned ABIAlign = TI.Align;
@@ -2450,18 +2450,33 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
24502450
// The preferred alignment of member pointers is that of a pointer.
24512451
if (T->isMemberPointerType())
24522452
return getPreferredTypeAlign(getPointerDiffType().getTypePtr());
2453-
2453+
24542454
if (!Target->allowsLargerPreferedTypeAlignment())
24552455
return ABIAlign;
24562456

2457-
// Double and long long should be naturally aligned if possible.
2457+
if (const auto *RT = T->getAs<RecordType>()) {
2458+
if (TI.AlignIsRequired)
2459+
return ABIAlign;
2460+
2461+
unsigned PreferredAlign = static_cast<unsigned>(
2462+
toBits(getASTRecordLayout(RT->getDecl()).PreferredAlignment));
2463+
assert(PreferredAlign >= ABIAlign &&
2464+
"PreferredAlign should be at least as large as ABIAlign.");
2465+
return PreferredAlign;
2466+
}
2467+
2468+
// Double (and, for targets supporting AIX `power` alignment, long double) and
2469+
// long long should be naturally aligned (despite requiring less alignment) if
2470+
// possible.
24582471
if (const auto *CT = T->getAs<ComplexType>())
24592472
T = CT->getElementType().getTypePtr();
24602473
if (const auto *ET = T->getAs<EnumType>())
24612474
T = ET->getDecl()->getIntegerType().getTypePtr();
24622475
if (T->isSpecificBuiltinType(BuiltinType::Double) ||
24632476
T->isSpecificBuiltinType(BuiltinType::LongLong) ||
2464-
T->isSpecificBuiltinType(BuiltinType::ULongLong))
2477+
T->isSpecificBuiltinType(BuiltinType::ULongLong) ||
2478+
(T->isSpecificBuiltinType(BuiltinType::LongDouble) &&
2479+
Target->defaultsToAIXPowerAlignment()))
24652480
// Don't increase the alignment if an alignment attribute was specified on a
24662481
// typedef declaration.
24672482
if (!TI.AlignIsRequired)

clang/lib/AST/RecordLayout.cpp

+19-22
Original file line numberDiff line numberDiff line change
@@ -29,45 +29,42 @@ void ASTRecordLayout::Destroy(ASTContext &Ctx) {
2929

3030
ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size,
3131
CharUnits alignment,
32+
CharUnits preferredAlignment,
3233
CharUnits unadjustedAlignment,
3334
CharUnits requiredAlignment,
3435
CharUnits datasize,
3536
ArrayRef<uint64_t> fieldoffsets)
3637
: Size(size), DataSize(datasize), Alignment(alignment),
38+
PreferredAlignment(preferredAlignment),
3739
UnadjustedAlignment(unadjustedAlignment),
3840
RequiredAlignment(requiredAlignment) {
3941
FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end());
4042
}
4143

4244
// Constructor for C++ records.
43-
ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
44-
CharUnits size, CharUnits alignment,
45-
CharUnits unadjustedAlignment,
46-
CharUnits requiredAlignment,
47-
bool hasOwnVFPtr, bool hasExtendableVFPtr,
48-
CharUnits vbptroffset,
49-
CharUnits datasize,
50-
ArrayRef<uint64_t> fieldoffsets,
51-
CharUnits nonvirtualsize,
52-
CharUnits nonvirtualalignment,
53-
CharUnits SizeOfLargestEmptySubobject,
54-
const CXXRecordDecl *PrimaryBase,
55-
bool IsPrimaryBaseVirtual,
56-
const CXXRecordDecl *BaseSharingVBPtr,
57-
bool EndsWithZeroSizedObject,
58-
bool LeadsWithZeroSizedBase,
59-
const BaseOffsetsMapTy& BaseOffsets,
60-
const VBaseOffsetsMapTy& VBaseOffsets)
61-
: Size(size), DataSize(datasize), Alignment(alignment),
62-
UnadjustedAlignment(unadjustedAlignment),
63-
RequiredAlignment(requiredAlignment), CXXInfo(new (Ctx) CXXRecordLayoutInfo)
64-
{
45+
ASTRecordLayout::ASTRecordLayout(
46+
const ASTContext &Ctx, CharUnits size, CharUnits alignment,
47+
CharUnits preferredAlignment, CharUnits unadjustedAlignment,
48+
CharUnits requiredAlignment, bool hasOwnVFPtr, bool hasExtendableVFPtr,
49+
CharUnits vbptroffset, CharUnits datasize, ArrayRef<uint64_t> fieldoffsets,
50+
CharUnits nonvirtualsize, CharUnits nonvirtualalignment,
51+
CharUnits preferrednvalignment, CharUnits SizeOfLargestEmptySubobject,
52+
const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual,
53+
const CXXRecordDecl *BaseSharingVBPtr, bool EndsWithZeroSizedObject,
54+
bool LeadsWithZeroSizedBase, const BaseOffsetsMapTy &BaseOffsets,
55+
const VBaseOffsetsMapTy &VBaseOffsets)
56+
: Size(size), DataSize(datasize), Alignment(alignment),
57+
PreferredAlignment(preferredAlignment),
58+
UnadjustedAlignment(unadjustedAlignment),
59+
RequiredAlignment(requiredAlignment),
60+
CXXInfo(new (Ctx) CXXRecordLayoutInfo) {
6561
FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end());
6662

6763
CXXInfo->PrimaryBase.setPointer(PrimaryBase);
6864
CXXInfo->PrimaryBase.setInt(IsPrimaryBaseVirtual);
6965
CXXInfo->NonVirtualSize = nonvirtualsize;
7066
CXXInfo->NonVirtualAlignment = nonvirtualalignment;
67+
CXXInfo->PreferredNVAlignment = preferrednvalignment;
7168
CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject;
7269
CXXInfo->BaseOffsets = BaseOffsets;
7370
CXXInfo->VBaseOffsets = VBaseOffsets;

0 commit comments

Comments
 (0)