26

我手里拿着一个Type*。我如何找出它的大小(这种类型的大小对象将在内存中占用)以位/字节为单位?我看到各种允许我获得“原始”或“标量”大小的方法,但这对聚合类型没有帮助......

4

2 回答 2

33

大小取决于目标(出于多种原因,对齐是其中之一)。

在 LLVM 3.2 及更高版本中,您需要使用DataLayout,尤其是它的getTypeAllocSize方法。这将返回以字节为单位的大小,还有一个名为getTypeAllocSizeInBits. DataLayout可以通过从当前模块创建实例来获取实例:DataLayout* TD = new DataLayout(M).

对于 LLVM 至 3.1 版(包括),使用TargetData而不是DataLayout. 但是,它公开了相同的getTypeAllocSize方法。

于 2013-01-30T15:59:16.883 回答
33

如果您需要大小,因为您将其插入到 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 优化器还将这些值转换为常量。

于 2015-06-14T14:18:57.270 回答