From 072094407d926cb9253171e022912c92a6498ae5 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Sun, 22 Nov 2009 17:37:31 +0000 Subject: [PATCH] Move bit-field layout out into a separate function. No functionality change. llvm-svn: 89604 --- clang/lib/AST/RecordLayoutBuilder.cpp | 165 ++++++++++++++------------ clang/lib/AST/RecordLayoutBuilder.h | 1 + 2 files changed, 92 insertions(+), 74 deletions(-) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index c084ba6f5152..8e4e160746e0 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -519,86 +519,103 @@ void ASTRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { LayoutField(*Field); } +void ASTRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { + bool FieldPacked = Packed || D->hasAttr(); + uint64_t FieldOffset = IsUnion ? 0 : DataSize; + uint64_t FieldSize = D->getBitWidth()->EvaluateAsInt(Ctx).getZExtValue(); + + std::pair FieldInfo = Ctx.getTypeInfo(D->getType()); + uint64_t TypeSize = FieldInfo.first; + unsigned FieldAlign = FieldInfo.second; + + if (FieldPacked) + FieldAlign = 1; + if (const AlignedAttr *AA = D->getAttr()) + FieldAlign = std::max(FieldAlign, AA->getMaxAlignment()); + + // The maximum field alignment overrides the aligned attribute. + if (MaxFieldAlignment) + FieldAlign = std::min(FieldAlign, MaxFieldAlignment); + + // Check if we need to add padding to give the field the correct + // alignment. + if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize) + FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1); + + // Padding members don't affect overall alignment + if (!D->getIdentifier()) + FieldAlign = 1; + + // Place this field at the current location. + FieldOffsets.push_back(FieldOffset); + + // Reserve space for this field. + if (IsUnion) + Size = std::max(Size, FieldSize); + else + Size = FieldOffset + FieldSize; + + // Update the data size. + DataSize = Size; + + // Remember max struct/class alignment. + UpdateAlignment(FieldAlign); +} + void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) { - bool FieldPacked = Packed; + if (D->isBitField()) { + LayoutBitField(D); + return; + } + + bool FieldPacked = Packed || D->hasAttr(); uint64_t FieldOffset = IsUnion ? 0 : DataSize; uint64_t FieldSize; unsigned FieldAlign; - - FieldPacked |= D->hasAttr(); - - if (const Expr *BitWidthExpr = D->getBitWidth()) { - // TODO: Need to check this algorithm on other targets! - // (tested on Linux-X86) - FieldSize = BitWidthExpr->EvaluateAsInt(Ctx).getZExtValue(); - - std::pair FieldInfo = Ctx.getTypeInfo(D->getType()); - uint64_t TypeSize = FieldInfo.first; - - FieldAlign = FieldInfo.second; - - if (FieldPacked) - FieldAlign = 1; - if (const AlignedAttr *AA = D->getAttr()) { - FieldAlign = std::max(FieldAlign, AA->getMaxAlignment()); - } - // The maximum field alignment overrides the aligned attribute. - if (MaxFieldAlignment) - FieldAlign = std::min(FieldAlign, MaxFieldAlignment); - - // Check if we need to add padding to give the field the correct - // alignment. - if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize) - FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1); - - // Padding members don't affect overall alignment - if (!D->getIdentifier()) - FieldAlign = 1; + + if (D->getType()->isIncompleteArrayType()) { + // This is a flexible array member; we can't directly + // query getTypeInfo about these, so we figure it out here. + // Flexible array members don't have any size, but they + // have to be aligned appropriately for their element type. + FieldSize = 0; + const ArrayType* ATy = Ctx.getAsArrayType(D->getType()); + FieldAlign = Ctx.getTypeAlign(ATy->getElementType()); + } else if (const ReferenceType *RT = D->getType()->getAs()) { + unsigned AS = RT->getPointeeType().getAddressSpace(); + FieldSize = Ctx.Target.getPointerWidth(AS); + FieldAlign = Ctx.Target.getPointerAlign(AS); } else { - if (D->getType()->isIncompleteArrayType()) { - // This is a flexible array member; we can't directly - // query getTypeInfo about these, so we figure it out here. - // Flexible array members don't have any size, but they - // have to be aligned appropriately for their element type. - FieldSize = 0; - const ArrayType* ATy = Ctx.getAsArrayType(D->getType()); - FieldAlign = Ctx.getTypeAlign(ATy->getElementType()); - } else if (const ReferenceType *RT = D->getType()->getAs()) { - unsigned AS = RT->getPointeeType().getAddressSpace(); - FieldSize = Ctx.Target.getPointerWidth(AS); - FieldAlign = Ctx.Target.getPointerAlign(AS); - } else { - std::pair FieldInfo = Ctx.getTypeInfo(D->getType()); - FieldSize = FieldInfo.first; - FieldAlign = FieldInfo.second; - } - - if (FieldPacked) - FieldAlign = 8; - if (const AlignedAttr *AA = D->getAttr()) { - FieldAlign = std::max(FieldAlign, AA->getMaxAlignment()); - } - // The maximum field alignment overrides the aligned attribute. - if (MaxFieldAlignment) - FieldAlign = std::min(FieldAlign, MaxFieldAlignment); - - // Round up the current record size to the field's alignment boundary. - FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); - - if (!IsUnion) { - while (true) { - // Check if we can place the field at this offset. - if (canPlaceFieldAtOffset(D, FieldOffset)) - break; - - // We couldn't place the field at the offset. Try again at a new offset. - FieldOffset += FieldAlign; - } - - UpdateEmptyClassOffsets(D, FieldOffset); - } + std::pair FieldInfo = Ctx.getTypeInfo(D->getType()); + FieldSize = FieldInfo.first; + FieldAlign = FieldInfo.second; } + if (FieldPacked) + FieldAlign = 8; + if (const AlignedAttr *AA = D->getAttr()) + FieldAlign = std::max(FieldAlign, AA->getMaxAlignment()); + + // The maximum field alignment overrides the aligned attribute. + if (MaxFieldAlignment) + FieldAlign = std::min(FieldAlign, MaxFieldAlignment); + + // Round up the current record size to the field's alignment boundary. + FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); + + if (!IsUnion) { + while (true) { + // Check if we can place the field at this offset. + if (canPlaceFieldAtOffset(D, FieldOffset)) + break; + + // We couldn't place the field at the offset. Try again at a new offset. + FieldOffset += FieldAlign; + } + + UpdateEmptyClassOffsets(D, FieldOffset); + } + // Place this field at the current location. FieldOffsets.push_back(FieldOffset); @@ -621,7 +638,7 @@ void ASTRecordLayoutBuilder::FinishLayout() { Size = 8; // Finally, round the size of the record up to the alignment of the // record itself. - Size = (Size + (Alignment-1)) & ~(Alignment-1); + Size = llvm::RoundUpToAlignment(Size, Alignment); } void ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) { diff --git a/clang/lib/AST/RecordLayoutBuilder.h b/clang/lib/AST/RecordLayoutBuilder.h index 077072343b1b..c738e31beb4c 100644 --- a/clang/lib/AST/RecordLayoutBuilder.h +++ b/clang/lib/AST/RecordLayoutBuilder.h @@ -74,6 +74,7 @@ class ASTRecordLayoutBuilder { void LayoutFields(const RecordDecl *D); void LayoutField(const FieldDecl *D); + void LayoutBitField(const FieldDecl *D); void SelectPrimaryBase(const CXXRecordDecl *RD); void SelectPrimaryVBase(const CXXRecordDecl *RD,