Add a new PrimaryBaseInfo struct that combines the record decl of a primary base with whether it's virtual or not.

llvm-svn: 90018
This commit is contained in:
Anders Carlsson 2009-11-27 22:05:05 +00:00
parent f942ee0297
commit 03ff379911
3 changed files with 68 additions and 47 deletions

View File

@ -47,6 +47,23 @@ class ASTRecordLayout {
// FieldCount - Number of fields.
unsigned FieldCount;
public:
/// PrimaryBaseInfo - Contains info about a primary base.
struct PrimaryBaseInfo {
PrimaryBaseInfo() : Base(0), IsVirtual(false) {}
PrimaryBaseInfo(const CXXRecordDecl *Base, bool IsVirtual)
: Base(Base), IsVirtual(IsVirtual) {}
/// Base - The primary base.
const CXXRecordDecl *Base;
/// IsVirtual - Whether the primary base is virtual or not.
bool IsVirtual;
};
private:
/// CXXRecordLayoutInfo - Contains C++ specific layout information.
struct CXXRecordLayoutInfo {
/// NonVirtualSize - The non-virtual size (in bits) of an object, which is
/// the size of the object without virtual bases.
@ -56,11 +73,9 @@ class ASTRecordLayout {
/// which is the alignment of the object without virtual bases.
uint64_t NonVirtualAlign;
/// PrimaryBase - The primary base for our vtable.
const CXXRecordDecl *PrimaryBase;
/// PrimaryBase - Wether or not the primary base was a virtual base.
bool PrimaryBaseWasVirtual;
/// PrimaryBase - The primary base info for this record.
PrimaryBaseInfo PrimaryBase;
/// BaseOffsets - Contains a map from base classes to their offset.
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsets;
@ -92,7 +107,7 @@ class ASTRecordLayout {
ASTRecordLayout(uint64_t size, unsigned alignment, uint64_t datasize,
const uint64_t *fieldoffsets, unsigned fieldcount,
uint64_t nonvirtualsize, unsigned nonvirtualalign,
const CXXRecordDecl *PB, bool PBVirtual,
const PrimaryBaseInfo &PrimaryBase,
const std::pair<const CXXRecordDecl *, uint64_t> *bases,
unsigned numbases,
const std::pair<const CXXRecordDecl *, uint64_t> *vbases,
@ -105,8 +120,7 @@ class ASTRecordLayout {
FieldOffsets[i] = fieldoffsets[i];
}
CXXInfo->PrimaryBase = PB;
CXXInfo->PrimaryBaseWasVirtual = PBVirtual;
CXXInfo->PrimaryBase = PrimaryBase;
CXXInfo->NonVirtualSize = nonvirtualsize;
CXXInfo->NonVirtualAlign = nonvirtualalign;
for (unsigned i = 0; i != numbases; ++i)
@ -162,17 +176,21 @@ public:
return CXXInfo->NonVirtualAlign;
}
/// getPrimaryBase - Get the primary base.
const CXXRecordDecl *getPrimaryBase() const {
/// getPrimaryBaseInfo - Get the primary base info.
const PrimaryBaseInfo &getPrimaryBaseInfo() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->PrimaryBase;
}
/// getPrimaryBaseWasVirtual - Indicates if the primary base was virtual.
bool getPrimaryBaseWasVirtual() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->PrimaryBaseWasVirtual;
// FIXME: Migrate off of this function and use getPrimaryBaseInfo directly.
const CXXRecordDecl *getPrimaryBase() const {
return getPrimaryBaseInfo().Base;
}
// FIXME: Migrate off of this function and use getPrimaryBaseInfo directly.
bool getPrimaryBaseWasVirtual() const {
return getPrimaryBaseInfo().IsVirtual;
}
/// getBaseClassOffset - Get the offset, in bits, for the given base class.

View File

@ -14,7 +14,6 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/TargetInfo.h"
#include <llvm/ADT/SmallSet.h>
#include <llvm/Support/MathExtras.h>
@ -24,7 +23,7 @@ using namespace clang;
ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx)
: Ctx(Ctx), Size(0), Alignment(8), Packed(false), UnfilledBitsInLastByte(0),
MaxFieldAlignment(0), DataSize(0), IsUnion(false), NonVirtualSize(0),
NonVirtualAlignment(8), PrimaryBase(0), PrimaryBaseWasVirtual(false) {}
NonVirtualAlignment(8) { }
/// LayoutVtable - Lay out the vtable and set PrimaryBase.
void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) {
@ -34,7 +33,7 @@ void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) {
}
SelectPrimaryBase(RD);
if (PrimaryBase == 0) {
if (!PrimaryBase.Base) {
int AS = 0;
UpdateAlignment(Ctx.Target.getPointerAlign(AS));
Size += Ctx.Target.getPointerWidth(AS);
@ -52,7 +51,7 @@ ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
// Skip the PrimaryBase here, as it is laid down first.
if (Base != PrimaryBase || PrimaryBaseWasVirtual)
if (Base != PrimaryBase.Base || PrimaryBase.IsVirtual)
LayoutBaseNonVirtually(Base, false);
}
}
@ -74,12 +73,13 @@ bool ASTRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const {
}
void ASTRecordLayoutBuilder::IdentifyPrimaryBases(const CXXRecordDecl *RD) {
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
const ASTRecordLayout::PrimaryBaseInfo &BaseInfo =
Ctx.getASTRecordLayout(RD).getPrimaryBaseInfo();
// If the record has a primary base class that is virtual, add it to the set
// of primary bases.
if (Layout.getPrimaryBaseWasVirtual())
IndirectPrimaryBases.insert(Layout.getPrimaryBase());
if (BaseInfo.IsVirtual)
IndirectPrimaryBases.insert(BaseInfo.Base);
// Now traverse all bases and find primary bases for them.
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
@ -107,7 +107,7 @@ ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD,
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (!i->isVirtual()) {
SelectPrimaryVBase(Base, FirstPrimary);
if (PrimaryBase)
if (PrimaryBase.Base)
return;
continue;
}
@ -115,7 +115,7 @@ ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD,
if (FirstPrimary==0)
FirstPrimary = Base;
if (!IndirectPrimaryBases.count(Base)) {
setPrimaryBase(Base, true);
setPrimaryBase(Base, /*IsVirtual=*/true);
return;
}
}
@ -141,14 +141,17 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
// base class, if one exists.
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
if (!i->isVirtual()) {
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (Base->isDynamicClass()) {
// We found it.
setPrimaryBase(Base, false);
return;
}
// Ignore virtual bases.
if (i->isVirtual())
continue;
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (Base->isDynamicClass()) {
// We found it.
PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base, /*IsVirtual=*/false);
return;
}
}
@ -166,8 +169,8 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
// Otherwise if is the first nearly empty virtual base, if one exists,
// otherwise there is no primary base class.
if (!PrimaryBase)
setPrimaryBase(FirstPrimary, true);
if (!PrimaryBase.Base)
setPrimaryBase(FirstPrimary, /*IsVirtual=*/true);
}
void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) {
@ -232,9 +235,10 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *Class,
}
if (Base->getNumVBases()) {
const ASTRecordLayout &L = Ctx.getASTRecordLayout(Base);
const CXXRecordDecl *PB = L.getPrimaryBase();
LayoutVirtualBases(Class, Base, PB, BaseOffset, mark, IndirectPrimary);
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Base);
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBaseInfo().Base;
LayoutVirtualBases(Class, Base, PrimaryBase, BaseOffset, mark,
IndirectPrimary);
}
}
}
@ -455,10 +459,10 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
if (RD) {
LayoutVtable(RD);
// PrimaryBase goes first.
if (PrimaryBase) {
if (PrimaryBaseWasVirtual)
IndirectPrimaryBases.insert(PrimaryBase);
LayoutBaseNonVirtually(PrimaryBase, PrimaryBaseWasVirtual);
if (PrimaryBase.Base) {
if (PrimaryBase.IsVirtual)
IndirectPrimaryBases.insert(PrimaryBase.Base);
LayoutBaseNonVirtually(PrimaryBase.Base, PrimaryBase.IsVirtual);
}
LayoutNonVirtualBases(RD);
}
@ -470,7 +474,7 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
if (RD) {
llvm::SmallSet<const CXXRecordDecl*, 32> mark;
LayoutVirtualBases(RD, RD, PrimaryBase, 0, mark, IndirectPrimaryBases);
LayoutVirtualBases(RD, RD, PrimaryBase.Base, 0, mark, IndirectPrimaryBases);
}
// Finally, round the size of the total struct up to the alignment of the
@ -687,7 +691,6 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
NonVirtualSize,
Builder.NonVirtualAlignment,
Builder.PrimaryBase,
Builder.PrimaryBaseWasVirtual,
Builder.Bases.data(),
Builder.Bases.size(),
Builder.VBases.data(),

View File

@ -10,6 +10,7 @@
#ifndef LLVM_CLANG_AST_RECORDLAYOUTBUILDER_H
#define LLVM_CLANG_AST_RECORDLAYOUTBUILDER_H
#include "clang/AST/RecordLayout.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/System/DataTypes.h"
@ -54,8 +55,8 @@ class ASTRecordLayoutBuilder {
uint64_t NonVirtualSize;
unsigned NonVirtualAlignment;
const CXXRecordDecl *PrimaryBase;
bool PrimaryBaseWasVirtual;
ASTRecordLayout::PrimaryBaseInfo PrimaryBase;
typedef llvm::SmallVector<std::pair<const CXXRecordDecl *,
uint64_t>, 4> BaseOffsetsTy;
@ -94,9 +95,8 @@ class ASTRecordLayoutBuilder {
/// base class.
void IdentifyPrimaryBases(const CXXRecordDecl *RD);
void setPrimaryBase(const CXXRecordDecl *PB, bool Virtual) {
PrimaryBase = PB;
PrimaryBaseWasVirtual = Virtual;
void setPrimaryBase(const CXXRecordDecl *Base, bool IsVirtual) {
PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base, IsVirtual);
}
bool IsNearlyEmpty(const CXXRecordDecl *RD) const;