1

有人可以解释一下这段代码有什么问题吗?

我认为这应该从全局数组中获取第二个参数,但实际上它会默默地粉碎 JIT 编译例程中的某个地方。

我的假设:

  1. GEP 指令通过应用偏移量计算元素的内存地址并返回指针。
  2. load 指令加载给定指针引用的值(换句话说,它取消引用指针)。
  3. ret 指令退出函数并将给定的值传递给调用者。

好像我错过了一些基本的东西,但是我应该放弃自己寻找答案的时间点已经消失了,我必须寻求帮助。

@arr = common global [256 x i64], align 8

define i64 @iterArray() {
entry:
  %0 = load i64* getelementptr inbounds ([256 x i64]* @arr, i32 1, i32 0)
  ret i64 %0
}
4

1 回答 1

1

您请求了 256 项数组中的第 257 项,这是一个问题。

给 gep 指令的第一个索引表示通过值操作数执行了多少步 - 这里的值操作数不是数组,而是指向数组的指针。这意味着那里的每一步都会向前跳过数组的整个大小 - 这就是 gep 实际上要求第 257 个项目的原因。使用 0 作为第一个 gep 索引可能会解决问题。然后使用 1 作为第二个索引将为您提供数组中的第二个项目,这就是您想要的。在这里阅读更多相关信息:http: //llvm.org/docs/GetElementPtr.html#what-is-the-first-index-of-the-gep-instruction

或者,在这里使用extractvalue指令更合适,它类似于 gep 隐式使用 0 作为第一个索引(还有一些其他差异)。

关于编译器崩溃的原因,我不确定 - 我猜虽然通常这样的内存访问会编译得很好(并且在运行时生成一个段错误或只返回一个错误的值),但在这里你特别要求 gep 是inbounds,这意味着边界检查已经完成——它会在这里失败——所以返回一个毒值,这意味着你的函数现在是有效的load undef。我不确定 LLVM 是做什么用的load undef——它可能应该被优化出来,并且功能应该只是return undef——但也许它做了一些不同的事情,导致你的代码被拒绝。

于 2013-05-17T18:56:18.303 回答