7

私が受講しているコースでは、単純なCのような言語用のコンパイラを作成しています。このコードのビット:

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

int not(int n) {
    if (n == 0) {
        return 1;
    } else {
        int result = 0;
        return result;
    }
}

..私はこのビットコードに素朴にコンパイルします:

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
}

ただし、optはそのコードを受け入れません。

opt: core023.ll:25:5: error: instruction expected to be numbered '%2'
%1 = load i32* %result_0

さて、名前のない一時レジスタについて私が理解していることから、それらは0から順番に番号が付けられることになっています。これがここに当てはまります。しかし、どうやら「%1 = sub ..」の行には%2の番号が付けられているはずです。何故ですか?%0と%1の間の命令のいずれかがシーケンス番号を増やしますか?それとも、他の何かからの単なる後続の障害ですか?

4

1 に答える 1

10

LLVMでは、名前を付けることができるが番号を付けないものすべてに番号が割り当てられます。これには基本ブロックも含まれます。あなたの場合

lab0:
    ret i32 1
    br label %lab2

すべてのターミネータ命令が基本ブロックを終了するため、2つの基本ブロックを定義します。これは、概念的には、コードが次のように解析されることを意味します

lab0:
    ret i32 1
1:
    br label %lab2

その後の次の空き番号は2です。

このような奇妙な動作を防ぐために、基本ブロックに常に明示的に名前を付けることをお勧めします。

于 2012-05-06T21:21:16.740 に答える