diff options
author | Chad Rosier <mcrosier@apple.com> | 2011-08-04 01:21:14 +0000 |
---|---|---|
committer | Chad Rosier <mcrosier@apple.com> | 2011-08-04 01:21:14 +0000 |
commit | 18903ee2d383a93d079a801258bf25d46ba1f995 (patch) | |
tree | 983435286ec5ba090595c468993835003a088587 /clang/lib | |
parent | bc673fb5f2fb6f1a8b148f9bc4bf3cabd2ff8184 (diff) | |
download | bcm5719-llvm-18903ee2d383a93d079a801258bf25d46ba1f995.tar.gz bcm5719-llvm-18903ee2d383a93d079a801258bf25d46ba1f995.zip |
Add partial support for using anonymous bitfields (e.g., int : 0) to enforce
alignment. This fixes cases where the anonymous bitfield is followed by a
non-bitfield member. E.g.,
struct t4
{
int foo : 1;
long : 0;
char bar;
};
Part of rdar://9859156
llvm-svn: 136858
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/RecordLayoutBuilder.cpp | 41 | ||||
-rw-r--r-- | clang/lib/Basic/TargetInfo.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Basic/Targets.cpp | 10 |
3 files changed, 42 insertions, 11 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index bb5b33406f4..19a762c30bc 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1348,6 +1348,13 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { } LastFD = FD; } + else if (Context.Target.useZeroLengthBitfieldAlignment() && + !Context.Target.useBitFieldTypeAlignment()) { + FieldDecl *FD = (*Field); + if (Context.ZeroBitfieldFollowsBitfield(FD, LastFD)) + ZeroLengthBitfield = FD; + LastFD = FD; + } LayoutField(*Field); } if (IsMsStruct && RemainingInAlignment && @@ -1442,7 +1449,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // This check is needed for 'long long' in -m32 mode. if (IsMsStruct && (TypeSize > FieldAlign)) FieldAlign = TypeSize; - + if (ZeroLengthBitfield) { // If a zero-length bitfield is inserted after a bitfield, // and the alignment of the zero-length bitfield is @@ -1559,17 +1566,29 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { Context.getTypeInfoInChars(D->getType()); FieldSize = FieldInfo.first; FieldAlign = FieldInfo.second; - + if (ZeroLengthBitfield) { - // If a zero-length bitfield is inserted after a bitfield, - // and the alignment of the zero-length bitfield is - // greater than the member that follows it, `bar', `bar' - // will be aligned as the type of the zero-length bitfield. - std::pair<CharUnits, CharUnits> FieldInfo = - Context.getTypeInfoInChars(ZeroLengthBitfield->getType()); - CharUnits ZeroLengthBitfieldAlignment = FieldInfo.second; - if (ZeroLengthBitfieldAlignment > FieldAlign) - FieldAlign = ZeroLengthBitfieldAlignment; + CharUnits ZeroLengthBitfieldBoundary = + Context.toCharUnitsFromBits( + Context.Target.getZeroLengthBitfieldBoundary()); + if (ZeroLengthBitfieldBoundary == CharUnits::Zero()) { + // If a zero-length bitfield is inserted after a bitfield, + // and the alignment of the zero-length bitfield is + // greater than the member that follows it, `bar', `bar' + // will be aligned as the type of the zero-length bitfield. + std::pair<CharUnits, CharUnits> FieldInfo = + Context.getTypeInfoInChars(ZeroLengthBitfield->getType()); + CharUnits ZeroLengthBitfieldAlignment = FieldInfo.second; + if (ZeroLengthBitfieldAlignment > FieldAlign) + FieldAlign = ZeroLengthBitfieldAlignment; + } + else if (ZeroLengthBitfieldBoundary > FieldAlign) { + // Align 'bar' based on a fixed alignment specified by the target. + assert (Context.Target.useZeroLengthBitfieldAlignment() && + "ZeroLengthBitfieldBoundary should only be used in conjunction" + "with useZeroLengthBitfieldAlignment."); + FieldAlign = ZeroLengthBitfieldBoundary; + } ZeroLengthBitfield = 0; } diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 7ea51467c18..91b16d57788 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -53,6 +53,8 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) { Int64Type = SignedLongLong; SigAtomicType = SignedInt; UseBitFieldTypeAlignment = true; + UseZeroLengthBitfieldAlignment = false; + ZeroLengthBitfieldBoundary = 0; FloatFormat = &llvm::APFloat::IEEEsingle; DoubleFormat = &llvm::APFloat::IEEEdouble; LongDoubleFormat = &llvm::APFloat::IEEEdouble; diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index ec45a87fa02..89b6ce960b0 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -1963,6 +1963,16 @@ public: // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc. UseBitFieldTypeAlignment = false; + /// Do force alignment of members that follow zero length bitfields. If + /// the alignment of the zero-length bitfield is greater than the member + /// that follows it, `bar', `bar' will be aligned as the type of the + /// zero length bitfield. + UseZeroLengthBitfieldAlignment = true; + + /// gcc forces the alignment to 4 bytes, regardless of the type of the + /// zero length bitfield. + ZeroLengthBitfieldBoundary = 32; + if (IsThumb) { // Thumb1 add sp, #imm requires the immediate value be multiple of 4, // so set preferred for small types to 32. |