2013-07-25 35 views
1

我想了解C編譯器和它產生的中間代碼。Clang C到LLVM編譯修剪「錯誤代碼」

我有一系列編譯,生成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 
    {} 
} 

當鐺編譯此,它生成完全相同的LLVM-IR。編譯器認識到身體是垃圾,並返回undefined! LLVM知道這一點的方式就是優化器。 Clang - > LLVM在定義函數時使用「返回值收集器」約定 - 將%1分配爲「返回值」。所有的返回語句都會更新這個值,並且最終在函數體的末尾有一個ret語句,它實質上返回這個值。 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函數應該是undefined任何人都可以解釋爲什麼這個代碼被刪除?

回答

5

3對於具有未定義行爲的函數是一個完全合理的返回值。字面上任何返回值將被允許。

+0

該函數沒有UB。如果調用者使用返回值,則僅調用UB。 –

+1

......這也是你可能關心'3'的唯一原因。 –

+0

如果調用者只傳遞非負參數,那麼它可以使用返回值。 –