diff options
author | Tilmann Scheller <tilmann.scheller@googlemail.com> | 2011-03-02 19:38:28 +0000 |
---|---|---|
committer | Tilmann Scheller <tilmann.scheller@googlemail.com> | 2011-03-02 19:38:28 +0000 |
commit | ab456cf6cd9e76f4f033984b4d5b103f28a4afe4 (patch) | |
tree | fde07a433ca5efad93d7fceb909391f87c78c5b5 /lib/CodeGen/CGVTables.cpp | |
parent | 88d117c2eedd7c5bec57ac983a98d5e12bdd2cc6 (diff) |
Add preliminary support for MSVC-style vtables.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126865 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGVTables.cpp')
-rw-r--r-- | lib/CodeGen/CGVTables.cpp | 63 |
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; } |