[clang] 73733ae - TypeInfo records more information about align requirement
Steven Wan via cfe-commits
cfe-commits at lists.llvm.org
Sat Aug 28 16:48:46 PDT 2021
Author: Steven Wan
Date: 2021-08-28T19:47:48-04:00
New Revision: 73733ae526a5152e5427973ac12dc54f7dd243fb
URL: https://github.com/llvm/llvm-project/commit/73733ae526a5152e5427973ac12dc54f7dd243fb
DIFF: https://github.com/llvm/llvm-project/commit/73733ae526a5152e5427973ac12dc54f7dd243fb.diff
LOG: TypeInfo records more information about align requirement
Extend the information preserved in `TypeInfo` by replacing the `AlignIsRequired` bool flag with a three-valued enum, the enum also indicates where the alignment attribute come from, which could be helpful in determining whether the attribute should overrule.
Reviewed By: rjmccall
Differential Revision: https://reviews.llvm.org/D108858
Added:
Modified:
clang/include/clang/AST/ASTContext.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/RecordLayoutBuilder.cpp
clang/lib/CodeGen/CGDebugInfo.cpp
clang/lib/CodeGen/MicrosoftCXXABI.cpp
clang/lib/CodeGen/TargetInfo.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index da372e854700b..5004cb6cb2671 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -164,24 +164,46 @@ namespace serialization {
template <class> class AbstractTypeReader;
} // namespace serialization
+enum class AlignRequirementKind {
+ /// The alignment was not explicit in code.
+ None,
+
+ /// The alignment comes from an alignment attribute on a typedef.
+ RequiredByTypedef,
+
+ /// The alignment comes from an alignment attribute on a record type.
+ RequiredByRecord,
+
+ /// The alignment comes from an alignment attribute on a enum type.
+ RequiredByEnum,
+};
+
struct TypeInfo {
uint64_t Width = 0;
unsigned Align = 0;
- bool AlignIsRequired : 1;
+ AlignRequirementKind AlignRequirement;
- TypeInfo() : AlignIsRequired(false) {}
- TypeInfo(uint64_t Width, unsigned Align, bool AlignIsRequired)
- : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {}
+ TypeInfo() : AlignRequirement(AlignRequirementKind::None) {}
+ TypeInfo(uint64_t Width, unsigned Align,
+ AlignRequirementKind AlignRequirement)
+ : Width(Width), Align(Align), AlignRequirement(AlignRequirement) {}
+ bool isAlignRequired() {
+ return AlignRequirement != AlignRequirementKind::None;
+ }
};
struct TypeInfoChars {
CharUnits Width;
CharUnits Align;
- bool AlignIsRequired : 1;
+ AlignRequirementKind AlignRequirement;
- TypeInfoChars() : AlignIsRequired(false) {}
- TypeInfoChars(CharUnits Width, CharUnits Align, bool AlignIsRequired)
- : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {}
+ TypeInfoChars() : AlignRequirement(AlignRequirementKind::None) {}
+ TypeInfoChars(CharUnits Width, CharUnits Align,
+ AlignRequirementKind AlignRequirement)
+ : Width(Width), Align(Align), AlignRequirement(AlignRequirement) {}
+ bool isAlignRequired() {
+ return AlignRequirement != AlignRequirementKind::None;
+ }
};
/// Holds long-lived AST nodes (such as types and decls) that can be
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 12b5d14f35c63..41dd9f7e3330b 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1858,7 +1858,7 @@ static getConstantArrayInfoInChars(const ASTContext &Context,
Width = llvm::alignTo(Width, Align);
return TypeInfoChars(CharUnits::fromQuantity(Width),
CharUnits::fromQuantity(Align),
- EltInfo.AlignIsRequired);
+ EltInfo.AlignRequirement);
}
TypeInfoChars ASTContext::getTypeInfoInChars(const Type *T) const {
@@ -1866,8 +1866,7 @@ TypeInfoChars ASTContext::getTypeInfoInChars(const Type *T) const {
return getConstantArrayInfoInChars(*this, CAT);
TypeInfo Info = getTypeInfo(T);
return TypeInfoChars(toCharUnitsFromBits(Info.Width),
- toCharUnitsFromBits(Info.Align),
- Info.AlignIsRequired);
+ toCharUnitsFromBits(Info.Align), Info.AlignRequirement);
}
TypeInfoChars ASTContext::getTypeInfoInChars(QualType T) const {
@@ -1875,7 +1874,7 @@ TypeInfoChars ASTContext::getTypeInfoInChars(QualType T) const {
}
bool ASTContext::isAlignmentRequired(const Type *T) const {
- return getTypeInfo(T).AlignIsRequired;
+ return getTypeInfo(T).AlignRequirement != AlignRequirementKind::None;
}
bool ASTContext::isAlignmentRequired(QualType T) const {
@@ -1927,7 +1926,7 @@ TypeInfo ASTContext::getTypeInfo(const Type *T) const {
TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
uint64_t Width = 0;
unsigned Align = 8;
- bool AlignIsRequired = false;
+ AlignRequirementKind AlignRequirement = AlignRequirementKind::None;
unsigned AS = 0;
switch (T->getTypeClass()) {
#define TYPE(Class, Base)
@@ -1961,7 +1960,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
"Overflow in array type bit size evaluation");
Width = EltInfo.Width * Size;
Align = EltInfo.Align;
- AlignIsRequired = EltInfo.AlignIsRequired;
+ AlignRequirement = EltInfo.AlignRequirement;
if (!getTargetInfo().getCXXABI().isMicrosoft() ||
getTargetInfo().getPointerWidth(0) == 64)
Width = llvm::alignTo(Width, Align);
@@ -2298,7 +2297,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
getTypeInfo(ED->getIntegerType()->getUnqualifiedDesugaredType());
if (unsigned AttrAlign = ED->getMaxAlignment()) {
Info.Align = AttrAlign;
- Info.AlignIsRequired = true;
+ Info.AlignRequirement = AlignRequirementKind::RequiredByEnum;
}
return Info;
}
@@ -2308,7 +2307,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
const ASTRecordLayout &Layout = getASTRecordLayout(RD);
Width = toBits(Layout.getSize());
Align = toBits(Layout.getAlignment());
- AlignIsRequired = RD->hasAttr<AlignedAttr>();
+ AlignRequirement = RD->hasAttr<AlignedAttr>()
+ ? AlignRequirementKind::RequiredByRecord
+ : AlignRequirementKind::None;
break;
}
@@ -2342,10 +2343,10 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
// attribute(aligned) can only round up) but matches its implementation.
if (unsigned AttrAlign = Typedef->getMaxAlignment()) {
Align = AttrAlign;
- AlignIsRequired = true;
+ AlignRequirement = AlignRequirementKind::RequiredByTypedef;
} else {
Align = Info.Align;
- AlignIsRequired = Info.AlignIsRequired;
+ AlignRequirement = Info.AlignRequirement;
}
Width = Info.Width;
break;
@@ -2391,7 +2392,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
}
assert(llvm::isPowerOf2_32(Align) && "Alignment must be power of 2");
- return TypeInfo(Width, Align, AlignIsRequired);
+ return TypeInfo(Width, Align, AlignRequirement);
}
unsigned ASTContext::getTypeUnadjustedAlign(const Type *T) const {
@@ -2481,7 +2482,7 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
// When used as part of a typedef, or together with a 'packed' attribute,
// the 'aligned' attribute can be used to decrease alignment.
- if ((TI.AlignIsRequired && T->getAs<TypedefType>() != nullptr) ||
+ if ((TI.isAlignRequired() && T->getAs<TypedefType>() != nullptr) ||
RD->isInvalidDecl())
return ABIAlign;
@@ -2506,7 +2507,7 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
Target->defaultsToAIXPowerAlignment()))
// Don't increase the alignment if an alignment attribute was specified on a
// typedef declaration.
- if (!TI.AlignIsRequired)
+ if (!TI.isAlignRequired())
return std::max(ABIAlign, (unsigned)getTypeSize(T));
return ABIAlign;
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index 83045253aa512..30e88da9ac4f5 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -1538,7 +1538,7 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
TypeInfo FieldInfo = Context.getTypeInfo(D->getType());
uint64_t StorageUnitSize = FieldInfo.Width;
unsigned FieldAlign = FieldInfo.Align;
- bool AlignIsRequired = FieldInfo.AlignIsRequired;
+ bool AlignIsRequired = FieldInfo.isAlignRequired();
// UnfilledBitsInLastUnit is the
diff erence between the end of the
// last allocated bitfield (i.e. the first bit offset available for
@@ -1889,7 +1889,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
- bool AlignIsRequired = false;
+ AlignRequirementKind AlignRequirement = AlignRequirementKind::None;
CharUnits FieldSize;
CharUnits FieldAlign;
// The amount of this class's dsize occupied by the field.
@@ -1904,7 +1904,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
// aligned appropriately for their element type.
EffectiveFieldSize = FieldSize =
IsIncompleteArrayType ? CharUnits::Zero() : TI.Width;
- AlignIsRequired = TI.AlignIsRequired;
+ AlignRequirement = TI.AlignRequirement;
};
if (D->getType()->isIncompleteArrayType()) {
@@ -1978,7 +1978,8 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
// and zero-width bit-fields count as prior members; members of empty class
// types marked `no_unique_address` are not considered to be prior members.
CharUnits PreferredAlign = FieldAlign;
- if (DefaultsToAIXPowerAlignment && !AlignIsRequired &&
+ if (DefaultsToAIXPowerAlignment &&
+ AlignRequirement == AlignRequirementKind::None &&
(FoundFirstNonOverlappingEmptyFieldForAIX || IsNaturalAlign)) {
auto performBuiltinTypeAlignmentUpgrade = [&](const BuiltinType *BTy) {
if (BTy->getKind() == BuiltinType::Double ||
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 5993ce8531f8f..fcccd42c116da 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -52,7 +52,7 @@ using namespace clang::CodeGen;
static uint32_t getTypeAlignIfRequired(const Type *Ty, const ASTContext &Ctx) {
auto TI = Ctx.getTypeInfo(Ty);
- return TI.AlignIsRequired ? TI.Align : 0;
+ return TI.isAlignRequired() ? TI.Align : 0;
}
static uint32_t getTypeAlignIfRequired(QualType Ty, const ASTContext &Ctx) {
@@ -4676,7 +4676,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
llvm::DIType *fieldType;
if (capture->isByRef()) {
TypeInfo PtrInfo = C.getTypeInfo(C.VoidPtrTy);
- auto Align = PtrInfo.AlignIsRequired ? PtrInfo.Align : 0;
+ auto Align = PtrInfo.isAlignRequired() ? PtrInfo.Align : 0;
// FIXME: This recomputes the layout of the BlockByRefWrapper.
uint64_t xoffset;
fieldType =
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 6522ea58c27c9..e84b794f93f77 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -847,7 +847,7 @@ MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const {
// arguments was not supported and resulted in a compiler error. In 19.14
// and later versions, such arguments are now passed indirectly.
TypeInfo Info = getContext().getTypeInfo(RD->getTypeForDecl());
- if (Info.AlignIsRequired && Info.Align > 4)
+ if (Info.isAlignRequired() && Info.Align > 4)
return RAA_Indirect;
// If C++ prohibits us from making a copy, construct the arguments directly
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index de9728a9c7d4a..7081b20a20200 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -1839,7 +1839,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
// Pass over-aligned aggregates on Windows indirectly. This behavior was
// added in MSVC 2015.
- if (IsWin32StructABI && TI.AlignIsRequired && TI.Align > 32)
+ if (IsWin32StructABI && TI.isAlignRequired() && TI.Align > 32)
return getIndirectResult(Ty, /*ByVal=*/false, State);
// Expand small (<= 128-bit) record types when we know that the stack layout
@@ -6992,7 +6992,7 @@ Address ARMABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
TyAlignForABI = CharUnits::fromQuantity(4);
}
- TypeInfoChars TyInfo(TySize, TyAlignForABI, false);
+ TypeInfoChars TyInfo(TySize, TyAlignForABI, AlignRequirementKind::None);
return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, TyInfo,
SlotSize, /*AllowHigherAlign*/ true);
}
More information about the cfe-commits
mailing list