[LLVMdev] Struct layout assumptions

Talin viridia at gmail.com
Sun Mar 2 12:47:59 PST 2008


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




More information about the llvm-dev mailing list