Hi LLVM-dev! 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 struct array { long refcount; long length; long items[1]; }; 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? 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* 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 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. Thanks for any help, Carl Friedrich
Carl, The thing you're missing is that LLVM's primitive types have well known, fixed sizes that are not target dependent. A ulong is 8 bytes. A uint is 4 bytes. A ushort is 2 bytes. Etc. and always. There are also methods in LLVM to help you deal with the size of a type in bits and bytes. In particular you might want to note the following methods: Type::isSized Type::getPrimitiveSize Type::getPrimitiveSizeInBites Reid On Mon, 2005-06-20 at 13:03 +0200, Carl Friedrich Bolz wrote:> Hi LLVM-dev! > > 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 > > struct array { > long refcount; > long length; > long items[1]; > }; > > 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? 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* > > > 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 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. > > Thanks for any help, > > Carl Friedrich > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev-------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 189 bytes Desc: This is a digitally signed message part URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20050620/73f4693f/attachment.sig>
Hi Reid, On Mon, Jun 20, 2005 at 07:08 -0700, Reid Spencer wrote:> The thing you're missing is that LLVM's primitive types have well known, > fixed sizes that are not target dependent. A ulong is 8 bytes. A uint is > 4 bytes. A ushort is 2 bytes. Etc. and always.Don't aligning rules make it hard to compute the size of a whole struct from the sizes of it's members? And what about pointers? cheers, holger
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/
> 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 > > 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 > }Chris you should maybe add this example to the getelementptr documentation. Aaron