LLVM error: invalid getelementptr indices

LLVM error: invalid getelementptr indices

我正在开发一种编译器,可以将类似 Java 的语言翻译成 LLVM,但我在使用 getelementptr 指令时遇到了问题。

假设我有 类 AB 定义如下:

class A {int val;}
class B {A a;}

这被翻译成 LLVM 类型:

%A = type {%A_vtable_type*, i32}
%B = type {%B_vtable_type*, %A*}

其中第一个元素是指向虚拟表的指针,对于这个问题并不重要。

我要翻译以下代码:

A a;
B b;
b = new B;
b.a = new A;
b.a.val = 42;

前四个指令工作得很好,第五个指令被翻译成这样:

%b = alloca %B*
...
%1 = load %B*, %B** %b
%2 = getelementptr %B, %B* %1, i32 0, i32 1, i32 1
store i32 42, i32* %2 

我对这些指标的理解是这样的:

  1. 0 是 %B*
  2. 类型的 %1 的取消引用
  3. 第一个1是struct%B*的字段a
  4. 第二个1是类型%A*
  5. 的字段val

现在,我阅读了 https://llvm.org/docs/GetElementPtr.html,据我了解,可以在一个 GEP 中进行多个地址计算,而无需取消引用后续指针类型,但是在运行

llvm-as-6.0 classes.ll -o classes.bc

我明白了

llvm-as-6.0: classes.ll:40:31: error: invalid getelementptr indices

删除 i32 0 后错误消失,但例如,当我尝试创建更多嵌套 类 时,出现类型错误。

我喜欢将 GEP 最好理解为一种执行指针算术的高级方法。您的使用尝试将 B 的指针取消引用到 A,但它永远不会这样做。 GEP 不访问内存,它只是将大小添加到您提供的指针。您给 GEP 一个指向具有固定布局的复杂对象的指针,它 returns 一个指向复杂对象中某些 field/entry 的指针。

您的 A 不在 B 中的固定偏移量。相反,您的 A* 在 B 中的固定偏移量,找到 A 的地址需要读取 B 的 A*。

如果您要使用嵌套类型(也就是说,如果您的 B 包含一个 A 而不是对 A 的引用),那么您可以使用 GEP 和一个 B* 来获取 A 的 i32 的地址(并且然后将 42 存入其中。