Memahami backend architecture LLVM: IR → SelectionDAG/GlobalISel (instruction selection) → MachineInstr → MCInst → object file, serta TableGen sebagai bahasa deskripsi target untuk register, instructions, dan scheduling models.

Setelah di episode 15 kita mempelajari Clang AST dan libTooling untuk analisis kode C/C++, pada episode ini kita masuk ke lapisan paling dalam LLVM: backend architecture — bagaimana LLVM IR diturunkan menjadi machine code untuk target spesifik.
Backend LLVM adalah bagian paling kompleks dari seluruh framework, tetapi juga yang paling powerful: satu framework mendukung X86, AArch64, RISC-V, WASM, NVPTX, AMDGPU, dan puluhan target lainnya. Memahami arsitektur backend memberikan kalian gambaran bagaimana optimasi level machine code dilakukan.
Mengonversi LLVM IR ke MachineInstr — representasi yang mendekati target spesifik tetapi belum di-registers-allocate.
Mengonversi virtual registers ke physical registers target. Kita bahas detailnya di episode 17.
Representasi paling rendah sebelum emisi: instruksi dalam format yang bisa langsung di-encode ke binary.
MCInst diemisikan ke format objek: ELF (Linux), Mach-O (macOS), COFF (Windows).
TableGen (.td files) adalah bahasa deklaratif yang mendeskripsikan target architecture. LLVM menggunakan TableGen untuk menghasilkan kode C++ otomatis — register definitions, instruction encodings, dan scheduling models.
def GR32 : RegisterClass<"X86", [i32], 32,
(sequence "EAX", "ECX", "EDX", "EBX")>;Arti: GR32 adalah register class untuk X86 yang berisi register 32-bit (EAX, ECX, EDX, EBX), dengan alignment 32-bit.
let Predicates = [HasSSE2] in
defm MOVAPDrmv : sse2_mm_mov_ps_rm<0x28, "movapd", f64>;Arti: instruksi MOVAPD hanya tersedia jika target mendukung SSE2 (Predicates = [HasSSE2]), mengkode opcode 0x28, dan beroperasi pada 64-bit float.
def SkylakeModel : SchedMachineModel {
let MicroOpBufferSize = 0; // In-order issue
let IssueWidth = 6;
let LoadLatency = 4;
}Model scheduling memberitahu instruction scheduler bagaimana target hardware mengeksekusi instruksi — berapa banyak yang bisa issue per cycle, latensi load, dan sebagainya.
Telusuri satu instruksi end-to-end dari IR hingga emisi:
# Generate IR
echo "define i32 @add(i32 %a, i32 %b) { %r = add i32 %a, %b; ret i32 %r }" | \
clang -S -emit-llvm -o - -x ir -
# Generate assembly target
llc -mcpu=x86-64 -o - program.bc
# Inspeksi instruction encoding
llvm-objdump -d program.oPerhatikan bagaimana satu add i32 di LLVM IR diturunkan menjadi addl %esi, %eax di x86 assembly — pemilihan register, encoding opcode, dan size suffix semuanya ditentukan oleh deskripsi TableGen.
Note
GlobalISel (instruction selection baru) secara bertahap menggantikan SelectionDAG untuk target baru. ARM64 sudah mengadopsi GlobalISel sebagai default. Untuk memahami backend secara mendalam, pelajari keduanya: SelectionDAG untuk pemahaman konseptual, GlobalISel untuk masa depan.
Inti yang harus dibawa pulang:
Di episode 17 selanjutnya kita akan membahas register allocation & MC layer — greedy allocator, live intervals, spill/reload, assembler/disassembler internal, relocation, dan emisi ELF/COFF/Mach-O. Sampai jumpa di episode 17!