[cfe-commits] r126865 - /cfe/trunk/lib/CodeGen/CGVTables.cpp

Tilmann Scheller tilmann.scheller at googlemail.com
Wed Mar 2 11:38:28 PST 2011


Author: tilmann
Date: Wed Mar  2 13:38:28 2011
New Revision: 126865

URL: http://llvm.org/viewvc/llvm-project?rev=126865&view=rev
Log:
Add preliminary support for MSVC-style vtables.

Modified:
    cfe/trunk/lib/CodeGen/CGVTables.cpp

Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=126865&r1=126864&r2=126865&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVTables.cpp Wed Mar  2 13:38:28 2011
@@ -2266,6 +2266,32 @@
 
   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 @@
 
   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 @@
     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 @@
         ImplicitVirtualDtor = DD;
         continue;
       } 
-
+      assert(!IsWin64 && "Need support for dtor!");
       // Add the complete dtor.
       MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
       
@@ -2335,11 +2378,14 @@
       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 @@
       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;
 }
 





More information about the cfe-commits mailing list