Struct layout assumptions

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

Hi Talin,

Either form is perfectly safe.

— Gordon

An optimization could only do that if it could prove it was safe, that
is, if it could find all possible uses and fix them up so they still
referred to the same field.

Basically an optimizer would have to prove that all accesses to those
objects were type safe, and that they didn't escape the analysis
scope, and didn't alias with other objects.

Having written a safe struct reorganizer in llvm before, I can tell
you that even if something like that did exist, it is highly unlikely
it would be able to prove its invarients for your code, and if it
could, then it would be safe and you wouldn't notice :slight_smile: