[cfe-commits] r96587 - in /cfe/trunk: lib/CodeGen/CGVtable.cpp test/CodeGenCXX/vtable-layout-abi-examples.cpp

Anders Carlsson andersca at mac.com
Thu Feb 18 09:26:41 PST 2010


Author: andersca
Date: Thu Feb 18 11:26:40 2010
New Revision: 96587

URL: http://llvm.org/viewvc/llvm-project?rev=96587&view=rev
Log:
More work on vcall offsets.

Modified:
    cfe/trunk/lib/CodeGen/CGVtable.cpp
    cfe/trunk/test/CodeGenCXX/vtable-layout-abi-examples.cpp

Modified: cfe/trunk/lib/CodeGen/CGVtable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVtable.cpp?rev=96587&r1=96586&r2=96587&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.cpp Thu Feb 18 11:26:40 2010
@@ -803,6 +803,11 @@
   // FIXME: This should be a real map and not a vector.
   llvm::SmallVector<MethodAndOffsetPairTy, 16> Offsets;
 
+  /// MethodsCanShareVCallOffset - Returns whether two virtual member functions
+  /// can share the same vcall offset.
+  static bool MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
+                                         const CXXMethodDecl *RHS);
+
 public:
   /// AddVCallOffset - Adds a vcall offset to the map. Returns true if the
   /// add was successful, or false if there was already a member function with
@@ -817,14 +822,50 @@
   void clear() { Offsets.clear(); }
 };
 
+bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
+                                                const CXXMethodDecl *RHS) {
+  assert(LHS->isVirtual() && "LHS must be virtual!");
+  assert(RHS->isVirtual() && "LHS must be virtual!");
+  
+  // FIXME: We need to check more things here.
+  
+  DeclarationName LHSName = LHS->getDeclName();
+  DeclarationName RHSName = RHS->getDeclName();
+  if (LHSName.getNameKind() != LHSName.getNameKind())
+    return false;
+  
+  switch (LHSName.getNameKind()) {
+  default:
+    assert(false && "Unhandled name kind!");
+  case DeclarationName::Identifier:
+    if (LHSName.getAsIdentifierInfo() != RHSName.getAsIdentifierInfo())
+      return false;
+  }
+  
+  return true;
+}
+
 bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD, 
                                     int64_t OffsetOffset) {
-  /// FIXME: Implement this.
+  // Check if we can reuse an offset.
+  for (unsigned I = 0, E = Offsets.size(); I != E; ++I) {
+    if (MethodsCanShareVCallOffset(Offsets[I].first, MD))
+      return false;
+  }
+  
+  // Add the offset.
+  Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
   return true;
 }
 
 int64_t VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) {
-  // FIXME: Implement this.
+  // Look for an offset.
+  for (unsigned I = 0, E = Offsets.size(); I != E; ++I) {
+    if (MethodsCanShareVCallOffset(Offsets[I].first, MD))
+      return Offsets[I].second;
+  }
+  
+  assert(false && "Should always find a vcall offset offset!");
   return 0;
 }
 
@@ -1010,7 +1051,11 @@
   ThisAdjustment Adjustment;
   
   if (!Offset.isEmpty()) {
-    assert(!Offset.VirtualBase && "FIXME: Handle virtual bases!");
+    if (Offset.VirtualBase) {
+      // Get the vcall offset offset.
+      Adjustment.VCallOffsetOffset = VCallOffsets.getVCallOffsetOffset(MD);
+    }
+
     Adjustment.NonVirtual = Offset.NonVirtualOffset;
   }
   
@@ -1069,8 +1114,20 @@
     if (!MD->isVirtual())
       continue;
 
-    // FIXME: Check if we already have a vcall offset for this member function
+    // OffsetIndex is the index of this vcall offset, relative to the vtable
+    // address point. (We subtract 3 to account for the information just
+    // above the address point, the RTTI info, the offset to top, and the
+    // vcall offset itself).
+    int64_t OffsetIndex = -(3 + VCallAndVBaseOffsets.size());
+    
+    // FIXME: We shouldn't use / 8 here.
+    int64_t OffsetOffset = OffsetIndex * 
+      (int64_t)Context.Target.getPointerWidth(0) / 8;
+    
+    // Don't add a vcall offset if we already have one for this member function
     // signature.
+    if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
+      continue;
     
     // Get the 'this' pointer adjustment offset.
     FinalOverriders::BaseOffset ThisAdjustmentOffset =

Modified: cfe/trunk/test/CodeGenCXX/vtable-layout-abi-examples.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/vtable-layout-abi-examples.cpp?rev=96587&r1=96586&r2=96587&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/vtable-layout-abi-examples.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/vtable-layout-abi-examples.cpp Thu Feb 18 11:26:40 2010
@@ -21,5 +21,30 @@
   int ia;
 };
 void A::f() {}
+
+// CHECK:      Vtable for 'Test1::B' (13 entries).
+// CHECK-NEXT:    0 | vbase_offset (16)
+// CHECK-NEXT:    1 | offset_to_top (0)
+// CHECK-NEXT:    2 | Test1::B RTTI
+// CHECK-NEXT:        -- (Test1::B, 0) vtable address --
+// CHECK-NEXT:    3 | void Test1::B::f()
+// CHECK-NEXT:    4 | void Test1::B::h()
+// CHECK-NEXT:    5 | vcall_offset (-16)
+// CHECK-NEXT:    6 | vcall_offset (0)
+// CHECK-NEXT:    7 | vcall_offset (-16)
+// CHECK-NEXT:    8 | offset_to_top (-16)
+// CHECK-NEXT:    9 | Test1::B RTTI
+// CHECK-NEXT:        -- (Test1::A, 16) vtable address --
+// CHECK-NEXT:   10 | void Test1::B::f()
+// CHECK-NEXT:        [this adjustment: 0 non-virtual, -24 vcall offset offset]
+// CHECK-NEXT:   11 | void Test1::A::g()
+// CHECK-NEXT:   12 | void Test1::B::h()
+// CHECK-NEXT:        [this adjustment: 0 non-virtual, -40 vcall offset offset]
+struct B: public virtual A {
+  void f ();
+  void h ();
+  int ib;
+};
+void B::f() {}
   
 }





More information about the cfe-commits mailing list