[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