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),
164 MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) {
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) {
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,
281 Context.getCanonicalType(BaseFT->getReturnType());
283 assert(CanDerivedReturnType->getTypeClass() ==
284 CanBaseReturnType->getTypeClass() &&
285 "Types must have same type class!");
287 if (CanDerivedReturnType == CanBaseReturnType) {
293 CanDerivedReturnType =
298 CanDerivedReturnType =
303 llvm_unreachable(
"Unexpected return type!");
309 if (CanDerivedReturnType.getUnqualifiedType() ==
315 const auto *DerivedRD =
317 ->getDefinitionOrSelf();
322 return ComputeBaseOffset(Context, BaseRD, DerivedRD);
328 SubobjectOffsetMapTy &SubobjectOffsets,
329 SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
330 SubobjectCountMapTy &SubobjectCounts) {
333 unsigned SubobjectNumber = 0;
335 SubobjectNumber = ++SubobjectCounts[RD];
338 assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
339 &&
"Subobject offset already exists!");
340 assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
341 &&
"Subobject offset already exists!");
343 SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] =
Base.getBaseOffset();
344 SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
348 for (
const auto &B : RD->
bases()) {
349 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
355 if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0)))
359 Context.getASTRecordLayout(LayoutClass);
362 BaseOffsetInLayoutClass =
368 BaseOffset =
Base.getBaseOffset() + Offset;
369 BaseOffsetInLayoutClass = OffsetInLayoutClass + Offset;
373 B.isVirtual(), BaseOffsetInLayoutClass,
374 SubobjectOffsets, SubobjectLayoutClassOffsets,
380 VisitedVirtualBasesSetTy &VisitedVirtualBases) {
384 for (
const auto &B : RD->
bases()) {
385 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
393 if (!VisitedVirtualBases.insert(BaseDecl).second) {
406 Out <<
"Final overriders for (";
409 Out <<
Base.getBaseOffset().getQuantity() <<
")\n";
412 for (
const auto *MD : RD->
methods()) {
415 MD = MD->getCanonicalDecl();
417 OverriderInfo Overrider = getOverrider(MD,
Base.getBaseOffset());
420 MD->printQualifiedName(Out);
422 Overrider.Method->printQualifiedName(Out);
423 Out <<
", " << Overrider.Offset.getQuantity() <<
')';
426 if (!Overrider.Method->isPureVirtual())
427 Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
429 if (!Offset.isEmpty()) {
430 Out <<
" [ret-adj: ";
431 if (Offset.VirtualBase) {
432 Offset.VirtualBase->printQualifiedName(Out);
436 Out << Offset.NonVirtualOffset.getQuantity() <<
" nv]";
444struct VCallOffsetMap {
446 typedef std::pair<const CXXMethodDecl *, CharUnits> MethodAndOffsetPairTy;
454 static bool MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
468 bool empty()
const {
return Offsets.empty(); }
479 if (LT == RT)
return true;
489bool VCallOffsetMap::MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
503 if (LHSName != RHSName)
507 return HasSameVirtualSignature(LHS, RHS);
513 for (
const auto &OffsetPair : Offsets) {
514 if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
519 Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
525 for (
const auto &OffsetPair : Offsets) {
526 if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
527 return OffsetPair.second;
530 llvm_unreachable(
"Should always find a vcall offset offset!");
534class VCallAndVBaseOffsetBuilder {
536 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
537 VBaseOffsetOffsetsMapTy;
556 VTableComponentVectorTy Components;
562 VCallOffsetMap VCallOffsets;
567 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
571 const FinalOverriders *Overriders;
587 CharUnits getCurrentOffsetOffset()
const;
593 const FinalOverriders *Overriders,
596 : VTables(VTables), MostDerivedClass(MostDerivedClass),
597 LayoutClass(LayoutClass), Context(MostDerivedClass->
getASTContext()),
598 Overriders(Overriders) {
601 AddVCallAndVBaseOffsets(
Base, BaseIsVirtual, OffsetInLayoutClass);
605 typedef VTableComponentVectorTy::const_reverse_iterator
const_iterator;
606 const_iterator components_begin()
const {
return Components.rbegin(); }
607 const_iterator components_end()
const {
return Components.rend(); }
609 const VCallOffsetMap &getVCallOffsets()
const {
return VCallOffsets; }
610 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
611 return VBaseOffsetOffsets;
636 if (PrimaryBaseIsVirtual) {
638 "Primary vbase should have a zero offset!");
641 Context.getASTRecordLayout(MostDerivedClass);
647 "Primary base should have a zero offset!");
649 PrimaryBaseOffset =
Base.getBaseOffset();
652 AddVCallAndVBaseOffsets(
654 PrimaryBaseIsVirtual, RealBaseOffset);
657 AddVBaseOffsets(
Base.getBase(), RealBaseOffset);
661 AddVCallOffsets(
Base, RealBaseOffset);
664CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset()
const {
669 size_t NumComponentsAboveAddrPoint = 3;
670 if (Context.getLangOpts().OmitVTableRTTI)
671 NumComponentsAboveAddrPoint--;
672 int64_t OffsetIndex =
673 -(int64_t)(NumComponentsAboveAddrPoint + Components.size());
677 CharUnits OffsetWidth = Context.toCharUnitsFromBits(
681 CharUnits OffsetOffset = OffsetWidth * OffsetIndex;
699 "Primary base should have a zero offset!");
706 for (
const auto *MD : RD->
methods()) {
711 CharUnits OffsetOffset = getCurrentOffsetOffset();
715 if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
722 FinalOverriders::OverriderInfo Overrider =
723 Overriders->getOverrider(MD,
Base.getBaseOffset());
727 Offset = Overrider.Offset - VBaseOffset;
730 Components.push_back(
735 for (
const auto &B : RD->
bases()) {
739 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
740 if (BaseDecl == PrimaryBase)
753VCallAndVBaseOffsetBuilder::AddVBaseOffsets(
const CXXRecordDecl *RD,
756 Context.getASTRecordLayout(LayoutClass);
759 for (
const auto &B : RD->
bases()) {
760 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
763 if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
768 assert(!VBaseOffsetOffsets.count(BaseDecl) &&
769 "vbase offset offset already exists!");
771 CharUnits VBaseOffsetOffset = getCurrentOffsetOffset();
772 VBaseOffsetOffsets.insert(
773 std::make_pair(BaseDecl, VBaseOffsetOffset));
775 Components.push_back(
780 AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
785class ItaniumVTableBuilder {
790 PrimaryBasesSetVectorTy;
792 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
793 VBaseOffsetOffsetsMapTy;
797 typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
813 bool MostDerivedClassIsVirtual;
824 const FinalOverriders Overriders;
828 llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
832 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
838 AddressPointsMapTy AddressPoints;
852 const uint64_t VTableIndex;
855 uint64_t VTableIndex)
856 : BaseOffset(BaseOffset),
857 BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
858 VTableIndex(VTableIndex) { }
865 MethodInfo(MethodInfo
const&) =
default;
868 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
872 MethodInfoMapTy MethodInfoMap;
876 MethodVTableIndicesTy MethodVTableIndices;
878 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
882 VTableThunksMapTy VTableThunks;
885 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
896 void ComputeThisAdjustments();
902 VisitedVirtualBasesSetTy PrimaryVirtualBases;
919 FinalOverriders::OverriderInfo Overrider);
947 CharUnits FirstBaseOffsetInLayoutClass)
const;
955 PrimaryBasesSetVectorTy &PrimaryBases);
970 bool BaseIsMorallyVirtual,
971 bool BaseIsVirtualInLayoutClass,
986 VisitedVirtualBasesSetTy &VBases);
991 VisitedVirtualBasesSetTy &VBases);
995 bool isBuildingConstructorVTable()
const {
996 return MostDerivedClass != LayoutClass;
1007 bool MostDerivedClassIsVirtual,
1009 : VTables(VTables), MostDerivedClass(MostDerivedClass),
1010 MostDerivedClassOffset(MostDerivedClassOffset),
1011 MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
1012 LayoutClass(LayoutClass), Context(MostDerivedClass->
getASTContext()),
1013 Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
1014 assert(!Context.getTargetInfo().getCXXABI().isMicrosoft());
1018 if (Context.getLangOpts().DumpVTableLayouts)
1019 dumpLayout(llvm::outs());
1022 uint64_t getNumThunks()
const {
1023 return Thunks.size();
1026 ThunksMapTy::const_iterator thunks_begin()
const {
1027 return Thunks.begin();
1030 ThunksMapTy::const_iterator thunks_end()
const {
1031 return Thunks.end();
1034 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
1035 return VBaseOffsetOffsets;
1038 const AddressPointsMapTy &getAddressPoints()
const {
1039 return AddressPoints;
1042 MethodVTableIndicesTy::const_iterator vtable_indices_begin()
const {
1043 return MethodVTableIndices.begin();
1046 MethodVTableIndicesTy::const_iterator vtable_indices_end()
const {
1047 return MethodVTableIndices.end();
1052 AddressPointsMapTy::const_iterator address_points_begin()
const {
1053 return AddressPoints.begin();
1056 AddressPointsMapTy::const_iterator address_points_end()
const {
1057 return AddressPoints.end();
1060 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
1061 return VTableThunks.begin();
1064 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
1065 return VTableThunks.end();
1069 void dumpLayout(raw_ostream&);
1074 assert(!isBuildingConstructorVTable() &&
1075 "Can't add thunks for construction vtable");
1080 if (llvm::is_contained(ThunksVector, Thunk))
1083 ThunksVector.push_back(Thunk);
1092template <
class VisitorTy>
1094visitAllOverriddenMethods(
const CXXMethodDecl *MD, VisitorTy &Visitor) {
1098 if (!Visitor(OverriddenMD))
1100 visitAllOverriddenMethods(OverriddenMD, Visitor);
1108 OverriddenMethodsSetTy& OverriddenMethods) {
1109 auto OverriddenMethodsCollector = [&](
const CXXMethodDecl *MD) {
1111 return OverriddenMethods.insert(MD).second;
1113 visitAllOverriddenMethods(MD, OverriddenMethodsCollector);
1116void ItaniumVTableBuilder::ComputeThisAdjustments() {
1119 for (
const auto &MI : MethodInfoMap) {
1121 const MethodInfo &MethodInfo = MI.second;
1124 uint64_t VTableIndex = MethodInfo.VTableIndex;
1125 if (Components[VTableIndex].
getKind() ==
1130 FinalOverriders::OverriderInfo Overrider =
1131 Overriders.getOverrider(MD, MethodInfo.BaseOffset);
1134 if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
1140 if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
1145 ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
1151 auto SetThisAdjustmentThunk = [&](uint64_t Idx) {
1173 auto [It, Inserted] = VTableThunks.try_emplace(Idx);
1176 It->second.Method = Method;
1182 SetThisAdjustmentThunk(VTableIndex);
1186 SetThisAdjustmentThunk(VTableIndex + 1);
1191 MethodInfoMap.clear();
1193 if (isBuildingConstructorVTable()) {
1198 for (
const auto &TI : VTableThunks) {
1203 switch (Component.
getKind()) {
1205 llvm_unreachable(
"Unexpected vtable component kind!");
1217 if (MD->
getParent() == MostDerivedClass)
1218 AddThunk(MD, Thunk);
1223ItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
1226 if (!Offset.isEmpty()) {
1227 if (Offset.VirtualBase) {
1229 if (Offset.DerivedClass == MostDerivedClass) {
1232 VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity();
1240 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1246BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
1255 llvm_unreachable(
"Class must be derived from the passed in base class!");
1260 BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, Path);
1262 CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
1264 if (Offset.VirtualBase) {
1268 Context.getASTRecordLayout(LayoutClass);
1272 OffsetToBaseSubobject +=
1281 if (OffsetToBaseSubobject ==
Base.getBaseOffset()) {
1284 Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
1289 return BaseOffset();
1294 FinalOverriders::OverriderInfo Overrider) {
1300 BaseOffsetInLayoutClass);
1306 BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
1307 OverriderBaseSubobject);
1308 if (Offset.isEmpty())
1313 if (Offset.VirtualBase) {
1315 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
1317 if (VCallOffsets.empty()) {
1320 VCallAndVBaseOffsetBuilder Builder(
1321 VTables, MostDerivedClass, MostDerivedClass,
1328 VCallOffsets = Builder.getVCallOffsets();
1332 VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
1336 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1341void ItaniumVTableBuilder::AddMethod(
const CXXMethodDecl *MD,
1345 "Destructor can't have return adjustment!");
1371static bool OverridesIndirectMethodInBases(
1373 ItaniumVTableBuilder::PrimaryBasesSetVectorTy &Bases) {
1379 if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
1386bool ItaniumVTableBuilder::IsOverriderUsed(
1389 CharUnits FirstBaseOffsetInLayoutClass)
const {
1392 if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
1401 if (Overrider->getParent() == FirstBaseInPrimaryBaseChain)
1404 ItaniumVTableBuilder::PrimaryBasesSetVectorTy PrimaryBases;
1407 PrimaryBases.insert(RD);
1420 "Primary base should always be at offset 0!");
1423 Context.getASTRecordLayout(LayoutClass);
1428 FirstBaseOffsetInLayoutClass) {
1434 "Primary base should always be at offset 0!");
1437 if (!PrimaryBases.insert(PrimaryBase))
1438 llvm_unreachable(
"Found a duplicate primary base!");
1445 return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
1455 BasesSetVectorTy &Bases) {
1456 OverriddenMethodsSetTy OverriddenMethods;
1457 ComputeAllOverriddenMethods(MD, OverriddenMethods);
1459 for (
const CXXRecordDecl *PrimaryBase : llvm::reverse(Bases)) {
1461 for (
const CXXMethodDecl *OverriddenMD : OverriddenMethods) {
1463 if (OverriddenMD->getParent() == PrimaryBase)
1464 return OverriddenMD;
1471void ItaniumVTableBuilder::AddMethods(
1475 PrimaryBasesSetVectorTy &PrimaryBases) {
1490 CharUnits PrimaryBaseOffsetInLayoutClass;
1493 "Primary vbase should have a zero offset!");
1496 Context.getASTRecordLayout(MostDerivedClass);
1502 Context.getASTRecordLayout(LayoutClass);
1504 PrimaryBaseOffsetInLayoutClass =
1508 "Primary base should have a zero offset!");
1510 PrimaryBaseOffset =
Base.getBaseOffset();
1511 PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
1515 PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
1516 FirstBaseOffsetInLayoutClass, PrimaryBases);
1518 if (!PrimaryBases.insert(PrimaryBase))
1519 llvm_unreachable(
"Found a duplicate primary base!");
1523 NewVirtualFunctionsTy NewVirtualFunctions;
1528 for (
const auto *MD : RD->
methods()) {
1534 FinalOverriders::OverriderInfo Overrider =
1535 Overriders.getOverrider(MD,
Base.getBaseOffset());
1541 FindNearestOverriddenMethod(MD, PrimaryBases)) {
1542 if (ComputeReturnAdjustmentBaseOffset(Context, MD,
1543 OverriddenMD).isEmpty()) {
1548 assert(MethodInfoMap.count(OverriddenMD) &&
1549 "Did not find the overridden method!");
1550 MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
1552 MethodInfo MethodInfo(
Base.getBaseOffset(), BaseOffsetInLayoutClass,
1553 OverriddenMethodInfo.VTableIndex);
1555 assert(!MethodInfoMap.count(MD) &&
1556 "Should not have method info for this method yet!");
1558 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1559 MethodInfoMap.erase(OverriddenMD);
1565 if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
1568 ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
1572 Overrider.Method->
getParent() == MostDerivedClass) {
1577 BaseOffset ReturnAdjustmentOffset =
1578 ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
1580 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1583 AddThunk(Overrider.Method,
1585 OverriddenMD->getThisType().getTypePtr()));
1594 NewImplicitVirtualFunctions.push_back(MD);
1596 NewVirtualFunctions.push_back(MD);
1600 NewImplicitVirtualFunctions,
1612 "unexpected or duplicate implicit virtual function");
1617 NewVirtualFunctions.append(NewImplicitVirtualFunctions.begin(),
1618 NewImplicitVirtualFunctions.end());
1622 FinalOverriders::OverriderInfo Overrider =
1623 Overriders.getOverrider(MD,
Base.getBaseOffset());
1626 MethodInfo MethodInfo(
Base.getBaseOffset(), BaseOffsetInLayoutClass,
1629 assert(!MethodInfoMap.count(MD) &&
1630 "Should not have method info for this method yet!");
1631 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1635 if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
1636 FirstBaseInPrimaryBaseChain,
1637 FirstBaseOffsetInLayoutClass)) {
1644 BaseOffset ReturnAdjustmentOffset;
1646 ReturnAdjustmentOffset =
1647 ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
1651 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1658 auto &VTT = VTableThunks[Components.size()];
1667void ItaniumVTableBuilder::LayoutVTable() {
1668 LayoutPrimaryAndSecondaryVTables(
BaseSubobject(MostDerivedClass,
1671 MostDerivedClassIsVirtual,
1672 MostDerivedClassOffset);
1674 VisitedVirtualBasesSetTy VBases;
1677 DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
1681 LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
1684 bool IsAppleKext = Context.getLangOpts().AppleKext;
1689void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
1691 bool BaseIsVirtualInLayoutClass,
CharUnits OffsetInLayoutClass) {
1692 assert(
Base.getBase()->isDynamicClass() &&
"class does not have a vtable!");
1694 unsigned VTableIndex = Components.size();
1695 VTableIndices.push_back(VTableIndex);
1698 VCallAndVBaseOffsetBuilder Builder(
1699 VTables, MostDerivedClass, LayoutClass, &Overriders,
Base,
1700 BaseIsVirtualInLayoutClass, OffsetInLayoutClass);
1701 Components.append(Builder.components_begin(), Builder.components_end());
1704 if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
1705 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[
Base.getBase()];
1707 if (VCallOffsets.empty())
1708 VCallOffsets = Builder.getVCallOffsets();
1713 if (
Base.getBase() == MostDerivedClass)
1714 VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
1717 CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
1721 if (!Context.getLangOpts().OmitVTableRTTI)
1724 uint64_t AddressPoint = Components.size();
1727 PrimaryBasesSetVectorTy PrimaryBases;
1728 AddMethods(
Base, OffsetInLayoutClass,
1729 Base.getBase(), OffsetInLayoutClass,
1733 if (RD == MostDerivedClass) {
1734 assert(MethodVTableIndices.empty());
1735 for (
const auto &I : MethodInfoMap) {
1737 const MethodInfo &MI = I.second;
1740 = MI.VTableIndex - AddressPoint;
1742 = MI.VTableIndex + 1 - AddressPoint;
1744 MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
1750 ComputeThisAdjustments();
1754 AddressPoints.insert(
1757 unsigned(VTableIndices.size() - 1),
1758 unsigned(AddressPoint - VTableIndex)}));
1770 Context.getASTRecordLayout(LayoutClass);
1773 OffsetInLayoutClass) {
1783 LayoutSecondaryVTables(
Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
1788 bool BaseIsMorallyVirtual,
1799 for (
const auto &B : RD->
bases()) {
1804 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1810 if (isBuildingConstructorVTable()) {
1816 if (!BaseIsMorallyVirtual && !BaseDecl->
getNumVBases())
1822 CharUnits BaseOffset =
Base.getBaseOffset() + RelativeBaseOffset;
1825 OffsetInLayoutClass + RelativeBaseOffset;
1829 if (BaseDecl == PrimaryBase) {
1831 BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
1836 LayoutPrimaryAndSecondaryVTables(
1838 BaseIsMorallyVirtual,
1840 BaseOffsetInLayoutClass);
1844void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
1846 VisitedVirtualBasesSetTy &VBases) {
1854 bool IsPrimaryVirtualBase =
true;
1856 if (isBuildingConstructorVTable()) {
1860 Context.getASTRecordLayout(LayoutClass);
1862 CharUnits PrimaryBaseOffsetInLayoutClass =
1867 if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
1868 IsPrimaryVirtualBase =
false;
1871 if (IsPrimaryVirtualBase)
1872 PrimaryVirtualBases.insert(PrimaryBase);
1877 for (
const auto &B : RD->
bases()) {
1878 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1882 if (B.isVirtual()) {
1883 if (!VBases.insert(BaseDecl).second)
1887 Context.getASTRecordLayout(LayoutClass);
1889 BaseOffsetInLayoutClass =
1892 BaseOffsetInLayoutClass =
1896 DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
1900void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
1901 const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) {
1906 for (
const auto &B : RD->
bases()) {
1907 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1912 !PrimaryVirtualBases.count(BaseDecl) &&
1913 VBases.insert(BaseDecl).second) {
1915 Context.getASTRecordLayout(MostDerivedClass);
1920 Context.getASTRecordLayout(LayoutClass);
1924 LayoutPrimaryAndSecondaryVTables(
1928 BaseOffsetInLayoutClass);
1934 LayoutVTablesForVirtualBases(BaseDecl, VBases);
1938static void printThunkMethod(
const ThunkInfo &Info, raw_ostream &Out) {
1943 Out <<
" method: " << Str;
1947void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
1951 Out <<
"Original map\n";
1960 Out <<
" " << Str0 <<
" -> " << Str1 <<
"\n";
1963 if (isBuildingConstructorVTable()) {
1964 Out <<
"Construction vtable for ('";
1967 Out << MostDerivedClassOffset.
getQuantity() <<
") in '";
1970 Out <<
"Vtable for '";
1973 Out <<
"' (" << Components.size() <<
" entries).\n";
1979 std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
1980 for (
const auto &AP : AddressPoints) {
1983 VTableIndices[AP.second.VTableIndex] + AP.second.AddressPointIndex;
1985 AddressPointsByIndex.insert(std::make_pair(Index,
Base));
1988 for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
1991 Out << llvm::format(
"%4d | ", I);
1996 switch (Component.
getKind()) {
1999 Out <<
"vcall_offset ("
2005 Out <<
"vbase_offset ("
2011 Out <<
"offset_to_top ("
2031 Out <<
" [deleted]";
2033 ThunkInfo Thunk = VTableThunks.lookup(I);
2037 Out <<
"\n [return adjustment: ";
2042 Out <<
" vbase offset offset";
2046 printThunkMethod(Thunk, Out);
2051 Out <<
"\n [this adjustment: ";
2056 Out <<
" vcall offset offset";
2060 printThunkMethod(Thunk, Out);
2076 Out <<
"() [complete]";
2078 Out <<
"() [deleting]";
2083 ThunkInfo Thunk = VTableThunks.lookup(I);
2087 Out <<
"\n [this adjustment: ";
2092 Out <<
" vcall offset offset";
2097 printThunkMethod(Thunk, Out);
2108 Out <<
"[unused] " << Str;
2118 uint64_t NextIndex = Index + 1;
2119 if (
unsigned Count = AddressPointsByIndex.count(NextIndex)) {
2122 AddressPointsByIndex.find(NextIndex)->second;
2125 Base.getBase()->printQualifiedName(Out);
2126 Out <<
", " <<
Base.getBaseOffset().getQuantity();
2127 Out <<
") vtable address --\n";
2130 AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
2133 std::set<std::string> ClassNames;
2134 for (
const auto &I :
2135 llvm::make_range(AddressPointsByIndex.equal_range(NextIndex))) {
2136 assert(I.second.getBaseOffset() == BaseOffset &&
2137 "Invalid base offset!");
2142 for (
const std::string &Name : ClassNames) {
2143 Out <<
" -- (" << Name;
2144 Out <<
", " << BaseOffset.getQuantity() <<
") vtable address --\n";
2152 if (isBuildingConstructorVTable())
2159 std::map<std::string, CharUnits> ClassNamesAndOffsets;
2160 for (
const auto &I : VBaseOffsetOffsets) {
2161 std::string ClassName = I.first->getQualifiedNameAsString();
2163 ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
2166 Out <<
"Virtual base offset offsets for '";
2169 Out << ClassNamesAndOffsets.size();
2170 Out << (ClassNamesAndOffsets.size() == 1 ?
" entry" :
" entries") <<
").\n";
2172 for (
const auto &I : ClassNamesAndOffsets)
2173 Out <<
" " << I.first <<
" | " << I.second.getQuantity() <<
'\n';
2178 if (!Thunks.empty()) {
2180 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
2182 for (
const auto &I : Thunks) {
2187 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
2190 for (
const auto &I : MethodNamesAndDecls) {
2191 const std::string &MethodName = I.first;
2194 ThunkInfoVectorTy ThunksVector = Thunks[MD];
2199 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
2200 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
2202 for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
2203 const ThunkInfo &Thunk = ThunksVector[I];
2205 Out << llvm::format(
"%4d | ", I);
2210 Out <<
" non-virtual";
2213 Out <<
" vbase offset offset";
2222 Out <<
"this adjustment: ";
2227 Out <<
" vcall offset offset";
2240 std::map<uint64_t, std::string> IndicesMap;
2242 for (
const auto *MD : MostDerivedClass->
methods()) {
2253 assert(MethodVTableIndices.count(GD));
2254 uint64_t VTableIndex = MethodVTableIndices[GD];
2255 IndicesMap[VTableIndex] = MethodName +
" [complete]";
2256 IndicesMap[VTableIndex + 1] = MethodName +
" [deleting]";
2258 assert(MethodVTableIndices.count(MD));
2259 IndicesMap[MethodVTableIndices[MD]] = MethodName;
2264 if (!IndicesMap.empty()) {
2265 Out <<
"VTable indices for '";
2267 Out <<
"' (" << IndicesMap.size() <<
" entries).\n";
2269 for (
const auto &I : IndicesMap) {
2270 uint64_t VTableIndex = I.first;
2271 const std::string &MethodName = I.second;
2273 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName
2284 unsigned numVTables) {
2287 for (
auto it = addressPoints.begin(); it != addressPoints.end(); ++it) {
2288 const auto &addressPointLoc = it->second;
2289 unsigned vtableIndex = addressPointLoc.VTableIndex;
2290 unsigned addressPoint = addressPointLoc.AddressPointIndex;
2291 if (indexMap[vtableIndex]) {
2294 assert(indexMap[vtableIndex] == addressPoint &&
2295 "Every vtable index should have a unique address point. Found a "
2296 "vtable that has two different address points.");
2298 indexMap[vtableIndex] = addressPoint;
2313 : VTableIndices(
std::move(VTableIndices)),
2314 VTableComponents(VTableComponents), VTableThunks(VTableThunks),
2315 AddressPoints(AddressPoints),
2316 AddressPointIndices(
2318 assert(!this->VTableIndices.empty() &&
2319 "VTableLayout requires at least one index.");
2320 assert(this->VTableIndices.front() == 0 &&
2321 "VTableLayout requires the first index is 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!");
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());
2448 const CXXRecordDecl *VBase =
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;
2590 typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
2591 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
2598 void AddThunk(
const CXXMethodDecl *MD,
const ThunkInfo &Thunk) {
2599 SmallVector<ThunkInfo, 1> &ThunksVector = Thunks[MD];
2602 if (llvm::is_contained(ThunksVector, Thunk))
2605 ThunksVector.push_back(Thunk);
2610 CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2612 void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
2613 CharUnits ThisOffset, ThisAdjustment &TA);
2617 void AddMethod(
const CXXMethodDecl *MD, ThunkInfo TI) {
2619 VTableThunks[Components.size()] = TI;
2622 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2624 "Destructor can't have return adjustment!");
2633 void AddMethods(BaseSubobject Base,
unsigned BaseDepth,
2634 const CXXRecordDecl *LastVBase,
2635 BasesSetVectorTy &VisitedBases);
2637 void LayoutVFTable() {
2639 if (HasRTTIComponent)
2642 BasesSetVectorTy VisitedBases;
2643 AddMethods(BaseSubobject(MostDerivedClass,
CharUnits::Zero()), 0,
nullptr,
2647 assert(!Components.empty() &&
"vftable can't be empty");
2649 assert(MethodVFTableLocations.empty());
2650 for (
const auto &I : MethodInfoMap) {
2651 const CXXMethodDecl *MD = I.first;
2652 const MethodInfo &MI = I.second;
2657 if (MD->
getParent() != MostDerivedClass || MI.Shadowed)
2661 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2667 MethodVFTableLocations[GlobalDecl(DD, DtorTy)] = Loc;
2669 MethodVFTableLocations[MD] = Loc;
2675 VFTableBuilder(MicrosoftVTableContext &VTables,
2676 const CXXRecordDecl *MostDerivedClass,
const VPtrInfo &Which)
2678 Context(MostDerivedClass->getASTContext()),
2679 MostDerivedClass(MostDerivedClass),
2680 MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)),
2682 Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) {
2689 HasRTTIComponent =
true;
2694 dumpLayout(llvm::outs());
2697 uint64_t getNumThunks()
const {
return Thunks.size(); }
2699 ThunksMapTy::const_iterator thunks_begin()
const {
return Thunks.begin(); }
2701 ThunksMapTy::const_iterator thunks_end()
const {
return Thunks.end(); }
2703 method_locations_range vtable_locations()
const {
2704 return method_locations_range(MethodVFTableLocations.begin(),
2705 MethodVFTableLocations.end());
2708 ArrayRef<VTableComponent> vtable_components()
const {
return Components; }
2710 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
2711 return VTableThunks.begin();
2714 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
2715 return VTableThunks.end();
2718 void dumpLayout(raw_ostream &);
2778VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2779 BasesSetVectorTy Bases;
2783 OverriddenMethodsSetTy VisitedOverriddenMethods;
2784 auto InitialOverriddenDefinitionCollector = [&](
2786 if (OverriddenMD->size_overridden_methods() == 0)
2787 Bases.insert(OverriddenMD->getParent());
2789 return VisitedOverriddenMethods.insert(OverriddenMD).second;
2791 visitAllOverriddenMethods(Overrider.Method,
2792 InitialOverriddenDefinitionCollector);
2797 if (Bases.size() == 0)
2798 return Overrider.Offset;
2803 return Bases.count(
Specifier->getType()->getAsCXXRecordDecl());
2817 CharUnits ThisOffset = Overrider.Offset;
2824 QualType CurTy = Element.Base->getType();
2829 if (Element.Base->isVirtual()) {
2840 LastVBaseOffset = ThisOffset =
2848 if (LastVBaseOffset.
isZero()) {
2852 ThisOffset = Overrider.Offset;
2856 ThisOffset = LastVBaseOffset;
2860 if (Ret > ThisOffset ||
First) {
2866 assert(!
First &&
"Method not found in the given subobject?");
2968void VFTableBuilder::CalculateVtordispAdjustment(
2969 FinalOverriders::OverriderInfo Overrider,
CharUnits ThisOffset,
2973 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2975 assert(VBaseMapEntry != VBaseMap.end());
2979 if (!VBaseMapEntry->second.hasVtorDisp() ||
2985 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2987 (OffsetOfVBaseWithVFPtr - WhichVFPtr.
FullOffsetInMDC).getQuantity() - 4;
2991 if (Overrider.Method->
getParent() == MostDerivedClass ||
2992 !Overrider.VirtualBase)
3004 TA.
NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
3018 typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
3019 VisitedGroupIndicesTy VisitedGroupIndices;
3020 for (
const auto *D : RD->
decls()) {
3021 const auto *ND = dyn_cast<NamedDecl>(D);
3024 VisitedGroupIndicesTy::iterator J;
3026 std::tie(J, Inserted) = VisitedGroupIndices.insert(
3027 std::make_pair(ND->getDeclName(), Groups.size()));
3029 Groups.push_back(MethodGroup());
3030 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND))
3035 for (
const MethodGroup &Group : Groups)
3036 VirtualMethods.append(Group.rbegin(), Group.rend());
3040 for (
const auto &B : RD->
bases()) {
3041 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() ==
Base)
3047void VFTableBuilder::AddMethods(
BaseSubobject Base,
unsigned BaseDepth,
3049 BasesSetVectorTy &VisitedBases) {
3059 const CXXRecordDecl *NextBase =
nullptr, *NextLastVBase = LastVBase;
3064 NextLastVBase = NextBase;
3072 "No primary virtual bases in this ABI");
3073 NextBase = PrimaryBase;
3074 NextBaseOffset =
Base.getBaseOffset();
3078 AddMethods(
BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
3079 NextLastVBase, VisitedBases);
3080 if (!VisitedBases.insert(NextBase))
3081 llvm_unreachable(
"Found a duplicate primary base!");
3097 FinalOverriders::OverriderInfo FinalOverrider =
3098 Overriders.getOverrider(MD,
Base.getBaseOffset());
3099 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
3101 FindNearestOverriddenMethod(MD, VisitedBases);
3104 bool ReturnAdjustingThunk =
false, ForceReturnAdjustmentMangling =
false;
3105 CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
3108 if ((OverriddenMD || FinalOverriderMD != MD) &&
3110 CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
3111 ThisAdjustmentOffset);
3119 MethodInfoMapTy::iterator OverriddenMDIterator =
3120 MethodInfoMap.find(OverriddenMD);
3123 if (OverriddenMDIterator == MethodInfoMap.end())
3126 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
3128 VBIndex = OverriddenMethodInfo.VBTableIndex;
3135 ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
3136 Context, MD, OverriddenMD).isEmpty() ||
3137 OverriddenMethodInfo.UsesExtraSlot;
3139 if (!ReturnAdjustingThunk) {
3142 MethodInfo MI(VBIndex, OverriddenMethodInfo.VFTableIndex);
3143 MethodInfoMap.erase(OverriddenMDIterator);
3145 assert(!MethodInfoMap.count(MD) &&
3146 "Should not have method info for this method yet!");
3147 MethodInfoMap.insert(std::make_pair(MD, MI));
3153 OverriddenMethodInfo.Shadowed =
true;
3157 ForceReturnAdjustmentMangling =
3158 !(MD == FinalOverriderMD && ThisAdjustmentOffset.
isEmpty());
3169 MethodInfo MI(VBIndex,
3170 HasRTTIComponent ? Components.size() - 1 : Components.size(),
3171 ReturnAdjustingThunk);
3173 assert(!MethodInfoMap.count(MD) &&
3174 "Should not have method info for this method yet!");
3175 MethodInfoMap.insert(std::make_pair(MD, MI));
3179 BaseOffset ReturnAdjustmentOffset;
3182 ReturnAdjustmentOffset =
3183 ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
3185 if (!ReturnAdjustmentOffset.isEmpty()) {
3186 ForceReturnAdjustmentMangling =
true;
3188 ReturnAdjustmentOffset.NonVirtualOffset.
getQuantity();
3189 if (ReturnAdjustmentOffset.VirtualBase) {
3196 ReturnAdjustmentOffset.VirtualBase);
3199 auto ThisType = (OverriddenMD ? OverriddenMD : MD)->getThisType().getTypePtr();
3200 AddMethod(FinalOverriderMD,
3202 ForceReturnAdjustmentMangling ? MD :
nullptr));
3209 Elem->printQualifiedName(Out);
3215 bool ContinueFirstLine) {
3217 bool Multiline =
false;
3218 const char *LinePrefix =
"\n ";
3220 if (!ContinueFirstLine)
3222 Out <<
"[return adjustment (to type '"
3234 if (Multiline || !ContinueFirstLine)
3236 Out <<
"[this adjustment: ";
3238 assert(
T.Virtual.Microsoft.VtordispOffset < 0);
3239 Out <<
"vtordisp at " <<
T.Virtual.Microsoft.VtordispOffset <<
", ";
3240 if (
T.Virtual.Microsoft.VBPtrOffset) {
3241 Out <<
"vbptr at " <<
T.Virtual.Microsoft.VBPtrOffset
3243 assert(
T.Virtual.Microsoft.VBOffsetOffset > 0);
3244 Out << LinePrefix <<
" vboffset at "
3245 <<
T.Virtual.Microsoft.VBOffsetOffset <<
" in the vbtable, ";
3248 Out <<
T.NonVirtual <<
" non-virtual]";
3252void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3253 Out <<
"VFTable for ";
3257 Out <<
"' (" << Components.size()
3258 << (Components.size() == 1 ?
" entry" :
" entries") <<
").\n";
3260 for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
3261 Out << llvm::format(
"%4d | ", I);
3266 switch (Component.
getKind()) {
3284 Out <<
" [deleted]";
3286 ThunkInfo Thunk = VTableThunks.lookup(I);
3299 Out <<
"() [vector deleting]";
3301 Out <<
"() [scalar deleting]";
3306 ThunkInfo Thunk = VTableThunks.lookup(I);
3309 "No return adjustment needed for destructors!");
3320 "Unexpected vftable component type %0 for component number %1");
3330 if (!Thunks.empty()) {
3332 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3334 for (
const auto &I : Thunks) {
3339 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3342 for (
const auto &MethodNameAndDecl : MethodNamesAndDecls) {
3343 const std::string &MethodName = MethodNameAndDecl.first;
3346 ThunkInfoVectorTy ThunksVector = Thunks[MD];
3347 llvm::stable_sort(ThunksVector, [](
const ThunkInfo &LHS,
3354 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
3355 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
3357 for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
3358 const ThunkInfo &Thunk = ThunksVector[I];
3360 Out << llvm::format(
"%4d | ", I);
3404void MicrosoftVTableContext::computeVTablePaths(
bool ForVBTables,
3407 assert(Paths.empty());
3408 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3412 Paths.push_back(std::make_unique<VPtrInfo>(RD));
3416 llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3417 for (
const auto &B : RD->
bases()) {
3418 const CXXRecordDecl *
Base = B.getType()->getAsCXXRecordDecl();
3419 if (B.isVirtual() && VBasesSeen.count(Base))
3422 if (!
Base->isDynamicClass())
3428 for (
const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) {
3435 auto P = std::make_unique<VPtrInfo>(*BaseInfo);
3439 if (P->MangledPath.empty() || P->MangledPath.back() != Base)
3440 P->NextBaseToMangle =
Base;
3445 if (P->ObjectWithVPtr == Base &&
3448 P->ObjectWithVPtr = RD;
3453 P->ContainingVBases.push_back(Base);
3454 else if (P->ContainingVBases.empty())
3458 P->FullOffsetInMDC = P->NonVirtualOffset;
3459 if (
const CXXRecordDecl *VB = P->getVBaseWithVPtr())
3462 Paths.push_back(std::move(P));
3466 VBasesSeen.insert(Base);
3470 for (
const auto &VB :
Base->vbases())
3471 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3498 llvm::make_pointee_range(Paths));
3502 bool Changed =
false;
3503 for (
size_t I = 0, E = PathsSorted.size(); I != E;) {
3505 size_t BucketStart = I;
3509 PathsSorted[BucketStart].get().MangledPath ==
3510 PathsSorted[I].get().MangledPath);
3513 if (I - BucketStart > 1) {
3514 for (
size_t II = BucketStart; II != I; ++II)
3516 assert(Changed &&
"no paths were extended to fix ambiguity");
3525typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3526 llvm::DenseSet<BaseSubobject>> FullPathTy;
3535 FullPathTy &FullPath,
3536 std::list<FullPathTy> &Paths) {
3538 Paths.push_back(FullPath);
3551 IntroducingObject, FullPath, Paths);
3552 FullPath.pop_back();
3558 FullPaths.remove_if([&](
const FullPathTy &SpecificPath) {
3559 for (
const FullPathTy &OtherPath : FullPaths) {
3560 if (&SpecificPath == &OtherPath)
3562 if (llvm::all_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3563 return OtherPath.contains(BSO);
3574 const FullPathTy &FullPath) {
3576 Context.getASTRecordLayout(RD);
3582 assert(Offset.getQuantity() == -1);
3586 assert(Offset.getQuantity() != -1);
3592 return BS.getType()->getAsCXXRecordDecl() == Base;
3607 std::list<FullPathTy> &FullPaths) {
3609 if (FullPaths.empty())
3611 if (FullPaths.size() == 1)
3612 return &FullPaths.front();
3614 const FullPathTy *BestPath =
nullptr;
3615 typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3616 OverriderSetTy LastOverrides;
3617 for (
const FullPathTy &SpecificPath : FullPaths) {
3618 assert(!SpecificPath.empty());
3619 OverriderSetTy CurrentOverrides;
3620 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3625 FinalOverriders Overriders(TopLevelRD,
CharUnits::Zero(), TopLevelRD);
3629 FinalOverriders::OverriderInfo OI =
3634 if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3640 if (llvm::none_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3641 return BSO.
getBase() == OverridingParent;
3644 CurrentOverrides.insert(OverridingMethod);
3646 OverriderSetTy NewOverrides =
3647 llvm::set_difference(CurrentOverrides, LastOverrides);
3648 if (NewOverrides.empty())
3650 OverriderSetTy MissingOverrides =
3651 llvm::set_difference(LastOverrides, CurrentOverrides);
3652 if (MissingOverrides.empty()) {
3654 BestPath = &SpecificPath;
3655 std::swap(CurrentOverrides, LastOverrides);
3660 const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3671 return BestPath ? BestPath : &FullPaths.front();
3677 const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD);
3678 FullPathTy FullPath;
3679 std::list<FullPathTy> FullPaths;
3680 for (
const std::unique_ptr<VPtrInfo>& Info : Paths) {
3683 BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath,
3687 Info->PathToIntroducingObject.clear();
3688 if (
const FullPathTy *BestPath =
3691 Info->PathToIntroducingObject.push_back(BSO.getBase());
3708void MicrosoftVTableContext::computeVTableRelatedInformation(
3713 if (VFPtrLocations.count(RD))
3719 auto VFPtrs = std::make_unique<VPtrInfoVector>();
3720 computeVTablePaths(
false, RD, *VFPtrs);
3722 VFPtrLocations[RD] = std::move(VFPtrs);
3725 MethodVFTableLocationsTy NewMethodLocations;
3726 for (
const std::unique_ptr<VPtrInfo> &VFPtr : *VFPtrLocations[RD]) {
3727 VFTableBuilder Builder(*
this, RD, *VFPtr);
3729 VFTableIdTy id(RD, VFPtr->FullOffsetInMDC);
3730 assert(VFTableLayouts.count(
id) == 0);
3731 SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks(
3732 Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
3733 VFTableLayouts[id] = std::make_unique<VTableLayout>(
3735 VTableThunks, EmptyAddressPointsMap);
3736 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
3738 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3739 for (
const auto &Loc : Builder.vtable_locations()) {
3740 auto Insert = NewMethodLocations.insert(Loc);
3742 const MethodVFTableLocation &NewLoc = Loc.second;
3743 MethodVFTableLocation &OldLoc =
Insert.first->second;
3750 MethodVFTableLocations.insert_range(NewMethodLocations);
3751 if (Context.getLangOpts().DumpVTableLayouts)
3752 dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3755void MicrosoftVTableContext::dumpMethodLocations(
3756 const CXXRecordDecl *RD,
const MethodVFTableLocationsTy &NewMethods,
3760 std::map<MethodVFTableLocation, std::string> IndicesMap;
3761 bool HasNonzeroOffset =
false;
3763 for (
const auto &I : NewMethods) {
3771 IndicesMap[I.second] = MethodName +
" [vector deleting]";
3773 IndicesMap[I.second] = MethodName;
3776 if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0)
3777 HasNonzeroOffset =
true;
3781 if (!IndicesMap.empty()) {
3782 Out <<
"VFTable indices for ";
3785 Out <<
"' (" << IndicesMap.size()
3786 << (IndicesMap.size() == 1 ?
" entry" :
" entries") <<
").\n";
3790 for (
const auto &I : IndicesMap) {
3791 CharUnits VFPtrOffset = I.first.VFPtrOffset;
3792 uint64_t VBIndex = I.first.VBTableIndex;
3793 if (HasNonzeroOffset &&
3794 (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3795 assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3796 Out <<
" -- accessible via ";
3798 Out <<
"vbtable index " << VBIndex <<
", ";
3799 Out <<
"vfptr at offset " << VFPtrOffset.
getQuantity() <<
" --\n";
3800 LastVFPtrOffset = VFPtrOffset;
3801 LastVBIndex = VBIndex;
3804 uint64_t VTableIndex = I.first.Index;
3805 const std::string &MethodName = I.second;
3806 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName <<
'\n';
3814const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation(
3816 VirtualBaseInfo *VBI;
3821 std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD];
3824 Entry = std::make_unique<VirtualBaseInfo>();
3828 computeVTablePaths(
true, RD, VBI->
VBPtrPaths);
3831 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3835 const VirtualBaseInfo &BaseInfo =
3836 computeVBTableRelatedInformation(VBPtrBase);
3843 for (
const auto &VB : RD->
vbases()) {
3844 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3845 if (VBI->
VBTableIndices.try_emplace(CurVBase, VBTableIndex).second)
3854 const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived);
3861 return computeVBTableRelatedInformation(RD).VBPtrPaths;
3866 computeVTableRelatedInformation(RD);
3868 assert(VFPtrLocations.count(RD) &&
"Couldn't find vfptr locations");
3869 return *VFPtrLocations[RD];
3875 computeVTableRelatedInformation(RD);
3877 VFTableIdTy id(RD, VFPtrOffset);
3878 assert(VFTableLayouts.count(
id) &&
"Couldn't find a VFTable at this offset");
3879 return *VFTableLayouts[id];
3885 "Only use this method for virtual methods or dtors");
3892 MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
3893 if (I != MethodVFTableLocations.end())
3898 computeVTableRelatedInformation(RD);
3900 I = MethodVFTableLocations.find(GD);
3901 assert(I != MethodVFTableLocations.end() &&
"Did not find index!");
Defines the clang::ASTContext interface.
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,...
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
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...
bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths, bool LookupInDependent=false) const
Look for entities within the base classes of this C++ class, transitively searching all base class su...
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...
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
const OriginalMethodMapTy & getOriginalMethodMap()
This method is reserved for the implementation and shouldn't be used directly.
uint64_t getMethodVTableIndex(GlobalDecl GD)
Locate a virtual function in the vtable.
bool isRelativeLayout() const
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.
void setOriginalMethod(const CXXMethodDecl *Key, const CXXMethodDecl *Val)
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.
virtual bool emitVectorDeletingDtors(const LangOptions &) const
Controls whether to emit MSVC vector deleting destructors.
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
VTableContextBase(bool MS)
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.
llvm::SmallVector< std::size_t > VTableIndicesTy
VTableLayout(VTableIndicesTy VTableIndices, ArrayRef< VTableComponent > VTableComponents, ArrayRef< VTableThunkTy > VTableThunks, const AddressPointsMapTy &AddressPoints)
llvm::SmallVector< unsigned, 4 > AddressPointsIndexMapTy
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.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
const FunctionProtoType * T
SmallVector< std::unique_ptr< VPtrInfo >, 2 > VPtrInfoVector
CXXDtorType
C++ destructor types.
@ Dtor_VectorDeleting
Vector deleting dtor.
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
for(const auto &A :T->param_types())
U cast(CodeGen::Address addr)
@ 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 * Class
The record decl of the class that the base is a base of.
const CXXBaseSpecifier * Base
The base specifier that states the link from a derived class to a base class, which will be followed ...
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.
SmallVector< const CXXRecordDecl *, 1 > BasePath
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.
const CXXRecordDecl * NextBaseToMangle
The next base to push onto the mangled path if this path is ambiguous in a derived class.
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::@103031170252120233124322035264172076254313213024 Itanium
uint32_t VBPtrOffset
The offset (in bytes) of the vbptr, relative to the beginning of the derived class.
struct clang::ReturnAdjustment::VirtualAdjustment::@167242364125115315334113104006210160165266060257 Microsoft
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::@106065375072164260365214033034320247050276346205 Itanium
int32_t VtordispOffset
The offset of the vtordisp (in bytes), relative to the ECX.
struct clang::ThisAdjustment::VirtualAdjustment::@312251255113040203233347230177110330127151157305 Microsoft
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...