Migrate over to the record layout builder.

llvm-svn: 76338
This commit is contained in:
Anders Carlsson 2009-07-18 21:19:52 +00:00
parent c7082933e6
commit a4267a654b
3 changed files with 15 additions and 193 deletions

View File

@ -37,12 +37,6 @@ class ASTRecordLayout {
friend class ASTContext;
friend class ASTRecordLayoutBuilder;
ASTRecordLayout(uint64_t S = 0, unsigned A = 8)
: Size(S), NextOffset(S), Alignment(A), FieldCount(0) {}
~ASTRecordLayout() {
delete [] FieldOffsets;
}
ASTRecordLayout(uint64_t Size, unsigned Alignment,
unsigned nextoffset,
const uint64_t *fieldoffsets, unsigned fieldcount)
@ -54,37 +48,10 @@ class ASTRecordLayout {
FieldOffsets[i] = fieldoffsets[i];
}
}
/// Initialize record layout. N is the number of fields in this record.
void InitializeLayout(unsigned N) {
FieldCount = N;
FieldOffsets = new uint64_t[N];
~ASTRecordLayout() {
delete [] FieldOffsets;
}
/// Finalize record layout. Adjust record size based on the alignment.
void FinalizeLayout(bool ForceNonEmpty = false) {
// In C++, records cannot be of size 0.
if (ForceNonEmpty && Size == 0)
Size = 8;
// Finally, round the size of the record up to the alignment of the
// record itself.
Size = (Size + (Alignment-1)) & ~(Alignment-1);
}
void SetFieldOffset(unsigned FieldNo, uint64_t Offset) {
assert (FieldNo < FieldCount && "Invalid Field No");
FieldOffsets[FieldNo] = Offset;
}
void SetAlignment(unsigned A) { Alignment = A; }
/// LayoutField - Field layout. StructPacking is the specified
/// packing alignment (maximum alignment) in bits to use for the
/// structure, or 0 if no packing alignment is specified.
void LayoutField(const FieldDecl *FD, unsigned FieldNo,
bool IsUnion, unsigned StructPacking,
ASTContext &Context);
ASTRecordLayout(const ASTRecordLayout&); // DO NOT IMPLEMENT
void operator=(const ASTRecordLayout&); // DO NOT IMPLEMENT
public:

View File

@ -24,6 +24,8 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "RecordLayoutBuilder.h"
using namespace clang;
enum FloatingRank {
@ -726,102 +728,6 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) {
return ABIAlign;
}
/// LayoutField - Field layout.
void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
bool IsUnion, unsigned StructPacking,
ASTContext &Context) {
unsigned FieldPacking = StructPacking;
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 (const PackedAttr *PA = FD->getAttr<PackedAttr>())
FieldPacking = PA->getAlignment();
if (const Expr *BitWidthExpr = FD->getBitWidth()) {
// TODO: Need to check this algorithm on other targets!
// (tested on Linux-X86)
FieldSize = BitWidthExpr->EvaluateAsInt(Context).getZExtValue();
std::pair<uint64_t, unsigned> FieldInfo =
Context.getTypeInfo(FD->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 (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
FieldAlign = std::max(FieldAlign, AA->getAlignment());
// 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 (!FD->getIdentifier())
FieldAlign = 1;
} else {
if (FD->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 = Context.getAsArrayType(FD->getType());
FieldAlign = Context.getTypeAlign(ATy->getElementType());
} else if (const ReferenceType *RT = FD->getType()->getAsReferenceType()) {
unsigned AS = RT->getPointeeType().getAddressSpace();
FieldSize = Context.Target.getPointerWidth(AS);
FieldAlign = Context.Target.getPointerAlign(AS);
} else {
std::pair<uint64_t, unsigned> FieldInfo =
Context.getTypeInfo(FD->getType());
FieldSize = FieldInfo.first;
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 (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
FieldAlign = std::max(FieldAlign, AA->getAlignment());
// Round up the current record size to the field's alignment boundary.
FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
}
// Place this field at the current location.
FieldOffsets[FieldNo] = FieldOffset;
// Reserve space for this field.
if (IsUnion) {
Size = std::max(Size, FieldSize);
} else {
Size = FieldOffset + FieldSize;
}
// Remember the next available offset.
NextOffset = Size;
// Remember max struct/class alignment.
Alignment = std::max(Alignment, FieldAlign);
}
static void CollectLocalObjCIvars(ASTContext *Ctx,
const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<FieldDecl*> &Fields) {
@ -934,9 +840,9 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
if (const ASTRecordLayout *Entry = ObjCLayouts[Key])
return *Entry;
unsigned FieldCount = D->ivar_size();
// Add in synthesized ivar count if laying out an implementation.
if (Impl) {
unsigned FieldCount = D->ivar_size();
unsigned SynthCount = CountSynthesizedIvars(D);
FieldCount += SynthCount;
// If there aren't any sythesized ivars then reuse the interface
@ -947,40 +853,10 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
return getObjCLayout(D, 0);
}
ASTRecordLayout *NewEntry = NULL;
if (ObjCInterfaceDecl *SD = D->getSuperClass()) {
const ASTRecordLayout &SL = getASTObjCInterfaceLayout(SD);
unsigned Alignment = SL.getAlignment();
// We start laying out ivars not at the end of the superclass
// structure, but at the next byte following the last field.
uint64_t Size = llvm::RoundUpToAlignment(SL.NextOffset, 8);
ObjCLayouts[Key] = NewEntry = new ASTRecordLayout(Size, Alignment);
NewEntry->InitializeLayout(FieldCount);
} else {
ObjCLayouts[Key] = NewEntry = new ASTRecordLayout();
NewEntry->InitializeLayout(FieldCount);
}
unsigned StructPacking = 0;
if (const PackedAttr *PA = D->getAttr<PackedAttr>())
StructPacking = PA->getAlignment();
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
NewEntry->SetAlignment(std::max(NewEntry->getAlignment(),
AA->getAlignment()));
// Layout each ivar sequentially.
unsigned i = 0;
llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
ShallowCollectObjCIvars(D, Ivars, Impl);
for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
NewEntry->LayoutField(Ivars[k], i++, false, StructPacking, *this);
// Finally, round the size of the total struct up to the alignment of the
// struct itself.
NewEntry->FinalizeLayout();
const ASTRecordLayout *NewEntry =
ASTRecordLayoutBuilder::ComputeLayout(*this, D, Impl);
ObjCLayouts[Key] = NewEntry;
return *NewEntry;
}
@ -1005,34 +881,10 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
const ASTRecordLayout *&Entry = ASTRecordLayouts[D];
if (Entry) return *Entry;
// Allocate and assign into ASTRecordLayouts here. The "Entry" reference can
// be invalidated (dangle) if the ASTRecordLayouts hashtable is inserted into.
ASTRecordLayout *NewEntry = new ASTRecordLayout();
const ASTRecordLayout *NewEntry =
ASTRecordLayoutBuilder::ComputeLayout(*this, D);
Entry = NewEntry;
// FIXME: Avoid linear walk through the fields, if possible.
NewEntry->InitializeLayout(std::distance(D->field_begin(), D->field_end()));
bool IsUnion = D->isUnion();
unsigned StructPacking = 0;
if (const PackedAttr *PA = D->getAttr<PackedAttr>())
StructPacking = PA->getAlignment();
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
NewEntry->SetAlignment(std::max(NewEntry->getAlignment(),
AA->getAlignment()));
// Layout each field, for now, just sequentially, respecting alignment. In
// the future, this will need to be tweakable by targets.
unsigned FieldIdx = 0;
for (RecordDecl::field_iterator Field = D->field_begin(),
FieldEnd = D->field_end();
Field != FieldEnd; (void)++Field, ++FieldIdx)
NewEntry->LayoutField(*Field, FieldIdx, IsUnion, StructPacking, *this);
// Finally, round the size of the total struct up to the alignment of the
// struct itself.
NewEntry->FinalizeLayout(getLangOptions().CPlusPlus);
return *NewEntry;
}

View File

@ -38,6 +38,9 @@ class ASTRecordLayoutBuilder {
const ObjCImplementationDecl *Impl);
void LayoutField(const FieldDecl *D);
/// FinishLayout - Finalize record layout. Adjust record size based on the
/// alignment.
void FinishLayout();
void UpdateAlignment(unsigned NewAlignment);