我手里拿着一个Type*
。我如何找出它的大小(这种类型的大小对象将在内存中占用)以位/字节为单位?我看到各种允许我获得“原始”或“标量”大小的方法,但这对聚合类型没有帮助......
2 回答
大小取决于目标(出于多种原因,对齐是其中之一)。
在 LLVM 3.2 及更高版本中,您需要使用DataLayout,尤其是它的getTypeAllocSize
方法。这将返回以字节为单位的大小,还有一个名为getTypeAllocSizeInBits
. DataLayout
可以通过从当前模块创建实例来获取实例:DataLayout* TD = new DataLayout(M)
.
对于 LLVM 至 3.1 版(包括),使用TargetData
而不是DataLayout
. 但是,它公开了相同的getTypeAllocSize
方法。
如果您只需要大小,因为您将其插入到 IR 中(例如,因此您可以将其发送到调用malloc()
),您可以使用该getelementptr
指令来完成脏工作(带有一点铸造),如此处所述(使用更新现代 LLVM):
尽管 LLVM 不包含特殊用途
sizeof
/offsetof
指令,但该getelementptr
指令可用于评估这些值。基本思想是使用getelementptr
fromnull
指针来计算所需的值。因为getelementptr
将值作为指针生成,所以在使用前将结果转换为整数。例如,要获取某种类型的大小
%T
,我们将使用如下内容:%Size = getelementptr %T* null, i32 1 %SizeI = ptrtoint %T* %Size to i32
这段代码有效地假装有一个
T
元素数组,从null
指针开始。这将获得指向T
数组中第二个元素(元素#1)的指针并将其视为整数。这会计算一个T
元素的大小。
这样做的好处是它在您不关心值是什么的情况下很有用;您只需要将正确的值从 IR 传递给某物。sizeof()
到目前为止,这是我在 IR 生成中需要类似操作的最常见情况。
该页面还继续描述如何进行offsetof()
等效操作:
为了获得结构中某些字段的偏移量,使用了类似的技巧。例如,要获取
{ i8, i32* }
(取决于指针的目标对齐要求)的第二个元素(元素#1)的地址,应该使用如下内容:%Offset = getelementptr {i8,i32*}* null, i32 0, i32 1 %OffsetI = ptrtoint i32** %Offset to i32
这与技巧的工作方式相同
sizeof
:我们假装在指针上有一个类型的实例null
并获取我们感兴趣的字段的地址。这个地址是该字段的偏移量。请注意,在这两种情况下,表达式将在代码生成时被评估为常量,因此使用此技术没有运行时开销。
IR 优化器还将这些值转换为常量。