diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 41 | ||||
-rw-r--r-- | lib/Basic/TargetInfo.cpp | 2 | ||||
-rw-r--r-- | lib/Basic/Targets.cpp | 10 |
3 files changed, 42 insertions, 11 deletions
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. |