[llvm-dev] Building aggregate types with dynamically sized elements

David Chisnall via llvm-dev llvm-dev at lists.llvm.org
Fri Jul 14 03:29:28 PDT 2017


On 14 Jul 2017, at 11:19, Christer Swahn <christer.e.swahn at gmail.com> wrote:
> 
> My concern as I said is about portability and alignment, if I roll my own type layout and offset computations. Any advice regarding this is much appreciated!

As I said, you will need to handle accesses via a sequence of GEPs and bitcasts of pointers (i.e. use a GEP to get the address of the variable-sized pointer field, then cast it to a pointer type for the array, then use a GEP on that, and so on).  For allocas, you will need to compute the size yourself and probably allocate an i8 array that you can then bitcast to the type of your top-level struct.  Getting the address of elements after the first variable-sized element is more tricky, and I’d generally suggest that you lower something like (C-style syntax):

struct foo
{
	int a;
	int array[somevariable];
	int b;
	int c;
};

to something more like:

struct foo
{
	int a;
	int array[1];
	struct __internal
	{
		int b;
		int c;
	} rest;
}

You can then do a fixed GEP to get the size of array.  Then a GEP with a variable index to get the address of the end of array.  You can then bitcast this to a pointer to struct __internal and do a GEP to get at the later elements.

This will give the wrong answer if the alignment of struct __internal is such that there is padding.  To work around this, you can do a GEP to get the offset of array and a GEP to get the address of rest, add the size to the offset of array and subtract this from the offset of rest.  This will give you the size of any padding, and if it is non-zero then you can do a bitcast to i8* in the middle and do a GEP to realign the pointer.

Note: If your algorithm for accessing the layouts is more complex than this, then you may be better off writing it in C, compiling it with clang, and inserting it into the module as an always_inline function that you just call.  The LLVM optimisers will then inline it and handle the constant propagation for you.  If it refers to type introspection structures that are in constant globals, then constant propagation should handle all of this correctly.

David



More information about the llvm-dev mailing list