зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
183d7181fd
Коммит
2153891806
|
@ -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);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче