2012-02-05 95 views
104

我想鐺編譯我C/C++代碼LLVM字節碼而不是二進制可執行文件。我怎樣才能做到這一點?如果我得到LLVM字節碼,我該如何將它進一步編譯爲二進制可執行文件。如何使鐺編譯成LLVM IR

基本上我想編譯成二進制可執行文件之前添加一些我自己的代碼到LLVM字節碼。

回答

143

鑑於一些C/C++文件foo.c

> clang -S -emit-llvm foo.c 

可生產foo.ll其是LLVM IR文件。

-emit-llvm該選項還可以通過手段被傳遞給編譯器前端直接的,也不驅動的-cc1

> clang -cc1 foo.c -emit-llvm 

可生產foo.ll與IR。 -cc1增加了一些很酷的選項,如-ast-print。查看-cc1 --help瞭解更多詳情。


爲了進一步編譯LLVM IR組裝,使用llc工具:

> llc foo.ll 

主要生產foo.s與組件(默認爲你運行它的計算機體系結構)。 llc是LLVM工具之一 - here is its documentation

+3

什麼-S在這裏做? – meawoppl 2014-02-27 16:17:53

+8

@meawoppl:-S像gcc中說的那樣發出文本彙編而不是彙編二進制 – 2014-02-28 16:53:26

+0

Ahha。我很難在關於它的文檔中找到任何內容。可以肯定的是,鏗鏘聲中的許多標誌鏡像gcc標誌結構? – meawoppl 2014-02-28 17:35:25

16

使用

clang -emit-llvm -o foo.bc -c foo.c 
clang -o foo foo.bc 
+6

我建議保持擴展的含義不變。 IOW中,'.o'應該指向二進制目標文件,將'.s'指定爲彙編文件,以及其他指令(按照慣例'.ll')指向LLVM IR文件。否則很容易混淆。 Clang/LLVM現在沒有自己的二進制對象鏈接器(儘管其中一個正在工作中)。 LLVM鏈接器'llvm-ld'只是將幾個IR文件合併到一個文件夾中: – 2012-02-05 13:06:51

+1

@EliBendersky:在涉及文件擴展名的地方你是正確的 - 如果使用'.bc',clang前端實際上做得正確;另外,請記住,'llvm-ld'可以作爲系統工具鏈的前端,也就是說,我以前使用'llvm-ld -native'的答案應該按預期工作.... – Christoph 2012-02-05 13:13:10

+0

不起作用。 foo.bc是一個對象文件。 – rickfoosusa 2014-09-25 21:15:04

17

如果你有多個源文件,你可能真的想使用鏈接時優化輸出一個位碼文件的整個程序。給出的其他答案會導致您最終得到每個源文件的位碼文件。

相反,你想鏈接時優化

clang -flto -c program1.c -o program1.o 
clang -flto -c program2.c -o program2.o 

和最終鏈接步驟來編譯,添加參數輪候冊,-plugin-OPT =也-發出-LLVM

clang -flto -Wl,-plugin-opt=also-emit-llvm program1.o program2.o -o program 

這給你已編譯的程序和與之對應(program.bc)的位碼。然後,您可以修改program.bc在任何你喜歡的方式,這樣做

clang program.bc -o program 

在任何時候重新編譯修改的程序,雖然知道你需要包括任何必要的連接標誌(外部庫等)在這一步再次。

請注意,您需要使用金連接器這個工作。如果要強制鐺使用特定的連接,創建一個符號連接到連接在叫你的計算機上的「fakebin」的地方一個特殊的目錄名爲「LD」,並添加選項

-B/home/jeremy/fakebin 

到任何連接步驟以上。

+1

這非常有幫助,謝謝! – baibo 2015-01-29 23:18:08

5

如果你有多個文件,你不希望有鍵入每個文件,我建議你遵循這些簡單的步驟(我用clang-3.8但你可以使用任何其他版本):

  1. 生成所有.ll文件

    clang-3.8 -S -emit-llvm *.c 
    
  2. 它們鏈接到一個單一的一個

    llvm-link-3.8 -S -v -o single.ll *.ll 
    
  3. (可選)優化你的代碼(也許有些別名分析)

    opt-3.8 -S -O3 -aa -basicaaa -tbaa -licm single.ll -o optimised.ll 
    
  4. 生成彙編(生成optimised.s文件)

    llc-3.8 optimised.ll 
    
  5. 創建可執行文件(命名爲a.out

    clang-3.8 optimised.s 
    
+0

您的解決方案非常獨特:您使用「-S」而不是將其作爲二進制輸出。有「-S」和沒有「-S」有沒有區別? – 2017-09-24 01:46:55

+0

@PeterTeoh我使用'-S'選項(在步驟2中),我指定我想在LLVM IR中生成輸出。基本上,所有的* .ll文件放在一個單一的。我這樣做是爲了檢查優化是否真的改變了代碼,即'single.ll'和'optimised.ll'現在應該看起來不同(代碼方式),並且您還可以顯示報告以查看是否存在任何差異。 – 2017-10-16 07:39:16