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

Anders Carlsson andersca at mac.com
Sat Feb 13 15:40:17 PST 2010


Author: andersca
Date: Sat Feb 13 17:40:17 2010
New Revision: 96136

URL: http://llvm.org/viewvc/llvm-project?rev=96136&view=rev
Log:
Add basic support for simple non-virtual 'this' pointer adjustments.

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

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.cpp Sat Feb 13 17:40:17 2010
@@ -156,11 +156,22 @@
     return OverridersMap.lookup(std::make_pair(Base, MD));
   }
   
+  /// getReturnAdjustmentOffset - Get the return adjustment offset for the
+  /// method decl in the given base subobject. Returns an empty base offset if
+  /// no adjustment is needed.
   BaseOffset getReturnAdjustmentOffset(BaseSubobject Base,
                                        const CXXMethodDecl *MD) const {
     return ReturnAdjustments.lookup(std::make_pair(Base, MD));
   }
 
+  /// getThisAdjustmentOffset - Get the 'this' pointer adjustment offset for the
+  /// method decl in the given base subobject. Returns an empty base offset if
+  /// no adjustment is needed.
+  BaseOffset getThisAdjustmentOffset(BaseSubobject Base,
+                                     const CXXMethodDecl *MD) const {
+    return ThisAdjustments.lookup(std::make_pair(Base, MD));
+  }
+  
   /// dump - dump the final overriders.
   void dump() const { 
       dump(llvm::errs(), BaseSubobject(MostDerivedClass, 0)); 
@@ -691,7 +702,7 @@
   /// AddressPoints - Address points for the vtable being built.
   CGVtableInfo::AddressPointsMapTy AddressPoints;
 
-  /// ReturnAdjustment - A return adjustment thunk.
+  /// ReturnAdjustment - A return adjustment.
   struct ReturnAdjustment {
     /// NonVirtual - The non-virtual adjustment from the derived object to its
     /// nearest virtual base.
@@ -710,13 +721,35 @@
   llvm::SmallVector<std::pair<uint64_t, ReturnAdjustment>, 16> 
     ReturnAdjustments;
 
+  /// ThisAdjustment - A 'this' pointer adjustment thunk.
+  struct ThisAdjustment {
+    /// NonVirtual - The non-virtual adjustment from the derived object to its
+    /// nearest virtual base.
+    int64_t NonVirtual;
+
+    /// FIXME: Add VCallOffsetOffset here.
+    
+    ThisAdjustment() : NonVirtual(0) { }
+
+    bool isEmpty() const { return !NonVirtual; }
+  };
+  
+  /// ThisAdjustments - The 'this' pointer adjustments needed in this vtable.
+  llvm::SmallVector<std::pair<uint64_t, ThisAdjustment>, 16> 
+    ThisAdjustments;
+  
   /// ComputeReturnAdjustment - Compute the return adjustment given a return
   /// adjustment base offset.
   ReturnAdjustment ComputeReturnAdjustment(FinalOverriders::BaseOffset Offset);
   
+  /// ComputeThisAdjustment - Compute the 'this' pointer  adjustment given a 
+  /// 'this' pointer adjustment base offset.
+  ThisAdjustment ComputeThisAdjustment(FinalOverriders::BaseOffset Offset);
+  
   /// AddMethod - Add a single virtual member function to the vtable
   /// components vector.
-  void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment);
+  void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment,
+                 ThisAdjustment ThisAdjustment);
 
   /// AddMethods - Add the methods of this base subobject and all its
   /// primary bases to the vtable components vector.
@@ -779,12 +812,33 @@
   return Adjustment;
 }
 
+VtableBuilder::ThisAdjustment
+VtableBuilder::ComputeThisAdjustment(FinalOverriders::BaseOffset Offset) {
+  ThisAdjustment Adjustment;
+  
+  if (!Offset.isEmpty()) {
+    assert(!Offset.VirtualBase && "FIXME: Handle virtual bases!");
+    Adjustment.NonVirtual = Offset.NonVirtualOffset;
+  }
+  
+  return Adjustment;
+}
+
 void 
 VtableBuilder::AddMethod(const CXXMethodDecl *MD,
-                         ReturnAdjustment ReturnAdjustment) {
+                         ReturnAdjustment ReturnAdjustment,
+                         ThisAdjustment ThisAdjustment) {
   if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
     assert(ReturnAdjustment.isEmpty() && 
            "Destructor can't have return adjustment!");
+    // Add the 'this' pointer adjustments if necessary.
+    if (!ThisAdjustment.isEmpty()) {
+      ThisAdjustments.push_back(std::make_pair(Components.size(),
+                                               ThisAdjustment));
+      ThisAdjustments.push_back(std::make_pair(Components.size() + 1,
+                                               ThisAdjustment));
+    }
+
     // Add both the complete destructor and the deleting destructor.
     Components.push_back(VtableComponent::MakeCompleteDtor(DD));
     Components.push_back(VtableComponent::MakeDeletingDtor(DD));
@@ -794,6 +848,11 @@
       ReturnAdjustments.push_back(std::make_pair(Components.size(),
                                                  ReturnAdjustment));
 
+    // Add the 'this' pointer adjustment if necessary.
+    if (!ThisAdjustment.isEmpty())
+      ThisAdjustments.push_back(std::make_pair(Components.size(),
+                                               ThisAdjustment));
+
     // Add the function.
     Components.push_back(VtableComponent::MakeFunction(MD));
   }
