Virtual function calls
Christophe de Dinechin
ddd at cup.hp.com
Thu Feb 24 20:01:06 UTC 2000
Here were my notes...
struct vtable_entry
{
#ifdef SHARED_LIBS
void (*fptr) ();
uint64 GP_value;
#else
void (*fptr) ();
#endif
}
CASE 1:
struct A {
virtual f();
}
A* ptr;
ptr->f();
struct vtbl<A> {
ptrdiff_t offset_to_top = 0;
typeinfo * typeinfo = typeinfo<A>;
VPTR-> vtable_entry f = A::f;
};
CASE 2:
struct B : A { }
struct vtbl<B> {
ptrdiff_t offset_to_top = 0;
typeinfo * typeinfo = typeinfo<B>;
VPTR-> vtable_entry f = A::f;
};
CASE 3:
struct C : A {
virtual f();
}
struct vtbl<C> {
ptrdiff_t offset_to_top = 0;
typeinfo * typeinfo = typeinfo<C>;
VPTR-> vtable_entry f = C::f;
CASE 4:
struct X { virtual unique(); };
struct D : X, A { }
struct vtbl<D> {
ptrdiff_t offset_to_top<X,D> = 0
typeinfo * typeinfo = typeinfo<D>
VPTR<D,X>->vtable_entry unique = X::unique;
ptrdiff_t offset_to_top<A> = -sizeof(vptr);
typeinfo * typeinfo = typeinfo<D>
VPTR<A>-> vtable_entry f = A::f;
}
Calling A::f():
with an A*: No adjustment
with a D*: Adjustment to an A* at call-site.
A* -> D* adjustmnent is known at compile time.
CASE 5:
struct E : X, A { virtual f(); }
E::f receives an E* as the this pointer, not an A*.
struct vtbl<E> {
ptrdiff_t offset_to_top<X,D> = 0
typeinfo * typeinfo = typeinfo<E>
VPTR<E,X>->vtable_entry unique = X::unique;
vtable_entry f = E::f
ptrdiff_t offset_to_top<A> = -sizeof(vptr);
typeinfo * typeinfo = typeinfo<E>
VPTR<A>-> vtable_entry f = E::f_thunk<A, E>; // Thunk converting from A to E
};
Calling E::f():
With an A*: Call site: no adjustment.
Adjustment done by E::f_thunk<A, E>
With an E*: Call site: no adjustment, calls through the vptr<E>->f.
CASE 6:
struct G : virtual A { }
struct vtbl<G> {
ptrdiff_t G_to_A_offset = 0;
ptrdiff_t offset_to_top<X,D> = 0
typeinfo * typeinfo = typeinfo<G>
VPTR<G>->
ptrdiff_t offset_to_top<A> = -sizeof(vptr);
typeinfo * typeinfo = typeinfo<G>
VPTR<A>-> vtable_entry f = A::f
};
Calling G::f:
Through an A*: as case 1
Throught a G*: Magically convert G* to A* (by adding the G_to_A_offset),
then use the A* to call A::f.
The "magical" conversion to be specified later, using a vbase offset.
CASE 7:
struct H : virtual A { virtual f(); }
struct vtbl<H> {
};
CASE 8:
struct I : H { }
CASE 9:
struct J : H { virtual f(); }
More information about the cxx-abi-dev
mailing list