[cfe-commits] r78490 - in /cfe/trunk/lib: AST/RecordLayoutBuilder.cpp AST/RecordLayoutBuilder.h CodeGen/CGRecordLayoutBuilder.cpp CodeGen/CGRecordLayoutBuilder.h
Anders Carlsson
andersca at mac.com
Sat Aug 8 12:38:24 PDT 2009
Author: andersca
Date: Sat Aug 8 14:38:24 2009
New Revision: 78490
URL: http://llvm.org/viewvc/llvm-project?rev=78490&view=rev
Log:
Take #pragma pack into account when laying out structs. Fixes rdar://problem/7095436.
Modified:
cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
cfe/trunk/lib/AST/RecordLayoutBuilder.h
cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.h
Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=78490&r1=78489&r2=78490&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Sat Aug 8 14:38:24 2009
@@ -22,8 +22,8 @@
using namespace clang;
ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx)
- : Ctx(Ctx), Size(0), Alignment(8), StructPacking(0), NextOffset(0),
- IsUnion(false), NonVirtualSize(0), NonVirtualAlignment(8) {}
+ : Ctx(Ctx), Size(0), Alignment(8), Packed(false), MaxFieldAlignment(0),
+ NextOffset(0), IsUnion(false), NonVirtualSize(0), NonVirtualAlignment(8) {}
/// LayoutVtable - Lay out the vtable and set PrimaryBase.
void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) {
@@ -198,10 +198,11 @@
void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
IsUnion = D->isUnion();
- if (D->hasAttr<PackedAttr>())
- StructPacking = 1;
+ Packed = D->hasAttr<PackedAttr>();
+
+ // The #pragma pack attribute specifies the maximum field alignment.
if (const PragmaPackAttr *PPA = D->getAttr<PragmaPackAttr>())
- StructPacking = PPA->getAlignment();
+ MaxFieldAlignment = PPA->getAlignment();
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
UpdateAlignment(AA->getAlignment());
@@ -242,8 +243,11 @@
NextOffset = Size;
}
- if (D->hasAttr<PackedAttr>())
- StructPacking = 1;
+ Packed = D->hasAttr<PackedAttr>();
+
+ // The #pragma pack attribute specifies the maximum field alignment.
+ if (const PragmaPackAttr *PPA = D->getAttr<PragmaPackAttr>())
+ MaxFieldAlignment = PPA->getAlignment();
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
UpdateAlignment(AA->getAlignment());
@@ -268,15 +272,12 @@
}
void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) {
- unsigned FieldPacking = StructPacking;
+ bool FieldPacked = Packed;
uint64_t FieldOffset = IsUnion ? 0 : Size;
uint64_t FieldSize;
unsigned FieldAlign;
- // FIXME: Should this override struct packing? Probably we want to
- // take the minimum?
- if (D->hasAttr<PackedAttr>())
- FieldPacking = 1;
+ FieldPacked |= D->hasAttr<PackedAttr>();
if (const Expr *BitWidthExpr = D->getBitWidth()) {
// TODO: Need to check this algorithm on other targets!
@@ -285,18 +286,17 @@
std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType());
uint64_t TypeSize = FieldInfo.first;
-
- // Determine the alignment of this bitfield. The packing
- // attributes define a maximum and the alignment attribute defines
- // a minimum.
- // FIXME: What is the right behavior when the specified alignment
- // is smaller than the specified packing?
+
FieldAlign = FieldInfo.second;
- if (FieldPacking)
- FieldAlign = std::min(FieldAlign, FieldPacking);
+
+ if (FieldPacked)
+ FieldAlign = 1;
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
FieldAlign = std::max(FieldAlign, AA->getAlignment());
-
+ // 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)
@@ -324,17 +324,13 @@
FieldAlign = FieldInfo.second;
}
- // Determine the alignment of this bitfield. The packing
- // attributes define a maximum and the alignment attribute defines
- // a minimum. Additionally, the packing alignment must be at least
- // a byte for non-bitfields.
- //
- // FIXME: What is the right behavior when the specified alignment
- // is smaller than the specified packing?
- if (FieldPacking)
- FieldAlign = std::min(FieldAlign, std::max(8U, FieldPacking));
+ if (FieldPacked)
+ FieldAlign = 8;
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
FieldAlign = std::max(FieldAlign, AA->getAlignment());
+ // 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 = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.h?rev=78490&r1=78489&r2=78490&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.h (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.h Sat Aug 8 14:38:24 2009
@@ -30,7 +30,8 @@
unsigned Alignment;
llvm::SmallVector<uint64_t, 16> FieldOffsets;
- unsigned StructPacking;
+ bool Packed;
+ unsigned MaxFieldAlignment;
uint64_t NextOffset;
bool IsUnion;
Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp?rev=78490&r1=78489&r2=78490&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp Sat Aug 8 14:38:24 2009
@@ -27,13 +27,15 @@
using namespace CodeGen;
void CGRecordLayoutBuilder::Layout(const RecordDecl *D) {
+ Alignment = Types.getContext().getASTRecordLayout(D).getAlignment() / 8;
+
if (D->isUnion()) {
LayoutUnion(D);
return;
}
Packed = D->hasAttr<PackedAttr>();
-
+
if (LayoutFields(D))
return;
@@ -115,6 +117,21 @@
const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType());
unsigned TypeAlignment = getTypeAlignment(Ty);
+ // If the type alignment is larger then the struct alignment, we must use
+ // a packed struct.
+ if (TypeAlignment > Alignment) {
+ assert(!Packed && "Alignment is wrong even with packed struct!");
+ return false;
+ }
+
+ if (const RecordType *RT = D->getType()->getAs<RecordType>()) {
+ const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
+ if (const PragmaPackAttr *PPA = RD->getAttr<PragmaPackAttr>()) {
+ if (PPA->getAlignment() != TypeAlignment * 8 && !Packed)
+ return false;
+ }
+ }
+
// Round up the field offset to the alignment of the field type.
uint64_t AlignedNextFieldOffsetInBytes =
llvm::RoundUpToAlignment(NextFieldOffsetInBytes, TypeAlignment);
@@ -193,6 +210,7 @@
bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
assert(!D->isUnion() && "Can't call LayoutFields on a union!");
+ assert(Alignment && "Did not set alignment!");
const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D);
Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.h?rev=78490&r1=78489&r2=78490&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.h (original)
+++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.h Sat Aug 8 14:38:24 2009
@@ -36,6 +36,9 @@
/// Packed - Whether the resulting LLVM struct will be packed or not.
bool Packed;
+ /// Alignment - Contains the alignment of the RecordDecl.
+ unsigned Alignment;
+
/// AlignmentAsLLVMStruct - Will contain the maximum alignment of all the
/// LLVM types.
unsigned AlignmentAsLLVMStruct;
@@ -69,7 +72,7 @@
llvm::SmallVector<LLVMBitFieldInfo, 16> LLVMBitFields;
CGRecordLayoutBuilder(CodeGenTypes &Types)
- : Types(Types), Packed(false), AlignmentAsLLVMStruct(1)
+ : Types(Types), Packed(false), Alignment(0), AlignmentAsLLVMStruct(1)
, BitsAvailableInLastField(0), NextFieldOffsetInBytes(0) { }
/// Layout - Will layout a RecordDecl.
More information about the cfe-commits
mailing list