2017-12-21 22 views
3

IRVMを生成するLLVMに関数パスを作成しています。問題は、アセンブルされたコードが期待どおりに動作していないように見えることです。私はLLVMをかなり新しくしているので、LLVMのIRセマンティクスを誤解しているのか、それともllcの動作が間違っているのかを知りたいと思います。LLVMのllcが間違ったコードを生成する

LLVM IRは、次のとおり

define void @fff(i32*) #0 { 
    %2 = alloca i32*, align 8 
    %3 = alloca i32, align 4 
    %4 = load i8*, i8** @dirty 
    br label %5 

; <label>:5:          ; preds = %1 
    store i32* %0, i32** %2, align 8 
    %6 = load i32*, i32** %2, align 8 
    %7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.4, i32 0, i32 0), i32* %6) 
    %8 = load i32*, i32** %2, align 8 
    %9 = load i32, i32* %8, align 4 
    %readDirty = load atomic i8, i8* %4 acquire, align 8 
    %10 = icmp eq i8 %readDirty, 1 
    br i1 %10, label %Restart, label %11, !prof !3 

; <label>:11:          ; preds = %5 
    store i32 %9, i32* %3, align 4 
    ret void 

Restart:           ; preds = %5 
    ;EDIT: bug was here. Must include label %5 as a possible destination block 
    indirectbr i8* blockaddress(@fff, %5), [] 
} 

以下のCコードにこの対応(略):使用して私はアセンブル

char *dirty=1; 
void fff(int *head) ATTR{ 
restart: 
    printf("head = %p\n", head); 
    int r = *head; 
    if(*dirty) 
     goto restart; //But using indirect branch 
} 

次に、リンクラン:

llc -filetype=obj simpleOut.ll -o out.o 
gcc -o exe out.o 
./exe 

アドレス0x7ffeea51d7a8の関数を呼び出すと、次のように出力されます。

head = 0x7ffeea51d7a8 
head = 0x2e889e825bf4005c 
Segmentation fault: 11 

x86_64版のアセンブリコードは次のとおりです。

;head reside in rcx 
100000d60: 55 pushq %rbp 
100000d61: 48 89 e5 movq %rsp, %rbp 
100000d64: 53 pushq %rbx 
100000d65: 48 83 ec 18  subq $24, %rsp 
100000d69: 48 89 f9 movq %rdi, %rcx 
100000d6c: 48 8d 3d dd 02 00 00 leaq 733(%rip), %rdi 
100000d73: ff 17 callq *(%rdi) 
100000d75: 48 8b 18 movq (%rax), %rbx 
100000d78: 48 8d 3d c0 01 00 00 leaq 448(%rip), %rdi 
100000d7f: 48 89 4d f0  movq %rcx, -16(%rbp) 
100000d83: 48 8b 75 f0  movq -16(%rbp), %rsi 
100000d87: b0 00 movb $0, %al 
100000d89: e8 62 01 00 00 callq 354 ;call to printf, corrupt rcx 
100000d8e: 48 8b 45 f0  movq -16(%rbp), %rax 
100000d92: 8b 00 movl (%rax), %eax 
100000d94: 80 3b 01 cmpb $1, (%rbx) 
100000d97: 74 0a je 10 <_fff+0x43> 
100000d99: 89 45 ec movl %eax, -20(%rbp) 
100000d9c: 48 83 c4 18  addq $24, %rsp 
100000da0: 5b popq %rbx 
100000da1: 5d popq %rbp 
100000da2: c3 retq 
100000da3: 48 8d 05 ce ff ff ff leaq -50(%rip), %rax 
100000daa: ff e0 jmpq *%rax ;jumps to 100000d78 
100000dac: 0f 1f 40 00  nopl (%rax) 

問題はLLVM声明store i32* %0, i32** %2, align 8もレジスタrcxが既にprintf機能により破損し、再起動、後movq %rcx, -16(%rbp)に変換することをあるように思われます。

これはバグのようですが、私はLLVMでバグレポートを提出します。ちょうど私がLLVM IRを誤解していないことを確認したいのです。

llcバージョンは5.0.0、自宅経由でインストールされます。 gcc(リンクに使用)はclang-900.0.39.2です。

おかげで

+0

'indirectbr'のラベルのリストは空です。これは物事を台無しにするかもしれない、と思う。ありがとう@arrowd。 – arrowd

+0

私は可能な目的地を追加するのを忘れました。私はそれを解決した後、それは問題を解決しました。私はこれを答えとして投稿できると思います。 –

+0

上記のIRを編集して変更を指摘できますか? –

答えて

3

documentationによると、indirectbr命令は、すべての可能な送信先のブロックのリストを供給する必要があります。ジャンプしているBBを省略すると、未定義の動作が発生します。

関連する問題