Deconflate virtual base offsets from non-virtual base offsets.

Deconflate a virtual base primary from a non-virtual base.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78971 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mike Stump 2009-08-14 01:44:03 +00:00
Родитель 183d7181fd
Коммит 2153891806
4 изменённых файлов: 53 добавлений и 18 удалений

Просмотреть файл

@ -60,10 +60,12 @@ class ASTRecordLayout {
bool PrimaryBaseWasVirtual;
/// 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;
/// VBaseOffsets - Contains a map from vbase classes to their offset.
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
llvm::DenseMap<const CXXRecordDecl *, uint64_t> VBaseOffsets;
};
/// CXXInfo - If the record layout is for a C++ record, this will have
@ -90,7 +92,8 @@ class ASTRecordLayout {
uint64_t nonvirtualsize, unsigned nonvirtualalign,
const CXXRecordDecl *PB, bool PBVirtual,
const CXXRecordDecl **bases, const uint64_t *baseoffsets,
unsigned basecount)
unsigned basecount, const CXXRecordDecl **vbases,
const uint64_t *vbaseoffsets,unsigned vbasecount)
: Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment),
FieldCount(fieldcount), CXXInfo(new CXXRecordLayoutInfo) {
if (FieldCount > 0) {
@ -105,6 +108,8 @@ class ASTRecordLayout {
CXXInfo->NonVirtualAlign = nonvirtualalign;
for (unsigned i = 0; i != basecount; ++i)
CXXInfo->BaseOffsets[bases[i]] = baseoffsets[i];
for (unsigned i = 0; i != vbasecount; ++i)
CXXInfo->VBaseOffsets[vbases[i]] = vbaseoffsets[i];
}
~ASTRecordLayout() {
@ -174,6 +179,14 @@ public:
return CXXInfo->BaseOffsets[Base];
}
/// getVBaseClassOffset - Get the offset, in bits, for the given base class.
uint64_t getVBaseClassOffset(const CXXRecordDecl *VBase) const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
return CXXInfo->VBaseOffsets[VBase];
}
};
} // end namespace clang

Просмотреть файл

@ -51,8 +51,8 @@ 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)
LayoutBaseNonVirtually(Base);
if (Base != PrimaryBase || PrimaryBaseWasVirtual)
LayoutBaseNonVirtually(Base, false);
}
}
}
@ -77,9 +77,10 @@ void ASTRecordLayoutBuilder::SelectPrimaryForBase(const CXXRecordDecl *RD,
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
if (PrimaryBaseWasVirtual) {
if (PrimaryBaseWasVirtual)
IndirectPrimary.insert(PrimaryBase);
}
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
const CXXRecordDecl *Base =
@ -163,7 +164,7 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD,
}
void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) {
LayoutBaseNonVirtually(RD);
LayoutBaseNonVirtually(RD, true);
}
void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
@ -182,7 +183,8 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
}
}
void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD) {
void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD,
bool IsVirtualBase) {
const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD);
assert(BaseInfo.getDataSize() > 0 &&
"FIXME: Handle empty classes.");
@ -193,9 +195,14 @@ void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD) {
// 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);
// Add base class offsets.
if (IsVirtualBase) {
VBases.push_back(RD);
VBaseOffsets.push_back(Size);
} else {
Bases.push_back(RD);
BaseOffsets.push_back(Size);
}
// Reserve space for this base.
Size += BaseSize;
@ -229,7 +236,7 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
if (PrimaryBase) {
if (PrimaryBaseWasVirtual)
IndirectPrimary.insert(PrimaryBase);
LayoutBaseNonVirtually(PrimaryBase);
LayoutBaseNonVirtually(PrimaryBase, PrimaryBaseWasVirtual);
}
LayoutNonVirtualBases(RD);
}
@ -406,6 +413,8 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
assert(Builder.Bases.size() == Builder.BaseOffsets.size() &&
"Base offsets vector must be same size as bases vector!");
assert(Builder.VBases.size() == Builder.VBaseOffsets.size() &&
"Base offsets vector must be same size as bases vector!");
// FIXME: This should be done in FinalizeLayout.
uint64_t DataSize =
@ -422,7 +431,10 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
Builder.PrimaryBaseWasVirtual,
Builder.Bases.data(),
Builder.BaseOffsets.data(),
Builder.Bases.size());
Builder.Bases.size(),
Builder.VBases.data(),
Builder.VBaseOffsets.data(),
Builder.VBases.size());
}
const ASTRecordLayout *

Просмотреть файл

@ -42,6 +42,9 @@ class ASTRecordLayoutBuilder {
llvm::SmallVector<const CXXRecordDecl *, 4> Bases;
llvm::SmallVector<uint64_t, 4> BaseOffsets;
llvm::SmallVector<const CXXRecordDecl *, 4> VBases;
llvm::SmallVector<uint64_t, 4> VBaseOffsets;
ASTRecordLayoutBuilder(ASTContext &Ctx);
@ -68,7 +71,7 @@ class ASTRecordLayoutBuilder {
void LayoutVtable(const CXXRecordDecl *RD,
llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary);
void LayoutNonVirtualBases(const CXXRecordDecl *RD);
void LayoutBaseNonVirtually(const CXXRecordDecl *RD);
void LayoutBaseNonVirtually(const CXXRecordDecl *RD, bool IsVBase);
void LayoutVirtualBase(const CXXRecordDecl *RD);
void LayoutVirtualBases(const CXXRecordDecl *RD,
llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary);

Просмотреть файл

@ -703,6 +703,7 @@ void CodeGenFunction::GenerateVtableForBase(const CXXRecordDecl *RD,
if (isPrimary) {
// The virtual base offsets come first...
// FIXME: audit
for (CXXRecordDecl::reverse_base_class_const_iterator i
= Class->bases_rbegin(),
e = Class->bases_rend(); i != e; ++i) {
@ -710,7 +711,7 @@ void CodeGenFunction::GenerateVtableForBase(const CXXRecordDecl *RD,
continue;
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
int64_t BaseOffset = Layout.getBaseClassOffset(Base) / 8;
int64_t BaseOffset = Layout.getVBaseClassOffset(Base) / 8;
llvm::Constant *m;
m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), BaseOffset);
m = llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty);
@ -741,7 +742,11 @@ void CodeGenFunction::GenerateVtableForBase(const CXXRecordDecl *RD,
if (TopPrimary) {
if (RD) {
int64_t BaseOffset = -(Layout.getBaseClassOffset(RD) / 8);
int64_t BaseOffset;
if (ForVirtualBase)
BaseOffset = -(Layout.getVBaseClassOffset(RD) / 8);
else
BaseOffset = -(Layout.getBaseClassOffset(RD) / 8);
m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), BaseOffset);
m = llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty);
}
@ -784,13 +789,15 @@ llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) {
// The primary base comes first.
GenerateVtableForBase(PrimaryBase, RD, rtti, methods, true,
PrimaryBaseWasVirtual, IndirectPrimary);
// Then come the non-virtual bases.
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
if (i->isVirtual())
continue;
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (Base != PrimaryBase)
if (Base != PrimaryBase || PrimaryBaseWasVirtual)
GenerateVtableForBase(Base, RD, rtti, methods, false, false,
IndirectPrimary);
}