summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/VTableBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/VTableBuilder.cpp')
-rw-r--r--clang/lib/AST/VTableBuilder.cpp126
1 files changed, 74 insertions, 52 deletions
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index ffa01681c52..c28aeefd99d 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -999,10 +999,6 @@ public:
dumpLayout(llvm::errs());
}
- bool isMicrosoftABI() const {
- return VTables.isMicrosoftABI();
- }
-
uint64_t getNumThunks() const {
return Thunks.size();
}
@@ -1157,7 +1153,7 @@ void VTableBuilder::ComputeThisAdjustments() {
// Add it.
VTableThunks[VTableIndex].This = ThisAdjustment;
- if (isa<CXXDestructorDecl>(MD) && !isMicrosoftABI()) {
+ if (isa<CXXDestructorDecl>(MD)) {
// Add an adjustment for the deleting destructor as well.
VTableThunks[VTableIndex + 1].This = ThisAdjustment;
}
@@ -1188,8 +1184,6 @@ void VTableBuilder::ComputeThisAdjustments() {
break;
case VTableComponent::CK_DeletingDtorPointer:
// We've already added the thunk when we saw the complete dtor pointer.
- // FIXME: check how this works in the Microsoft ABI
- // while working on the multiple inheritance patch.
continue;
}
@@ -1326,15 +1320,9 @@ VTableBuilder::AddMethod(const CXXMethodDecl *MD,
assert(ReturnAdjustment.isEmpty() &&
"Destructor can't have return adjustment!");
- // FIXME: Should probably add a layer of abstraction for vtable generation.
- if (!isMicrosoftABI()) {
- // Add both the complete destructor and the deleting destructor.
- Components.push_back(VTableComponent::MakeCompleteDtor(DD));
- Components.push_back(VTableComponent::MakeDeletingDtor(DD));
- } else {
- // Add the scalar deleting destructor.
- Components.push_back(VTableComponent::MakeDeletingDtor(DD));
- }
+ // Add both the complete destructor and the deleting destructor.
+ Components.push_back(VTableComponent::MakeCompleteDtor(DD));
+ Components.push_back(VTableComponent::MakeDeletingDtor(DD));
} else {
// Add the return adjustment if necessary.
if (!ReturnAdjustment.isEmpty())
@@ -1693,18 +1681,12 @@ VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,
if (Base.getBase() == MostDerivedClass)
VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
- // FIXME: Should probably add a layer of abstraction for vtable generation.
- if (!isMicrosoftABI()) {
- // Add the offset to top.
- CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
- Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop));
+ // Add the offset to top.
+ CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
+ Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop));
- // Next, add the RTTI.
- Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
- } else {
- // FIXME: unclear what to do with RTTI in MS ABI as emitting it anywhere
- // breaks the vftable layout. Just skip RTTI for now, can't mangle anyway.
- }
+ // Next, add the RTTI.
+ Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
uint64_t AddressPoint = Components.size();
@@ -1722,16 +1704,10 @@ VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,
const CXXMethodDecl *MD = I->first;
const MethodInfo &MI = I->second;
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- // FIXME: Should probably add a layer of abstraction for vtable generation.
- if (!isMicrosoftABI()) {
- MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
- = MI.VTableIndex - AddressPoint;
- MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
- = MI.VTableIndex + 1 - AddressPoint;
- } else {
- MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
- = MI.VTableIndex - AddressPoint;
- }
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
+ = MI.VTableIndex - AddressPoint;
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
+ = MI.VTableIndex + 1 - AddressPoint;
} else {
MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
}
@@ -2044,8 +2020,6 @@ void VTableBuilder::dumpLayout(raw_ostream& Out) {
Out << DD->getQualifiedNameAsString();
if (IsComplete)
Out << "() [complete]";
- else if (isMicrosoftABI())
- Out << "() [scalar deleting]";
else
Out << "() [deleting]";
@@ -2230,18 +2204,11 @@ void VTableBuilder::dumpLayout(raw_ostream& Out) {
MD);
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- // FIXME: Should add a layer of abstraction for vtable generation.
- if (!isMicrosoftABI()) {
- GlobalDecl GD(DD, Dtor_Complete);
- assert(MethodVTableIndices.count(GD));
- uint64_t VTableIndex = MethodVTableIndices[GD];
- IndicesMap[VTableIndex] = MethodName + " [complete]";
- IndicesMap[VTableIndex + 1] = MethodName + " [deleting]";
- } else {
- GlobalDecl GD(DD, Dtor_Deleting);
- assert(MethodVTableIndices.count(GD));
- IndicesMap[MethodVTableIndices[GD]] = MethodName + " [scalar deleting]";
- }
+ GlobalDecl GD(DD, Dtor_Complete);
+ assert(MethodVTableIndices.count(GD));
+ uint64_t VTableIndex = MethodVTableIndices[GD];
+ IndicesMap[VTableIndex] = MethodName + " [complete]";
+ IndicesMap[VTableIndex + 1] = MethodName + " [deleting]";
} else {
assert(MethodVTableIndices.count(MD));
IndicesMap[MethodVTableIndices[MD]] = MethodName;
@@ -2352,10 +2319,12 @@ static VTableLayout *CreateVTableLayout(const VTableBuilder &Builder) {
VTableThunks.size(),
VTableThunks.data(),
Builder.getAddressPoints(),
- Builder.isMicrosoftABI());
+ /*IsMicrosoftABI=*/false);
}
void VTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) {
+ assert(!IsMicrosoftABI && "Shouldn't be called in this ABI!");
+
const VTableLayout *&Entry = VTableLayouts[RD];
// Check if we've computed this information before.
@@ -3132,6 +3101,55 @@ static void EnumerateVFPtrs(
}
}
+/// CalculatePathToMangle - Calculate the subset of records that should be used
+/// to mangle the vftable for the given vfptr.
+/// Should only be called if a class has multiple vftables.
+static void
+CalculatePathToMangle(const CXXRecordDecl *RD, VFPtrInfo &VFPtr) {
+ // FIXME: In some rare cases this code produces a slightly incorrect mangling.
+ // It's very likely that the vbtable mangling code can be adjusted to mangle
+ // both vftables and vbtables correctly.
+
+ VFPtrInfo::BasePath &FullPath = VFPtr.PathToBaseWithVFPtr;
+ if (FullPath.empty()) {
+ // Mangle the class's own vftable.
+ assert(RD->getNumVBases() &&
+ "Something's wrong: if the most derived "
+ "class has more than one vftable, it can only have its own "
+ "vftable if it has vbases");
+ VFPtr.PathToMangle.push_back(RD);
+ return;
+ }
+
+ unsigned Begin = 0;
+
+ // First, skip all the bases before the vbase.
+ if (VFPtr.LastVBase) {
+ while (FullPath[Begin] != VFPtr.LastVBase) {
+ Begin++;
+ assert(Begin < FullPath.size());
+ }
+ }
+
+ // Then, put the rest of the base path in the reverse order.
+ for (unsigned I = FullPath.size(); I != Begin; --I) {
+ const CXXRecordDecl *CurBase = FullPath[I - 1],
+ *ItsBase = (I == 1) ? RD : FullPath[I - 2];
+ bool BaseIsVirtual = false;
+ for (CXXRecordDecl::base_class_const_iterator J = ItsBase->bases_begin(),
+ F = ItsBase->bases_end(); J != F; ++J) {
+ if (J->getType()->getAsCXXRecordDecl() == CurBase) {
+ BaseIsVirtual = J->isVirtual();
+ break;
+ }
+ }
+
+ // Should skip the current base if it is a non-virtual base with no siblings.
+ if (BaseIsVirtual || ItsBase->getNumBases() != 1)
+ VFPtr.PathToMangle.push_back(CurBase);
+ }
+}
+
static void EnumerateVFPtrs(ASTContext &Context, const CXXRecordDecl *ForClass,
MicrosoftVFTableContext::VFPtrListTy &Result) {
Result.clear();
@@ -3140,6 +3158,10 @@ static void EnumerateVFPtrs(ASTContext &Context, const CXXRecordDecl *ForClass,
EnumerateVFPtrs(Context, ForClass, ClassLayout,
BaseSubobject(ForClass, CharUnits::Zero()), 0,
VFPtrInfo::BasePath(), VisitedVBases, Result);
+ if (Result.size() > 1) {
+ for (unsigned I = 0, E = Result.size(); I != E; ++I)
+ CalculatePathToMangle(ForClass, Result[I]);
+ }
}
void MicrosoftVFTableContext::computeVTableRelatedInformation(
OpenPOWER on IntegriCloud