forked from OSchip/llvm-project
Add a field for C++ specific data to ASTRecordLayout. Use it to store the non-virtual size and alignment + base offsets.
llvm-svn: 77352
This commit is contained in:
parent
a399dfae19
commit
fc8cfa8b9f
|
@ -20,6 +20,7 @@ namespace clang {
|
|||
class ASTContext;
|
||||
class FieldDecl;
|
||||
class RecordDecl;
|
||||
class CXXRecordDecl;
|
||||
|
||||
/// ASTRecordLayout -
|
||||
/// This class contains layout information for one RecordDecl,
|
||||
|
@ -29,26 +30,78 @@ namespace clang {
|
|||
/// ObjCInterfaceDecl. FIXME - Find appropriate name.
|
||||
/// These objects are managed by ASTContext.
|
||||
class ASTRecordLayout {
|
||||
uint64_t Size; // Size of record in bits.
|
||||
uint64_t DataSize; // Size of record in bits without tail padding.
|
||||
/// Size - Size of record in bits.
|
||||
uint64_t Size;
|
||||
|
||||
/// DataSize - Size of record in bits without tail padding.
|
||||
uint64_t DataSize;
|
||||
|
||||
/// FieldOffsets - Array of field offsets in bits.
|
||||
uint64_t *FieldOffsets;
|
||||
unsigned Alignment; // Alignment of record in bits.
|
||||
unsigned FieldCount; // Number of fields
|
||||
|
||||
// Alignment - Alignment of record in bits.
|
||||
unsigned Alignment;
|
||||
|
||||
// FieldCount - Number of fields.
|
||||
unsigned FieldCount;
|
||||
|
||||
struct CXXRecordLayoutInfo {
|
||||
/// NonVirtualSize - The non-virtual size (in bits) of an object, which is
|
||||
/// the size of the object without virtual bases.
|
||||
uint64_t NonVirtualSize;
|
||||
|
||||
/// NonVirtualAlign - The non-virtual alignment (in bits) of an object,
|
||||
/// which is the alignment of the object without virtual bases.
|
||||
uint64_t NonVirtualAlign;
|
||||
|
||||
/// BaseOffsets - Contains a map from base classes to their offset.
|
||||
/// FIXME: Does it make sense to store offsets for virtual base classes
|
||||
/// here?
|
||||
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
|
||||
llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsets;
|
||||
};
|
||||
|
||||
/// CXXInfo - If the record layout is for a C++ record, this will have
|
||||
/// C++ specific information about the record.
|
||||
CXXRecordLayoutInfo *CXXInfo;
|
||||
|
||||
friend class ASTContext;
|
||||
friend class ASTRecordLayoutBuilder;
|
||||
|
||||
ASTRecordLayout(uint64_t size, unsigned alignment, unsigned datasize,
|
||||
const uint64_t *fieldoffsets, unsigned fieldcount)
|
||||
: Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment),
|
||||
FieldCount(fieldcount) {
|
||||
FieldCount(fieldcount), CXXInfo(0) {
|
||||
if (FieldCount > 0) {
|
||||
FieldOffsets = new uint64_t[FieldCount];
|
||||
for (unsigned i = 0; i < FieldCount; ++i)
|
||||
FieldOffsets[i] = fieldoffsets[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Constructor for C++ records.
|
||||
ASTRecordLayout(uint64_t size, unsigned alignment, unsigned datasize,
|
||||
const uint64_t *fieldoffsets, unsigned fieldcount,
|
||||
uint64_t nonvirtualsize, unsigned nonvirtualalign,
|
||||
const CXXRecordDecl **bases, const uint64_t *baseoffsets,
|
||||
unsigned basecount)
|
||||
: Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment),
|
||||
FieldCount(fieldcount), CXXInfo(new CXXRecordLayoutInfo) {
|
||||
if (FieldCount > 0) {
|
||||
FieldOffsets = new uint64_t[FieldCount];
|
||||
for (unsigned i = 0; i < FieldCount; ++i)
|
||||
FieldOffsets[i] = fieldoffsets[i];
|
||||
}
|
||||
|
||||
CXXInfo->NonVirtualSize = nonvirtualsize;
|
||||
CXXInfo->NonVirtualAlign = nonvirtualalign;
|
||||
for (unsigned i = 0; i != basecount; ++i)
|
||||
CXXInfo->BaseOffsets[bases[i]] = baseoffsets[i];
|
||||
}
|
||||
|
||||
~ASTRecordLayout() {
|
||||
delete [] FieldOffsets;
|
||||
delete CXXInfo;
|
||||
}
|
||||
|
||||
ASTRecordLayout(const ASTRecordLayout&); // DO NOT IMPLEMENT
|
||||
|
@ -76,6 +129,30 @@ public:
|
|||
uint64_t getDataSize() const {
|
||||
return DataSize;
|
||||
}
|
||||
|
||||
/// getNonVirtualSize - Get the non-virtual size (in bits) of an object,
|
||||
/// which is the size of the object without virtual bases.
|
||||
uint64_t getNonVirtualSize() const {
|
||||
assert(CXXInfo && "Record layout does not have C++ specific info!");
|
||||
|
||||
return CXXInfo->NonVirtualSize;
|
||||
}
|
||||
|
||||
/// getNonVirtualSize - Get the non-virtual alignment (in bits) of an object,
|
||||
/// which is the alignment of the object without virtual bases.
|
||||
unsigned getNonVirtualAlign() const {
|
||||
assert(CXXInfo && "Record layout does not have C++ specific info!");
|
||||
|
||||
return CXXInfo->NonVirtualAlign;
|
||||
}
|
||||
|
||||
/// getBaseClassOffset - Get the offset, in bits, for the given base class.
|
||||
uint64_t getBaseClassOffset(const CXXRecordDecl *Base) const {
|
||||
assert(CXXInfo && "Record layout does not have C++ specific info!");
|
||||
assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");
|
||||
|
||||
return CXXInfo->BaseOffsets[Base];
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
@ -22,7 +22,7 @@ using namespace clang;
|
|||
|
||||
ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx)
|
||||
: Ctx(Ctx), Size(0), Alignment(8), StructPacking(0), NextOffset(0),
|
||||
IsUnion(false) {}
|
||||
IsUnion(false), NonVirtualSize(0), NonVirtualAlignment(8) {}
|
||||
|
||||
void
|
||||
ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
|
||||
|
@ -44,15 +44,16 @@ void ASTRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *RD) {
|
|||
assert(BaseInfo.getDataSize() > 0 &&
|
||||
"FIXME: Handle empty classes.");
|
||||
|
||||
// FIXME: Should get the non-virtual alignment of the base.
|
||||
unsigned BaseAlign = BaseInfo.getAlignment();
|
||||
|
||||
// FIXME: Should get the non-virtual size of the base.
|
||||
uint64_t BaseSize = BaseInfo.getDataSize();
|
||||
unsigned BaseAlign = BaseInfo.getNonVirtualAlign();
|
||||
uint64_t BaseSize = BaseInfo.getNonVirtualSize();
|
||||
|
||||
// Round up the current record size to the base's alignment boundary.
|
||||
Size = (Size + (BaseAlign-1)) & ~(BaseAlign-1);
|
||||
|
||||
// Add base class offsets.
|
||||
Bases.push_back(RD);
|
||||
BaseOffsets.push_back(Size);
|
||||
|
||||
// Non-virtual base class has offset too.
|
||||
FieldOffsets.push_back(Size);
|
||||
|
||||
|
@ -81,6 +82,9 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
|
|||
|
||||
LayoutFields(D);
|
||||
|
||||
NonVirtualSize = Size;
|
||||
NonVirtualAlignment = Alignment;
|
||||
|
||||
// Finally, round the size of the total struct up to the alignment of the
|
||||
// struct itself.
|
||||
FinishLayout();
|
||||
|
@ -238,22 +242,33 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
|
|||
|
||||
Builder.Layout(D);
|
||||
|
||||
bool IsPODForThePurposeOfLayout;
|
||||
if (!Ctx.getLangOptions().CPlusPlus) {
|
||||
// In C, all record types are POD.
|
||||
IsPODForThePurposeOfLayout = true;
|
||||
} else {
|
||||
// FIXME: This is not always correct. See the part about bitfields at
|
||||
// http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
|
||||
IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD();
|
||||
}
|
||||
if (!isa<CXXRecordDecl>(D))
|
||||
return new ASTRecordLayout(Builder.Size, Builder.Alignment, Builder.Size,
|
||||
Builder.FieldOffsets.data(),
|
||||
Builder.FieldOffsets.size());
|
||||
|
||||
// FIXME: This is not always correct. See the part about bitfields at
|
||||
// http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
|
||||
// FIXME: IsPODForThePurposeOfLayout should be stored in the record layout.
|
||||
bool IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD();
|
||||
|
||||
assert(Builder.Bases.size() == Builder.BaseOffsets.size() &&
|
||||
"Base offsets vector must be same size as bases vector!");
|
||||
|
||||
// FIXME: This should be done in FinalizeLayout.
|
||||
uint64_t DataSize =
|
||||
IsPODForThePurposeOfLayout ? Builder.Size : Builder.NextOffset;
|
||||
uint64_t NonVirtualSize =
|
||||
IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize;
|
||||
|
||||
return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize,
|
||||
Builder.FieldOffsets.data(),
|
||||
Builder.FieldOffsets.size());
|
||||
Builder.FieldOffsets.size(),
|
||||
NonVirtualSize,
|
||||
Builder.NonVirtualAlignment,
|
||||
Builder.Bases.data(),
|
||||
Builder.BaseOffsets.data(),
|
||||
Builder.Bases.size());
|
||||
}
|
||||
|
||||
const ASTRecordLayout *
|
||||
|
|
|
@ -26,13 +26,18 @@ class ASTRecordLayoutBuilder {
|
|||
ASTContext &Ctx;
|
||||
|
||||
uint64_t Size;
|
||||
uint64_t Alignment;
|
||||
unsigned Alignment;
|
||||
llvm::SmallVector<uint64_t, 16> FieldOffsets;
|
||||
|
||||
unsigned StructPacking;
|
||||
unsigned NextOffset;
|
||||
bool IsUnion;
|
||||
|
||||
uint64_t NonVirtualSize;
|
||||
unsigned NonVirtualAlignment;
|
||||
llvm::SmallVector<const CXXRecordDecl *, 4> Bases;
|
||||
llvm::SmallVector<uint64_t, 4> BaseOffsets;
|
||||
|
||||
ASTRecordLayoutBuilder(ASTContext &Ctx);
|
||||
|
||||
void Layout(const RecordDecl *D);
|
||||
|
|
Loading…
Reference in New Issue