這篇是How to get started with the LLVM C API的讀後感,不過用我自己的方式表達。
先講結論
我重寫了程式碼,放在整篇文章的最後面,先看輸出結果。再回頭看程式碼。
1 | $ cc `llvm-config --cflags` -c sum.c |
這邊可以看兩個部份, Bitcode內容,以及JIT技術。之前介紹過LLVM的Bitcode,利用LLVM API可以生成Bitcode
建立Module
這邊就不特別提了,原來的連結寫得比較清楚。
1 | LLVMModuleRef mod = LLVMModuleCreateWithName("my_module"); |
Bitcode生成
建立Function signature
1 | LLVMValueRef createSumFunc(LLVMModuleRef mod) |
顧名思義,sum就是有兩個int參數,然後輸出一個int參數的Function,我們先建立奇對應的Signature,然後把Bitcode填入其中。param_type
就是輸入參數,而ret_type
就是想要的輸出參數,利用LLVMFunctionType
將奇關聯起來,最後呼叫LLVMAddFunction
建立一個LLVMValueRef物件。
如果對照Bitcode內容的話,就是以下這段
define i32 @sum(i32, i32)
填入IR Code
1 | void implementIR(LLVMValueRef sum) |
上面的第一行sum函數中間,新增一個Label,叫做entry。回頭看Bitcode
define i32 @sum(i32, i32) {
entry:
}
接著校新增真正的IR Code了,需要一個IRBuilder,然後連結到我們想要填Code的位置,也就是上面的第二行第三行。
接著需要IR Code之中的加法運算,以及Value Return。也就是上面的第四第五行。之後釋放掉IRBuilder的資源。
define i32 @sum(i32, i32) {
entry:
%tmp = add i32 %0, %1
ret i32 %tmp
|
之後呼叫
1 | void dumpBitCode(LLVMModuleRef mod) |
就能輸出完整的Bitcode了,這些跟JIT無關,可以單獨使用。
JIT CCode Generation
JIT Environment setup
在使用JIT之前,要先把環境準備好
1 | LLVMLinkInJIT(); |
記住使用完後要將engine的資源釋放。
將外部的資料結構轉成LLVM所看得懂得資訊
1 | LLVMGenericValueRef args[] = { |
x, y是外部的參數,而args
是餵進去給JIT Function的LLVM參數。
執行JIT Function
1 | LLVMGenericValueRef res = LLVMRunFunction(engine, sum, ArraySize(args), args); |
sum
是我們的IR Function,args
是輸入參數。
將LLVM得到的結果傳回外部
1 | printf("%d\n", (int)LLVMGenericValueToInt(res, 0)); |
Full Source code
1 | /** |