Compiler ASM – Generador de Assembly Nativo Multi‑arquitectura

Archivo: src/compiler_asm.rs (3.547 líneas)

Este backend de compilación Ahead‑of‑Time genera código ensamblador nativo directamente desde el AST de Forja, sin pasar por bytecode ni JIT. Soporta tres arquitecturas objetivo: x86‑64 Windows, x86‑64 Linux y AArch64 (ARM64), con convenciones de llamada, registro y sintaxis específicas de cada plataforma.


TargetArch — Arquitectura Objetivo

Enum TargetArch
pub enum TargetArch {
    X86_64Windows,
    X86_64Linux,
    AArch64,
}

Métodos de TargetArch

MétodoFirmaDescripción
detect() pub fn detect() -> Self Auto‑detecta la arquitectura en compilación usando cfg!(target_arch) y cfg!(target_os). Prioriza cfg!(windows) para elegir entre MSVC y SystemV.
name() pub fn name(&self) -> &str Retorna el nombre descriptivo: "x86_64-windows", "x86_64-linux", "aarch64".
from_str() pub fn from_str(s: &str) -> Option<Self> Parsea un string como "x86_64-windows", "x86_64-linux", "aarch64" y devuelve el enum.
syntax_directive() pub fn syntax_directive(&self) -> &str Devuelve la directiva de sintaxis: ".intel_syntax noprefix" para x86‑64, ".arch armv8-a" para ARM64.
section_rodata() fn section_rodata(&self) -> &str Sección de solo lectura: ".section .rdata" en Windows, ".section .rodata" en Linux, ".section .rodata" en ARM.
ret_reg() fn ret_reg(&self) -> &str Registro de retorno: rax (x86‑64) o x0 (ARM64).
ret_reg_32() fn ret_reg_32(&self) -> &str Registro de retorno de 32 bits: eax o w0.
arg_regs() fn arg_regs(&self) -> &[&str] Convención de llamada: [rcx, rdx, r8, r9] (Windows x64) o [rdi, rsi, rdx, rcx, r8, r9] (SystemV), [x0..x7] (ARM64).
tmp_reg() / tmp2_reg() fn tmp_reg(&self) -> &str Registros temporales volátiles: r10/r11 (x86‑64), x9/x10 (ARM64).
fp_reg() / sp_reg() fn fp_reg(&self) -> &str Frame pointer (rbp/x29) y stack pointer (rsp/sp).
shadow_space() fn shadow_space(&self) -> i32 Espacio de sombra obligatorio en x64 Windows: 32 bytes. Linux y ARM retornan 0.
float_reg() fn float_reg(&self) -> &str Registro de punto flotante: xmm0 (x86‑64), d0 (ARM64).

CompilerAsm — Generador de Código

Estructura CompilerAsm
pub struct CompilerAsm {
    arch: TargetArch,
    output: Vec<String>,
    labels: HashMap<String, String>,
    register_pool: Vec<&'static str>,
    register_available: Vec<bool>,
    var_register_map: HashMap<String, &'static str>,
    classes_asm_info: HashMap<String, ClaseAsmInfo>,
    funciones_declaraciones: HashMap<String, Declaracion>,
    string_literals: Vec<String>,
    label_counter: usize,
}

Desglose completo de funciones

Constructor y configuración

MétodoFirmaDescripción
new() pub fn new() -> Self Crea un nuevo compilador detectando automáticamente la arquitectura actual.
with_target() pub fn with_target(target: TargetArch) -> Self Crea un compilador para una arquitectura específica (útil para cross‑compilation).

Registro de variables y pooling

MétodoDescripción
init_register_pool(arch) -> (Vec<&str>, Vec<bool>)Inicializa el pool de registros según la arquitectura. x86‑64: [rax, rbx, rcx, rdx, rsi, rdi, r8..r15]. ARM64: [x0..x18].
alloc_reg() -> Option<&str>Busca el primer registro disponible, lo marca como usado y retorna su nombre.
free_reg(reg: &str)Marca un registro como disponible nuevamente.
free_all_regs()Libera todos los registros del pool.
alloc_var_reg(nombre: &str) -> Option<&str>Asigna un registro a una variable Forja. Si ya tenía registro, lo retorna.
free_var_reg(nombre: &str)Libera el registro asociado a una variable.

