From: Mike Stump Date: Tue, 26 Jan 2010 21:35:27 +0000 (+0000) Subject: Refine the non-virtual this adjustments for thunks by using the offset X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=15189fb2fb2b3b3df678e94b036b77b994704655;p=clang Refine the non-virtual this adjustments for thunks by using the offset 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 --- diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 39962e01b2..cb3f1816d8 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -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(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(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(OGD.getDecl())->getThisType(CGM.getContext()); + int64_t NonVirtualAdjustment2 = -(getNVOffset(BaseType, DerivedType)/8); + if (NonVirtualAdjustment2 != NonVirtualAdjustment) { + NonVirtualAdjustment = NonVirtualAdjustment2; + } + if (NonVirtualAdjustment) { ThunkAdjustment ThisAdjustment(NonVirtualAdjustment, 0); diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp index e7fd911fb0..04d4855491 100644 --- a/test/CodeGenCXX/virt.cpp +++ b/test/CodeGenCXX/virt.cpp @@ -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