aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGVTables.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGVTables.cpp')
-rw-r--r--lib/CodeGen/CGVTables.cpp63
1 files changed, 61 insertions, 2 deletions
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index 6acbe436c8..c527c87b49 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -2266,6 +2266,32 @@ void CodeGenVTables::ComputeMethodVTableIndices(const CXXRecordDecl *RD) {
int64_t CurrentIndex = 0;
+ // The MSVC Win64 ABI uses a different ordering of the
+ // virtual function pointers:
+ //
+ // The order of the virtual function pointers in a virtual table is
+ // the reverse order of declaration of the corresponding member functions
+ // in the class except for overloaded member functions. Overloaded member
+ // functions are moved below the first declaration of the
+ // respective overloaded member function. All declarations for one
+ // overloaded member function are added in reverse order of declaration.
+ //
+ // E.g. for the following class:
+ // class A {
+ // virtual b();
+ // virtual a(int a);
+ // virtual c();
+ // virtual a(float a);
+ // };
+ //
+ // The vtable layout looks like this:
+ // c()
+ // a(float b)
+ // a(int a)
+ // b()
+ //
+ const bool IsWin64 = CGM.getContext().Target.isWin64();
+
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
@@ -2285,6 +2311,9 @@ void CodeGenVTables::ComputeMethodVTableIndices(const CXXRecordDecl *RD) {
const CXXDestructorDecl *ImplicitVirtualDtor = 0;
+ llvm::StringMap<llvm::SmallVector<const CXXMethodDecl *, 16> *> Methods;
+ llvm::SmallVector<llvm::SmallVector<const CXXMethodDecl *, 16> *, 16> Order;
+
for (CXXRecordDecl::method_iterator i = RD->method_begin(),
e = RD->method_end(); i != e; ++i) {
const CXXMethodDecl *MD = *i;
@@ -2293,6 +2322,20 @@ void CodeGenVTables::ComputeMethodVTableIndices(const CXXRecordDecl *RD) {
if (!MD->isVirtual())
continue;
+ if (IsWin64) {
+ if (Methods.count(MD->getNameAsString()) == 0) {
+ // No entry yet.
+ llvm::SmallVector<const CXXMethodDecl *, 16> *entry = new llvm::SmallVector<const CXXMethodDecl *, 16>();
+ entry->push_back(MD);
+ Methods[MD->getNameAsString()] = entry;
+ Order.push_back(entry);
+ } else {
+ // This is an overloaded method, add to already existing entry.
+ llvm::SmallVector<const CXXMethodDecl *, 16> *entry = Methods[MD->getNameAsString()];
+ entry->push_back(MD);
+ }
+ }
+
// Check if this method overrides a method in the primary base.
if (const CXXMethodDecl *OverriddenMD =
FindNearestOverriddenMethod(MD, PrimaryBases)) {
@@ -2327,7 +2370,7 @@ void CodeGenVTables::ComputeMethodVTableIndices(const CXXRecordDecl *RD) {
ImplicitVirtualDtor = DD;
continue;
}
-
+ assert(!IsWin64 && "Need support for dtor!");
// Add the complete dtor.
MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
@@ -2335,11 +2378,14 @@ void CodeGenVTables::ComputeMethodVTableIndices(const CXXRecordDecl *RD) {
MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
} else {
// Add the entry.
- MethodVTableIndices[MD] = CurrentIndex++;
+ if (!IsWin64) {
+ MethodVTableIndices[MD] = CurrentIndex++;
+ }
}
}
if (ImplicitVirtualDtor) {
+ assert(!IsWin64 && "Need support for implicit virtual dtor!");
// Itanium C++ ABI 2.5.2:
// If a class has an implicitly-defined virtual destructor,
// its entries come after the declared virtual function pointers.
@@ -2353,6 +2399,19 @@ void CodeGenVTables::ComputeMethodVTableIndices(const CXXRecordDecl *RD) {
CurrentIndex++;
}
+ if (IsWin64) {
+ for (llvm::SmallVector<llvm::SmallVector<const CXXMethodDecl *, 16> *, 16>::iterator i = Order.begin(),
+ e = Order.end(); i != e; ++i) {
+ llvm::SmallVector<const CXXMethodDecl *, 16> *elem = *i;
+
+ while (elem->size() > 0) {
+ const CXXMethodDecl *method = elem->pop_back_val();
+ // Add the entry.
+ MethodVTableIndices[method] = CurrentIndex++;
+ }
+ }
+ }
+
NumVirtualFunctionPointers[RD] = CurrentIndex;
}