📝 Compilador
← Volver

Partes de un compilador

Documento de referencia sobre los componentes que intervienen en el proceso de compilación, los conceptos relacionados y el orden en el que se suelen ejecutar.


1. Conceptos generales

Compilador

Programa que traduce código fuente escrito en un lenguaje (lenguaje de alto nivel, como C, Rust o Go) a otro lenguaje, normalmente código máquina (binario que entiende la CPU) o un bytecode intermedio (como el de la JVM o el CLR de .NET).

Intérprete

A diferencia del compilador, el intérprete ejecuta el código directamente, instrucción a instrucción, sin generar un binario independiente.

Transpilador (source-to-source compiler)

Tipo especial de compilador que traduce de un lenguaje de alto nivel a otro lenguaje de alto nivel, en lugar de bajar a código máquina.

Cross-compiler (compilador cruzado)

Compilador que se ejecuta en una plataforma (host) pero genera código para una plataforma distinta (target).

Cross-platform (multiplataforma)

No es una parte del compilador en sí, sino una propiedad del software: que un mismo programa o código fuente pueda ejecutarse o compilarse para varias plataformas (Windows, Linux, macOS, etc.).

JIT (Just-In-Time) y AOT (Ahead-Of-Time)


2. Fases internas del compilador

Las siguientes fases son las que ocurren dentro del compilador cuando recibe un archivo fuente.

2.1 Preprocesador (opcional)

Procesa directivas antes de la compilación propiamente dicha: inclusión de archivos (#include), macros (#define), compilación condicional (#ifdef)…

2.2 Lexer (analizador léxico / scanner / tokenizer)

Lee el código fuente carácter a carácter y lo agrupa en tokens: palabras clave, identificadores, literales, operadores, símbolos…

2.3 Parser (analizador sintáctico)

Toma los tokens y construye un árbol de sintaxis abstracta (AST) verificando que la estructura cumple la gramática del lenguaje.

2.4 Analizador semántico

Comprueba que el AST tiene sentido: tipos compatibles, variables declaradas antes de usarse, número correcto de argumentos en funciones, ámbitos (scopes), etc.

2.5 Generación de código intermedio (IR)

Traduce el AST a una representación intermedia (IR) más simple y abstracta que el código fuente, pero independiente de la máquina concreta.

2.6 Optimizador

Transforma el IR para que el código resultante sea más rápido o más pequeño sin cambiar su comportamiento.

2.7 Generador de código

Convierte el IR optimizado en código ensamblador o código máquina específico de la arquitectura destino (x86_64, ARM, RISC-V…).

2.8 Ensamblador (assembler)

Traduce el código ensamblador (texto legible como mov eax, 1) a código objeto binario (.o en Linux, .obj en Windows).


3. Fases posteriores a la compilación

3.1 Linker (enlazador)

Combina uno o varios archivos objeto y bibliotecas (estáticas .a/.lib o dinámicas .so/.dll) en un único ejecutable o biblioteca final.

3.2 Loader (cargador)

Forma parte del sistema operativo, no del compilador. Carga el ejecutable en memoria, resuelve bibliotecas dinámicas pendientes y prepara el programa para ejecutarse.


4. Orden típico de ejecución

Código fuente (.c, .rs, .ts, …)
        │
        ▼
1. Preprocesador        (opcional, p. ej. en C/C++)
        │
        ▼
2. Lexer                → tokens
        │
        ▼
3. Parser               → AST
        │
        ▼
4. Análisis semántico   → AST anotado (con tipos, ámbitos…)
        │
        ▼
5. Generación de IR     → código intermedio
        │
        ▼
6. Optimizador          → IR optimizado
        │
        ▼
7. Generador de código  → ensamblador o código máquina
        │
        ▼
8. Ensamblador          → archivos objeto (.o / .obj)
        │
        ▼
9. Linker               → ejecutable o biblioteca final
        │
        ▼
10. Loader (SO)         → programa en memoria, listo para ejecutar
        │
        ▼
        Ejecución

Las fases 2–7 suelen agruparse en lo que se llama frontend (1–4) y backend (5–7) del compilador. El middle-end es la parte de optimización del IR.


5. Resumen rápido (chuleta)

Componente ¿Qué hace? Entrada → Salida
Preprocesador Procesa macros e includes Fuente → Fuente expandida
Lexer Divide en tokens Texto → Tokens
Parser Comprueba sintaxis y crea AST Tokens → AST
Analizador semántico Comprueba tipos y reglas AST → AST anotado
Generador IR Crea representación intermedia AST → IR
Optimizador Mejora el IR IR → IR optimizado
Generador de código Genera asm/máquina IR → Ensamblador
Ensamblador Asm → binario Ensamblador → Objeto (.o)
Linker Une objetos y libs Objetos → Ejecutable
Loader Carga en memoria Ejecutable → Proceso en RAM
Concepto ¿Qué es?
Compilador Fuente → código máquina / bytecode
Intérprete Ejecuta el fuente directamente
Transpilador Fuente de alto nivel → fuente de alto nivel
Cross-compiler Compila en una plataforma para otra distinta
Cross-platform Software que funciona en varias plataformas
JIT Compila durante la ejecución
AOT Compila antes de la ejecución