Architecture
VTIL is structured as a classic compiler pipeline: source binary → lifting → IR optimization → analysis/emission. Each stage is modular and can be used independently.
Pipeline overview
Core data structures
vtil::routine
The top-level container. Holds a map of all basic blocks, the entry point, and metadata about used registers and stack layout.
vtil::basic_block
A straight-line sequence of VTIL instructions with a single entry and one or more exits (JMP, JS, VEXIT). Blocks maintain predecessor/successor edges for CFG traversal.
vtil::instruction
Represents a single IL operation - an opcode plus up to three operands. Operands can be immediates, register references (physical or virtual), or memory operands.
Register model
VTIL uses a hybrid register model mixing physical x86 registers (rax, rbx) with unbounded virtual temporaries ($t0, $t1, …), closely mirroring native semantics without SSA form.
Optimizer passes
- Dead code elimination - removes writes with no live uses
- Constant folding - evaluates constant sub-expressions
- Expression simplification - applies algebraic identities
- Register coalescing - merges redundant temporaries
- Stack propagation - resolves stack-relative memory references