diff options
author | David Majnemer <david.majnemer@gmail.com> | 2014-07-30 01:30:47 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2014-07-30 01:30:47 +0000 |
commit | 34b5749989062e3049296cf656cc3551ebe47e65 (patch) | |
tree | b909046d61f66d0a403d635856ead8c437d42457 /clang/lib/AST/ASTContext.cpp | |
parent | 9dcc254a47256162dbd616fc34c9dac774969306 (diff) | |
download | bcm5719-llvm-34b5749989062e3049296cf656cc3551ebe47e65.tar.gz bcm5719-llvm-34b5749989062e3049296cf656cc3551ebe47e65.zip |
MS ABI: Consider alignment attributes on typedefs for layout
The MS ABI has a notion of 'required alignment' for fields; this
alignment supercedes pragma pack directives.
MSVC takes into account alignment attributes on typedefs when
determining whether or not a field has a certain required alignment.
Do the same in clang by tracking whether or not we saw such an attribute
when calculating the type's bitwidth and alignment.
This fixes PR20418.
Reviewers: rnk
Differential Revision: http://reviews.llvm.org/D4714
llvm-svn: 214274
Diffstat (limited to 'clang/lib/AST/ASTContext.cpp')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 81 |
1 files changed, 42 insertions, 39 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index bccdae91d2e..c7685e4a6dd 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1413,9 +1413,9 @@ std::pair<CharUnits, CharUnits> ASTContext::getTypeInfoInChars(const Type *T) const { if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) return getConstantArrayInfoInChars(*this, CAT); - std::pair<uint64_t, unsigned> Info = getTypeInfo(T); - return std::make_pair(toCharUnitsFromBits(Info.first), - toCharUnitsFromBits(Info.second)); + TypeInfo Info = getTypeInfo(T); + return std::make_pair(toCharUnitsFromBits(Info.Width), + toCharUnitsFromBits(Info.Align)); } std::pair<CharUnits, CharUnits> @@ -1423,14 +1423,20 @@ ASTContext::getTypeInfoInChars(QualType T) const { return getTypeInfoInChars(T.getTypePtr()); } -std::pair<uint64_t, unsigned> ASTContext::getTypeInfo(const Type *T) const { - TypeInfoMap::iterator it = MemoizedTypeInfo.find(T); - if (it != MemoizedTypeInfo.end()) - return it->second; +bool ASTContext::isAlignmentRequired(const Type *T) const { + return getTypeInfo(T).AlignIsRequired; +} + +bool ASTContext::isAlignmentRequired(QualType T) const { + return isAlignmentRequired(T.getTypePtr()); +} + +TypeInfo ASTContext::getTypeInfo(const Type *T) const { + TypeInfo &TI = MemoizedTypeInfo[T]; + if (!TI.Align) + TI = getTypeInfoImpl(T); - std::pair<uint64_t, unsigned> Info = getTypeInfoImpl(T); - MemoizedTypeInfo.insert(std::make_pair(T, Info)); - return Info; + return TI; } /// getTypeInfoImpl - Return the size of the specified type, in bits. This @@ -1439,10 +1445,10 @@ std::pair<uint64_t, unsigned> ASTContext::getTypeInfo(const Type *T) const { /// FIXME: Pointers into different addr spaces could have different sizes and /// alignment requirements: getPointerInfo should take an AddrSpace, this /// should take a QualType, &c. -std::pair<uint64_t, unsigned> -ASTContext::getTypeInfoImpl(const Type *T) const { - uint64_t Width=0; - unsigned Align=8; +TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { + uint64_t Width = 0; + unsigned Align = 8; + bool AlignIsRequired = false; switch (T->getTypeClass()) { #define TYPE(Class, Base) #define ABSTRACT_TYPE(Class, Base) @@ -1471,12 +1477,12 @@ ASTContext::getTypeInfoImpl(const Type *T) const { case Type::ConstantArray: { const ConstantArrayType *CAT = cast<ConstantArrayType>(T); - std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(CAT->getElementType()); + TypeInfo EltInfo = getTypeInfo(CAT->getElementType()); uint64_t Size = CAT->getSize().getZExtValue(); - assert((Size == 0 || EltInfo.first <= (uint64_t)(-1)/Size) && + assert((Size == 0 || EltInfo.Width <= (uint64_t)(-1) / Size) && "Overflow in array type bit size evaluation"); - Width = EltInfo.first*Size; - Align = EltInfo.second; + Width = EltInfo.Width * Size; + Align = EltInfo.Align; if (!getTargetInfo().getCXXABI().isMicrosoft() || getTargetInfo().getPointerWidth(0) == 64) Width = llvm::RoundUpToAlignment(Width, Align); @@ -1485,8 +1491,8 @@ ASTContext::getTypeInfoImpl(const Type *T) const { case Type::ExtVector: case Type::Vector: { const VectorType *VT = cast<VectorType>(T); - std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(VT->getElementType()); - Width = EltInfo.first*VT->getNumElements(); + TypeInfo EltInfo = getTypeInfo(VT->getElementType()); + Width = EltInfo.Width * VT->getNumElements(); Align = Width; // If the alignment is not a power of 2, round up to the next power of 2. // This happens for non-power-of-2 length vectors. @@ -1638,10 +1644,9 @@ ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Complex: { // Complex types have the same alignment as their elements, but twice the // size. - std::pair<uint64_t, unsigned> EltInfo = - getTypeInfo(cast<ComplexType>(T)->getElementType()); - Width = EltInfo.first*2; - Align = EltInfo.second; + TypeInfo EltInfo = getTypeInfo(cast<ComplexType>(T)->getElementType()); + Width = EltInfo.Width * 2; + Align = EltInfo.Align; break; } case Type::ObjCObject: @@ -1692,16 +1697,16 @@ ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Typedef: { const TypedefNameDecl *Typedef = cast<TypedefType>(T)->getDecl(); - std::pair<uint64_t, unsigned> Info - = getTypeInfo(Typedef->getUnderlyingType().getTypePtr()); + TypeInfo Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr()); // If the typedef has an aligned attribute on it, it overrides any computed // alignment we have. This violates the GCC documentation (which says that // attribute(aligned) can only round up) but matches its implementation. - if (unsigned AttrAlign = Typedef->getMaxAlignment()) + if (unsigned AttrAlign = Typedef->getMaxAlignment()) { Align = AttrAlign; - else - Align = Info.second; - Width = Info.first; + AlignIsRequired = true; + } else + Align = Info.Align; + Width = Info.Width; break; } @@ -1714,10 +1719,9 @@ ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Atomic: { // Start with the base type information. - std::pair<uint64_t, unsigned> Info - = getTypeInfo(cast<AtomicType>(T)->getValueType()); - Width = Info.first; - Align = Info.second; + TypeInfo Info = getTypeInfo(cast<AtomicType>(T)->getValueType()); + Width = Info.Width; + Align = Info.Align; // If the size of the type doesn't exceed the platform's max // atomic promotion width, make the size and alignment more @@ -1735,7 +1739,7 @@ ASTContext::getTypeInfoImpl(const Type *T) const { } assert(llvm::isPowerOf2_32(Align) && "Alignment must be power of 2"); - return std::make_pair(Width, Align); + return TypeInfo(Width, Align, AlignIsRequired); } /// toCharUnitsFromBits - Convert a size in bits to a size in characters. @@ -1771,13 +1775,12 @@ CharUnits ASTContext::getTypeAlignInChars(const Type *T) const { /// alignment in cases where it is beneficial for performance to overalign /// a data type. unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { - unsigned ABIAlign = getTypeAlign(T); + TypeInfo TI = getTypeInfo(T); + unsigned ABIAlign = TI.Align; if (Target->getTriple().getArch() == llvm::Triple::xcore) return ABIAlign; // Never overalign on XCore. - const TypedefType *TT = T->getAs<TypedefType>(); - // Double and long long should be naturally aligned if possible. T = T->getBaseElementTypeUnsafe(); if (const ComplexType *CT = T->getAs<ComplexType>()) @@ -1787,7 +1790,7 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { T->isSpecificBuiltinType(BuiltinType::ULongLong)) // Don't increase the alignment if an alignment attribute was specified on a // typedef declaration. - if (!TT || !TT->getDecl()->getMaxAlignment()) + if (!TI.AlignIsRequired) return std::max(ABIAlign, (unsigned)getTypeSize(T)); return ABIAlign; |