r221996 - Add one illustrative class hierarchy as an example in a comment to the VFTableBuilder code
Timur Iskhodzhanov
timurrrr at google.com
Fri Nov 14 06:10:15 PST 2014
Author: timurrrr
Date: Fri Nov 14 08:10:15 2014
New Revision: 221996
URL: http://llvm.org/viewvc/llvm-project?rev=221996&view=rev
Log:
Add one illustrative class hierarchy as an example in a comment to the VFTableBuilder code
Modified:
cfe/trunk/lib/AST/VTableBuilder.cpp
Modified: cfe/trunk/lib/AST/VTableBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/VTableBuilder.cpp?rev=221996&r1=221995&r2=221996&view=diff
==============================================================================
--- cfe/trunk/lib/AST/VTableBuilder.cpp (original)
+++ cfe/trunk/lib/AST/VTableBuilder.cpp Fri Nov 14 08:10:15 2014
@@ -2390,6 +2390,7 @@ namespace {
// first vfptr whose table provides a compatible overridden method. In many
// cases, this permits the original vf-table entry to directly call
// the method instead of passing through a thunk.
+// See example before VFTableBuilder::ComputeThisOffset below.
//
// A compatible overridden method is one which does not have a non-trivial
// covariant-return adjustment.
@@ -2412,6 +2413,9 @@ namespace {
// a) a user-defined ctor/dtor
// and
// b) a method overriding a method in a virtual base.
+//
+// To get a better understanding of this code,
+// you might want to see examples in test/CodeGenCXX/microsoft-abi-vtables-*.cpp
class VFTableBuilder {
public:
@@ -2642,6 +2646,60 @@ static bool BaseInSet(const CXXBaseSpeci
return Bases->count(Specifier->getType()->getAsCXXRecordDecl());
}
+// Let's study one class hierarchy as an example:
+// struct A {
+// virtual void f();
+// int x;
+// };
+//
+// struct B : virtual A {
+// virtual void f();
+// };
+//
+// Record layouts:
+// struct A:
+// Â Â 0 | Â Â (A vftable pointer)
+// 4 | int x
+//
+// struct B:
+// Â Â 0 | Â Â (B vbtable pointer)
+// Â 4 | Â Â struct A (virtual base)
+// Â 4 | Â Â Â Â (A vftable pointer)
+// 8 | int x
+//
+// Let's assume we have a pointer to the A part of an object of dynamic type B:
+// B b;
+// A *a = (A*)&b;
+// a->f();
+//
+// In this hierarchy, f() belongs to the vftable of A, so B::f() expects
+// "this" parameter to point at the A subobject, which is B+4.
+// In the B::f() prologue, it adjusts "this" back to B by subtracting 4,
+// peformed as a *static* adjustment.
+//
+// Interesting thing happens when we alter the relative placement of A and B
+// subobjects in a class:
+// struct C : virtual B { };
+//
+// C c;
+// A *a = (A*)&c;
+// a->f();
+//
+// Respective record layout is:
+// 0 | (C vbtable pointer)
+// 4 | struct A (virtual base)
+// 4 | (A vftable pointer)
+// 8 | int x
+// 12 | struct B (virtual base)
+// 12 | (B vbtable pointer)
+//
+// The final overrider of f() in class C is still B::f(), so B+4 should be
+// passed as "this" to that code. However, "a" points at B-8, so the respective
+// vftable entry should hold a thunk that adds 12 to the "this" argument before
+// performing a tail call to B::f().
+//
+// With this example in mind, we can now calculate the 'this' argument offset
+// for the given method, relative to the beginning of the MostDerivedClass.
CharUnits
VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
InitialOverriddenDefinitionCollector Collector;
More information about the cfe-commits
mailing list