question about the DIBuilder::createStructType

Hello,

I’m using DIBuilder to create debugging information, I’m not clear about two things:

[1] Could you help explain the meaning and the difference between"alignment" and “offset” of a type ?

e.g class Actor{
int age;
const char* name;
}

Besides, I found the denotation of createMemberType and createStructType both have “Member Alignment” and “Member Size” fields, are they the same thing ? If they are, then for the “Actor”, which member is it referring to ?

[2] In createMemberType, the last arg “Ty” is parent type, does it mean “Actor” in the example ?

thanks

Hi, Hui Zang,

It helps to remember that at runtime a variable of a structure type has to be allocated store, and to think about how that variable is laid out in store.

You must use createMemberType to create a DIType for each field (aka member) in the structure; you then store those DIType’s as the elements of a DIArray which you pass as the ‘Elements’ parameter to createStructType.

When creating a structure member, you have to specify this information :

SizeinBits - the actual size of the member

OffsetInBits - the number of bits between the start of the member in the layout of the structure and the start of the structure

AlignInBits - the address boundary (if any) to which the element has to be aligned.

Remember that on some processor architectures (e.g. Sun), basic data items (e.g shorts, ints, floats) have to be allocated to store at addresses which are multiples of their size; e.g. shorts must be allocated at addresses

which are multiples of two bytes, ints allocated at addresses which are multiples of 4 bytes, etc. If this rule is not followed, e.g. a 4-byte integer is allocated at an odd address, then any attempt to load or store that variable will result in a bus error. On architectures which do not have this constraint, it is sufficient for objects to be byte-aligned.

So in your example, you might have

age : size 32, offset 0, align 32

name: size 32, offset 32, align 32

or

age : size 32, offset 0, align 8
name: size 32, offset 32, align 8

depending on your target processor.

The sizeInBits and AliginInBits parameters to createStructType describe the whole structure (e.g. Actor: sizeInBits:64 aligInBits: 32). Note that the size of the structure may be more than the sum of the size of the individual members - there may be gaps in the structure layout, depending on the sizes and alignments of its members. The alignment of a structure is generally the largest alignment of any of its members; the structure type must be laid out so that if a structure variable starts at an address which is a multiple of the structure’s alignment then each of its members starts at an address which is a multiple of its alignment.

E.g. if you have a structure

struct S
{

int I1;

short S;

int I2;

} V;

and an int is 4 bytes and a short 2 bytes, then either you must leave a 2-byte gap between S and I2 in the layout or you must re-order the fields (if the language you are implementing allows that) so that S comes after I1 and I2 in the layout; otherwise either I1 or I2 will be misaligned in store regardless of the address at which V is allocated.

The ‘Ty’ parameter to createMemberType specifies the type of the member. In your example, you will need to create DIType objects for the types ‘int’ and ‘const char*’; use the first one in the call to createMemberType for “age” and the second one in the call for “name”.

As a general principle, when creating the DIType object for a given type, you must work from the bottom up (or recursively, from the top down) through the hierarchy of types which you are compiling : you must create the DIype for a type before you create the DItype for any other type which uses that type (e.g. as a member of a structure, or an element of an array, or the target type of a pointer type, etc.). Note that you can have cycles of type dependencies in your hierarchy; e.g. a struct S could have a field P which is of type S* - so before you try to create the DIType for a given type you must check whether you have already created it, otherwise you could recurse endlessly around the cycles! (until your stack blows up…)

Hope this helps,

Richard

Hello, Richard

Thanks a lot !

Hi, Hui Zang,

Here’s a helpful article:

http://xathrya.web.id/blog/2013/12/17/data-structure-alignment-in-c-on-x86-and-x64-machine/

I am not familiar with Chapel, and don’t know what a Chapel::Type is. If the APIs you use to manipulate instances of that type support traversal (e.g. given a Chapel::Type that represents a structure, there is an operation that gives you a list of Chapel::Type’s that represent the members of that structure) you might be able to get the information from that.

In my case, I work with an abstract syntax tree that has been generated by a parser; traversing it gets me to nodes in the tree which represent structure types, and the necessary size/offset/alignment information for the structure members is generated by a layout algorithm.

Regards,

Richard

Hello, Richard

Thanks ! My case is similar, there is a AST that I traverse. Could you tell me more about that layout algorithm ?