Backend LLVM

Archivo: src/backend_llvm.rs (871 líneas)

¿Por qué existe?

Backend que genera código máquina nativo usando LLVM como infraestructura. Soporta tipos básicos, funciones, clases/structs, enums y closures. A diferencia del JIT de jit.rs (que emite bytes x86-64 a mano), este backend serializa el programa a LLVM IR textual y delega las optimizaciones y la generación de código de bajo nivel a LLVM.

AST → (type checker) → AST tipado → LlvmBackend → LLVM IR → ObjectCode (.o)

Arquitectura / Estructuras clave

ComponenteDescripción
LlvmTypeTipos LLVM: I8, I64, Double, I1 (bool), Ptr, Void, Struct(name, campos) y Array(tipo, len). to_llvm_ir() serializa a texto IR; is_pointer() detecta tipos por referencia
LlvmValueResultado de una instrucción: nombre SSA (%t0, %r, …) + tipo
LlvmInstructionIR instrucción por instrucción: Add/Sub/Mul/Div, Icmp/Fcmp (con ops IcmpOp/FcmpOp), And/Or/Xor, Alloca/Store/Load, Call, Br/BrCond, Ret, Gep, Bitcast, Phi
LlvmBlockBloque básico: nombre + lista de instrucciones
LlvmFunctionFunción: nombre, tipo de retorno, parámetros, bloques, y flag is_declaration (declarada externa vs. definida)
LlvmModuleMódulo completo: funciones, tipos globales (global_types) y strings globales (global_strings). to_llvm_ir() emite el target datalayout, el target triple y todo el IR
LlvmBackendGenerador principal: new_temp()/new_block_label() para nombres SSA únicos, register_class() (clase → struct), add_string_literal(), e inyección de GC intrinsics

GC Intrinsics

inject_gc_intrinsics() analiza las funciones del módulo y declara + inyecta las intrínsecas LLVM GC:

IntrínsecaPropósito
llvm.experimental.gc.statepointMarca safe points para el recolector
llvm.experimental.gc.relocateReubica punteros después de una colección
__gc_write_barrierWrite barrier para el generational GC
__gc_pollPolling check para el GC thread (safe point en loops)
__gc_allocAsignación de memoria con soporte GC

inject_function_gc() detecta loops buscando BrCond cuyos targets apuntan a bloques anteriores y, al encontrarlos, inserta una llamada a __gc_poll al inicio del bloque junto con un StackMap y un SafePoint registrados en el GcIntrinsicsManager (de gc_intrinsics.rs). to_llvm_ir_with_gc() aplica toda la inyección y serializa.

Layouts para enums, genéricos, closures y async

LayoutRepresentación LLVM
EnumLayoutTagged union: %Enum = { i8, [max(tamaños) x i8] } con tag_for(variante) y to_llvm_type()
result_type(T, E)Result[T,E] = { i8 tag, payload } (tag 0 = Ok, 1 = Error)
option_type(T)Option[T] = { i1 is_some, T value }
ClosureLayoutClosure = { fn_ptr, env_ptr, env_size: i64 }
AsyncLayoutState machine async: { state: i64, resume_fn: ptr, vars capturadas... } con add_captured_var()

Optimización

ComponenteDescripción
OptLevelNiveles None (debug), Less (-O1), Default (-O2) y Aggressive (-O3)
OptLevel::to_passes()Passes por nivel: always-inline, promote-memory-to-register, gvn, licm, loop-unroll, loop-vectorize, slp-vectorize, simplifycfg, merge-functions
LlvmOptPipelineEjecuta los passes y acumula OptStats (funciones optimizadas, constantes plegadas, dead code eliminado)

Builtins del runtime

declare_builtins(module) declara las funciones del runtime Forja como externas: forja_escribir_entero, forja_escribir_decimal, forja_escribir_texto, forja_leer, malloc, free y memcpy.

Target triple

target_triple() detecta la plataforma en compilación: x86_64-pc-windows-msvc (Windows), x86_64-unknown-linux-gnu (Linux), arm64-apple-darwin (macOS) o x86_64-unknown-unknown como fallback.

Nota: el módulo está marcado #![allow(dead_code)]: varias piezas (pipeline de passes real, alocación de ObjectCode) están esbozadas y listas para conectarse con la infraestructura LLVM cuando se integre la dependencia externa.