我手里拿着一个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指令可用于评估这些值。基本思想是使用getelementptrfromnull指针来计算所需的值。因为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 优化器还将这些值转换为常量。