LLVM 筆記(五)—— LLVM IR


ilocker:關注 Android 安全(新手) QQ: 2597294287

LLVM 的 IR (Intermediate Representation) 是其設計中的最重要的部分。優化器在進行代碼優化時所進行的分析和轉換都是針對 IR 的。

在設計 IR 時,考慮到了很多明確的目標,包括:支持輕量級的運行時優化、交叉函數/過程間優化、整體程序分析和侵入式調整轉換等等。

原文:including supporting lightweight runtime optimizations, cross-function/interprocedural optimizations, whole program analysis, and aggressive restructuring transformations, etc.

LLVM IR 本身具備定義良好的語義,下面是一個 .ll 文件的簡單示例:

define i32 @add1(i32 %a, i32 %b) {
entry:
  %tmp1 = add i32 %a, %b
  ret i32 %tmp1
}

define i32 @add2(i32 %a, i32 %b) {
entry:
  %tmp1 = icmp eq i32 %a, 0
  br i1 %tmp1, label %done, label %recurse

recurse:
  %tmp2 = sub i32 %a, 1
  %tmp3 = add i32 %b, 1
  %tmp4 = call i32 @add2(i32 %tmp2, i32 %tmp3)
  ret i32 %tmp4

done:
  ret i32 %b
}

這段 IR 對應的 c 代碼如下:

1 unsigned add1(unsigned a, unsigned b) {
2   return a+b;
3 }
4 
5 unsigned add2(unsigned a, unsigned b) {
6   if (a == 0) 
7 return b;
8   return add2(a-1, b+1);
9 }

從示例可以看出,LLVM IR 是一個 low-level RISC-like 虛擬指令集,支持 add、subtract (減)、compare、branch 指令。支持 label,並且通常看起來像是一種奇怪格式的匯編語言。

與大多數 RISC 指令集不同,LLVM IR 是強類型的,並具有一個簡單的類型系統。如:i32 是 32 位整數,而 i32** 是指向 32 位整數的指針的指針。

LLVM IR 抽象了一些機器細節。比如,借助 call 和 ret 指令及其顯示參數抽象了調用約定 (call convention)。

LLVM IR 不使用一套固定的命名寄存器,而是使用以 % 字符命名的臨時變量 (如:%tmp1、%a、%b)。

LLVM IR 有三種定義形式:上面示例中的文本形式;內存中的數據結構 (做優化時使用);高效的密集型的磁盤二進制“位代碼 (bitcode)”格式。

llvm-as 工具可以將 .ll 文件 (文本形式的 IR) 轉換為 .bc 文件 (位代碼格式的 IR)。llvm-dis 工具可以將 .bc 文件轉換為 .ll 文件。

優化器針對 IR 進行優化,而不用去管前端輸入的是何種編程語言,后端生成的是何種目標平台的指令。LLVM IR 在設計時必須考慮到前端能夠容易生成 IR,並且支持針對真實的目標平台執行重要的優化。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM