The GEP Instruction: i32 vs i64



我一直在试图理解LLVM的GetElementPtr (GEP)指令,并遇到了这个文档:

http://llvm.org/docs/GetElementPtr.html

它很有帮助,但有几件事我觉得很困惑。特别是,在"GEP对什么进行了取消引用?"' (http://llvm.org/docs/GetElementPtr.html#id6)下面的代码被讨论:

%MyVar = uninitialized global { [40 x i32 ]* }
...
%idx = getelementptr { [40 x i32]* }, { [40 x i32]* }* %MyVar, i64 0, i32 0, i64 0, i64 17

%MyVar是一个全局变量,它是一个指向结构体的指针,该结构体包含一个指向40个int型数组的指针。这很清楚。我理解%MyVar之后的参数是它的索引,但我不明白为什么其中一些被声明为i64而另一些被声明为i32

我的理解是这段代码是为64位机器编写的,并且指针被假定为64位宽。%MyVar所指向的数组的内容是32位宽的。为什么最后一个索引是i64 17而不是i32 17呢?

我还应该指出,这个例子说明了GEP的非法使用(结构中的指针必须被解引用,以便索引到40个int型数组),我试图很好地理解为什么会出现这种情况。

这个问题的答案是nothing。这意味着GEP永远不会对指针解引用:它只根据您传递给它的指针计算新地址。它从不读取任何内存。

看这个例子:

%idx = getelementptr { [40 x i32]* }, { [40 x i32]* }* %MyVar, i64 0, i32 0, i64 0, i64 17

我们从%MyVar开始,这是一个{ [40 x i32]* }*,一个指向结构体的指针,其中包含指向数组的指针。

在用i64 0索引之后,我们有一个对{ [40 x i32]* }结构体的引用。%MyVar已经指向这个,不需要解引用。

在索引第二个i32 0之后,我们现在引用[40 x i32]*,这是该结构体的唯一成员。它具有与结构体本身相同的内存位置,即%MyVar

第三个索引i64 0现在指向[40 x i32]数组本身。这是非法的。 GEP需要对前一步获得的指针解引用才能获得该内存地址。一般来说,GEP永远不能"通过"指针索引,除了传递给它的初始值总是指针的明显例外。

我还将指出i32 0i64 0对于索引的目的是相同的,它们都指向struct/array中的第一个元素。对于前面提到的常量17也是如此。

最新更新