[codeview] Emit vtable shape information
The shape of the vtable is passed down as the size of the
__vtbl_ptr_type. This special pointer type appears both as the pointee
type of the vptr type, and by itself in every dynamic class. For classes
with multiple vtables, only the shape of the primary vftable is
included, as the shape of all secondary vftables will be the same as in
the base class.
Fixes PR28150
llvm-svn: 280254
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index e30864e..63d9a47 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -937,6 +937,9 @@
case dwarf::DW_TAG_base_type:
return lowerTypeBasic(cast<DIBasicType>(Ty));
case dwarf::DW_TAG_pointer_type:
+ if (cast<DIDerivedType>(Ty)->getName() == "__vtbl_ptr_type")
+ return lowerTypeVFTableShape(cast<DIDerivedType>(Ty));
+ LLVM_FALLTHROUGH;
case dwarf::DW_TAG_reference_type:
case dwarf::DW_TAG_rvalue_reference_type:
return lowerTypePointer(cast<DIDerivedType>(Ty));
@@ -1321,6 +1324,12 @@
return TI;
}
+TypeIndex CodeViewDebug::lowerTypeVFTableShape(const DIDerivedType *Ty) {
+ unsigned VSlotCount = Ty->getSizeInBits() / (8 * Asm->MAI->getPointerSize());
+ SmallVector<VFTableSlotKind, 4> Slots(VSlotCount, VFTableSlotKind::Near);
+ return TypeTable.writeKnownType(VFTableShapeRecord(Slots));
+}
+
static MemberAccess translateAccessFlags(unsigned RecordTag, unsigned Flags) {
switch (Flags & DINode::FlagAccessibility) {
case DINode::FlagPrivate: return MemberAccess::Private;
@@ -1453,6 +1462,8 @@
// Direct overloaded methods gathered by name.
MethodsMap Methods;
+ TypeIndex VShapeTI;
+
std::vector<const DICompositeType *> NestedClasses;
};
@@ -1501,11 +1512,13 @@
collectMemberInfo(Info, DDTy);
} else if (DDTy->getTag() == dwarf::DW_TAG_inheritance) {
Info.Inheritance.push_back(DDTy);
+ } else if (DDTy->getTag() == dwarf::DW_TAG_pointer_type &&
+ DDTy->getName() == "__vtbl_ptr_type") {
+ Info.VShapeTI = getTypeIndex(DDTy);
} else if (DDTy->getTag() == dwarf::DW_TAG_friend) {
// Ignore friend members. It appears that MSVC emitted info about
// friends in the past, but modern versions do not.
}
- // FIXME: Get Clang to emit function virtual table here and handle it.
} else if (auto *Composite = dyn_cast<DICompositeType>(Element)) {
Info.NestedClasses.push_back(Composite);
}
@@ -1646,6 +1659,14 @@
continue;
}
+ // Virtual function pointer member.
+ if ((Member->getFlags() & DINode::FlagArtificial) &&
+ Member->getName().startswith("_vptr$")) {
+ Fields.writeMemberType(VFPtrRecord(getTypeIndex(Member->getBaseType())));
+ MemberCount++;
+ continue;
+ }
+
// Data member.
uint64_t MemberOffsetInBits =
Member->getOffsetInBits() + MemberInfo.BaseOffset;
@@ -1704,7 +1725,7 @@
}
TypeIndex FieldTI = TypeTable.writeFieldList(Fields);
- return std::make_tuple(FieldTI, TypeIndex(), MemberCount,
+ return std::make_tuple(FieldTI, Info.VShapeTI, MemberCount,
!Info.NestedClasses.empty());
}