Asignación de Registros (register_alloc.rs)
Archivo: src/register_alloc.rs (482 líneas)
¿Por qué existe?
Implementa el algoritmo de Linear Scan Register Allocation (Poletto & Sarkar, 1999) para el JIT de Forja. Convierte los registros virtuales del IR register-based en registros físicos x86-64, con spill a stack cuando se agotan los registros disponibles.
Arquitectura / Estructuras clave
El módulo modela los registros físicos con sus encodings reales, las clases de registros, los intervalos de vida y el allocador propiamente dicho.
| Componente | Descripción |
|---|---|
PhysReg | Registros físicos x86-64: RAX, RCX, RDX, RSI, RDI, R8-R11, callee-saved RBX/RBP/R12-R15 y XMM0-XMM7 |
PhysReg::rex_index() | Índice real para REX encoding (0-15) de x86-64 |
is_callee_saved() / is_xmm() | Clasificación de registros; modrm_byte y push_pop_byte ayudan al codegen |
GP_REGS / CALLEE_SAVED / TEMP_REGS / EXTENDED_REGS | Constantes: generales, callee-saved, temporales (caller-saved preferidos) y extendidos disponibles (R12, R13, R15; RBX/R14/RBP quedan reservados como punteros/frame) |
VirtReg | Alias usize de registro virtual |
LiveInterval | Rango de vida de un registro virtual: start, end (exclusive), reg_class y posiciones de uses para splitting |
RegClass | Integer (GP) o Float (XMM) |
Location | Ubicación asignada: Reg(PhysReg) o Stack(offset desde RBP) |
RegisterAllocator | Allocador lineal: add_interval, allocate(), spill_count(), get_assignments() |
split_interval | Divide intervalos con gaps de uso superiores a GAP_THRESHOLD (10) en sub-intervalos independientes para reducir spills |
Cómo se integra
Recibe los LiveIntervals de register_ir.rs::compute_live_intervals, ejecuta el algoritmo y produce las asignaciones VirtReg → Location que codegen_reg.rs usa para emitir código nativo. El proceso: (1) aplicar interval splitting, (2) ordenar por start, (3) para cada intervalo expirar los viejos, buscar registro libre (temporales primero, luego extendidos; XMM para float) y si no hay, spillear el que termina más tarde con swap si conviene.
GAP_THRESHOLD instrucciones, se parte en sub-intervalos, cada uno con su propia asignación (registro o stack). Esto evita mantener un registro ocupado durante regiones donde la variable no se usa.