问题
I'm holding a Type*
in my hand. How do I find out its size (the size objects of this type will occupy in memory) in bits / bytes? I see all kinds of methods allowing me to get "primitive" or "scalar" size, but that won't help me with aggregate types...
回答1:
If you only need the size because you are inserting it into the IR (e.g., so you can send it to a call to malloc()
), you can use the getelementptr
instruction to do the dirty work (with a little casting), as described here (with updating for modern LLVM):
Though LLVM does not contain a special purpose
sizeof
/offsetof
instruction, thegetelementptr
instruction can be used to evaluate these values. The basic idea is to usegetelementptr
from thenull
pointer to compute the value as desired. Becausegetelementptr
produces the value as a pointer, the result is casted to an integer before use.For example, to get the size of some type,
%T
, we would use something like this:%Size = getelementptr %T* null, i32 1 %SizeI = ptrtoint %T* %Size to i32
This code is effectively pretending that there is an array of
T
elements, starting at thenull
pointer. This gets a pointer to the 2ndT
element (element #1) in the array and treats it as an integer. This computes the size of oneT
element.
The good thing about doing this is that it is useful in exactly the cases where you do not care what the value is; where you just need to pass the correct value from the IR to something. That's by far the most common case for my need for sizeof()
-alike operations in the IR generation.
The page also goes on to describe how to do an offsetof()
equivalent:
To get the offset of some field in a structure, a similar trick is used. For example, to get the address of the 2nd element (element #1) of
{ i8, i32* }
(which depends on the target alignment requirement for pointers), something like this should be used:%Offset = getelementptr {i8,i32*}* null, i32 0, i32 1 %OffsetI = ptrtoint i32** %Offset to i32
This works the same way as the
sizeof
trick: we pretend there is an instance of the type at thenull
pointer and get the address of the field we are interested in. This address is the offset of the field.Note that in both of these cases, the expression will be evaluated to a constant at code generation time, so there is no runtime overhead to using this technique.
The IR optimizer also converts the values to constants.
回答2:
The size depends on the target (for several reasons, alignment being one of them).
In LLVM versions 3.2 and above, you need to use DataLayout, in particular its getTypeAllocSize
method. This returns the size in bytes, there's also a bit version named getTypeAllocSizeInBits
. A DataLayout
instance can be obtained by creating it from the current module: DataLayout* TD = new DataLayout(M)
.
With LLVM up to version 3.1 (including), use TargetData
instead of DataLayout
. It exposes the same getTypeAllocSize
methods, though.
来源:https://stackoverflow.com/questions/14608250/how-can-i-find-the-size-of-a-type