]> granicus.if.org Git - clang/commitdiff
Refine the non-virtual this adjustments for thunks by using the offset
authorMike Stump <mrs@apple.com>
Tue, 26 Jan 2010 21:35:27 +0000 (21:35 +0000)
committerMike Stump <mrs@apple.com>
Tue, 26 Jan 2010 21:35:27 +0000 (21:35 +0000)
to the declaring class from the nearest virtual base class.  WIP.

This fixes 40% of all the problems remaining in one of my testcases.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94592 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGVtable.cpp
test/CodeGenCXX/virt.cpp

index 39962e01b2e08aca28824a3e602f8bc873191e73..cb3f1816d8a224297a02065e77aa804aec5643f6 100644 (file)
@@ -634,7 +634,8 @@ public:
     // entry.
     Methods.AddMethod(GD);
 
-    VCallOffset[GD] = Offset/8;
+    VCallOffset[GD] = Offset/8 - CurrentVBaseOffset/8;
+
     if (MorallyVirtual) {
       GlobalDecl UGD = getUnique(GD);
       const CXXMethodDecl *UMD = cast<CXXMethodDecl>(UGD.getDecl());
@@ -645,7 +646,7 @@ public:
       // Allocate the first one, after that, we reuse the previous one.
       if (idx == 0) {
         VCallOffsetForVCall[UGD] = Offset/8;
-        NonVirtualOffset[UMD] = -CurrentVBaseOffset/8 + Offset/8;
+        NonVirtualOffset[UMD] = Offset/8 - CurrentVBaseOffset/8;
         idx = VCalls.size()+1;
         VCalls.push_back(Offset/8 - CurrentVBaseOffset/8);
         D1(printf("  vcall for %s at %d with delta %d\n",
@@ -715,6 +716,9 @@ public:
     }
     VCalls.clear();
     VCall.clear();
+    VCallOffsetForVCall.clear();
+    VCallOffset.clear();
+    NonVirtualOffset.clear();
   }
 
   void AddAddressPoints(const CXXRecordDecl *RD, uint64_t Offset,
@@ -1044,6 +1048,7 @@ bool VtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
   for (CXXMethodDecl::method_iterator mi = MD->begin_overridden_methods(),
        e = MD->end_overridden_methods(); mi != e; ++mi) {
     GlobalDecl OGD;
+    GlobalDecl OGD2;
     
     const CXXMethodDecl *OMD = *mi;
     if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(OMD))
@@ -1057,6 +1062,8 @@ bool VtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
     if (!Methods.getIndex(OGD, Index))
       continue;
 
+    OGD2 = OGD;
+
     // Get the original method, which we should be computing thunks, etc,
     // against.
     OGD = Methods.getOrigMethod(Index);
@@ -1087,10 +1094,12 @@ bool VtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
 
     ThisAdjustments.erase(Index);
     if (MorallyVirtual || VCall.count(UMD)) {
+
       Index_t &idx = VCall[UMD];
       if (idx == 0) {
-        NonVirtualOffset[UMD] = CurrentVBaseOffset/8 - OverrideOffset/8;
-        VCallOffset[GD] = OverrideOffset/8;
+        VCallOffset[GD] = VCallOffset[OGD];
+        // NonVirtualOffset[UMD] = CurrentVBaseOffset/8 - OverrideOffset/8;
+        NonVirtualOffset[UMD] = VCallOffset[OGD];
         VCallOffsetForVCall[UMD] = OverrideOffset/8;
         idx = VCalls.size()+1;
         VCalls.push_back(OverrideOffset/8 - CurrentVBaseOffset/8);
@@ -1098,13 +1107,13 @@ bool VtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
                   MD->getNameAsString().c_str(), (int)-idx-3,
                   (int)VCalls[idx-1], MostDerivedClass->getNameAsCString()));
       } else {
-        VCallOffset[GD] = VCallOffset[OGD];
+        VCallOffset[GD] = NonVirtualOffset[UMD];
         VCalls[idx-1] = -VCallOffsetForVCall[UGD] + OverrideOffset/8;
         D1(printf("  vcall patch for %s at %d with delta %d most derived %s\n",
                   MD->getNameAsString().c_str(), (int)-idx-3,
                   (int)VCalls[idx-1], MostDerivedClass->getNameAsCString()));
       }
-      int64_t NonVirtualAdjustment = NonVirtualOffset[UMD];
+      int64_t NonVirtualAdjustment = -VCallOffset[OGD];
       int64_t VirtualAdjustment = 
         -((idx + extra + 2) * LLVMPointerWidth / 8);
       
@@ -1123,8 +1132,16 @@ bool VtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
       return true;
     }
 
-    int64_t NonVirtualAdjustment = -VCallOffset[OGD] + OverrideOffset/8;
+    VCallOffset[GD] = VCallOffset[OGD2] - OverrideOffset/8;
 
+    int64_t NonVirtualAdjustment = -VCallOffset[GD];
+    QualType DerivedType = MD->getThisType(CGM.getContext());
+    QualType BaseType = cast<const CXXMethodDecl>(OGD.getDecl())->getThisType(CGM.getContext());
+    int64_t NonVirtualAdjustment2 = -(getNVOffset(BaseType, DerivedType)/8);
+    if (NonVirtualAdjustment2 != NonVirtualAdjustment) {
+      NonVirtualAdjustment = NonVirtualAdjustment2;
+    }
+      
     if (NonVirtualAdjustment) {
       ThunkAdjustment ThisAdjustment(NonVirtualAdjustment, 0);
       
index e7fd911fb002fd57fd5caff3c023103a564ade87..04d48554910fb29add43f4782d282a851d377c9c 100644 (file)
@@ -402,8 +402,8 @@ struct test16_D : test16_NV1, virtual test16_B2 {
 // CHECK-LP64-NEXT: .quad __ZN8test16_B5foo_BEv
 // CHECK-LP64-NEXT: .quad -48
 // CHECK-LP64-NEXT: .quad __ZTI8test16_D
-// CHECK-LP64-NEXT .quad __ZTcvn16_n40_v16_n32_N8test16_D4foo1Ev
-// CHECK-LP64: .quad __ZN10test16_NV27foo_NV2Ev
+// CHECK-LP64-NEXT: .quad __ZTcvn16_n40_v16_n32_N8test16_D4foo1Ev
+// CHECK-LP64-NEXT: .quad __ZN10test16_NV27foo_NV2Ev
 // CHECK-LP64-NEXT: .quad __ZN10test16_NV28foo_NV2bEv