2016-11-20 25 views
1

在函數中,我想知道參數是如何傳遞到函數體中的,以便跟蹤參數的流向。我試了一個簡單的代碼,並發現似乎有一個alloc - store模式爲每個參數,我想知道它是否是真的?Clang如何爲函數參數生成代碼?

甲演示代碼是

int add(int x, int y){ 
    return x+y; 
} 

IR它產生的LLVM是:

; Function Attrs: nounwind uwtable 
define i32 @add(i32 %x, i32 %y) #0 { 
    %1 = alloca i32, align 4 
    %2 = alloca i32, align 4 
    store i32 %x, i32* %1, align 4 
    store i32 %y, i32* %2, align 4 
    %3 = load i32, i32* %1, align 4 
    %4 = load i32, i32* %2, align 4 
    %5 = add nsw i32 %3, %4 
    ret i32 %5 
} 

在我們可以看到,例如,

  1. 對於每一個參數,所述鏘使用alloc指令來定義 局部變量

  2. alloc指令後,store指令是用來給 賦值的嗎?

我的問題是:

  1. 是所有功能LLVM IR在此allocstore模式產生的?或者LLVM如何處理這些參數?
  2. parameters的順序是由它使用的慣例決定的?
+0

次要評論:您似乎在問如何clang生成LLVM IR,而不是LLVM如何生成代碼。 –

+0

@IsmailBadawi感謝您的評論,我編輯了這個問題。 – Qoros

回答

1

我認爲這種模式適用於沒有編譯時優化的代碼;但是,如果你不是編譯-O3(或任何適用的mem2reg優化)的代碼,這種模式優化了:

(鐺-emit-LLVM -S -O0 add.c)

define i32 @add(i32 %x, i32 %y) #0 { 
    %1 = alloca i32, align 4 
    %2 = alloca i32, align 4 
    store i32 %x, i32* %1, align 4 
    store i32 %y, i32* %2, align 4 
    %3 = load i32, i32* %1, align 4 
    %4 = load i32, i32* %2, align 4 
    %5 = add nsw i32 %3, %4 
    ret i32 %5 
} 

(選擇-mem2reg add.ll -o add_m.ll)

define i32 @add(i32 %x, i32 %y) #0 { 
    %1 = add nsw i32 %y, %x 
    ret i32 %1 
} 

所以,如果你控制一切,你所分析的代碼,那麼你就可以靠這個模式。相反,我會建議您使用LLVM API來獲取函數參數。下面的代碼遍歷函數F的參數,並將其轉換爲值後打印出來。

for (auto AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI) 
{ 
    Value* v = &*AI; 
    errs() << *v << "\n"; 
} 

上述示例中的值與IR中的任何其他值的使用方式相同。

+0

謝謝,Brian。我按照你的指示嘗試過,但是它打印的是'i32%x'。我想知道如何測試兩個值是否相等,例如,在二進制文件中,每個指針存儲它指向的地址。 – Qoros

+0

這是一個不同的問題。檢索每個函數參數的Value *後,您就可以使用它進行進一步分析。這可能與最初標記的一樣是靜態的,在這種情況下,您可能需要構建控制流圖以及通過每個函數使用變量。動態地,您可以通過添加額外的IR來檢查相等性,即通過構建比較或將值傳遞給單獨的支持例程來檢查輸入值。 我的例子是爲了展示一種簡單的方式來初始訪問這些值並對它們做些什麼。 – Brian

+0

感謝您的指導。 – Qoros

相關問題