4. Generación de código intermedio: Traducción inicial.

La generación de código intermedio es una etapa fundamental en el proceso de compilación. Su objetivo es traducir el código fuente en un formato intermedio que no depende de ninguna arquitectura específica de hardware. Este formato intermedio actúa como un puente entre el análisis del programa y la generación del código máquina final.
(Alfred & Ullman, 1998, capítulo 5)

Veamos los conceptos clave y cómo se aplica al ejemplo planteado:

 ¿Qué es el Código Intermedio?

El código intermedio es una representación abstracta del programa que:

  •     Es independiente de la arquitectura: No está diseñado para ejecutarse directamente en una máquina específica.
  •     Es más fácil de optimizar: Permite realizar transformaciones que mejoran el rendimiento del programa.
  •     Es más simple que el código fuente: Reduce los detalles del lenguaje de programación original, enfocándose en operaciones básicas que pueden traducirse fácilmente al lenguaje máquina.
    (Alfred & Ullman, 1998, capítulo 5)


Un formato intermedio común es el tres direcciones (Three-Address Code), donde cada instrucción tiene como máximo tres operandos: uno para el resultado y dos para los valores de entrada. También se utilizan registros temporales para almacenar valores intermedios.

entero suma = x + y;

Ejemplo 4. Suma de dos variables.
Fuente: Eduardo, O. Q. E. (2024). Ejemplo 4 [Fragmento de código]. 

 En este fragmento de código:

  •     Declaramos una variable suma de tipo entero.
  •     Realizamos una operación de suma entre dos variables, x y y.
  •     Asignamos el resultado de la suma a la variable suma.

Podría traducirse a un código intermedio como en el Ejemplo 8, imagina que tienes dos "cajas" donde guardas números: una caja llamada x y otra llamada y. Y también tienes varios "espacios de trabajo" llamados registros (en este caso R1, R2, y R3) donde puedes guardar temporalmente números para hacer operaciones con ellos:

LOAD R1, x       ; Carga el valor de x en el registro R1

LOAD R2, y       ; Carga el valor de y en el registro R2

ADD R3, R1, R2   ; Suma R1 y R2, guarda el resultado en R3

STORE suma, R3   ; Guarda el valor de R3 en la variable suma

Ejemplo 8. Código intermedio.
Fuente: Eduardo, O. Q. E. (2024). Ejemplo 8 [Fragmento de código].

Aquí, R1, R2, y R3 son registros de la CPU.

El código intermedio del Ejemplo 8 es independiente de la arquitectura de la computadora, lo que facilita su traducción a diferentes plataformas.

Explicación paso a paso del código intermedio:

   1. LOAD R1, x:

  •    Carga el valor de la variable x desde la memoria a un registro temporal llamado R1.
  •    Los registros son pequeñas "casillas" dentro de la CPU que sirven para realizar operaciones rápidamente.


  2. LOAD R2, y:

  •   Carga el valor de y en otro registro temporal, R2.


  3. ADD R3, R1, R2:

  •     Realiza la suma de los valores almacenados en los registros R1 y R2.
  •     Almacena el resultado en un tercer registro, R3.


   4. STORE suma, R3:

  •     Toma el valor resultante de la operación (almacenado en R3) y lo guarda en la variable suma, que está en la memoria.
    (Alfred & Ullman, 1998, capítulo 5)

¿Por qué es útil el código intermedio?

    1. Independencia de hardware:

  •         Al ser genérico, el código intermedio puede ser traducido a diferentes lenguajes máquina dependiendo de la arquitectura del sistema (por ejemplo, x86, ARM, etc.).
  •         Esto permite que el compilador sea portátil, ya que solo necesita un traductor para cada tipo de hardware.


    2. Facilidad de optimización:

  •         El código intermedio es más simple que el código fuente, lo que facilita detectar redundancias, eliminar instrucciones innecesarias o reorganizar operaciones para mejorar el rendimiento.


    3. Modularidad:

  •         La separación entre el análisis del código y la generación del lenguaje máquina final hace que el compilador sea más fácil de desarrollar y mantener.

Relación con Otras Fases del Compilador

    1. Entrada desde el Análisis Semántico:

  •         El código intermedio se genera después de que el análisis semántico ha validado que las operaciones son correctas (por ejemplo, que x e y son variables válidas y del mismo tipo compatible).


    2. Salida hacia la Generación de Código Final:

  •         El código intermedio es traducido al lenguaje máquina específico del hardware objetivo, como instrucciones en ensamblador.
    (Alfred & Ullman, 1998, capítulo 5)


Referencia en APA: Alfred, A. V., & Ullman, J. D. (1998). Generación de código. En Principles of compiler design (Capítulo 5). Compiladores. (n.d.). Google Books. https://books.google.com.gt/books?id=yG6qJBAnE9UC&printsec=frontcover#v=onepage&q&f=false

Comentarios