Llvm GEP指令:i32 vs i64

Llvm GEP指令:i32 vs i64,llvm,llvm-ir,Llvm,Llvm Ir,我一直试图理解LLVM的GetElementPtr(GEP)指令,并偶然发现了以下文档: 这很有帮助,但有几件事我感到困惑。特别是在“GEP取消引用了什么?”()一节中,讨论了以下代码: %MyVar = uninitialized global { [40 x i32 ]* } ... %idx = getelementptr { [40 x i32]* }, { [40 x i32]* }* %MyVar, i64 0, i32 0, i64 0, i64 17 %MyVar是一个全局变

我一直试图理解LLVM的GetElementPtr(GEP)指令,并偶然发现了以下文档:

这很有帮助,但有几件事我感到困惑。特别是在“GEP取消引用了什么?”()一节中,讨论了以下代码:

%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个整数数组的指针。这是清楚的。我知道
%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
索引之后,我们有一个对结构
{[40 x i32]*}
的引用<代码>%MyVar已指向此,无需取消引用

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

第三个索引
i64 0
现在将引用
[40 x i32]
数组本身这是非法的。GEP需要取消对上一步中获得的指针的引用,才能获得此内存地址。一般来说,GEP永远不能“通过”指针编制索引,唯一明显的例外是,传递给它的初始值始终是指针


我还要指出,
i32 0
i64 0
在索引方面是相同的,它们都引用结构/数组中的第一个元素。你提到的常数
17
也是如此。

这太棒了!非常感谢。