Skip to content

Commit

Permalink
[AIX] Implement AIX special alignment rule about double/long double
Browse files Browse the repository at this point in the history
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
  • Loading branch information
xling-liao committed Jul 27, 2020
1 parent bef19ab commit 05ad8e9
Show file tree
Hide file tree
Showing 15 changed files with 1,148 additions and 136 deletions.
61 changes: 38 additions & 23 deletions clang/include/clang/AST/RecordLayout.h
Expand Up @@ -70,6 +70,11 @@ class ASTRecordLayout {
// Alignment - Alignment of record in characters.
CharUnits Alignment;

// PreferredAlignment - Preferred alignment of record in characters. This
// can be different than Alignment in cases where it is beneficial for
// performance or backwards compatibility preserving (e.g. AIX-ABI).
CharUnits PreferredAlignment;

// UnadjustedAlignment - Maximum of the alignments of the record members in
// characters.
CharUnits UnadjustedAlignment;
Expand All @@ -91,6 +96,11 @@ class ASTRecordLayout {
/// which is the alignment of the object without virtual bases.
CharUnits NonVirtualAlignment;

/// PreferredNVAlignment - The preferred non-virtual alignment (in chars) of
/// an object, which is the preferred alignment of the object without
/// virtual bases.
CharUnits PreferredNVAlignment;

/// SizeOfLargestEmptySubobject - The size of the largest empty subobject
/// (either a base or a member). Will be zero if the class doesn't contain
/// any empty subobjects.
Expand Down Expand Up @@ -139,30 +149,26 @@ class ASTRecordLayout {
CXXRecordLayoutInfo *CXXInfo = nullptr;

ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
CharUnits unadjustedAlignment,
CharUnits preferredAlignment, CharUnits unadjustedAlignment,
CharUnits requiredAlignment, CharUnits datasize,
ArrayRef<uint64_t> fieldoffsets);

using BaseOffsetsMapTy = CXXRecordLayoutInfo::BaseOffsetsMapTy;

// Constructor for C++ records.
ASTRecordLayout(const ASTContext &Ctx,
CharUnits size, CharUnits alignment,
CharUnits unadjustedAlignment,
CharUnits requiredAlignment,
bool hasOwnVFPtr, bool hasExtendableVFPtr,
CharUnits vbptroffset,
CharUnits datasize,
ArrayRef<uint64_t> fieldoffsets,
ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
CharUnits preferredAlignment, CharUnits unadjustedAlignment,
CharUnits requiredAlignment, bool hasOwnVFPtr,
bool hasExtendableVFPtr, CharUnits vbptroffset,
CharUnits datasize, ArrayRef<uint64_t> fieldoffsets,
CharUnits nonvirtualsize, CharUnits nonvirtualalignment,
CharUnits preferrednvalignment,
CharUnits SizeOfLargestEmptySubobject,
const CXXRecordDecl *PrimaryBase,
bool IsPrimaryBaseVirtual,
const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual,
const CXXRecordDecl *BaseSharingVBPtr,
bool EndsWithZeroSizedObject,
bool LeadsWithZeroSizedBase,
const BaseOffsetsMapTy& BaseOffsets,
const VBaseOffsetsMapTy& VBaseOffsets);
bool EndsWithZeroSizedObject, bool LeadsWithZeroSizedBase,
const BaseOffsetsMapTy &BaseOffsets,
const VBaseOffsetsMapTy &VBaseOffsets);

~ASTRecordLayout() = default;

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

/// getPreferredFieldAlignment - Get the record preferred alignment in
/// characters.
CharUnits getPreferredAlignment() const { return PreferredAlignment; }

/// getUnadjustedAlignment - Get the record alignment in characters, before
/// alignment adjustement.
CharUnits getUnadjustedAlignment() const { return UnadjustedAlignment; }
Expand All @@ -193,9 +203,7 @@ class ASTRecordLayout {

/// getDataSize() - Get the record data size, which is the record size
/// without tail padding, in characters.
CharUnits getDataSize() const {
return DataSize;
}
CharUnits getDataSize() const { return DataSize; }

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

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

return CXXInfo->NonVirtualAlignment;
}

/// getPreferredNVAlignment - Get the preferred non-virtual alignment (in
/// chars) of an object, which is the preferred alignment of the object
/// without virtual bases.
CharUnits getPreferredNVAlignment() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");

return CXXInfo->PreferredNVAlignment;
}

/// getPrimaryBase - Get the primary base for this record.
const CXXRecordDecl *getPrimaryBase() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
Expand Down Expand Up @@ -287,9 +304,7 @@ class ASTRecordLayout {
return !CXXInfo->VBPtrOffset.isNegative();
}

CharUnits getRequiredAlignment() const {
return RequiredAlignment;
}
CharUnits getRequiredAlignment() const { return RequiredAlignment; }

