llvm – GEP指令: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个整数的数组中)并且我试图很好地理解为什么会出现这种情况.

最佳答案 这个问题的答案是“GEP取消引用了什么?”没什么.这意味着GEP永远不会取消引用指针:它只根据您传递它的指针计算新地址.它永远不会读取任何内存.

看看这个例子:

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

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

在使用i64 0索引之后,我们引用了一个struct {[40 x i32] *}. %MyVar已经指出了这一点,没有必要的解除引用.

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

第三个索引i64 0现在将引用[40 x i32]数组本身.这是非法的. GEP需要取消引用在前一步骤中获得的指针以获得该存储器地址.一般来说,GEP永远不能“通过”一个指针,明显的例外是你传递给它的初始值总是一个指针.

我还要指出,i32 0和i64 0在索引方面是相同的,都指向struct / array中的第一个元素.对于你提到的常数17也是如此.

点赞