Generación de código principal

MétodoDescripción
compilar(programa) -> Result<String, Vec<ErrorForja>>Punto de entrada. Inyecta cabecera, genera strings en .rdata, runtime functions, clases, y compila declaración por declaración.
recolectar_clases(declaraciones)Primera pasada: recolecta definiciones de clase, campos y métodos para construir classes_asm_info.
generar_strings_rdata()Genera etiquetas y datos de strings literales en la sección de solo lectura.
generar_runtime_funciones()Genera funciones runtime: _forja_itoa, _forja_write_newline, _forja_write_str, _forja_write_int.
generar_clases_asm(declaraciones)Genera constructores, getters de campos y tablas de métodos virtuales.
compilar_declaracion(decl)Traduce una declaración a ASM: variables (mov reg, val), condicionales (cmp + jcc), bucles, funciones (prólogo/epílogo).
compilar_expresion_asm(expr) -> StringTraduce una expresión a ASM inline: literales, aritmética, acceso a variables, llamadas.
compilar_escribir(argumentos)Genera código para escribir(): literales via lea rcx, [msg], numéricos via _forja_itoa.
compilar_llamada_funcion(nombre, argumentos)Evalúa args, los coloca en registros ABI, emite call nombre. Maneja shadow space.
inline_funcion(nombre, argumentos)Expande una función inlineable copiando su cuerpo con reemplazo de parámetros.

Helpers de emisión

MétodoDescripción
gen_itoa(reg_num) -> Vec<String>Convierte un entero en registro a string ASCII (división por 10 + push/pop).
gen_write_newline()Genera código para imprimir un salto de línea vía syscall o WriteFile.
gen_write_str_literal(s)Carga dirección de etiqueta y escribe string por syscall.
gen_write_int_value(reg_num)Combina itoa + write_str para imprimir un entero.
buscar_campo_offset(objeto, miembro) -> i32Calcula offset de un campo dentro de la estructura de una clase.
nueva_etiqueta(prefijo) -> StringGenera una etiqueta única (ej: ".L_if_true_3").
emit_line(texto)Agrega una línea de ASM al buffer de salida.

Inferencia de tipos ASM

FunciónDescripción
tipo_forja_a_asm(tipo: &Option<Tipo>) -> TipoAsmConvierte tipo Forja (Entero, Decimal, etc.) a TipoAsm::I64, F64.
inferir_tipo_campo_asm(campo) -> TipoAsmInfere el tipo ASM de un campo de clase.
tipo_asm_size(tipo) -> i32Retorna tamaño en bytes: 8 para I64/F64/Bool/Ptr, 4 para I32.
es_candidata_inline(decl) -> boolDetermina si una función puede ser inlineada (cuerpo pequeño, sin constructos complejos).

Pipeline de compilación completo

  1. Detección: TargetArch::detect() o with_target() para cross‑compilation.
  2. Recolección: Pasada sobre el AST para recolectar clases y candidatas inline.
  3. Cabecera: Directivas de sintaxis, .rdata con strings, funciones runtime.
  4. Clases: Constructores, getters y tablas virtuales.
  5. Compilación: compilar_declaracion para cada declaración global.
  6. Expresiones: compilar_expresion_asm dentro de los cuerpos.
  7. Inline: Expansión de funciones inlineables.

Funciones públicas expuestas

FunciónDescripción
compilar_a_asm(programa) -> Result<String, Vec<ErrorForja>>Compila un programa Forja a ASM nativo (detección automática).
compilar_a_asm_con_target(programa, target) -> Result<String, Vec<ErrorForja>>Compila a ASM para una arquitectura específica (cross‑compilation).
⚠️ Limitaciones: El backend ASM es el más cercano al hardware pero también el más verboso. No soporta todas las características de Forja (clases con herencia compleja, pattern matching anidado). Para programas completos se recomienda usar bytecode + VM Fast o LLVM backend.