aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGVtable.cpp
diff options
context:
space:
mode:
authorMike Stump <mrs@apple.com>2010-01-26 21:35:27 +0000
committerMike Stump <mrs@apple.com>2010-01-26 21:35:27 +0000
commit15189fb2fb2b3b3df678e94b036b77b994704655 (patch)
tree4bfb0fede92a1cf6569c6f85ebd3ed0f6ae813d0 /lib/CodeGen/CGVtable.cpp
parentffbdead156eb0bc94d1cc7e28eadcca52dfb8194 (diff)
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
Diffstat (limited to 'lib/CodeGen/CGVtable.cpp')
-rw-r--r--lib/CodeGen/CGVtable.cpp31
1 files changed, 24 insertions, 7 deletions
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<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);