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 | 61a62216a0bb33fb668ab653d9f9a704e43d2fc6 (patch) | |
tree | 999fee0c071a7f8b6d95330248ea3595c03e0be1 | |
parent | a5e19c6b2554f6d9c4b9850d4dbbbfa3643282e5 (diff) |
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
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@136858 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/TargetInfo.h | 22 | ||||
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 41 | ||||
-rw-r--r-- | lib/Basic/TargetInfo.cpp | 2 | ||||
-rw-r--r-- | lib/Basic/Targets.cpp | 10 | ||||
-rw-r--r-- | test/CodeGen/arm-apcs-zerolength-bitfield.c | 35 |
5 files changed, 89 insertions, 21 deletions
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index e09098ea05..ce39ac0884 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -132,6 +132,16 @@ protected: /// boundary. unsigned UseBitFieldTypeAlignment : 1; + /// Control whether zero length bitfields (e.g., int : 0;) force alignment of + /// the next bitfield. 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. + unsigned UseZeroLengthBitfieldAlignment : 1; + + /// If non-zero, specifies a fixed alignment value for bitfields that follow + /// zero length bitfield, regardless of the zero length bitfield type. + unsigned ZeroLengthBitfieldBoundary; + public: IntType getSizeType() const { return SizeType; } IntType getIntMaxType() const { return IntMaxType; } @@ -266,6 +276,18 @@ public: return UseBitFieldTypeAlignment; } + /// useZeroLengthBitfieldAlignment() - Check whether zero length bitfields + /// should force alignment of the next member. + bool useZeroLengthBitfieldAlignment() const { + return UseZeroLengthBitfieldAlignment; + } + + /// getZeroLengthBitfieldBoundary() - Get the fixed alignment value in + /// bits for a member that follows zero length bitfield. + unsigned getZeroLengthBitfieldBoundary() const { + return ZeroLengthBitfieldBoundary; + } + /// hasAlignMac68kSupport - Check whether this target support '#pragma options /// align=mac68k'. bool hasAlignMac68kSupport() const { diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index bb5b33406f..19a762c30b 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/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/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index 7ea51467c1..91b16d5778 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/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/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index ec45a87fa0..89b6ce960b 100644 --- a/lib/Basic/Targets.cpp +++ b/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. diff --git a/test/CodeGen/arm-apcs-zerolength-bitfield.c b/test/CodeGen/arm-apcs-zerolength-bitfield.c index 0b26d382e2..4b16e0c832 100644 --- a/test/CodeGen/arm-apcs-zerolength-bitfield.c +++ b/test/CodeGen/arm-apcs-zerolength-bitfield.c @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -target-abi apcs-gnu -triple armv7-apple-darwin10 %s -verify +// +// Note: gcc forces the alignment to 4 bytes, regardless of the type of the +// zero length bitfield. +// rdar://9859156 #include <stddef.h> @@ -8,8 +12,8 @@ struct t1 char : 0; char bar; }; -static int arr1_offset[(offsetof(struct t1, bar) == 1) ? 0 : -1]; -static int arr1_sizeof[(sizeof(struct t1) == 2) ? 0 : -1]; +static int arr1_offset[(offsetof(struct t1, bar) == 4) ? 0 : -1]; +static int arr1_sizeof[(sizeof(struct t1) == 8) ? 0 : -1]; struct t2 { @@ -17,8 +21,8 @@ struct t2 short : 0; char bar; }; -static int arr2_offset[(offsetof(struct t2, bar) == 1) ? 0 : -1]; -static int arr2_sizeof[(sizeof(struct t2) == 2) ? 0 : -1]; +static int arr2_offset[(offsetof(struct t2, bar) == 4) ? 0 : -1]; +static int arr2_sizeof[(sizeof(struct t2) == 8) ? 0 : -1]; struct t3 { @@ -26,8 +30,8 @@ struct t3 int : 0; char bar; }; -static int arr3_offset[(offsetof(struct t3, bar) == 1) ? 0 : -1]; -static int arr3_sizeof[(sizeof(struct t3) == 2) ? 0 : -1]; +static int arr3_offset[(offsetof(struct t3, bar) == 4) ? 0 : -1]; +static int arr3_sizeof[(sizeof(struct t3) == 8) ? 0 : -1]; struct t4 { @@ -35,8 +39,8 @@ struct t4 long : 0; char bar; }; -static int arr4_offset[(offsetof(struct t4, bar) == 1) ? 0 : -1]; -static int arr4_sizeof[(sizeof(struct t4) == 2) ? 0 : -1]; +static int arr4_offset[(offsetof(struct t4, bar) == 4) ? 0 : -1]; +static int arr4_sizeof[(sizeof(struct t4) == 8) ? 0 : -1]; struct t5 { @@ -44,8 +48,8 @@ struct t5 long long : 0; char bar; }; -static int arr5_offset[(offsetof(struct t5, bar) == 1) ? 0 : -1]; -static int arr5_sizeof[(sizeof(struct t5) == 2) ? 0 : -1]; +static int arr5_offset[(offsetof(struct t5, bar) == 4) ? 0 : -1]; +static int arr5_sizeof[(sizeof(struct t5) == 8) ? 0 : -1]; struct t6 { @@ -109,6 +113,17 @@ struct t11 static int arr11_offset[(offsetof(struct t11, bar2) == 1) ? 0 : -1]; static int arr11_sizeof[(sizeof(struct t11) == 2) ? 0 : -1]; +struct t12 +{ + int foo : 1; + char : 0; + long long : 0; + char : 0; + char bar; +}; +static int arr12_offset[(offsetof(struct t12, bar) == 4) ? 0 : -1]; +static int arr12_sizeof[(sizeof(struct t12) == 8) ? 0 : -1]; + int main() { return 0; } |