这个LLVM寄存器号有什么问题?

kei*_*ter 6 code-generation llvm

我正在为我正在学习的课程编写一个简单的类C语言的编译器.这段代码:

int main() {
    printInt(not(0));
    return 0;
}

int not(int n) {
    if (n == 0) {
        return 1;
    } else {
        int result = 0;
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

..我天真地编译到这个bitcode:

declare void @printInt(i32)
declare void @printDouble(double)
declare void @printString(i8*)
declare i32 @readInt()
declare double @readDouble()

define i32 @main() {
entry:
    %0 = call i32 @not(i32 0)
    call void @printInt(i32 %0)
    ret i32 0
    unreachable
}

define i32 @not(i32 %n_0) {
entry:
    %0 = icmp eq i32 %n_0, 0
    br i1 %0, label %lab0, label %lab1
lab0:
    ret i32 1
    br label %lab2
lab1:
    %result_0 = alloca i32 
    store i32 0, i32* %result_0
    %1 = load i32* %result_0
    ret i32 %1
    br label %lab2
lab2:
    unreachable
}
Run Code Online (Sandbox Code Playgroud)

但是,opt不接受该代码.

opt: core023.ll:25:5: error: instruction expected to be numbered '%2'
%1 = load i32* %result_0
Run Code Online (Sandbox Code Playgroud)

现在,从我对未命名的临时寄存器的理解,它们应该从0开始按顺序编号.这就是这种情况.但显然"%1 = sub .."行应编号为%2.这是为什么?%0和%1之间的任何指令都会增加序列号吗?或许它只是其他东西的后续错误?

Job*_*Job 9

在LLVM,一切可以有一个名称,但不分配有一个编号.这还包括基本块.在你的情况下

lab0:
    ret i32 1
    br label %lab2
Run Code Online (Sandbox Code Playgroud)

定义了两个基本块,因为每个终结符指令都结束了一个基本块.这意味着,从概念上讲,您的代码被解析为

lab0:
    ret i32 1
1:
    br label %lab2
Run Code Online (Sandbox Code Playgroud)

之后的下一个免费号码是2.

为了防止这样的奇怪行为,我建议始终明确命名基本块.