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
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) {
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() {
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
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);
}
}
}
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 =
}
void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) {
- LayoutBaseNonVirtually(RD);
+ LayoutBaseNonVirtually(RD, true);
}
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.");
// 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;
if (PrimaryBase) {
if (PrimaryBaseWasVirtual)
IndirectPrimary.insert(PrimaryBase);
- LayoutBaseNonVirtually(PrimaryBase);
+ LayoutBaseNonVirtually(PrimaryBase, PrimaryBaseWasVirtual);
}
LayoutNonVirtualBases(RD);
}
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 =
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 *
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);
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);
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) {
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);
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);
}
// 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);
}