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 : VTableComponents(VTableComponents), VTableThunks(VTableThunks),
2315 AddressPoints, VTableIndices.size())) {
2316 if (VTableIndices.size() <= 1)
2317 assert(VTableIndices.size() == 1 && VTableIndices[0] == 0);
2323 assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
2324 "Different thunks should have unique indices!");
2325 return LHS.first < RHS.first;
2343 MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
2344 if (I != MethodVTableIndices.end())
2349 computeVTableRelatedInformation(RD);
2351 I = MethodVTableIndices.find(GD);
2352 assert(I != MethodVTableIndices.end() &&
"Did not find index!");
2359 ClassPairTy ClassPair(RD, VBase);
2361 VirtualBaseClassOffsetOffsetsMapTy::iterator I =
2362 VirtualBaseClassOffsetOffsets.find(ClassPair);
2363 if (I != VirtualBaseClassOffsetOffsets.end())
2366 VCallAndVBaseOffsetBuilder Builder(*
this, RD, RD,
nullptr,
2371 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2373 ClassPairTy ClassPair(RD, I.first);
2375 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2378 I = VirtualBaseClassOffsetOffsets.find(ClassPair);
2379 assert(I != VirtualBaseClassOffsetOffsets.end() &&
"Did not find index!");
2386 computeVTableRelatedInformation(MD->getParent());
2389 if (
const auto *DD = dyn_cast<CXXDestructorDecl>(OriginalMD))
2399 auto I = OriginalMethodMap.find(MD);
2403 if (I == OriginalMethodMap.end())
2413static std::unique_ptr<VTableLayout>
2416 VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
2418 return std::make_unique<VTableLayout>(
2419 Builder.VTableIndices, Builder.vtable_components(), VTableThunks,
2420 Builder.getAddressPoints());
2424ItaniumVTableContext::computeVTableRelatedInformation(
const CXXRecordDecl *RD) {
2425 std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD];
2435 MethodVTableIndices.insert(Builder.vtable_indices_begin(),
2436 Builder.vtable_indices_end());
2439 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
2447 const CXXRecordDecl *VBase =
2450 if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
2453 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2455 ClassPairTy ClassPair(RD, I.first);
2457 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2461std::unique_ptr<VTableLayout>
2464 bool MostDerivedClassIsVirtual,
const CXXRecordDecl *LayoutClass) {
2465 ItaniumVTableBuilder Builder(*
this, MostDerivedClass, MostDerivedClassOffset,
2466 MostDerivedClassIsVirtual, LayoutClass);
2514class VFTableBuilder {
2516 typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
2517 MethodVFTableLocationsTy;
2519 typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
2520 method_locations_range;
2538 const FinalOverriders Overriders;
2543 MethodVFTableLocationsTy MethodVFTableLocations;
2546 bool HasRTTIComponent =
false;
2553 const uint64_t VBTableIndex;
2556 const uint64_t VFTableIndex;
2567 MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
2568 bool UsesExtraSlot =
false)
2569 : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2570 Shadowed(
false), UsesExtraSlot(UsesExtraSlot) {}
2573 : VBTableIndex(0), VFTableIndex(0), Shadowed(
false),
2574 UsesExtraSlot(
false) {}
2577 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
2581 MethodInfoMapTy MethodInfoMap;
2583 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
2587 VTableThunksMapTy VTableThunks;
2589 typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
2590 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
2597 void AddThunk(
const CXXMethodDecl *MD,
const ThunkInfo &Thunk) {
2598 SmallVector<ThunkInfo, 1> &ThunksVector = Thunks[MD];
2601 if (llvm::is_contained(ThunksVector, Thunk))
2604 ThunksVector.push_back(Thunk);
2609 CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2611 void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
2612 CharUnits ThisOffset, ThisAdjustment &TA);
2616 void AddMethod(
const CXXMethodDecl *MD, ThunkInfo TI) {
2618 VTableThunks[Components.size()] = TI;
2621 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2623 "Destructor can't have return adjustment!");
2632 void AddMethods(BaseSubobject Base,
unsigned BaseDepth,
2633 const CXXRecordDecl *LastVBase,
2634 BasesSetVectorTy &VisitedBases);
2636 void LayoutVFTable() {
2638 if (HasRTTIComponent)
2641 BasesSetVectorTy VisitedBases;
2642 AddMethods(BaseSubobject(MostDerivedClass,
CharUnits::Zero()), 0,
nullptr,
2646 assert(!Components.empty() &&
"vftable can't be empty");
2648 assert(MethodVFTableLocations.empty());
2649 for (
const auto &I : MethodInfoMap) {
2650 const CXXMethodDecl *MD = I.first;
2651 const MethodInfo &MI = I.second;
2656 if (MD->
getParent() != MostDerivedClass || MI.Shadowed)
2660 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2661 MethodVFTableLocations[GlobalDecl(DD,
Dtor_Deleting)] = Loc;
2663 MethodVFTableLocations[MD] = Loc;
2669 VFTableBuilder(MicrosoftVTableContext &VTables,
2670 const CXXRecordDecl *MostDerivedClass,
const VPtrInfo &Which)
2672 Context(MostDerivedClass->getASTContext()),
2673 MostDerivedClass(MostDerivedClass),
2674 MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)),
2676 Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) {
2683 HasRTTIComponent =
true;
2688 dumpLayout(llvm::outs());
2691 uint64_t getNumThunks()
const {
return Thunks.size(); }
2693 ThunksMapTy::const_iterator thunks_begin()
const {
return Thunks.begin(); }
2695 ThunksMapTy::const_iterator thunks_end()
const {
return Thunks.end(); }
2697 method_locations_range vtable_locations()
const {
2698 return method_locations_range(MethodVFTableLocations.begin(),
2699 MethodVFTableLocations.end());
2702 ArrayRef<VTableComponent> vtable_components()
const {
return Components; }
2704 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
2705 return VTableThunks.begin();
2708 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
2709 return VTableThunks.end();
2712 void dumpLayout(raw_ostream &);
2772VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2773 BasesSetVectorTy Bases;
2777 OverriddenMethodsSetTy VisitedOverriddenMethods;
2778 auto InitialOverriddenDefinitionCollector = [&](
2780 if (OverriddenMD->size_overridden_methods() == 0)
2781 Bases.insert(OverriddenMD->getParent());
2783 return VisitedOverriddenMethods.insert(OverriddenMD).second;
2785 visitAllOverriddenMethods(Overrider.Method,
2786 InitialOverriddenDefinitionCollector);
2791 if (Bases.size() == 0)
2792 return Overrider.Offset;
2797 return Bases.count(
Specifier->getType()->getAsCXXRecordDecl());
2811 CharUnits ThisOffset = Overrider.Offset;
2818 QualType CurTy = Element.Base->getType();
2823 if (Element.Base->isVirtual()) {
2834 LastVBaseOffset = ThisOffset =
2842 if (LastVBaseOffset.
isZero()) {
2846 ThisOffset = Overrider.Offset;
2850 ThisOffset = LastVBaseOffset;
2854 if (Ret > ThisOffset ||
First) {
2860 assert(!
First &&
"Method not found in the given subobject?");
2962void VFTableBuilder::CalculateVtordispAdjustment(
2963 FinalOverriders::OverriderInfo Overrider,
CharUnits ThisOffset,
2967 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2969 assert(VBaseMapEntry != VBaseMap.end());
2973 if (!VBaseMapEntry->second.hasVtorDisp() ||
2979 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2981 (OffsetOfVBaseWithVFPtr - WhichVFPtr.
FullOffsetInMDC).getQuantity() - 4;
2985 if (Overrider.Method->
getParent() == MostDerivedClass ||
2986 !Overrider.VirtualBase)
2998 TA.
NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
3012 typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
3013 VisitedGroupIndicesTy VisitedGroupIndices;
3014 for (
const auto *D : RD->
decls()) {
3015 const auto *ND = dyn_cast<NamedDecl>(D);
3018 VisitedGroupIndicesTy::iterator J;
3020 std::tie(J, Inserted) = VisitedGroupIndices.insert(
3021 std::make_pair(ND->getDeclName(), Groups.size()));
3023 Groups.push_back(MethodGroup());
3024 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND))
3029 for (
const MethodGroup &Group : Groups)
3030 VirtualMethods.append(Group.rbegin(), Group.rend());
3034 for (
const auto &B : RD->
bases()) {
3035 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() ==
Base)
3041void VFTableBuilder::AddMethods(
BaseSubobject Base,
unsigned BaseDepth,
3043 BasesSetVectorTy &VisitedBases) {
3053 const CXXRecordDecl *NextBase =
nullptr, *NextLastVBase = LastVBase;
3058 NextLastVBase = NextBase;
3066 "No primary virtual bases in this ABI");
3067 NextBase = PrimaryBase;
3068 NextBaseOffset =
Base.getBaseOffset();
3072 AddMethods(
BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
3073 NextLastVBase, VisitedBases);
3074 if (!VisitedBases.insert(NextBase))
3075 llvm_unreachable(
"Found a duplicate primary base!");
3091 FinalOverriders::OverriderInfo FinalOverrider =
3092 Overriders.getOverrider(MD,
Base.getBaseOffset());
3093 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
3095 FindNearestOverriddenMethod(MD, VisitedBases);
3098 bool ReturnAdjustingThunk =
false, ForceReturnAdjustmentMangling =
false;
3099 CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
3102 if ((OverriddenMD || FinalOverriderMD != MD) &&
3104 CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
3105 ThisAdjustmentOffset);
3113 MethodInfoMapTy::iterator OverriddenMDIterator =
3114 MethodInfoMap.find(OverriddenMD);
3117 if (OverriddenMDIterator == MethodInfoMap.end())
3120 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
3122 VBIndex = OverriddenMethodInfo.VBTableIndex;
3129 ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
3130 Context, MD, OverriddenMD).isEmpty() ||
3131 OverriddenMethodInfo.UsesExtraSlot;
3133 if (!ReturnAdjustingThunk) {
3136 MethodInfo MI(VBIndex, OverriddenMethodInfo.VFTableIndex);
3137 MethodInfoMap.erase(OverriddenMDIterator);
3139 assert(!MethodInfoMap.count(MD) &&
3140 "Should not have method info for this method yet!");
3141 MethodInfoMap.insert(std::make_pair(MD, MI));
3147 OverriddenMethodInfo.Shadowed =
true;
3151 ForceReturnAdjustmentMangling =
3152 !(MD == FinalOverriderMD && ThisAdjustmentOffset.
isEmpty());
3163 MethodInfo MI(VBIndex,
3164 HasRTTIComponent ? Components.size() - 1 : Components.size(),
3165 ReturnAdjustingThunk);
3167 assert(!MethodInfoMap.count(MD) &&
3168 "Should not have method info for this method yet!");
3169 MethodInfoMap.insert(std::make_pair(MD, MI));
3173 BaseOffset ReturnAdjustmentOffset;
3176 ReturnAdjustmentOffset =
3177 ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
3179 if (!ReturnAdjustmentOffset.isEmpty()) {
3180 ForceReturnAdjustmentMangling =
true;
3182 ReturnAdjustmentOffset.NonVirtualOffset.
getQuantity();
3183 if (ReturnAdjustmentOffset.VirtualBase) {
3190 ReturnAdjustmentOffset.VirtualBase);
3193 auto ThisType = (OverriddenMD ? OverriddenMD : MD)->getThisType().getTypePtr();
3194 AddMethod(FinalOverriderMD,
3196 ForceReturnAdjustmentMangling ? MD :
nullptr));
3203 Elem->printQualifiedName(Out);
3209 bool ContinueFirstLine) {
3211 bool Multiline =
false;
3212 const char *LinePrefix =
"\n ";
3214 if (!ContinueFirstLine)
3216 Out <<
"[return adjustment (to type '"
3228 if (Multiline || !ContinueFirstLine)
3230 Out <<
"[this adjustment: ";
3232 assert(
T.Virtual.Microsoft.VtordispOffset < 0);
3233 Out <<
"vtordisp at " <<
T.Virtual.Microsoft.VtordispOffset <<
", ";
3234 if (
T.Virtual.Microsoft.VBPtrOffset) {
3235 Out <<
"vbptr at " <<
T.Virtual.Microsoft.VBPtrOffset
3237 assert(
T.Virtual.Microsoft.VBOffsetOffset > 0);
3238 Out << LinePrefix <<
" vboffset at "
3239 <<
T.Virtual.Microsoft.VBOffsetOffset <<
" in the vbtable, ";
3242 Out <<
T.NonVirtual <<
" non-virtual]";
3246void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3247 Out <<
"VFTable for ";
3251 Out <<
"' (" << Components.size()
3252 << (Components.size() == 1 ?
" entry" :
" entries") <<
").\n";
3254 for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
3255 Out << llvm::format(
"%4d | ", I);
3260 switch (Component.
getKind()) {
3278 Out <<
" [deleted]";
3280 ThunkInfo Thunk = VTableThunks.lookup(I);
3291 Out <<
"() [scalar deleting]";
3296 ThunkInfo Thunk = VTableThunks.lookup(I);
3299 "No return adjustment needed for destructors!");
3310 "Unexpected vftable component type %0 for component number %1");
3320 if (!Thunks.empty()) {
3322 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3324 for (
const auto &I : Thunks) {
3329 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3332 for (
const auto &MethodNameAndDecl : MethodNamesAndDecls) {
3333 const std::string &MethodName = MethodNameAndDecl.first;
3336 ThunkInfoVectorTy ThunksVector = Thunks[MD];
3337 llvm::stable_sort(ThunksVector, [](
const ThunkInfo &LHS,
3344 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
3345 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
3347 for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
3348 const ThunkInfo &Thunk = ThunksVector[I];
3350 Out << llvm::format(
"%4d | ", I);
3394void MicrosoftVTableContext::computeVTablePaths(
bool ForVBTables,
3397 assert(Paths.empty());
3398 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3402 Paths.push_back(std::make_unique<VPtrInfo>(RD));
3406 llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3407 for (
const auto &B : RD->
bases()) {
3408 const CXXRecordDecl *
Base = B.getType()->getAsCXXRecordDecl();
3409 if (B.isVirtual() && VBasesSeen.count(Base))
3412 if (!
Base->isDynamicClass())
3418 for (
const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) {
3425 auto P = std::make_unique<VPtrInfo>(*BaseInfo);
3429 if (P->MangledPath.empty() || P->MangledPath.back() != Base)
3430 P->NextBaseToMangle =
Base;
3435 if (P->ObjectWithVPtr == Base &&
3438 P->ObjectWithVPtr = RD;
3443 P->ContainingVBases.push_back(Base);
3444 else if (P->ContainingVBases.empty())
3448 P->FullOffsetInMDC = P->NonVirtualOffset;
3449 if (
const CXXRecordDecl *VB = P->getVBaseWithVPtr())
3452 Paths.push_back(std::move(P));
3456 VBasesSeen.insert(Base);
3460 for (
const auto &VB :
Base->vbases())
3461 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3488 llvm::make_pointee_range(Paths));
3492 bool Changed =
false;
3493 for (
size_t I = 0, E = PathsSorted.size(); I != E;) {
3495 size_t BucketStart = I;
3499 PathsSorted[BucketStart].get().MangledPath ==
3500 PathsSorted[I].get().MangledPath);
3503 if (I - BucketStart > 1) {
3504 for (
size_t II = BucketStart; II != I; ++II)
3506 assert(Changed &&
"no paths were extended to fix ambiguity");
3515typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3516 llvm::DenseSet<BaseSubobject>> FullPathTy;
3525 FullPathTy &FullPath,
3526 std::list<FullPathTy> &Paths) {
3528 Paths.push_back(FullPath);
3541 IntroducingObject, FullPath, Paths);
3542 FullPath.pop_back();
3548 FullPaths.remove_if([&](
const FullPathTy &SpecificPath) {
3549 for (
const FullPathTy &OtherPath : FullPaths) {
3550 if (&SpecificPath == &OtherPath)
3552 if (llvm::all_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3553 return OtherPath.contains(BSO);
3564 const FullPathTy &FullPath) {
3566 Context.getASTRecordLayout(RD);
3572 assert(Offset.getQuantity() == -1);
3576 assert(Offset.getQuantity() != -1);
3582 return BS.getType()->getAsCXXRecordDecl() == Base;
3597 std::list<FullPathTy> &FullPaths) {
3599 if (FullPaths.empty())
3601 if (FullPaths.size() == 1)
3602 return &FullPaths.front();
3604 const FullPathTy *BestPath =
nullptr;
3605 typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3606 OverriderSetTy LastOverrides;
3607 for (
const FullPathTy &SpecificPath : FullPaths) {
3608 assert(!SpecificPath.empty());
3609 OverriderSetTy CurrentOverrides;
3610 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3615 FinalOverriders Overriders(TopLevelRD,
CharUnits::Zero(), TopLevelRD);
3619 FinalOverriders::OverriderInfo OI =
3624 if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3630 if (llvm::none_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3631 return BSO.
getBase() == OverridingParent;
3634 CurrentOverrides.insert(OverridingMethod);
3636 OverriderSetTy NewOverrides =
3637 llvm::set_difference(CurrentOverrides, LastOverrides);
3638 if (NewOverrides.empty())
3640 OverriderSetTy MissingOverrides =
3641 llvm::set_difference(LastOverrides, CurrentOverrides);
3642 if (MissingOverrides.empty()) {
3644 BestPath = &SpecificPath;
3645 std::swap(CurrentOverrides, LastOverrides);
3650 const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3661 return BestPath ? BestPath : &FullPaths.front();
3667 const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD);
3668 FullPathTy FullPath;
3669 std::list<FullPathTy> FullPaths;
3670 for (
const std::unique_ptr<VPtrInfo>& Info : Paths) {
3673 BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath,
3677 Info->PathToIntroducingObject.clear();
3678 if (
const FullPathTy *BestPath =
3681 Info->PathToIntroducingObject.push_back(BSO.getBase());
3698void MicrosoftVTableContext::computeVTableRelatedInformation(
3703 if (VFPtrLocations.count(RD))
3709 auto VFPtrs = std::make_unique<VPtrInfoVector>();
3710 computeVTablePaths(
false, RD, *VFPtrs);
3712 VFPtrLocations[RD] = std::move(VFPtrs);
3715 MethodVFTableLocationsTy NewMethodLocations;
3716 for (
const std::unique_ptr<VPtrInfo> &VFPtr : *VFPtrLocations[RD]) {
3717 VFTableBuilder Builder(*
this, RD, *VFPtr);
3719 VFTableIdTy id(RD, VFPtr->FullOffsetInMDC);
3720 assert(VFTableLayouts.count(
id) == 0);
3721 SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks(
3722 Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
3723 VFTableLayouts[id] = std::make_unique<VTableLayout>(
3724 ArrayRef<size_t>{0}, Builder.vtable_components(), VTableThunks,
3725 EmptyAddressPointsMap);
3726 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
3728 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3729 for (
const auto &Loc : Builder.vtable_locations()) {
3730 auto Insert = NewMethodLocations.insert(Loc);
3732 const MethodVFTableLocation &NewLoc = Loc.second;
3733 MethodVFTableLocation &OldLoc =
Insert.first->second;
3740 MethodVFTableLocations.insert_range(NewMethodLocations);
3741 if (Context.getLangOpts().DumpVTableLayouts)
3742 dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3745void MicrosoftVTableContext::dumpMethodLocations(
3746 const CXXRecordDecl *RD,
const MethodVFTableLocationsTy &NewMethods,
3750 std::map<MethodVFTableLocation, std::string> IndicesMap;
3751 bool HasNonzeroOffset =
false;
3753 for (
const auto &I : NewMethods) {
3761 IndicesMap[I.second] = MethodName +
" [scalar deleting]";
3763 IndicesMap[I.second] = MethodName;
3766 if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0)
3767 HasNonzeroOffset =
true;
3771 if (!IndicesMap.empty()) {
3772 Out <<
"VFTable indices for ";
3775 Out <<
"' (" << IndicesMap.size()
3776 << (IndicesMap.size() == 1 ?
" entry" :
" entries") <<
").\n";
3780 for (
const auto &I : IndicesMap) {
3781 CharUnits VFPtrOffset = I.first.VFPtrOffset;
3782 uint64_t VBIndex = I.first.VBTableIndex;
3783 if (HasNonzeroOffset &&
3784 (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3785 assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3786 Out <<
" -- accessible via ";
3788 Out <<
"vbtable index " << VBIndex <<
", ";
3789 Out <<
"vfptr at offset " << VFPtrOffset.
getQuantity() <<
" --\n";
3790 LastVFPtrOffset = VFPtrOffset;
3791 LastVBIndex = VBIndex;
3794 uint64_t VTableIndex = I.first.Index;
3795 const std::string &MethodName = I.second;
3796 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName <<
'\n';
3804const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation(
3806 VirtualBaseInfo *VBI;
3811 std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD];
3814 Entry = std::make_unique<VirtualBaseInfo>();
3818 computeVTablePaths(
true, RD, VBI->
VBPtrPaths);
3821 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3825 const VirtualBaseInfo &BaseInfo =
3826 computeVBTableRelatedInformation(VBPtrBase);
3833 for (
const auto &VB : RD->
vbases()) {
3834 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3835 if (VBI->
VBTableIndices.try_emplace(CurVBase, VBTableIndex).second)
3844 const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived);
3851 return computeVBTableRelatedInformation(RD).VBPtrPaths;
3856 computeVTableRelatedInformation(RD);
3858 assert(VFPtrLocations.count(RD) &&
"Couldn't find vfptr locations");
3859 return *VFPtrLocations[RD];
3865 computeVTableRelatedInformation(RD);
3867 VFTableIdTy id(RD, VFPtrOffset);
3868 assert(VFTableLayouts.count(
id) &&
"Couldn't find a VFTable at this offset");
3869 return *VFTableLayouts[id];
3875 "Only use this method for virtual methods or dtors");
3881 MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
3882 if (I != MethodVFTableLocations.end())
3887 computeVTableRelatedInformation(RD);
3889 I = MethodVFTableLocations.find(GD);
3890 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
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.
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< unsigned, 4 > AddressPointsIndexMapTy
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.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
const FunctionProtoType * T
SmallVector< std::unique_ptr< VPtrInfo >, 2 > VPtrInfoVector
@ 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...