Vcall offsets and mangling
Christophe de Dinechin
ddd at cup.hp.com
Wed Jun 21 22:58:39 UTC 2000
Mark,
If memory serves me right, the problem with virtual base thunks had been
identified (by Jason?), and the intent was indeed to use COMDAT thunks for this.
I did not check my mail nor the web page to find a reference, though. Someone
else may confirm if they have the same recollection.
Christophe
Mark Mitchell wrote:
>
> Folks --
>
> We learned some interesting things about what worked and what didn't
> when we implemented the ABI mangling in G++. Alex has a rewritten
> specification that is very complete. He'll post it shortly. There
> were a lot of things unspecified, and some things specified in ways
> that were notably inconvenient for the implementation.
>
> Also, I noticed this today, trying to finish up the vcall offset
> implementation in g++:
>
> struct A {
> virtual void f {};
> };
>
> struct B : virtual public A {
> int i;
> };
>
> struct C : virtual public A {
> int j;
> };
>
> struct D: public B, public C {};
>
> The basic idea of the thunk thing is that all thunks are knowable
> statically, allowing the fall-through implementation of thunks. So,
> the ABI actually mandates where you emit thunks, and says that you
> emit them with the overriding virtual function.
>
> Consider the graph above. Here, we need a thunk for the C-in-D
> vtable. (Why? A is a primary base of C. So, C's vtable contains an
> entry for f. But, in D, A is also a primary base of B, and therefore
> located at a non-zero offset from C. So, C's vtable must contain a
> thunk adjusting from C* to A* before calling f.)
>
> We have a vcall offset for A::f in the C-in-D vtable. We don't have a
> thunk for A::f, though. When A was emitted (without knowledge of C,
> let alone D), there was no reason to expect any thunks to A::f. We
> could have emitted an A-as-a-virtual-base thunk with A::f, just in
> case, but that's wasteful if A never is a virtual base. Doing so
> would violate the you-don't-pay-for-what-you-don't-use principle.
>
> (This can only happen because A is a primary base. If A were not
> primary, then C's vtable wouldn't contain a reference to A::f.)
>
> I think the right solution is, in this situation, to fall back on
> generating thunks, in COMDAT groups, where you need them to define
> vtables, just like the good old days. These thunks will pay the
> double-jump penalty.
>
> On thinking about this further, I actually think a better solution
> would have been to handle thunk emission in the linker. The linker
> could insert the thunks that are needed at link-time. You could have
> COMDAT thunks defined in case the linker didn't want to do that; an
> optimizing linker would ignore the COMDAT thunks and put in the right
> instructions in front of the virtual functions so that the
> fall-through thing worked right.
>
> Can we fall back to making thunks weak, and generating them when you
> need them for the vtable? This doesn't stop an implementation from
> emitting strong definitions right in front of the virtual functions,
> as we'd planned, as an optimization. And it doesn't stop the linker
> from playing the games mentioned above. All it means is that
> implementation is easier -- and that object files (not executables)
> will be a little bigger since they will contain extra copies of the
> thunks.
>
> Unfortunately, neither I nor Alex can be at the meeting tomorrow.
> But, I will call in at 10:00 AM. I have to be off by 10:55 AM, or so,
> for an 11:00 conference call; Alex is unavailable at 11:00 as well.
> He may or may not be able to join me on the phone some of the time.
>
> --
> Mark Mitchell mark at codesourcery.com
> CodeSourcery, LLC http://www.codesourcery.com
More information about the cxx-abi-dev
mailing list