@@ -847,7 +906,13 @@
     ReturnAdjustment ReturnAdjustment = 
       ComputeReturnAdjustment(ReturnAdjustmentOffset);
     
-    AddMethod(Overrider.Method, ReturnAdjustment);
+    // Check if this overrider needs a 'this' pointer adjustment.
+    FinalOverriders::BaseOffset ThisAdjustmentOffset =
+      Overriders.getThisAdjustmentOffset(Base, MD);
+    
+    ThisAdjustment ThisAdjustment = ComputeThisAdjustment(ThisAdjustmentOffset);
+    
+    AddMethod(Overrider.Method, ReturnAdjustment, ThisAdjustment);
   }
 }
 
@@ -927,6 +992,7 @@
   }
   
   unsigned NextReturnAdjustmentIndex = 0;
+  unsigned NextThisAdjustmentIndex = 0;
   for (unsigned I = 0, E = Components.size(); I != E; ++I) {
     uint64_t Index = I;
     
@@ -990,7 +1056,7 @@
       if (MD->isPure())
         Out << " [pure]";
 
-      // If this function pointer has a return adjustment thunk, dump it.
+      // If this function pointer has a return adjustment, dump it.
       if (NextReturnAdjustmentIndex < ReturnAdjustments.size() && 
           ReturnAdjustments[NextReturnAdjustmentIndex].first == I) {
         const ReturnAdjustment Adjustment = 
@@ -1005,6 +1071,20 @@
 
         NextReturnAdjustmentIndex++;
       }
+      
+      // If this function pointer has a 'this' pointer adjustment, dump it.
+      if (NextThisAdjustmentIndex < ThisAdjustments.size() && 
+          ThisAdjustments[NextThisAdjustmentIndex].first == I) {
+        const ThisAdjustment Adjustment = 
+          ThisAdjustments[NextThisAdjustmentIndex].second;
+        
+        Out << "\n       [this adjustment: ";
+        Out << Adjustment.NonVirtual << " non-virtual";
+        
+        Out << ']';
+        
+        NextThisAdjustmentIndex++;
+      }
 
       break;
     }

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

==============================================================================
--- cfe/trunk/test/CodeGenCXX/vtable-layout.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/vtable-layout.cpp Sat Feb 13 17:40:17 2010
@@ -1,6 +1,16 @@
 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm-only -fdump-vtable-layouts 2>&1 | FileCheck %s
-namespace Test1 {
 
+// For now, just verify this doesn't crash.
+namespace test0 {
+  struct Obj {};
+
+  struct Base {           virtual const Obj *foo() = 0; };
+  struct Derived : Base { virtual       Obj *foo() { return new Obj(); } };
+
+  void test(Derived *D) { D->foo(); }
+}
+
+namespace Test1 {
 // CHECK:      Vtable for 'Test1::A' (3 entries).
 // CHECK-NEXT:   0 | offset_to_top (0)
 // CHECK-NEXT:   1 | Test1::A RTTI
@@ -202,7 +212,7 @@
 
 namespace Test5 {
 
-// Simple secondary vtables without this-adjustments.
+// Simple secondary vtables without 'this' pointer adjustments.
 struct A {
   virtual void f();
   virtual void g();
@@ -240,12 +250,33 @@
 void C::h() { }  
 }
 
-// For now, just verify this doesn't crash.
-namespace test0 {
-  struct Obj {};
+namespace Test6 {
 
-  struct Base {           virtual const Obj *foo() = 0; };
-  struct Derived : Base { virtual       Obj *foo() { return new Obj(); } };
+// Simple non-virtual 'this' pointer adjustments.
+struct A1 {
+  virtual void f();
+  int a;
+};
 
-  void test(Derived *D) { D->foo(); }
-}
+struct A2 {
+  virtual void f();
+  int a;
+};
+
+// CHECK:     Vtable for 'Test6::C' (6 entries).
+// CHECK-NEXT:   0 | offset_to_top (0)
+// CHECK-NEXT:   1 | Test6::C RTTI
+// CHECK-NEXT:       -- (Test6::A1, 0) vtable address --
+// CHECK-NEXT:       -- (Test6::C, 0) vtable address --
+// CHECK-NEXT:   2 | void Test6::C::f()
+// CHECK-NEXT:   3 | offset_to_top (-16)
+// CHECK-NEXT:   4 | Test6::C RTTI
+// CHECK-NEXT:       -- (Test6::A2, 16) vtable address --
+// CHECK-NEXT:   5 | void Test6::C::f()
+// CHECK-NEXT:       [this adjustment: -16 non-virtual]
+struct C : A1, A2 {
+  virtual void f();
+};
+void C::f() { }
+
+}
\ No newline at end of file





More information about the cfe-commits mailing list