1

C 用の clang コンパイラと、それが生成する中間コードを理解しようとしています。

コンパイルして LLVM-IR を生成する一連の関数がありますが、その理由がわかりません。

最初は次のとおりです。

int f(int x){
}

これにより、LLVM コードが生成されます。

define i32 @f(i32 %x) nounwind uwtable readnone{
  ret i32 undef
}

それは完全に理解できると思います。関数本体が定義されていません!

次の C 関数は次のとおりです。

int f(int x){
  if (x < 0) 
    {}
  else
    {}
}

これを clang でコンパイルすると、まったく同じ LLVM-IR が生成されます。コンパイラは本体がガベージであることを認識し、未定義を返します!!! これがガベージであることを LLVM が認識する方法は、オプティマイザです。Clang --> LLVM は「戻り値コレクター」規約を使用します -- 関数を定義するとき -- %1 が「戻り値」として割り当てられます。すべての return ステートメントがこの値を更新し、最終的に、関数本体の最後に LLVM の ret ステートメントが 1 つあり、基本的にこの値を返します。LLVM は、変数が更新または初期化されずに割り当てられ、返されたことを認識し、未定義に設定します。

今キッカーのために!

int f(int x){
  if (x<0)
    {}
  else
    {           
      return 3;
    }
}

以下のLLVM-IRに変換されます。

define i32 @f(i32 %x) nounwind uwtable readnone {
  ret i32 3
}

何らかの理由で、未定義のコードが削除されます。(x<0) の場合、C 関数は未定義でなければなりません!! このコードが削除された理由を誰か説明できますか?

4

1 に答える 1

5

3未定義の動作を持つ関数の完全に妥当な戻り値です。文字通り、あらゆる戻り値が許可されます。

于 2013-07-25T23:49:33.097 に答える