bool endsWithZeroSizedObject() const {
return CXXInfo && CXXInfo->EndsWithZeroSizedObject;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/TargetInfo.h
Expand Up @@ -1401,6 +1401,9 @@ class TargetInfo : public virtual TransferrableTargetInfo,
/// Whether target allows to overalign ABI-specified preferred alignment
virtual bool allowsLargerPreferedTypeAlignment() const { return true; }

/// Whether target defaults to the `power` alignment rules of AIX.
virtual bool defaultsToAIXPowerAlignment() const { return false; }

/// Set supported OpenCL extensions and optional core features.
virtual void setSupportedOpenCLOpts() {}

Expand Down
25 changes: 20 additions & 5 deletions clang/lib/AST/ASTContext.cpp
Expand Up @@ -2439,8 +2439,8 @@ CharUnits ASTContext::getTypeUnadjustedAlignInChars(const Type *T) const {

/// getPreferredTypeAlign - Return the "preferred" alignment of the specified
/// type for the current target in bits. This can be different than the ABI
/// alignment in cases where it is beneficial for performance to overalign
/// a data type.
/// alignment in cases where it is beneficial for performance or backwards
/// compatibility preserving to overalign a data type.
unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
TypeInfo TI = getTypeInfo(T);
unsigned ABIAlign = TI.Align;
Expand All @@ -2450,18 +2450,33 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
// The preferred alignment of member pointers is that of a pointer.
if (T->isMemberPointerType())
return getPreferredTypeAlign(getPointerDiffType().getTypePtr());

if (!Target->allowsLargerPreferedTypeAlignment())
return ABIAlign;

// Double and long long should be naturally aligned if possible.
if (const auto *RT = T->getAs<RecordType>()) {
if (TI.AlignIsRequired)
return ABIAlign;

unsigned PreferredAlign = static_cast<unsigned>(
toBits(getASTRecordLayout(RT->getDecl()).PreferredAlignment));
assert(PreferredAlign >= ABIAlign &&
"PreferredAlign should be at least as large as ABIAlign.");
return PreferredAlign;
}

// Double (and, for targets supporting AIX `power` alignment, long double) and
// long long should be naturally aligned (despite requiring less alignment) if
// possible.
if (const auto *CT = T->getAs<ComplexType>())
T = CT->getElementType().getTypePtr();
if (const auto *ET = T->getAs<EnumType>())
T = ET->getDecl()->getIntegerType().getTypePtr();
if (T->isSpecificBuiltinType(BuiltinType::Double) ||
T->isSpecificBuiltinType(BuiltinType::LongLong) ||
T->isSpecificBuiltinType(BuiltinType::ULongLong))
T->isSpecificBuiltinType(BuiltinType::ULongLong) ||
(T->isSpecificBuiltinType(BuiltinType::LongDouble) &&
Target->defaultsToAIXPowerAlignment()))
// Don't increase the alignment if an alignment attribute was specified on a
// typedef declaration.
if (!TI.AlignIsRequired)
Expand Down
41 changes: 19 additions & 22 deletions clang/lib/AST/RecordLayout.cpp
Expand Up @@ -29,45 +29,42 @@ void ASTRecordLayout::Destroy(ASTContext &Ctx) {

ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size,
CharUnits alignment,
CharUnits preferredAlignment,
CharUnits unadjustedAlignment,
CharUnits requiredAlignment,
CharUnits datasize,
ArrayRef<uint64_t> fieldoffsets)
: Size(size), DataSize(datasize), Alignment(alignment),
PreferredAlignment(preferredAlignment),
UnadjustedAlignment(unadjustedAlignment),
RequiredAlignment(requiredAlignment) {
FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end());
}

// Constructor for C++ records.
ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
CharUnits size, CharUnits alignment,
CharUnits unadjustedAlignment,
CharUnits requiredAlignment,
bool hasOwnVFPtr, bool hasExtendableVFPtr,
CharUnits vbptroffset,
CharUnits datasize,
ArrayRef<uint64_t> fieldoffsets,
CharUnits nonvirtualsize,
CharUnits nonvirtualalignment,
CharUnits SizeOfLargestEmptySubobject,
const CXXRecordDecl *PrimaryBase,
bool IsPrimaryBaseVirtual,
const CXXRecordDecl *BaseSharingVBPtr,
bool EndsWithZeroSizedObject,
bool LeadsWithZeroSizedBase,
const BaseOffsetsMapTy& BaseOffsets,
const VBaseOffsetsMapTy& VBaseOffsets)
: Size(size), DataSize(datasize), Alignment(alignment),
UnadjustedAlignment(unadjustedAlignment),
RequiredAlignment(requiredAlignment), CXXInfo(new (Ctx) CXXRecordLayoutInfo)
{
ASTRecordLayout::ASTRecordLayout(
const ASTContext &Ctx, CharUnits size, CharUnits alignment,
CharUnits preferredAlignment, CharUnits unadjustedAlignment,
CharUnits requiredAlignment, bool hasOwnVFPtr, bool hasExtendableVFPtr,
CharUnits vbptroffset, CharUnits datasize, ArrayRef<uint64_t> fieldoffsets,
CharUnits nonvirtualsize, CharUnits nonvirtualalignment,
CharUnits preferrednvalignment, CharUnits SizeOfLargestEmptySubobject,
const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual,
const CXXRecordDecl *BaseSharingVBPtr, bool EndsWithZeroSizedObject,
bool LeadsWithZeroSizedBase, const BaseOffsetsMapTy &BaseOffsets,
const VBaseOffsetsMapTy &VBaseOffsets)
: Size(size), DataSize(datasize), Alignment(alignment),
PreferredAlignment(preferredAlignment),
UnadjustedAlignment(unadjustedAlignment),
RequiredAlignment(requiredAlignment),
CXXInfo(new (Ctx) CXXRecordLayoutInfo) {
FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end());

CXXInfo->PrimaryBase.setPointer(PrimaryBase);
CXXInfo->PrimaryBase.setInt(IsPrimaryBaseVirtual);
CXXInfo->NonVirtualSize = nonvirtualsize;
CXXInfo->NonVirtualAlignment = nonvirtualalignment;
CXXInfo->PreferredNVAlignment = preferrednvalignment;
CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject;
CXXInfo->BaseOffsets = BaseOffsets;
CXXInfo->VBaseOffsets = VBaseOffsets;
Expand Down

0 comments on commit 05ad8e9

Please sign in to comment.