]> granicus.if.org Git - clang/commitdiff
More work on thunks; almost there now.
authorAnders Carlsson <andersca@mac.com>
Mon, 22 Mar 2010 20:06:40 +0000 (20:06 +0000)
committerAnders Carlsson <andersca@mac.com>
Mon, 22 Mar 2010 20:06:40 +0000 (20:06 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99199 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGVtable.cpp

index b78867841cc49fb83dd1e824b98d70ae9a1bb054..49dbd290637abaf2bc64a30b0e3d652666ebaf17 100644 (file)
@@ -1384,8 +1384,8 @@ public:
 };
 
 void VtableBuilder::AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk) {
-  if (isBuildingConstructorVtable())
-    return;
+  assert(!isBuildingConstructorVtable() && 
+         "Can't add thunks for construction vtable");
 
   llvm::SmallVector<ThunkInfo, 1> &ThunksVector = MethodThunks[MD];
   
@@ -1436,6 +1436,10 @@ void VtableBuilder::ComputeThisAdjustments() {
       Overriders.getOverrider(BaseSubobject(MD->getParent(), 
                                             MethodInfo.BaseOffset), MD);
     
+    // Check if we need an adjustment at all.
+    if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset)
+      continue;
+
     ThisAdjustment ThisAdjustment =
       ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
 
@@ -1463,20 +1467,24 @@ void VtableBuilder::ComputeThisAdjustments() {
        I != E; ++I) {
     const VtableComponent &Component = Components[I->first];
     const ThunkInfo &Thunk = I->second;
+    const CXXMethodDecl *MD;
     
     switch (Component.getKind()) {
     default:
       llvm_unreachable("Unexpected vtable component kind!");
     case VtableComponent::CK_FunctionPointer:
-      AddThunk(Component.getFunctionDecl(), Thunk);
+      MD = Component.getFunctionDecl();
       break;
     case VtableComponent::CK_CompleteDtorPointer:
-      AddThunk(Component.getDestructorDecl(), Thunk);
+      MD = Component.getDestructorDecl();
       break;
     case VtableComponent::CK_DeletingDtorPointer:
       // We've already added the thunk when we saw the complete dtor pointer.
-      break;
+      continue;
     }
+
+    if (MD->getParent() == MostDerivedClass)
+      AddThunk(MD, Thunk);
   }
 }
 
@@ -1565,10 +1573,6 @@ VtableBuilder::ThisAdjustment
 VtableBuilder::ComputeThisAdjustment(const CXXMethodDecl *MD, 
                                      uint64_t BaseOffsetInLayoutClass,
                                      FinalOverriders::OverriderInfo Overrider) {
-  // Check if we need an adjustment at all.
-  if (BaseOffsetInLayoutClass == Overrider.Offset)
-    return ThisAdjustment();
-
   // Ignore adjustments for pure virtual member functions.
   if (Overrider.Method->isPure())
     return ThisAdjustment();
@@ -1825,6 +1829,24 @@ VtableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass,
         
         MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
         MethodInfoMap.erase(OverriddenMD);
+        
+        // If the overridden method exists in a virtual base class or a direct
+        // or indirect base class of a virtual base class, we need to emit a
+        // thunk if we ever have a class hierarchy where the base class is not
+        // a primary base in the complete object.
+        if (!isBuildingConstructorVtable() && OverriddenMD != MD) {
+          // Compute the this adjustment.
+          ThisAdjustment ThisAdjustment =
+            ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
+                                  Overrider);
+
+          if (ThisAdjustment.VCallOffsetOffset) {
+            // This is a virtual thunk, add it.
+            AddThunk(Overrider.Method, 
+                     ThunkInfo(ThisAdjustment, ReturnAdjustment()));
+          }
+        }
+
         continue;
       }
     }
@@ -2360,6 +2382,9 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
         
         Out << '\n';
       }
+      
+      Out << '\n';
+
     }
   }
 }