19#include "llvm/ADT/SetOperations.h"
20#include "llvm/ADT/SetVector.h"
21#include "llvm/ADT/SmallPtrSet.h"
22#include "llvm/Support/Format.h"
23#include "llvm/Support/raw_ostream.h"
29#define DUMP_OVERRIDERS 0
50 BaseOffset() : DerivedClass(
nullptr),
VirtualBase(
nullptr),
55 NonVirtualOffset(NonVirtualOffset) { }
62class FinalOverriders {
65 struct OverriderInfo {
102 typedef std::pair<const CXXMethodDecl *, CharUnits> MethodBaseOffsetPairTy;
104 typedef llvm::DenseMap<MethodBaseOffsetPairTy,
105 OverriderInfo> OverridersMapTy;
109 OverridersMapTy OverridersMap;
114 typedef llvm::DenseMap<std::pair<const CXXRecordDecl *, unsigned>,
117 typedef llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCountMapTy;
123 SubobjectOffsetMapTy &SubobjectOffsets,
124 SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
125 SubobjectCountMapTy &SubobjectCounts);
132 VisitedVirtualBasesSetTy& VisitedVirtualBases);
143 assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) &&
144 "Did not find overrider!");
146 return OverridersMap.lookup(std::make_pair(MD, BaseOffset));
151 VisitedVirtualBasesSetTy VisitedVirtualBases;
153 VisitedVirtualBases);
158FinalOverriders::FinalOverriders(
const CXXRecordDecl *MostDerivedClass,
161 : MostDerivedClass(MostDerivedClass),
162 MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass),
167 SubobjectOffsetMapTy SubobjectOffsets;
168 SubobjectOffsetMapTy SubobjectLayoutClassOffsets;
169 SubobjectCountMapTy SubobjectCounts;
172 MostDerivedClassOffset,
173 SubobjectOffsets, SubobjectLayoutClassOffsets,
180 for (
const auto &Overrider : FinalOverriders) {
184 for (
const auto &M : Methods) {
185 unsigned SubobjectNumber = M.first;
186 assert(SubobjectOffsets.count(std::make_pair(MD->
getParent(),
188 "Did not find subobject offset!");
193 assert(M.second.size() == 1 &&
"Final overrider is not unique!");
197 assert(SubobjectLayoutClassOffsets.count(
198 std::make_pair(OverriderRD,
Method.Subobject))
199 &&
"Did not find subobject offset!");
201 SubobjectLayoutClassOffsets[std::make_pair(OverriderRD,
204 OverriderInfo& Overrider = OverridersMap[std::make_pair(MD, BaseOffset)];
205 assert(!Overrider.Method &&
"Overrider should not exist yet!");
207 Overrider.Offset = OverriderOffset;
208 Overrider.Method =
Method.Method;
209 Overrider.VirtualBase =
Method.InVirtualSubobject;
219static BaseOffset ComputeBaseOffset(
const ASTContext &Context,
224 unsigned NonVirtualStart = 0;
228 for (
int I =
Path.size(),
E = 0; I !=
E; --I) {
231 if (Element.Base->isVirtual()) {
233 QualType VBaseType = Element.Base->getType();
240 for (
unsigned I = NonVirtualStart,
E =
Path.size(); I !=
E; ++I) {
254 return BaseOffset(DerivedRD,
VirtualBase, NonVirtualOffset);
258static BaseOffset ComputeBaseOffset(
const ASTContext &Context,
265 llvm_unreachable(
"Class must be derived from the passed in base class!");
267 return ComputeBaseOffset(Context, DerivedRD, Paths.front());
271ComputeReturnAdjustmentBaseOffset(
ASTContext &Context,
283 assert(CanDerivedReturnType->getTypeClass() ==
284 CanBaseReturnType->getTypeClass() &&
285 "Types must have same type class!");
287 if (CanDerivedReturnType == CanBaseReturnType) {
292 if (isa<ReferenceType>(CanDerivedReturnType)) {
293 CanDerivedReturnType =
297 }
else if (isa<PointerType>(CanDerivedReturnType)) {
298 CanDerivedReturnType =
303 llvm_unreachable(
"Unexpected return type!");
309 if (CanDerivedReturnType.getUnqualifiedType() ==
317 cast<RecordType>(CanDerivedReturnType)->getOriginalDecl())
321 cast<RecordType>(CanBaseReturnType)->getOriginalDecl());
323 return ComputeBaseOffset(Context, BaseRD, DerivedRD);
329 SubobjectOffsetMapTy &SubobjectOffsets,
330 SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
331 SubobjectCountMapTy &SubobjectCounts) {
334 unsigned SubobjectNumber = 0;
336 SubobjectNumber = ++SubobjectCounts[RD];
339 assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
340 &&
"Subobject offset already exists!");
341 assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
342 &&
"Subobject offset already exists!");
344 SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] =
Base.getBaseOffset();
345 SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
349 for (
const auto &B : RD->
bases()) {
350 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
356 if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0)))
362 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
363 BaseOffsetInLayoutClass =
369 BaseOffset =
Base.getBaseOffset() + Offset;
370 BaseOffsetInLayoutClass = OffsetInLayoutClass + Offset;
374 B.isVirtual(), BaseOffsetInLayoutClass,
375 SubobjectOffsets, SubobjectLayoutClassOffsets,
381 VisitedVirtualBasesSetTy &VisitedVirtualBases) {
385 for (
const auto &B : RD->
bases()) {
386 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
394 if (!VisitedVirtualBases.insert(BaseDecl).second) {
399 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
407 Out <<
"Final overriders for (";
410 Out <<
Base.getBaseOffset().getQuantity() <<
")\n";
413 for (
const auto *MD : RD->
methods()) {
416 MD = MD->getCanonicalDecl();
418 OverriderInfo Overrider = getOverrider(MD,
Base.getBaseOffset());
421 MD->printQualifiedName(Out);
423 Overrider.Method->printQualifiedName(Out);
424 Out <<
", " << Overrider.Offset.getQuantity() <<
')';
427 if (!Overrider.Method->isPureVirtual())
428 Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
430 if (!Offset.isEmpty()) {
431 Out <<
" [ret-adj: ";
432 if (Offset.VirtualBase) {
433 Offset.VirtualBase->printQualifiedName(Out);
437 Out << Offset.NonVirtualOffset.getQuantity() <<
" nv]";
445struct VCallOffsetMap {
447 typedef std::pair<const CXXMethodDecl *, CharUnits> MethodAndOffsetPairTy;
455 static bool MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
469 bool empty()
const {
return Offsets.empty(); }
480 if (
LT == RT)
return true;
490bool VCallOffsetMap::MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
496 if (isa<CXXDestructorDecl>(LHS))
497 return isa<CXXDestructorDecl>(RHS);
504 if (LHSName != RHSName)
508 return HasSameVirtualSignature(LHS, RHS);
514 for (
const auto &OffsetPair : Offsets) {
515 if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
520 Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
526 for (
const auto &OffsetPair : Offsets) {
527 if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
528 return OffsetPair.second;
531 llvm_unreachable(
"Should always find a vcall offset offset!");
535class VCallAndVBaseOffsetBuilder {
537 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
538 VBaseOffsetOffsetsMapTy;
557 VTableComponentVectorTy Components;
563 VCallOffsetMap VCallOffsets;
568 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
572 const FinalOverriders *Overriders;
588 CharUnits getCurrentOffsetOffset()
const;
594 const FinalOverriders *Overriders,
597 : VTables(VTables), MostDerivedClass(MostDerivedClass),
598 LayoutClass(LayoutClass), Context(MostDerivedClass->
getASTContext()),
599 Overriders(Overriders) {
602 AddVCallAndVBaseOffsets(
Base, BaseIsVirtual, OffsetInLayoutClass);
606 typedef VTableComponentVectorTy::const_reverse_iterator const_iterator;
607 const_iterator components_begin()
const {
return Components.rbegin(); }
608 const_iterator components_end()
const {
return Components.rend(); }
610 const VCallOffsetMap &getVCallOffsets()
const {
return VCallOffsets; }
611 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
612 return VBaseOffsetOffsets;
637 if (PrimaryBaseIsVirtual) {
639 "Primary vbase should have a zero offset!");
648 "Primary base should have a zero offset!");
650 PrimaryBaseOffset =
Base.getBaseOffset();
653 AddVCallAndVBaseOffsets(
655 PrimaryBaseIsVirtual, RealBaseOffset);
658 AddVBaseOffsets(
Base.getBase(), RealBaseOffset);
662 AddVCallOffsets(
Base, RealBaseOffset);
665CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset()
const {
670 size_t NumComponentsAboveAddrPoint = 3;
672 NumComponentsAboveAddrPoint--;
673 int64_t OffsetIndex =
674 -(int64_t)(NumComponentsAboveAddrPoint + Components.size());
679 VTables.isRelativeLayout()
682 CharUnits OffsetOffset = OffsetWidth * OffsetIndex;
700 "Primary base should have a zero offset!");
707 for (
const auto *MD : RD->
methods()) {
712 CharUnits OffsetOffset = getCurrentOffsetOffset();
716 if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
723 FinalOverriders::OverriderInfo Overrider =
724 Overriders->getOverrider(MD,
Base.getBaseOffset());
728 Offset = Overrider.Offset - VBaseOffset;
731 Components.push_back(
736 for (
const auto &B : RD->
bases()) {
740 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
741 if (BaseDecl == PrimaryBase)
754VCallAndVBaseOffsetBuilder::AddVBaseOffsets(
const CXXRecordDecl *RD,
760 for (
const auto &B : RD->
bases()) {
761 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
764 if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
769 assert(!VBaseOffsetOffsets.count(BaseDecl) &&
770 "vbase offset offset already exists!");
772 CharUnits VBaseOffsetOffset = getCurrentOffsetOffset();
773 VBaseOffsetOffsets.insert(
774 std::make_pair(BaseDecl, VBaseOffsetOffset));
776 Components.push_back(
781 AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
786class ItaniumVTableBuilder {
791 PrimaryBasesSetVectorTy;
793 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
794 VBaseOffsetOffsetsMapTy;
798 typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
814 bool MostDerivedClassIsVirtual;
825 const FinalOverriders Overriders;
829 llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
833 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
839 AddressPointsMapTy AddressPoints;
853 const uint64_t VTableIndex;
856 uint64_t VTableIndex)
857 : BaseOffset(BaseOffset),
858 BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
859 VTableIndex(VTableIndex) { }
866 MethodInfo(MethodInfo
const&) =
default;
869 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
873 MethodInfoMapTy MethodInfoMap;
877 MethodVTableIndicesTy MethodVTableIndices;
879 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
883 VTableThunksMapTy VTableThunks;
886 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
897 void ComputeThisAdjustments();
903 VisitedVirtualBasesSetTy PrimaryVirtualBases;
920 FinalOverriders::OverriderInfo Overrider);
948 CharUnits FirstBaseOffsetInLayoutClass)
const;
956 PrimaryBasesSetVectorTy &PrimaryBases);
971 bool BaseIsMorallyVirtual,
972 bool BaseIsVirtualInLayoutClass,
987 VisitedVirtualBasesSetTy &VBases);
992 VisitedVirtualBasesSetTy &VBases);
996 bool isBuildingConstructorVTable()
const {
997 return MostDerivedClass != LayoutClass;
1008 bool MostDerivedClassIsVirtual,
1010 : VTables(VTables), MostDerivedClass(MostDerivedClass),
1011 MostDerivedClassOffset(MostDerivedClassOffset),
1012 MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
1013 LayoutClass(LayoutClass), Context(MostDerivedClass->
getASTContext()),
1014 Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
1020 dumpLayout(llvm::outs());
1023 uint64_t getNumThunks()
const {
1024 return Thunks.size();
1027 ThunksMapTy::const_iterator thunks_begin()
const {
1028 return Thunks.begin();
1031 ThunksMapTy::const_iterator thunks_end()
const {
1032 return Thunks.end();
1035 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
1036 return VBaseOffsetOffsets;
1039 const AddressPointsMapTy &getAddressPoints()
const {
1040 return AddressPoints;
1043 MethodVTableIndicesTy::const_iterator vtable_indices_begin()
const {
1044 return MethodVTableIndices.begin();
1047 MethodVTableIndicesTy::const_iterator vtable_indices_end()
const {
1048 return MethodVTableIndices.end();
1053 AddressPointsMapTy::const_iterator address_points_begin()
const {
1054 return AddressPoints.begin();
1057 AddressPointsMapTy::const_iterator address_points_end()
const {
1058 return AddressPoints.end();
1061 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
1062 return VTableThunks.begin();
1065 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
1066 return VTableThunks.end();
1070 void dumpLayout(raw_ostream&);
1075 assert(!isBuildingConstructorVTable() &&
1076 "Can't add thunks for construction vtable");
1081 if (llvm::is_contained(ThunksVector, Thunk))
1084 ThunksVector.push_back(Thunk);
1093template <
class VisitorTy>
1095visitAllOverriddenMethods(
const CXXMethodDecl *MD, VisitorTy &Visitor) {
1099 if (!Visitor(OverriddenMD))
1101 visitAllOverriddenMethods(OverriddenMD, Visitor);
1109 OverriddenMethodsSetTy& OverriddenMethods) {
1110 auto OverriddenMethodsCollector = [&](
const CXXMethodDecl *MD) {
1112 return OverriddenMethods.insert(MD).second;
1114 visitAllOverriddenMethods(MD, OverriddenMethodsCollector);
1117void ItaniumVTableBuilder::ComputeThisAdjustments() {
1120 for (
const auto &MI : MethodInfoMap) {
1122 const MethodInfo &MethodInfo = MI.second;
1125 uint64_t VTableIndex = MethodInfo.VTableIndex;
1126 if (Components[VTableIndex].
getKind() ==
1131 FinalOverriders::OverriderInfo Overrider =
1132 Overriders.getOverrider(MD, MethodInfo.BaseOffset);
1135 if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
1141 if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
1146 ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
1152 auto SetThisAdjustmentThunk = [&](uint64_t Idx) {
1174 auto [It, Inserted] = VTableThunks.try_emplace(Idx);
1177 It->second.Method =
Method;
1178 It->second.ThisType =
Method->getThisType().getTypePtr();
1183 SetThisAdjustmentThunk(VTableIndex);
1185 if (isa<CXXDestructorDecl>(MD)) {
1187 SetThisAdjustmentThunk(VTableIndex + 1);
1192 MethodInfoMap.clear();
1194 if (isBuildingConstructorVTable()) {
1199 for (
const auto &TI : VTableThunks) {
1204 switch (Component.
getKind()) {
1206 llvm_unreachable(
"Unexpected vtable component kind!");
1218 if (MD->
getParent() == MostDerivedClass)
1219 AddThunk(MD, Thunk);
1224ItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
1227 if (!Offset.isEmpty()) {
1228 if (Offset.VirtualBase) {
1230 if (Offset.DerivedClass == MostDerivedClass) {
1233 VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity();
1236 VTables.getVirtualBaseOffsetOffset(Offset.DerivedClass,
1237 Offset.VirtualBase).getQuantity();
1241 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1247BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
1256 llvm_unreachable(
"Class must be derived from the passed in base class!");
1261 BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD,
Path);
1263 CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
1265 if (Offset.VirtualBase) {
1273 OffsetToBaseSubobject +=
1282 if (OffsetToBaseSubobject ==
Base.getBaseOffset()) {
1285 Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
1290 return BaseOffset();
1295 FinalOverriders::OverriderInfo Overrider) {
1297 if (Overrider.Method->isPureVirtual())
1301 BaseOffsetInLayoutClass);
1303 BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
1307 BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
1308 OverriderBaseSubobject);
1309 if (Offset.isEmpty())
1314 if (Offset.VirtualBase) {
1316 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
1318 if (VCallOffsets.empty()) {
1321 VCallAndVBaseOffsetBuilder Builder(
1322 VTables, MostDerivedClass, MostDerivedClass,
1329 VCallOffsets = Builder.getVCallOffsets();
1333 VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
1337 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1342void ItaniumVTableBuilder::AddMethod(
const CXXMethodDecl *MD,
1346 "Destructor can't have return adjustment!");
1372static bool OverridesIndirectMethodInBases(
1380 if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
1387bool ItaniumVTableBuilder::IsOverriderUsed(
1390 CharUnits FirstBaseOffsetInLayoutClass)
const {
1393 if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
1402 if (Overrider->getParent() == FirstBaseInPrimaryBaseChain)
1408 PrimaryBases.insert(RD);
1421 "Primary base should always be at offset 0!");
1429 FirstBaseOffsetInLayoutClass) {
1435 "Primary base should always be at offset 0!");
1438 if (!PrimaryBases.insert(PrimaryBase))
1439 llvm_unreachable(
"Found a duplicate primary base!");
1446 return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
1456 BasesSetVectorTy &Bases) {
1457 OverriddenMethodsSetTy OverriddenMethods;
1458 ComputeAllOverriddenMethods(MD, OverriddenMethods);
1460 for (
const CXXRecordDecl *PrimaryBase : llvm::reverse(Bases)) {
1462 for (
const CXXMethodDecl *OverriddenMD : OverriddenMethods) {
1464 if (OverriddenMD->getParent() == PrimaryBase)
1465 return OverriddenMD;
1472void ItaniumVTableBuilder::AddMethods(
1476 PrimaryBasesSetVectorTy &PrimaryBases) {
1491 CharUnits PrimaryBaseOffsetInLayoutClass;
1494 "Primary vbase should have a zero offset!");
1505 PrimaryBaseOffsetInLayoutClass =
1509 "Primary base should have a zero offset!");
1511 PrimaryBaseOffset =
Base.getBaseOffset();
1512 PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
1516 PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
1517 FirstBaseOffsetInLayoutClass, PrimaryBases);
1519 if (!PrimaryBases.insert(PrimaryBase))
1520 llvm_unreachable(
"Found a duplicate primary base!");
1524 NewVirtualFunctionsTy NewVirtualFunctions;
1529 for (
const auto *MD : RD->
methods()) {
1530 if (!ItaniumVTableContext::hasVtableSlot(MD))
1535 FinalOverriders::OverriderInfo Overrider =
1536 Overriders.getOverrider(MD,
Base.getBaseOffset());
1542 FindNearestOverriddenMethod(MD, PrimaryBases)) {
1543 if (ComputeReturnAdjustmentBaseOffset(Context, MD,
1544 OverriddenMD).isEmpty()) {
1545 VTables.setOriginalMethod(MD, OverriddenMD);
1549 assert(MethodInfoMap.count(OverriddenMD) &&
1550 "Did not find the overridden method!");
1551 MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
1553 MethodInfo MethodInfo(
Base.getBaseOffset(), BaseOffsetInLayoutClass,
1554 OverriddenMethodInfo.VTableIndex);
1556 assert(!MethodInfoMap.count(MD) &&
1557 "Should not have method info for this method yet!");
1559 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1560 MethodInfoMap.erase(OverriddenMD);
1566 if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
1569 ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
1573 Overrider.Method->getParent() == MostDerivedClass) {
1578 BaseOffset ReturnAdjustmentOffset =
1579 ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
1581 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1584 AddThunk(Overrider.Method,
1586 OverriddenMD->getThisType().getTypePtr()));
1595 NewImplicitVirtualFunctions.push_back(MD);
1597 NewVirtualFunctions.push_back(MD);
1601 NewImplicitVirtualFunctions,
1609 if (isa<CXXDestructorDecl>(A) != isa<CXXDestructorDecl>(B))
1610 return isa<CXXDestructorDecl>(A);
1613 "unexpected or duplicate implicit virtual function");
1618 NewVirtualFunctions.append(NewImplicitVirtualFunctions.begin(),
1619 NewImplicitVirtualFunctions.end());
1623 FinalOverriders::OverriderInfo Overrider =
1624 Overriders.getOverrider(MD,
Base.getBaseOffset());
1627 MethodInfo MethodInfo(
Base.getBaseOffset(), BaseOffsetInLayoutClass,
1630 assert(!MethodInfoMap.count(MD) &&
1631 "Should not have method info for this method yet!");
1632 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1636 if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
1637 FirstBaseInPrimaryBaseChain,
1638 FirstBaseOffsetInLayoutClass)) {
1645 BaseOffset ReturnAdjustmentOffset;
1647 ReturnAdjustmentOffset =
1648 ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
1652 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1659 auto &VTT = VTableThunks[Components.size()];
1668void ItaniumVTableBuilder::LayoutVTable() {
1669 LayoutPrimaryAndSecondaryVTables(
BaseSubobject(MostDerivedClass,
1672 MostDerivedClassIsVirtual,
1673 MostDerivedClassOffset);
1675 VisitedVirtualBasesSetTy VBases;
1678 DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
1682 LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
1685 bool IsAppleKext = Context.
getLangOpts().AppleKext;
1690void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
1692 bool BaseIsVirtualInLayoutClass,
CharUnits OffsetInLayoutClass) {
1693 assert(
Base.getBase()->isDynamicClass() &&
"class does not have a vtable!");
1695 unsigned VTableIndex = Components.size();
1696 VTableIndices.push_back(VTableIndex);
1699 VCallAndVBaseOffsetBuilder Builder(
1700 VTables, MostDerivedClass, LayoutClass, &Overriders,
Base,
1701 BaseIsVirtualInLayoutClass, OffsetInLayoutClass);
1702 Components.append(Builder.components_begin(), Builder.components_end());
1705 if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
1706 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[
Base.getBase()];
1708 if (VCallOffsets.empty())
1709 VCallOffsets = Builder.getVCallOffsets();
1714 if (
Base.getBase() == MostDerivedClass)
1715 VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
1718 CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
1725 uint64_t AddressPoint = Components.size();
1728 PrimaryBasesSetVectorTy PrimaryBases;
1729 AddMethods(
Base, OffsetInLayoutClass,
1730 Base.getBase(), OffsetInLayoutClass,
1734 if (RD == MostDerivedClass) {
1735 assert(MethodVTableIndices.empty());
1736 for (
const auto &I : MethodInfoMap) {
1738 const MethodInfo &MI = I.second;
1741 = MI.VTableIndex - AddressPoint;
1743 = MI.VTableIndex + 1 - AddressPoint;
1745 MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
1751 ComputeThisAdjustments();
1755 AddressPoints.insert(
1758 unsigned(VTableIndices.size() - 1),
1759 unsigned(AddressPoint - VTableIndex)}));
1774 OffsetInLayoutClass) {
1784 LayoutSecondaryVTables(
Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
1789 bool BaseIsMorallyVirtual,
1800 for (
const auto &B : RD->
bases()) {
1805 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1811 if (isBuildingConstructorVTable()) {
1817 if (!BaseIsMorallyVirtual && !BaseDecl->
getNumVBases())
1823 CharUnits BaseOffset =
Base.getBaseOffset() + RelativeBaseOffset;
1826 OffsetInLayoutClass + RelativeBaseOffset;
1830 if (BaseDecl == PrimaryBase) {
1832 BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
1837 LayoutPrimaryAndSecondaryVTables(
1839 BaseIsMorallyVirtual,
1841 BaseOffsetInLayoutClass);
1845void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
1847 VisitedVirtualBasesSetTy &VBases) {
1855 bool IsPrimaryVirtualBase =
true;
1857 if (isBuildingConstructorVTable()) {
1863 CharUnits PrimaryBaseOffsetInLayoutClass =
1868 if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
1869 IsPrimaryVirtualBase =
false;
1872 if (IsPrimaryVirtualBase)
1873 PrimaryVirtualBases.insert(PrimaryBase);
1878 for (
const auto &B : RD->
bases()) {
1879 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1883 if (B.isVirtual()) {
1884 if (!VBases.insert(BaseDecl).second)
1890 BaseOffsetInLayoutClass =
1893 BaseOffsetInLayoutClass =
1897 DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
1901void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
1902 const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) {
1907 for (
const auto &B : RD->
bases()) {
1908 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1913 !PrimaryVirtualBases.count(BaseDecl) &&
1914 VBases.insert(BaseDecl).second) {
1925 LayoutPrimaryAndSecondaryVTables(
1929 BaseOffsetInLayoutClass);
1935 LayoutVTablesForVirtualBases(BaseDecl, VBases);
1939static void printThunkMethod(
const ThunkInfo &Info, raw_ostream &Out) {
1943 PredefinedIdentKind::PrettyFunctionNoVirtual, Info.
Method);
1944 Out <<
" method: " << Str;
1948void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
1952 Out <<
"Original map\n";
1954 for (
const auto &
P : VTables.getOriginalMethodMap()) {
1961 Out <<
" " << Str0 <<
" -> " << Str1 <<
"\n";
1964 if (isBuildingConstructorVTable()) {
1965 Out <<
"Construction vtable for ('";
1968 Out << MostDerivedClassOffset.
getQuantity() <<
") in '";
1971 Out <<
"Vtable for '";
1974 Out <<
"' (" << Components.size() <<
" entries).\n";
1980 std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
1981 for (
const auto &AP : AddressPoints) {
1984 VTableIndices[AP.second.VTableIndex] + AP.second.AddressPointIndex;
1986 AddressPointsByIndex.insert(std::make_pair(Index,
Base));
1989 for (
unsigned I = 0,
E = Components.size(); I !=
E; ++I) {
1992 Out << llvm::format(
"%4d | ", I);
1997 switch (Component.
getKind()) {
2000 Out <<
"vcall_offset ("
2006 Out <<
"vbase_offset ("
2012 Out <<
"offset_to_top ("
2026 PredefinedIdentKind::PrettyFunctionNoVirtual, MD);
2032 Out <<
" [deleted]";
2034 ThunkInfo Thunk = VTableThunks.lookup(I);
2038 Out <<
"\n [return adjustment: ";
2043 Out <<
" vbase offset offset";
2047 printThunkMethod(Thunk, Out);
2052 Out <<
"\n [this adjustment: ";
2057 Out <<
" vcall offset offset";
2061 printThunkMethod(Thunk, Out);
2077 Out <<
"() [complete]";
2079 Out <<
"() [deleting]";
2084 ThunkInfo Thunk = VTableThunks.lookup(I);
2088 Out <<
"\n [this adjustment: ";
2093 Out <<
" vcall offset offset";
2098 printThunkMethod(Thunk, Out);
2108 PredefinedIdentKind::PrettyFunctionNoVirtual, MD);
2109 Out <<
"[unused] " << Str;
2119 uint64_t NextIndex = Index + 1;
2120 if (
unsigned Count = AddressPointsByIndex.count(NextIndex)) {
2123 AddressPointsByIndex.find(NextIndex)->second;
2126 Base.getBase()->printQualifiedName(Out);
2127 Out <<
", " <<
Base.getBaseOffset().getQuantity();
2128 Out <<
") vtable address --\n";
2131 AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
2134 std::set<std::string> ClassNames;
2135 for (
const auto &I :
2136 llvm::make_range(AddressPointsByIndex.equal_range(NextIndex))) {
2137 assert(I.second.getBaseOffset() == BaseOffset &&
2138 "Invalid base offset!");
2143 for (
const std::string &Name : ClassNames) {
2144 Out <<
" -- (" << Name;
2145 Out <<
", " << BaseOffset.
getQuantity() <<
") vtable address --\n";
2153 if (isBuildingConstructorVTable())
2160 std::map<std::string, CharUnits> ClassNamesAndOffsets;
2161 for (
const auto &I : VBaseOffsetOffsets) {
2162 std::string ClassName = I.first->getQualifiedNameAsString();
2164 ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
2167 Out <<
"Virtual base offset offsets for '";
2170 Out << ClassNamesAndOffsets.size();
2171 Out << (ClassNamesAndOffsets.size() == 1 ?
" entry" :
" entries") <<
").\n";
2173 for (
const auto &I : ClassNamesAndOffsets)
2174 Out <<
" " << I.first <<
" | " << I.second.getQuantity() <<
'\n';
2179 if (!Thunks.empty()) {
2181 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
2183 for (
const auto &I : Thunks) {
2186 PredefinedIdentKind::PrettyFunctionNoVirtual, MD);
2188 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
2191 for (
const auto &I : MethodNamesAndDecls) {
2192 const std::string &MethodName = I.first;
2195 ThunkInfoVectorTy ThunksVector = Thunks[MD];
2200 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
2201 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
2203 for (
unsigned I = 0,
E = ThunksVector.size(); I !=
E; ++I) {
2204 const ThunkInfo &Thunk = ThunksVector[I];
2206 Out << llvm::format(
"%4d | ", I);
2211 Out <<
" non-virtual";
2214 Out <<
" vbase offset offset";
2223 Out <<
"this adjustment: ";
2228 Out <<
" vcall offset offset";
2241 std::map<uint64_t, std::string> IndicesMap;
2243 for (
const auto *MD : MostDerivedClass->
methods()) {
2245 if (!ItaniumVTableContext::hasVtableSlot(MD))
2250 PredefinedIdentKind::PrettyFunctionNoVirtual, MD);
2254 assert(MethodVTableIndices.count(GD));
2255 uint64_t VTableIndex = MethodVTableIndices[GD];
2256 IndicesMap[VTableIndex] = MethodName +
" [complete]";
2257 IndicesMap[VTableIndex + 1] = MethodName +
" [deleting]";
2259 assert(MethodVTableIndices.count(MD));
2260 IndicesMap[MethodVTableIndices[MD]] = MethodName;
2265 if (!IndicesMap.empty()) {
2266 Out <<
"VTable indices for '";
2268 Out <<
"' (" << IndicesMap.size() <<
" entries).\n";
2270 for (
const auto &I : IndicesMap) {
2271 uint64_t VTableIndex = I.first;
2272 const std::string &MethodName = I.second;
2274 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName
2285 unsigned numVTables) {
2288 for (
auto it = addressPoints.begin(); it != addressPoints.end(); ++it) {
2289 const auto &addressPointLoc = it->second;
2290 unsigned vtableIndex = addressPointLoc.VTableIndex;
2291 unsigned addressPoint = addressPointLoc.AddressPointIndex;
2292 if (indexMap[vtableIndex]) {
2295 assert(indexMap[vtableIndex] == addressPoint &&
2296 "Every vtable index should have a unique address point. Found a "
2297 "vtable that has two different address points.");
2299 indexMap[vtableIndex] = addressPoint;
2314 : VTableComponents(VTableComponents), VTableThunks(VTableThunks),
2316 AddressPoints, VTableIndices.size())) {
2317 if (VTableIndices.size() <= 1)
2318 assert(VTableIndices.size() == 1 && VTableIndices[0] == 0);
2324 assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
2325 "Different thunks should have unique indices!");
2326 return LHS.first < RHS.first;
2344 MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
2345 if (I != MethodVTableIndices.end())
2350 computeVTableRelatedInformation(RD);
2352 I = MethodVTableIndices.find(GD);
2353 assert(I != MethodVTableIndices.end() &&
"Did not find index!");
2360 ClassPairTy ClassPair(RD, VBase);
2362 VirtualBaseClassOffsetOffsetsMapTy::iterator I =
2363 VirtualBaseClassOffsetOffsets.find(ClassPair);
2364 if (I != VirtualBaseClassOffsetOffsets.end())
2367 VCallAndVBaseOffsetBuilder Builder(*
this, RD, RD,
nullptr,
2372 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2374 ClassPairTy ClassPair(RD, I.first);
2376 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2379 I = VirtualBaseClassOffsetOffsets.find(ClassPair);
2380 assert(I != VirtualBaseClassOffsetOffsets.end() &&
"Did not find index!");
2386 const auto *MD = cast<CXXMethodDecl>(GD.
getDecl());
2387 computeVTableRelatedInformation(MD->getParent());
2390 if (
const auto *DD = dyn_cast<CXXDestructorDecl>(OriginalMD))
2400 auto I = OriginalMethodMap.find(MD);
2404 if (I == OriginalMethodMap.end())
2414static std::unique_ptr<VTableLayout>
2417 VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
2419 return std::make_unique<VTableLayout>(
2420 Builder.VTableIndices, Builder.vtable_components(), VTableThunks,
2421 Builder.getAddressPoints());
2425ItaniumVTableContext::computeVTableRelatedInformation(
const CXXRecordDecl *RD) {
2426 std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD];
2436 MethodVTableIndices.insert(Builder.vtable_indices_begin(),
2437 Builder.vtable_indices_end());
2440 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
2451 if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
2454 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2456 ClassPairTy ClassPair(RD, I.first);
2458 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2462std::unique_ptr<VTableLayout>
2465 bool MostDerivedClassIsVirtual,
const CXXRecordDecl *LayoutClass) {
2466 ItaniumVTableBuilder Builder(*
this, MostDerivedClass, MostDerivedClassOffset,
2467 MostDerivedClassIsVirtual, LayoutClass);
2515class VFTableBuilder {
2517 typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
2518 MethodVFTableLocationsTy;
2520 typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
2521 method_locations_range;
2539 const FinalOverriders Overriders;
2544 MethodVFTableLocationsTy MethodVFTableLocations;
2547 bool HasRTTIComponent =
false;
2554 const uint64_t VBTableIndex;
2557 const uint64_t VFTableIndex;
2568 MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
2569 bool UsesExtraSlot =
false)
2570 : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2571 Shadowed(
false), UsesExtraSlot(UsesExtraSlot) {}
2574 : VBTableIndex(0), VFTableIndex(0), Shadowed(
false),
2575 UsesExtraSlot(
false) {}
2578 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
2582 MethodInfoMapTy MethodInfoMap;
2584 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
2588 VTableThunksMapTy VTableThunks;
2591 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
2602 if (llvm::is_contained(ThunksVector, Thunk))
2605 ThunksVector.push_back(Thunk);
2610 CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2612 void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
2619 VTableThunks[Components.size()] = TI;
2624 "Destructor can't have return adjustment!");
2635 BasesSetVectorTy &VisitedBases);
2637 void LayoutVFTable() {
2639 if (HasRTTIComponent)
2642 BasesSetVectorTy VisitedBases;
2647 assert(!Components.empty() &&
"vftable can't be empty");
2649 assert(MethodVFTableLocations.empty());
2650 for (
const auto &I : MethodInfoMap) {
2652 const MethodInfo &MI = I.second;
2657 if (MD->
getParent() != MostDerivedClass || MI.Shadowed)
2664 MethodVFTableLocations[MD] =
Loc;
2673 Context(MostDerivedClass->getASTContext()),
2674 MostDerivedClass(MostDerivedClass),
2675 MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)),
2677 Overriders(MostDerivedClass,
CharUnits(), MostDerivedClass) {
2684 HasRTTIComponent =
true;
2689 dumpLayout(llvm::outs());
2692 uint64_t getNumThunks()
const {
return Thunks.size(); }
2694 ThunksMapTy::const_iterator thunks_begin()
const {
return Thunks.begin(); }
2696 ThunksMapTy::const_iterator thunks_end()
const {
return Thunks.end(); }
2698 method_locations_range vtable_locations()
const {
2699 return method_locations_range(MethodVFTableLocations.begin(),
2700 MethodVFTableLocations.end());
2705 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
2706 return VTableThunks.begin();
2709 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
2710 return VTableThunks.end();
2713 void dumpLayout(raw_ostream &);
2773VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2774 BasesSetVectorTy Bases;
2778 OverriddenMethodsSetTy VisitedOverriddenMethods;
2779 auto InitialOverriddenDefinitionCollector = [&](
2781 if (OverriddenMD->size_overridden_methods() == 0)
2782 Bases.insert(OverriddenMD->getParent());
2784 return VisitedOverriddenMethods.insert(OverriddenMD).second;
2786 visitAllOverriddenMethods(Overrider.Method,
2787 InitialOverriddenDefinitionCollector);
2792 if (Bases.size() == 0)
2793 return Overrider.Offset;
2796 Overrider.Method->getParent()->lookupInBases(
2798 return Bases.count(
Specifier->getType()->getAsCXXRecordDecl());
2812 CharUnits ThisOffset = Overrider.Offset;
2819 QualType CurTy = Element.Base->getType();
2824 if (Element.Base->isVirtual()) {
2835 LastVBaseOffset = ThisOffset =
2842 if (isa<CXXDestructorDecl>(Overrider.Method)) {
2843 if (LastVBaseOffset.
isZero()) {
2847 ThisOffset = Overrider.Offset;
2851 ThisOffset = LastVBaseOffset;
2855 if (Ret > ThisOffset ||
First) {
2861 assert(!
First &&
"Method not found in the given subobject?");
2963void VFTableBuilder::CalculateVtordispAdjustment(
2964 FinalOverriders::OverriderInfo Overrider,
CharUnits ThisOffset,
2968 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2970 assert(VBaseMapEntry != VBaseMap.end());
2974 if (!VBaseMapEntry->second.hasVtorDisp() ||
2980 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2982 (OffsetOfVBaseWithVFPtr - WhichVFPtr.
FullOffsetInMDC).getQuantity() - 4;
2986 if (Overrider.Method->getParent() == MostDerivedClass ||
2987 !Overrider.VirtualBase)
2999 TA.
NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
3013 typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
3014 VisitedGroupIndicesTy VisitedGroupIndices;
3015 for (
const auto *
D : RD->
decls()) {
3016 const auto *ND = dyn_cast<NamedDecl>(
D);
3019 VisitedGroupIndicesTy::iterator J;
3021 std::tie(J, Inserted) = VisitedGroupIndices.insert(
3022 std::make_pair(ND->getDeclName(), Groups.size()));
3024 Groups.push_back(MethodGroup());
3025 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND))
3030 for (
const MethodGroup &Group : Groups)
3031 VirtualMethods.append(Group.rbegin(), Group.rend());
3035 for (
const auto &B : RD->
bases()) {
3036 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() ==
Base)
3044 BasesSetVectorTy &VisitedBases) {
3054 const CXXRecordDecl *NextBase =
nullptr, *NextLastVBase = LastVBase;
3059 NextLastVBase = NextBase;
3067 "No primary virtual bases in this ABI");
3068 NextBase = PrimaryBase;
3069 NextBaseOffset =
Base.getBaseOffset();
3073 AddMethods(
BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
3074 NextLastVBase, VisitedBases);
3075 if (!VisitedBases.insert(NextBase))
3076 llvm_unreachable(
"Found a duplicate primary base!");
3092 FinalOverriders::OverriderInfo FinalOverrider =
3093 Overriders.getOverrider(MD,
Base.getBaseOffset());
3094 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
3096 FindNearestOverriddenMethod(MD, VisitedBases);
3099 bool ReturnAdjustingThunk =
false, ForceReturnAdjustmentMangling =
false;
3100 CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
3103 if ((OverriddenMD || FinalOverriderMD != MD) &&
3105 CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
3106 ThisAdjustmentOffset);
3114 MethodInfoMapTy::iterator OverriddenMDIterator =
3115 MethodInfoMap.find(OverriddenMD);
3118 if (OverriddenMDIterator == MethodInfoMap.end())
3121 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
3123 VBIndex = OverriddenMethodInfo.VBTableIndex;
3130 ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
3131 Context, MD, OverriddenMD).isEmpty() ||
3132 OverriddenMethodInfo.UsesExtraSlot;
3134 if (!ReturnAdjustingThunk) {
3137 MethodInfo MI(VBIndex, OverriddenMethodInfo.VFTableIndex);
3138 MethodInfoMap.erase(OverriddenMDIterator);
3140 assert(!MethodInfoMap.count(MD) &&
3141 "Should not have method info for this method yet!");
3142 MethodInfoMap.insert(std::make_pair(MD, MI));
3148 OverriddenMethodInfo.Shadowed =
true;
3152 ForceReturnAdjustmentMangling =
3153 !(MD == FinalOverriderMD && ThisAdjustmentOffset.
isEmpty());
3164 MethodInfo MI(VBIndex,
3165 HasRTTIComponent ? Components.size() - 1 : Components.size(),
3166 ReturnAdjustingThunk);
3168 assert(!MethodInfoMap.count(MD) &&
3169 "Should not have method info for this method yet!");
3170 MethodInfoMap.insert(std::make_pair(MD, MI));
3174 BaseOffset ReturnAdjustmentOffset;
3177 ReturnAdjustmentOffset =
3178 ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
3180 if (!ReturnAdjustmentOffset.isEmpty()) {
3181 ForceReturnAdjustmentMangling =
true;
3183 ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
3184 if (ReturnAdjustmentOffset.VirtualBase) {
3191 ReturnAdjustmentOffset.VirtualBase);
3194 auto ThisType = (OverriddenMD ? OverriddenMD : MD)->getThisType().getTypePtr();
3195 AddMethod(FinalOverriderMD,
3197 ForceReturnAdjustmentMangling ? MD :
nullptr));
3204 Elem->printQualifiedName(Out);
3210 bool ContinueFirstLine) {
3212 bool Multiline =
false;
3213 const char *LinePrefix =
"\n ";
3215 if (!ContinueFirstLine)
3217 Out <<
"[return adjustment (to type '"
3229 if (Multiline || !ContinueFirstLine)
3231 Out <<
"[this adjustment: ";
3233 assert(
T.Virtual.Microsoft.VtordispOffset < 0);
3234 Out <<
"vtordisp at " <<
T.Virtual.Microsoft.VtordispOffset <<
", ";
3235 if (
T.Virtual.Microsoft.VBPtrOffset) {
3236 Out <<
"vbptr at " <<
T.Virtual.Microsoft.VBPtrOffset
3238 assert(
T.Virtual.Microsoft.VBOffsetOffset > 0);
3239 Out << LinePrefix <<
" vboffset at "
3240 <<
T.Virtual.Microsoft.VBOffsetOffset <<
" in the vbtable, ";
3243 Out <<
T.NonVirtual <<
" non-virtual]";
3247void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3248 Out <<
"VFTable for ";
3252 Out <<
"' (" << Components.size()
3253 << (Components.size() == 1 ?
" entry" :
" entries") <<
").\n";
3255 for (
unsigned I = 0,
E = Components.size(); I !=
E; ++I) {
3256 Out << llvm::format(
"%4d | ", I);
3261 switch (Component.
getKind()) {
3279 Out <<
" [deleted]";
3281 ThunkInfo Thunk = VTableThunks.lookup(I);
3292 Out <<
"() [scalar deleting]";
3297 ThunkInfo Thunk = VTableThunks.lookup(I);
3300 "No return adjustment needed for destructors!");
3311 "Unexpected vftable component type %0 for component number %1");
3321 if (!Thunks.empty()) {
3323 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3325 for (
const auto &I : Thunks) {
3330 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3333 for (
const auto &MethodNameAndDecl : MethodNamesAndDecls) {
3334 const std::string &MethodName = MethodNameAndDecl.first;
3337 ThunkInfoVectorTy ThunksVector = Thunks[MD];
3338 llvm::stable_sort(ThunksVector, [](
const ThunkInfo &LHS,
3345 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
3346 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
3348 for (
unsigned I = 0,
E = ThunksVector.size(); I !=
E; ++I) {
3349 const ThunkInfo &Thunk = ThunksVector[I];
3351 Out << llvm::format(
"%4d | ", I);
3395void MicrosoftVTableContext::computeVTablePaths(
bool ForVBTables,
3398 assert(Paths.empty());
3403 Paths.push_back(std::make_unique<VPtrInfo>(RD));
3408 for (
const auto &B : RD->
bases()) {
3410 if (B.isVirtual() && VBasesSeen.count(
Base))
3413 if (!
Base->isDynamicClass())
3419 for (
const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) {
3426 auto P = std::make_unique<VPtrInfo>(*BaseInfo);
3430 if (
P->MangledPath.empty() ||
P->MangledPath.back() !=
Base)
3431 P->NextBaseToMangle =
Base;
3436 if (
P->ObjectWithVPtr ==
Base &&
3439 P->ObjectWithVPtr = RD;
3444 P->ContainingVBases.push_back(
Base);
3445 else if (
P->ContainingVBases.empty())
3449 P->FullOffsetInMDC =
P->NonVirtualOffset;
3453 Paths.push_back(std::move(
P));
3457 VBasesSeen.insert(
Base);
3461 for (
const auto &VB :
Base->vbases())
3462 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3473 if (
P.NextBaseToMangle) {
3474 P.MangledPath.push_back(
P.NextBaseToMangle);
3475 P.NextBaseToMangle =
nullptr;
3489 llvm::make_pointee_range(Paths));
3493 bool Changed =
false;
3494 for (
size_t I = 0,
E = PathsSorted.size(); I !=
E;) {
3496 size_t BucketStart = I;
3500 PathsSorted[BucketStart].get().MangledPath ==
3501 PathsSorted[I].get().MangledPath);
3504 if (I - BucketStart > 1) {
3505 for (
size_t II = BucketStart; II != I; ++II)
3507 assert(Changed &&
"no paths were extended to fix ambiguity");
3516typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3517 llvm::DenseSet<BaseSubobject>> FullPathTy;
3526 FullPathTy &FullPath,
3527 std::list<FullPathTy> &Paths) {
3529 Paths.push_back(FullPath);
3542 IntroducingObject, FullPath, Paths);
3543 FullPath.pop_back();
3549 FullPaths.remove_if([&](
const FullPathTy &SpecificPath) {
3550 for (
const FullPathTy &OtherPath : FullPaths) {
3551 if (&SpecificPath == &OtherPath)
3553 if (llvm::all_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3554 return OtherPath.contains(BSO);
3565 const FullPathTy &FullPath) {
3573 assert(Offset.getQuantity() == -1);
3577 assert(Offset.getQuantity() != -1);
3583 return BS.getType()->getAsCXXRecordDecl() == Base;
3598 std::list<FullPathTy> &FullPaths) {
3600 if (FullPaths.empty())
3602 if (FullPaths.size() == 1)
3603 return &FullPaths.front();
3605 const FullPathTy *BestPath =
nullptr;
3606 typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3607 OverriderSetTy LastOverrides;
3608 for (
const FullPathTy &SpecificPath : FullPaths) {
3609 assert(!SpecificPath.empty());
3610 OverriderSetTy CurrentOverrides;
3611 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3616 FinalOverriders Overriders(TopLevelRD,
CharUnits::Zero(), TopLevelRD);
3620 FinalOverriders::OverriderInfo OI =
3625 if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3631 if (llvm::none_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3632 return BSO.
getBase() == OverridingParent;
3635 CurrentOverrides.insert(OverridingMethod);
3637 OverriderSetTy NewOverrides =
3638 llvm::set_difference(CurrentOverrides, LastOverrides);
3639 if (NewOverrides.empty())
3641 OverriderSetTy MissingOverrides =
3642 llvm::set_difference(LastOverrides, CurrentOverrides);
3643 if (MissingOverrides.empty()) {
3645 BestPath = &SpecificPath;
3646 std::swap(CurrentOverrides, LastOverrides);
3651 const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3662 return BestPath ? BestPath : &FullPaths.front();
3669 FullPathTy FullPath;
3670 std::list<FullPathTy> FullPaths;
3671 for (
const std::unique_ptr<VPtrInfo>& Info : Paths) {
3674 BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath,
3678 Info->PathToIntroducingObject.clear();
3679 if (
const FullPathTy *BestPath =
3682 Info->PathToIntroducingObject.push_back(BSO.getBase());
3699void MicrosoftVTableContext::computeVTableRelatedInformation(
3704 if (VFPtrLocations.count(RD))
3710 auto VFPtrs = std::make_unique<VPtrInfoVector>();
3711 computeVTablePaths(
false, RD, *VFPtrs);
3713 VFPtrLocations[RD] = std::move(VFPtrs);
3716 MethodVFTableLocationsTy NewMethodLocations;
3717 for (
const std::unique_ptr<VPtrInfo> &VFPtr : *VFPtrLocations[RD]) {
3718 VFTableBuilder Builder(*
this, RD, *VFPtr);
3720 VFTableIdTy id(RD, VFPtr->FullOffsetInMDC);
3721 assert(VFTableLayouts.count(
id) == 0);
3723 Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
3724 VFTableLayouts[id] = std::make_unique<VTableLayout>(
3726 EmptyAddressPointsMap);
3727 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
3730 for (
const auto &
Loc : Builder.vtable_locations()) {
3731 auto Insert = NewMethodLocations.insert(
Loc);
3741 MethodVFTableLocations.insert_range(NewMethodLocations);
3743 dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3746void MicrosoftVTableContext::dumpMethodLocations(
3747 const CXXRecordDecl *RD,
const MethodVFTableLocationsTy &NewMethods,
3751 std::map<MethodVFTableLocation, std::string> IndicesMap;
3752 bool HasNonzeroOffset =
false;
3754 for (
const auto &I : NewMethods) {
3755 const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I.first.getDecl());
3761 if (isa<CXXDestructorDecl>(MD)) {
3762 IndicesMap[I.second] = MethodName +
" [scalar deleting]";
3764 IndicesMap[I.second] = MethodName;
3767 if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0)
3768 HasNonzeroOffset =
true;
3772 if (!IndicesMap.empty()) {
3773 Out <<
"VFTable indices for ";
3776 Out <<
"' (" << IndicesMap.size()
3777 << (IndicesMap.size() == 1 ?
" entry" :
" entries") <<
").\n";
3781 for (
const auto &I : IndicesMap) {
3782 CharUnits VFPtrOffset = I.first.VFPtrOffset;
3783 uint64_t VBIndex = I.first.VBTableIndex;
3784 if (HasNonzeroOffset &&
3785 (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3786 assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3787 Out <<
" -- accessible via ";
3789 Out <<
"vbtable index " << VBIndex <<
", ";
3790 Out <<
"vfptr at offset " << VFPtrOffset.
getQuantity() <<
" --\n";
3791 LastVFPtrOffset = VFPtrOffset;
3792 LastVBIndex = VBIndex;
3795 uint64_t VTableIndex = I.first.Index;
3796 const std::string &MethodName = I.second;
3797 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName <<
'\n';
3805const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation(
3812 std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD];
3815 Entry = std::make_unique<VirtualBaseInfo>();
3819 computeVTablePaths(
true, RD, VBI->
VBPtrPaths);
3827 computeVBTableRelatedInformation(VBPtrBase);
3834 for (
const auto &VB : RD->
vbases()) {
3835 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3836 if (VBI->
VBTableIndices.try_emplace(CurVBase, VBTableIndex).second)
3845 const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived);
3852 return computeVBTableRelatedInformation(RD).
VBPtrPaths;
3857 computeVTableRelatedInformation(RD);
3859 assert(VFPtrLocations.count(RD) &&
"Couldn't find vfptr locations");
3860 return *VFPtrLocations[RD];
3866 computeVTableRelatedInformation(RD);
3868 VFTableIdTy id(RD, VFPtrOffset);
3869 assert(VFTableLayouts.count(
id) &&
"Couldn't find a VFTable at this offset");
3870 return *VFTableLayouts[id];
3876 "Only use this method for virtual methods or dtors");
3877 if (isa<CXXDestructorDecl>(GD.
getDecl()))
3882 MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
3883 if (I != MethodVFTableLocations.end())
3888 computeVTableRelatedInformation(RD);
3890 I = MethodVFTableLocations.find(GD);
3891 assert(I != MethodVFTableLocations.end() &&
"Did not find index!");
Defines the clang::ASTContext interface.
ASTImporterLookupTable & LT
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
static Decl::Kind getKind(const Decl *D)
static QualType getPointeeType(const MemRegion *R)
static void findPathsToSubobject(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout, const CXXRecordDecl *RD, CharUnits Offset, BaseSubobject IntroducingObject, FullPathTy &FullPath, std::list< FullPathTy > &Paths)
static const FullPathTy * selectBestPath(ASTContext &Context, const CXXRecordDecl *RD, const VPtrInfo &Info, std::list< FullPathTy > &FullPaths)
static CharUnits getOffsetOfFullPath(ASTContext &Context, const CXXRecordDecl *RD, const FullPathTy &FullPath)
static void removeRedundantPaths(std::list< FullPathTy > &FullPaths)
static std::unique_ptr< VTableLayout > CreateVTableLayout(const ItaniumVTableBuilder &Builder)
static bool vfptrIsEarlierInMDC(const ASTRecordLayout &Layout, const MethodVFTableLocation &LHS, const MethodVFTableLocation &RHS)
static bool isDirectVBase(const CXXRecordDecl *Base, const CXXRecordDecl *RD)
static void PrintBasePath(const VPtrInfo::BasePath &Path, raw_ostream &Out)
static VTableLayout::AddressPointsIndexMapTy MakeAddressPointIndices(const VTableLayout::AddressPointsMapTy &addressPoints, unsigned numVTables)
static bool rebucketPaths(VPtrInfoVector &Paths)
static bool extendPath(VPtrInfo &P)
static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out, bool ContinueFirstLine)
static void GroupNewVirtualOverloads(const CXXRecordDecl *RD, SmallVector< const CXXMethodDecl *, 10 > &VirtualMethods)
static void computeFullPathsForVFTables(ASTContext &Context, const CXXRecordDecl *RD, VPtrInfoVector &Paths)
static bool setsIntersect(const llvm::SmallPtrSet< const CXXRecordDecl *, 4 > &A, ArrayRef< const CXXRecordDecl * > B)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const LangOptions & getLangOpts() const
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
const CXXRecordDecl * getBaseSharingVBPtr() const
bool hasOwnVBPtr() const
hasOwnVBPtr - Does this class provide its own virtual-base table pointer, rather than inheriting one ...
llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
const VBaseOffsetsMapTy & getVBaseOffsetsMap() const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not.
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
Represents a base class of a C++ class.
bool isVirtual() const
Determines whether the base class is a virtual base class (or not).
QualType getType() const
Retrieves the type of the base class.
Represents a C++ destructor within a class.
A mapping from each virtual member function to its set of final overriders.
Represents a static or instance method of a struct/union/class.
overridden_method_range overridden_methods() const
unsigned size_overridden_methods() const
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getThisType() const
Return the type of the this pointer.
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Represents a C++ struct/union/class.
base_class_iterator bases_end()
method_range methods() const
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
base_class_iterator bases_begin()
base_class_range vbases()
base_class_iterator vbases_begin()
bool isDynamicClass() const
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const
Retrieve the final overriders for each virtual member function in the class hierarchy where this clas...
CXXRecordDecl * getDefinitionOrSelf() const
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
CanProxy< U > getAs() const
Retrieve a canonical type pointer with a different static type, upcasting or downcasting as needed.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
SourceLocation getLocation() const
The name of a declaration.
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
bool isImmediateFunction() const
QualType getReturnType() const
bool isDeleted() const
Whether this function has been deleted.
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
Represents a prototype with parameter type info, e.g.
Qualifiers getMethodQuals() const
ArrayRef< QualType > getParamTypes() const
FunctionType - C99 6.7.5.3 - Function Declarators.
QualType getReturnType() const
GlobalDecl - represents a global declaration.
GlobalDecl getCanonicalDecl() const
CXXDtorType getDtorType() const
const Decl * getDecl() const
const CXXMethodDecl * findOriginalMethodInMap(const CXXMethodDecl *MD) const
uint64_t getMethodVTableIndex(GlobalDecl GD)
Locate a virtual function in the vtable.
std::unique_ptr< VTableLayout > createConstructionVTableLayout(const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset, bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass)
~ItaniumVTableContext() override
CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, const CXXRecordDecl *VBase)
Return the offset in chars (relative to the vtable address point) where the offset of the virtual bas...
ItaniumVTableContext(ASTContext &Context, VTableComponentLayout ComponentLayout=Pointer)
GlobalDecl findOriginalMethod(GlobalDecl GD)
Return the method that added the v-table slot that will be used to call the given method.
unsigned getVBTableIndex(const CXXRecordDecl *Derived, const CXXRecordDecl *VBase)
Returns the index of VBase in the vbtable of Derived.
const VPtrInfoVector & enumerateVBTables(const CXXRecordDecl *RD)
MethodVFTableLocation getMethodVFTableLocation(GlobalDecl GD)
const VPtrInfoVector & getVFPtrOffsets(const CXXRecordDecl *RD)
const VTableLayout & getVFTableLayout(const CXXRecordDecl *RD, CharUnits VFPtrOffset)
~MicrosoftVTableContext() override
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
std::string getQualifiedNameAsString() const
void printQualifiedName(raw_ostream &OS) const
Returns a human-readable qualified name for this declaration, like A::B::i, for i being member of nam...
The set of methods that override a given virtual method in each subobject where it occurs.
PointerType - C99 6.7.5.1 - Pointer Declarators.
static std::string ComputeName(PredefinedIdentKind IK, const Decl *CurrentDecl, bool ForceElaboratedPrinting=false)
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
QualType getCanonicalType() const
Base for LValueReferenceType and RValueReferenceType.
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const T * castAs() const
Member-template castAs<specific type>.
Represents a single component in a vtable.
static VTableComponent MakeCompleteDtor(const CXXDestructorDecl *DD)
static VTableComponent MakeRTTI(const CXXRecordDecl *RD)
const CXXMethodDecl * getUnusedFunctionDecl() const
static VTableComponent MakeOffsetToTop(CharUnits Offset)
CharUnits getVBaseOffset() const
static VTableComponent MakeUnusedFunction(const CXXMethodDecl *MD)
Kind getKind() const
Get the kind of this vtable component.
static VTableComponent MakeFunction(const CXXMethodDecl *MD)
@ CK_DeletingDtorPointer
A pointer to the deleting destructor.
@ CK_UnusedFunctionPointer
An entry that is never used.
@ CK_CompleteDtorPointer
A pointer to the complete destructor.
static VTableComponent MakeVBaseOffset(CharUnits Offset)
const CXXRecordDecl * getRTTIDecl() const
static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD)
CharUnits getOffsetToTop() const
const CXXMethodDecl * getFunctionDecl() const
static VTableComponent MakeVCallOffset(CharUnits Offset)
CharUnits getVCallOffset() const
const CXXDestructorDecl * getDestructorDecl() const
static bool hasVtableSlot(const CXXMethodDecl *MD)
Determine whether this function should be assigned a vtable slot.
ThunksMapTy Thunks
Contains all thunks that a given method decl will need.
VTableLayout(ArrayRef< size_t > VTableIndices, ArrayRef< VTableComponent > VTableComponents, ArrayRef< VTableThunkTy > VTableThunks, const AddressPointsMapTy &AddressPoints)
llvm::DenseMap< BaseSubobject, AddressPointLocation > AddressPointsMapTy
std::pair< uint64_t, ThunkInfo > VTableThunkTy
Defines the clang::TargetInfo interface.
bool Ret(InterpState &S, CodePtr &PC)
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
const FunctionProtoType * T
@ PrettyFunctionNoVirtual
The same as PrettyFunction, except that the 'virtual' keyword is omitted for virtual member functions...
Represents an element in a path from a derived class to a base class.
const CXXRecordDecl * VBase
If nonnull, holds the last vbase which contains the vfptr that the method definition is adjusted to.
CharUnits VFPtrOffset
This is the offset of the vfptr from the start of the last vbase, or the complete type if there are n...
union clang::ReturnAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
A this pointer adjustment.
union clang::ThisAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
The this pointer adjustment as well as an optional return adjustment for a thunk.
ThisAdjustment This
The this pointer adjustment.
const CXXMethodDecl * Method
Holds a pointer to the overridden method this thunk is for, if needed by the ABI to distinguish diffe...
ReturnAdjustment Return
The return adjustment.
Uniquely identifies a virtual method within a class hierarchy by the method itself and a class subobj...
Holds information about the inheritance path to a virtual base or function table pointer.
CharUnits NonVirtualOffset
IntroducingObject is at this offset from its containing complete object or virtual base.
CharUnits FullOffsetInMDC
Static offset from the top of the most derived class to this vfptr, including any virtual base offset...
const CXXRecordDecl * getVBaseWithVPtr() const
The vptr is stored inside the non-virtual component of this virtual base.
const CXXRecordDecl * IntroducingObject
This is the class that introduced the vptr by declaring new virtual methods or virtual bases.
BasePath MangledPath
The bases from the inheritance path that got used to mangle the vbtable name.
BasePath PathToIntroducingObject
This holds the base classes path from the complete type to the first base with the given vfptr offset...
All virtual base related information about a given record decl.
VPtrInfoVector VBPtrPaths
Information on all virtual base tables used when this record is the most derived class.
llvm::DenseMap< const CXXRecordDecl *, unsigned > VBTableIndices
A map from virtual base to vbtable index for doing a conversion from the the derived class to the a b...
struct clang::ReturnAdjustment::VirtualAdjustment::@179 Itanium
struct clang::ReturnAdjustment::VirtualAdjustment::@180 Microsoft
uint32_t VBPtrOffset
The offset (in bytes) of the vbptr, relative to the beginning of the derived class.
int64_t VBaseOffsetOffset
The offset (in bytes), relative to the address point of the virtual base class offset.
uint32_t VBIndex
Index of the virtual base in the vbtable.
struct clang::ThisAdjustment::VirtualAdjustment::@182 Microsoft
int32_t VtordispOffset
The offset of the vtordisp (in bytes), relative to the ECX.
int32_t VBOffsetOffset
The offset (in bytes) of the vbase offset in the vbtable.
int64_t VCallOffsetOffset
The offset (in bytes), relative to the address point, of the virtual call offset.
int32_t VBPtrOffset
The offset of the vbptr of the derived class (in bytes), relative to the ECX after vtordisp adjustmen...
struct clang::ThisAdjustment::VirtualAdjustment::@181 Itanium