個人的な学習メモです。
LLVM IRとは1
LLVMコンパイラにおける中間表現(intermediate representation)である。コンパイラの汎用最適化で扱うコードであり、高水準言語とプラットフォームに依存しない表現となっている。
IRにはインメモリコード(LLVMのライブラリでのデータ)、ビットコード、そしてヒューマンリーダブルなIRコードの3つの形式がある。
命令列2
グローバルな関数や変数は@、ローカルな関数や変数には%が付けられる。
%result = mul i32 %X, 8
名前付きの変数は%resultのような書きかたであり、一時的な変数は%0などとなる。オペコード(mul)とプリミティブタイプ(i32)、オペランドで表現する。
モジュール3
IRでもプログラムのモジュール構造は保持されている。
; Declare the string constant as a global constant.
@.str = private unnamed_addr constant [13 x i8] c"hello world\0A\00"
; External declaration of the puts function
declare i32 @puts(ptr nocapture) nounwind
; Definition of main function
define i32 @main() {
; Call puts function to write out the string to stdout.
call i32 @puts(ptr @.str)
ret i32 0
}
; Named metadata
!0 = !{i32 42, null, !"string"}
!foo = !{!0}
一般にモジュールはグローバル値(関数や変数)のリストで構成される。グローバル値はポインタで表され、以下のリンケージタイプのいずれかを持つ。
リンケージタイプ4
| リンケージタイプ | 意味 |
|---|---|
| private | モジュール内のオブジェクトからのみアクセスされる変数を表す |
| internal | Cのstaticに相当し、オブジェクトファイルでのローカルシンボルを表す |
| available_externally | 外部宣言の明示で、グローバル値の定義がモジュール外のどこにあるか分かっていることを表す(インライン化などの最適化を行うために存在しているリンケージタイプ) |
| linkonce | このリンケージタイプを持つグローバル値はリンケージが発生すると、同じ名前の他のグローバル値とマージされる(インライン関数やテンプレートなど、それを使用する各翻訳単位で生成する必要があるコードを実装するために使用できる) |
| weak | linkonceと同じマージセマンティクスを示すが、未参照のグローバル値は削除されない |
| common | weakと似ているが、C言語のグローバルスコープでの「int X;」のような暫定的な定義に使われる。未参照の場合は削除されない |
| appending | 配列へのポインタ型のグローバル変数にのみ適用できる。このリンケージを持つ2つのグローバル変数が一緒にリンクされると、2つのグローバル配列が一緒に追記される |
| extern_weak | このリンケージのセマンティクスは、ELFオブジェクト・ファイル・モデルに従う。シンボルはリンクされるまでweakで、リンクされなければ、未定義の参照ではなくNULLになる |
| linkonce_odr, weak_odr |
odrサフィックスはそのすべてのグローバル値が等価であることを示す(これは関数をインライン化し、定数を折りたたんでロードできることを意味する) |
| external | グローバル値は外部から見えており、外部のシンボル参照を解決するために使用することができる |