[LLVMdev] variable sized structs in LLVM

Chris Lattner sabre at nondot.org
Fri Jun 24 11:07:52 PDT 2005


On Mon, 20 Jun 2005, Carl Friedrich Bolz wrote:
> I'm having problems figuring out how to do variable sized structs in LLVM 
> (which are neccessary for PyPy's LLVM backend, on which I'm working). I'm 
> trying to do the equivalent of
...
> in LLVM, where the items array can be arbitrarily long. I guess that the 
> struct definition should be something like:
>
> %array = type {int, int, [1 x int]}
>
> but how would I allocate such a thing, with the items array being, say, 9 
> items long? In C I would do something like:
>
> malloc(sizeof(struct array) + ((9 - 1) * sizeof(long)));
>
> but there is no sizeof in LLVM, right?

sizeof in llvm is really 'offsetof from the null pointer'.  See below for 
an example.  In short, yes we do have it, though it's not super-intuitive.

> If I try compile C code like that with 
> the LLVM C frontend, I get
>
> %struct.array = type { int, int, [1 x int] }
>
> ...
>
> %tmp.0 = malloc [44 x sbyte]
> %tmp.5 = cast [44 x sbyte]* %tmp.0 to %struct.array*

This is almost exactly what you want to do.  Please make the array be 
[0 x int] though, as it is undefined in llvm to access past the end of an 
array with non-zero length.  I added a note about zero-length arrays here:

http://llvm.cs.uiuc.edu/docs/LangRef.html#i_getelementptr
http://llvm.cs.uiuc.edu/docs/LangRef.html#t_array

> It is clear what happens here, but I don't know how I would reproduce that, 
> because I can't easily find out the length in bytes of the array.

I'm not sure I understand.  Are you saying that, at runtime, you need ot 
know the actual length of the array?  If so, you should store this 
information as one of the elements of the struct before the array.  If you 
have a pascal style array for example, you could do something like this:
    { uint, [0 x float] }

... storing the actual dynamic size of the array in the uint member.

As you mention above, you should use malloc and cast the return value.  If 
you want to get the desired size in a target-independent way (always 
good), you should do something like this:

%array = type { int, int, [0 x int] }
implementation
%array *%NewArray(int %Length) {
   ;; Get the offset of the 'Length' element of the array from the null
   ;; pointer.
   %Size = getelementptr %array* null, int 0, uint 2, int %Length
   %SizeU = cast int* %Size to uint
   %Ptr = malloc sbyte, uint %SizeU
   %Result = cast sbyte* %Ptr to %array*
   ret %array* %Result
}

> I can think of workarounds (like using the struct module of the Python 
> standard library to calculate the sizes) but I have the feeling that I'm 
> missing something and there is a simple way to do that in LLVM.

This shouldn't be necessary.

-Chris

-- 
http://nondot.org/sabre/
http://llvm.cs.uiuc.edu/




More information about the llvm-dev mailing list