Memahami LLVM IR sebagai RISC-like low-level ISA, SSA form (static single assignment), hierarki module → function → basic block → instruction, serta tipe data int, float, pointer, struct, vector, dan function type — dengan praktik dump IR dari program C.

Setelah di episode 3 kita memahami struktur proyek LLVM dan cara build dari source, pada episode ini kita memasuki jantung LLVM: LLVM IR (Intermediate Representation).
LLVM IR adalah bahasa assembly textual yang berada di tengah-tengah antara source code tingkat tinggi dan assembly target spesifik. Memahami IR adalah kunci untuk menulis pass optimasi (episode 7-8), membangun front-end (episode 10-13), dan menggunakan LLVM API (episode 9). Tanpa pemahaman IR yang solid, semua topik lanjutan akan terasa seperti menghafal tanpa mengerti.
LLVM IR adalah Intermediate Representation — format representasi kode yang bukan source code tingkat tinggi dan bukan assembly target spesifik. IR ini dirancang sebagai RISC-like low-level ISA yang cukup dekat dengan hardware untuk optimasi performa, tetapi cukup abstrak untuk menjadi target front-end bahasa apapun.
Tiga bentuk LLVM IR:
| Bentuk | Kegunaan |
|---|---|
| Textual (.ll) | Dibaca manusia, diedit manual, ditampilkan di terminal |
| Bitcode (.bc) | Binary format, lebih kompak, lebih cepat diproses |
| In-memory | Representasi di memori saat optimasi berjalan |
LLVM IR menggunakan SSA (Static Single Assignment) — setiap variabel hanya di-assign tepat sekali. Konsekuensinya: tidak ada "mutation" variabel; untuk mengubah nilai, kalian membuat variabel baru.
%x1 = add i32 1, 2
%x2 = add i32 %x1, 3
ret i32 %x2SSA memudahkan optimasi: karena setiap nilai punya tepat satu definisi, analisis data-flow jauh lebih sederhana. Kita akan melihat bagaimana mem2reg mengonversi memory access ke SSA di episode 8.
declare (external) atau define (implementation).ret, br, switch).add, load, store, br, call).| Tipe | Contoh | Keterangan |
|---|---|---|
| Integer | i1, i8, i32, i64 | 1 bit sampai 64 bit (atau lebih) |
| Floating point | float, double | IEEE 754 |
| Pointer | ptr | Opaque pointers (LLVM 15+, tidak ada lagi i32*) |
| Struct | %struct.Name = { i32, float } | Struct definisi |
| Vector | <4 x float> | SIMD vector tetap |
| Array | [10 x i32] | Array statis |
| Function | i32 (i32, i32)* | Function pointer |
Note
LLVM 15+ menggunakan opaque pointers — semua pointer memiliki tipe ptr tanpa menunjuk ke tipe tertentu. Ini menyederhanakan IR dan mengurangi kebutuhan bitcast. Jika kalian membaca tutorial lama yang masih memakai i32* atau float*, ketahuilah bahwa ini sudah deprecated.
Cara paling cepat mempelajari IR: tulis program C sederhana, lalu dump IR-nya:
int add(int a, int b) {
return a + b;
}
int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}Dump IR:
clang -emit-llvm -S -o - program.cHasilnya adalah .ll file yang bisa kalian baca dan edit. Mari kita bedah satu bagian:
define i32 @add(i32 %a, i32 %b) {
entry:
%result = add i32 %a, %b
ret i32 %result
}| Elemen | Arti |
|---|---|
define i32 @add | Fungsi bernama add yang mengembalikan i32 |
(i32 %a, i32 %b) | Dua parameter: %a dan %b |
entry: | Basic block pertama |
%result = add i32 %a, %b | Instruksi add operasi integer |
ret i32 %result | Return hasil |
Perhatikan: setiap nilai (%a, %b, %result) hanya di-assign sekali — itulah SSA.
Inti yang harus dibawa pulang:
i1/i8/i32/i64, float/double, ptr, struct, vector, array, function.clang -emit-llvm -S untuk dump IR dari program C.Di episode 5 selanjutnya kita akan belajar menulis & membaca .ll manual — syntax global, define, attributes, unnamed values, serta tools llvm-as, llvm-dis, dan opt -verify. Kita akan menulis fungsi aritmatika dan rekursif murni dalam teks IR tanpa bahasa sumber. Sampai jumpa di episode 5!