A question about the layout of structs: I decided to make my vtables out
of structs rather than arrays. In other words, instead of being a table
of opaque pointers, I decided to individually declare each entry with
the correct type for that method. I figure that the various optimizers
could do a better job if I preserve the type info.
OK, so we come to the issue of inheritance: Suppose I have a class A and
subclass B, each of which have two methods.
One way to layout the vtable for B is to include the vtable for A as a
sub-structure, i.e.:
A.vtable = { A.method1 *, A.method2 * }
B.vtable = { { A.method1 *, A.method2 * }, B.method1 *, B.method2 * }
The advantage of this form is that when you upcast B to an A, the
pointer to the B vtable can be upcast as well - i.e. its a valid pointer
to a B vtable is also a valid pointer to an A vtable.
However, when it comes to actually calling methods this form is somewhat
cumbersome to work with. It means that each member in B can't simply
record a member index of which table entry it corresponds to; Instead it
has to record the entire set of GEP indices to get to that table entry.
A more convenient form is to simply flatten the structure:
A.vtable = { A.method1 *, A.method2 * }
B.vtable = { A.method1 *, A.method2 *, B.method1 *, B.method2 * }
Now each member can be referred to via a simple integer index.
However, the problem here is that I don't know if its legal to bitcast
from B.vtable to A.vtable. As far as I know, the optimizer might
re-order the member fields, or muck with the padding.
What sort of invariants can I rely on in this case?
-- Talin