我一直试图理解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个整数的数组)并且我试图很好地理解为什么这是案件。
答案 0 :(得分:2)
问题的答案,“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
建立索引后,我们引用了一个结构{ [40 x i32]* }
。 %MyVar
已经指出了这一点,不需要解除引用。
在使用第二个i32 0
建立索引之后,我们现在引用结构的唯一成员[40 x i32]*
。它与结构本身具有相同的内存位置,位于%MyVar
。
第三个索引i64 0
现在将引用[40 x i32]
数组本身。 这是非法的。 GEP需要取消引用上一步中获得的指针才能获得此内存地址。一般来说,GEP永远不能“通过”一个指针,明显的例外是你传递给它的初始值总是一个指针。
我还要指出i32 0
和i64 0
在索引方面是相同的,都指向struct / array中的第一个元素。对于你提到的常数17
也是如此。