10

私が見ている問題を小さな例に煮詰めました。これが私が使用しているLLVMアセンブラコードです(foo.llで):

target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-pc-linux-gnu"

define fastcc i32 @foo(i32) {
entry:
    %x = add i32 %0, 1
    ret i32 %x
}

define i32 @main(i32, i8**) {
entry:
    %2 = call i32 @foo(i32 %0)
    ret i32 %2
}

次に、次のようにコンパイルします。

clang -O1 -o foo foo.ll

...そして実行すると、次のようになります。

Illegal instruction (core dumped)

...だから、デバッガーを起動すると、次のようになります。

Program received signal SIGILL, Illegal instruction.
0x00000000004004d0 in main ()
(gdb) bt
#0  0x00000000004004d0 in main ()
(gdb) disas
Dump of assembler code for function main:
=> 0x00000000004004d0 <+0>: ud2    
End of assembler dump.
(gdb) 

次のいずれかを変更すると、プログラムは正常に実行されることに注意してください。

  • -O1 を clang フラグから削除します
  • foo.ll の @foo の宣言から fastcc を削除します。

参考までに、「clang -v」は次のとおりです。

clang version 3.3 (tags/RELEASE_33/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix

また、ここで役立つ場合は、 "objdump -d foo" の結果です

4

2 に答える 2

5

あなたの呼び出し先は「fastcall」とマークされていますが、呼び出しはそうではありません。呼び出し規則が一致する必要があります。そうしないと、未定義の動作になり、「ud2」まで最適化されるか、まったく最適化されない可能性があります。これは FAQ です: http://llvm.org/docs/FAQ.html#why-does-instcombine-simplifycfg-turn-a-call-to-a-function-with-a-mismatched-calling-convention-into -unreachable-why-not-make-the-verifier-reject-it

于 2014-06-15T08:09:25.680 に答える
1

関数呼び出しを最適化するときに、clang が未定義の命令 ud2 (無効なオペコード エラーを発生させる) を生成し、何かを処理できないことを示すバグがあります。

基本的に、処理を高速化するために、戻り値をレジスタに配置します。戻り値がレジスタに収まらない (したがって、スタックに返される) 場合は、ret の代わりに ud2 を発行します。

これは既知のバグです (少なくとも 3.2 では)。

于 2013-11-15T00:27:39.377 に答える