llvm study
Contents
Overview
llvm 示意圖 通過front end後程式碼會被轉為中間碼( LLVM Intermediate Representation (IR) ) 紅色部分為llvm提供的功能。 出作業應該不會用到1 (要自己寫),但可能會用到 2. IR interpreter (指令lli) 3. IR compiler (指令 llc)
llvm 指令
v = operation type op1, op2 , opn
%sum = add i32 %op1, %op2
運算結果 運算元 型態 運算子們
llvm function
宣告
define i32 @add1 ( i32 %a, i32 %b )
define 回傳型態 @函數名稱( 參數列 )
回傳
ret i32 5 ; 回傳integer ,值為5
ret void ; 回傳void
ret { i32, i8 } { i32 4, i8 2 } ; 回傳結構 {int 32, int 8} , 值為 4 , 2
範例
define i32 @add1(i32 %a, i32 %b) {
entry:
%tmp1 = add i32 %a, %b
ret i32 %tmp1
}
Identifiers
- regular expression: ‘[%@][a-zA-Z$._][a-zA-Z$._0-9]*‘.
- @全域變數
- %區域變數
- 雙引號為字串,可用跳脫字元 \, 後面接ASCII code (ex: 換行為\0A, 而非\n)
- @1 $2這些應該是暫存變數(不確定)
- 全部皆為SSA(single static assigment)
- 將變數編上編號
- 每個變數只會賦值一次
利用clang front end 做測試
安裝
sudo apt-get install clang llvm
把C code 變成 llvm IR (以test.c為例)
clang test.c -emit-llvm -S
C code
#include<stdio.h>
int main()
{
int a, b;
a = 1;
b = a + 1;
printf("%d\n", b);
}
llvm IR (test.ll)
; Function Attrs: nounwind uwtable
define i32 @main() #0 {
%a = alloca i32, align 4
%b = alloca i32, align 4
store i32 1, i32* %a, align 4
%1 = load i32* %a, align 4
%2 = add nsw i32 %1, 1
store i32 %2, i32* %b, align 4
%3 = load i32* %b, align 4
%4 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i32 %3)
ret i32 0
}
declare i32 @printf(i8*, ...) #1
1. 用interpreter執行llvm IR
lli test.ll
2. 把llvm IR 編譯成assembly code
llc test.ll
產生出 test.s 利用clang把assembly轉成machine code
clang test.ll
執行
./test.ll
結論
用llvm學習compiler,不需考慮暫存器分配(assembly code geneate),但需要考慮SSA。