[cfe-commits] r149161 - /cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
Douglas Gregor
dgregor at apple.com
Fri Jan 27 16:53:29 PST 2012
Author: dgregor
Date: Fri Jan 27 18:53:29 2012
New Revision: 149161
URL: http://llvm.org/viewvc/llvm-project?rev=149161&view=rev
Log:
Allow the external AST source to provide a layout without specifying
the alignment (because it's not encoded in DWARF). In this case, make
an educated guess at the alignment.
Modified:
cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=149161&r1=149160&r2=149161&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Fri Jan 27 18:53:29 2012
@@ -561,6 +561,10 @@
/// \brief Whether the external AST source has provided a layout for this
/// record.
unsigned ExternalLayout : 1;
+
+ /// \brief Whether we need to infer alignment, even when we have an
+ /// externally-provided layout.
+ unsigned InferAlignment : 1;
/// Packed - Whether the record is packed or not.
unsigned Packed : 1;
@@ -641,8 +645,8 @@
EmptySubobjectMap *EmptySubobjects)
: Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()),
- ExternalLayout(false), Packed(false), IsUnion(false),
- IsMac68kAlign(false), IsMsStruct(false),
+ ExternalLayout(false), InferAlignment(false),
+ Packed(false), IsUnion(false), IsMac68kAlign(false), IsMsStruct(false),
UnfilledBitsInLastByte(0), MaxFieldAlignment(CharUnits::Zero()),
DataSize(0), NonVirtualSize(CharUnits::Zero()),
NonVirtualAlignment(CharUnits::One()),
@@ -747,6 +751,14 @@
UpdateAlignment(NewAlignment, NewAlignment);
}
+ /// \brief Retrieve the externally-supplied field offset for the given
+ /// field.
+ ///
+ /// \param Field The field whose offset is being queried.
+ /// \param ComputedOffset The offset that we've computed for this field.
+ uint64_t updateExternalFieldOffset(const FieldDecl *Field,
+ uint64_t ComputedOffset);
+
void CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset,
uint64_t UnpackedOffset, unsigned UnpackedAlign,
bool isPacked, const FieldDecl *D);
@@ -1416,8 +1428,13 @@
// Update based on external alignment.
if (ExternalLayout) {
- Alignment = Context.toCharUnitsFromBits(ExternalAlign);
- UnpackedAlignment = Alignment;
+ if (ExternalAlign > 0) {
+ Alignment = Context.toCharUnitsFromBits(ExternalAlign);
+ UnpackedAlignment = Alignment;
+ } else {
+ // The external source didn't have alignment information; infer it.
+ InferAlignment = true;
+ }
}
}
}
@@ -1712,12 +1729,6 @@
uint64_t TypeSize = FieldInfo.first;
unsigned FieldAlign = FieldInfo.second;
- if (ExternalLayout) {
- assert(ExternalFieldOffsets.find(D) != ExternalFieldOffsets.end() &&
- "Field does not have an external offset");
- FieldOffset = ExternalFieldOffsets[D];
- }
-
// This check is needed for 'long long' in -m32 mode.
if (IsMsStruct && (TypeSize > FieldAlign) &&
(Context.hasSameType(D->getType(),
@@ -1778,19 +1789,17 @@
UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
}
- if (!ExternalLayout) {
- // Check if we need to add padding to give the field the correct alignment.
- if (FieldSize == 0 ||
- (MaxFieldAlignment.isZero() &&
- (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize))
- FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
-
- if (FieldSize == 0 ||
- (MaxFieldAlignment.isZero() &&
- (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize))
- UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
- UnpackedFieldAlign);
- }
+ // Check if we need to add padding to give the field the correct alignment.
+ if (FieldSize == 0 ||
+ (MaxFieldAlignment.isZero() &&
+ (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize))
+ FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
+
+ if (FieldSize == 0 ||
+ (MaxFieldAlignment.isZero() &&
+ (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize))
+ UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
+ UnpackedFieldAlign);
// Padding members don't affect overall alignment, unless zero length bitfield
// alignment is enabled.
@@ -1800,6 +1809,9 @@
if (!IsMsStruct)
ZeroLengthBitfield = 0;
+ if (ExternalLayout)
+ FieldOffset = updateExternalFieldOffset(D, FieldOffset);
+
// Place this field at the current location.
FieldOffsets.push_back(FieldOffset);
@@ -1844,13 +1856,6 @@
CharUnits FieldSize;
CharUnits FieldAlign;
- if (ExternalLayout) {
- assert(ExternalFieldOffsets.find(D) != ExternalFieldOffsets.end() &&
- "Field does not have an external offset");
- FieldOffset = Context.toCharUnitsFromBits(ExternalFieldOffsets[D]);
- }
-
-
if (D->getType()->isIncompleteArrayType()) {
// This is a flexible array member; we can't directly
// query getTypeInfo about these, so we figure it out here.
@@ -1928,12 +1933,22 @@
UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
}
- if (!ExternalLayout) {
- // Round up the current record size to the field's alignment boundary.
- FieldOffset = FieldOffset.RoundUpToAlignment(FieldAlign);
- UnpackedFieldOffset =
- UnpackedFieldOffset.RoundUpToAlignment(UnpackedFieldAlign);
-
+ // Round up the current record size to the field's alignment boundary.
+ FieldOffset = FieldOffset.RoundUpToAlignment(FieldAlign);
+ UnpackedFieldOffset =
+ UnpackedFieldOffset.RoundUpToAlignment(UnpackedFieldAlign);
+
+ if (ExternalLayout) {
+ FieldOffset = Context.toCharUnitsFromBits(
+ updateExternalFieldOffset(D, Context.toBits(FieldOffset)));
+
+ if (!IsUnion && EmptySubobjects) {
+ // Record the fact that we're placing a field at this offset.
+ bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
+ (void)Allowed;
+ assert(Allowed && "Externally-placed field cannot be placed here");
+ }
+ } else {
if (!IsUnion && EmptySubobjects) {
// Check if we can place the field at this offset.
while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
@@ -1941,11 +1956,6 @@
FieldOffset += FieldAlign;
}
}
- } else if (!IsUnion && EmptySubobjects) {
- // Record the fact that we're placing a field at this offset.
- bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
- (void)Allowed;
- assert(Allowed && "Externally-placed field cannot be placed here");
}
// Place this field at the current location.
@@ -1971,6 +1981,11 @@
}
void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
+ if (ExternalLayout) {
+ setSize(ExternalSize);
+ return;
+ }
+
// In C++, records cannot be of size 0.
if (Context.getLangOptions().CPlusPlus && getSizeInBits() == 0) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
@@ -2027,8 +2042,8 @@
void RecordLayoutBuilder::UpdateAlignment(CharUnits NewAlignment,
CharUnits UnpackedNewAlignment) {
// The alignment is not modified when using 'mac68k' alignment or when
- // we have an externally-supplied layout.
- if (IsMac68kAlign || ExternalLayout)
+ // we have an externally-supplied layout that also provides overall alignment.
+ if (IsMac68kAlign || (ExternalLayout && !InferAlignment))
return;
if (NewAlignment > Alignment) {
@@ -2044,6 +2059,25 @@
}
}
+uint64_t
+RecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field,
+ uint64_t ComputedOffset) {
+ assert(ExternalFieldOffsets.find(Field) != ExternalFieldOffsets.end() &&
+ "Field does not have an external offset");
+
+ uint64_t ExternalFieldOffset = ExternalFieldOffsets[Field];
+
+ if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
+ // The externally-supplied field offset is before the field offset we
+ // computed. Assume that the structure is packed.
+ Alignment = CharUnits::fromQuantity(1);
+ InferAlignment = false;
+ }
+
+ // Use the externally-supplied field offset.
+ return ExternalFieldOffset;
+}
+
void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
uint64_t UnpaddedOffset,
uint64_t UnpackedOffset,
More information about the cfe-commits
mailing list