Sei sulla pagina 1di 8

UNIDAD 2 Generacin de cdigo intermedio

Competencia especfica de la unidad:


Aplicar las herramientas para desarrollar una mquina virtual que ejecute cdigo intermedio a
partir del cdigo fuente de un lenguaje prototipo. Disea mediante el uso de reglas semnticas
dirigidas por sintaxis, un analizador semntico para un compilador.
EL cdigo fuente puede ser traducido en su cdigo de la mquina destino, entonces, por qu
hemos de traducir el cdigo fuente en un cdigo intermedio que luego se traduce en su cdigo
de destino? Vamos a ver las razones por las que necesitamos un cdigo intermedio.

Si un compilador traduce el idioma de origen a su ordenador de destino sin tener la opcin de


generar cdigo intermedio, a continuacin, en cada nueva mquina, una nativa del compilador
completo es necesario.
Cdigo Intermedio elimina la necesidad de un nuevo compilador completo para cada mquina
de la seccin de anlisis mismo de todos los compiladores.
La segunda parte del compilador, sntesis, se modifica de acuerdo a la mquina de destino.
Es ms fcil de aplicar las modificaciones del cdigo fuente para mejorar rendimiento del
cdigo mediante la aplicacin de tcnicas de optimizacin cdigo el cdigo intermedio.
Representacin intermedia
Cdigos intermedios puede ser representado en una variedad de formas y tienen sus propios
beneficios.

Alto nivel IR - Alto nivel de representacin de cdigo intermedio est muy cerca de la
lengua de origen. Pueden ser fcilmente generados desde el cdigo fuente y podemos
aplicar fcilmente modificaciones de cdigo para mejorar el rendimiento. Pero para
optimizacin de la mquina destino, es menos preferido.

Bajo Nivel IR - Este es cerca de la mquina de destino, lo que lo hace adecuado para
registro y asignacin de memoria, un conjunto de instrucciones seleccin, etc. es
bueno para optimizaciones dependientes de la mquina.

Cdigo intermedio puede ser especfica para cada idioma (p. ej., cdigo de bytes de Java) o
independiente de la lengua (tres-cdigo de direccin).
Cdigo Three-Address
Generador de cdigo intermedio recibe la entrada de su predecesor, analizador semntico, en
la forma de un rbol de sintaxis anotado. rbol de sintaxis que luego se puede convertir en una
representacin lineal, por ejemplo, postfija notacin. Cdigo intermedio tiende a ser cdigo

independiente de la mquina. Por lo tanto, generador de cdigo supone que tiene nmero
ilimitado de almacenamiento en memoria (registro) para generar el cdigo.
Por ejemplo:
a = b + c * d;
El generador de cdigo intermedio, tratar de dividir esta expresin en sub-expresiones y, a
continuacin, generar el cdigo correspondiente.
r1 = c * d;
r2 = b + r1;
r3 = r2 + r1;
a = r3
R que se utilizan como registros en el programa de destino.
Un cdigo de direccin tiene un mximo de tres direcciones para calcular la expresin. Un
cdigo de direccin puede estar representado en dos formas : cudruples y triples.
Cuadruplica
Cada instruccin cuadruplica exposicin se divide en cuatro campos: operador, arg1, arg2, y
resultado. El ejemplo anterior se representa a continuacin cuadruplica en formato:
Op.
*
+
+
=

Arg1
c
b
r2
r3

Arg2
d
r1
r1

Resultado
r1
r2
r3
a

Triples
Cada instruccin en triples presentacin tiene tres campos : op, arg1, arg2.Los resultados de
las respectivas sub-expresiones son indicados por la posicin de expresin. Similitud con
Triples representan DAG y rbol de sintaxis. Son equivalentes a DAG al tiempo que
representan las expresiones.
Op
Arg1
Arg2
*
c
d
+
b
(0)
+
(1)
(0)
=
(2)
Triples ante el problema de optimizacin cdigo un inmovilismo mientras que, en la medida en
que los resultados son posicionales y cambiar el orden o la posicin de una expresin puede
causar problemas.
Indirectos Triples
Esta representacin es una mejora sobre representacin triples. Se usa punteros en lugar de
su posicin para almacenar los resultados. Esto permite a los optimizadores libremente volver a
colocar la sub-expresin para producir un cdigo optimizado.
Declaraciones
Una variable o procedimiento tiene que ser declarado antes de que se pueda utilizar.
Declaracin implica asignacin de espacio en la memoria y la entrada de tipo y nombre de la
tabla de smbolos. Un programa puede ser codificada y diseado siguiendo la estructura de la

mquina destino en mente, pero es posible que no siempre se pueda convertir con precisin un
cdigo fuente para su idioma de destino.
Tomando el conjunto del programa, como una coleccin de procedimientos y subprocedimientos, es posible declarar que todos los nombres locales en el procedimiento.
Asignacin de memoria se realiza de manera consecutiva y nombres son asignados a la
memoria en la secuencia en la que se declara en el programa. Podemos utilizar el
desplazamiento variable y ponerlo a cero {offset = 0} que denotan la direccin base.
La fuente lenguaje de programacin y la arquitectura del equipo de destino puede variar en la
forma los nombres se almacenan, por lo tanto se utiliza direccionamiento relativo. Mientras que
el primer nombre se asigna memoria a partir de la posicin de memoria 0 {offset= 0}, el
siguiente nombre declar despus, debe ser asignada la memoria junto a la primera.
Ejemplo:
Tomamos el ejemplo de lenguaje de programacin C en una variable de tipo entero se le asigna
2 bytes de memoria y una variable de tipo float se asigna 4 bytes de memoria.
int a;
float b;
Allocation process:
{offset = 0}
int a;
id.type = int
id.width = 2
offset = offset + id.width
{offset = 2}
float b;
id.type = float
id.width = 4
offset = offset + id.width
{offset = 6}
Para entrar en este detalle en una tabla de smbolos, un procedimientoentrar puede ser
utilizado. Este mtodo puede tener la siguiente estructura:
enter(name, type, offset)
Este procedimiento debe crear una entrada en la tabla de smbolos, de nombre de la variable,
en su tipo y el tipo de desplazamiento de direccin relativa en su rea de datos.
Cdigo mquina
La aparicin de los lenguajes de alto nivel mejor la productividad de los programadores al
liberarlos de los detalles de bajo nivel de la computadora que estaban programando. El
compilador es quien se encarga de realizar la conversin del cdigo fuente en lenguaje de alto
nivel al cdigo mquina de la computadora que ejecutar el programa. Por tanto, el compilador
quien ahora maneja los detalles de bajo nivel de la arquitectura a programar. Esto implica que
el desarrollo del compilador requiere del conocimiento de los detalles de la arquitectura de la
mquina destino. En este apartado conoceremos la computadora abstracta que Tiny traduce
sus programas.
La mquina abstracta
En este apartado describimos la computadora para la cual el compilador de Tiny genera cdigo
objeto. Est diseada para facilitar la traduccin de un lenguaje similar al Pascal a una
arquitectura abstracta. Esta computadora es un subconjunto de la computadora Dream(Dream
machine) diseada por Frank DeRemer. Se trata de una computadora orientada a pila (stack)

sin registros direccionales, por lo que carece de instrucciones como carga registro X con ;
es decir, todas las instrucciones suponen que los datos estn en la pila y guardan los
resultados en la pila.
Adems, se han eliminado algunas restricciones normales en las mquinas reales:
Las instrucciones de ramificacin no estn limitadas a un determinado rango.
Todas las instrucciones tienen el mismo formato, y no dos o tres formatos diferentes,
como en la arquitectura IA32, por ejemplo.
La computadora tiene tres memorias diferentes y separadas entre s:

De cdigo
De datos
De direcciones de retorno

Los lmites de cada tipo de memoria estn indicados por una serie de registros. La siguiente
figura ilustra estas memorias y sus registros lmite:
La memoria de cdigo se considera de slo-lectura. Ningn programa puede saltar (branch)
fuera de su rea de cdigo, ya que todas sus instrucciones estn confinadas al rango de
direcciones limitado por los registros CBR y CLR. Ni el cdigo ni las direcciones de retorno
pueden modificarse ni copiarse, debido a que todas las lecturas y escrituras a memoria estn
restringidas a realizarse entre los registros GBR (Global Base Register) y STR (Stack Top
Register).
En otras palabras, en esta mquina es imposible ejecutar cdigo que se auto modifique. El
lmite de la memoria disponible est determinado por el registro SLR (Stack Limit Register).
Este registro simula el tamao limitado de la memoria fsica de las computadoras reales; sin
embargo, para fines del compilador de Tiny, supondremos que la mquina no tiene limitacin de
memoria, es decir, el contenido de SLR es infinito.
Todo el direccionamiento de las variables globales y locales es relativo a GBR (Global
Base Register) o a LBR (Local Base Register), segn corresponda. Por tanto, la instruccin
LLV i (Load Local Value i) significa coloca en el tope de la pila (push) el valor de la palabra
del marco local (local frame). Por tanto, i puede verse como un desplazamiento (offset) a partir
de LBR. La ejecucin de esta instruccin ajustar el registro del tope de la pila (STR). Otro
ejemplo es SGVi (Storage Global Value i), que significa saca de la pila el valor en el tope
(pop) y almacenalo en la i-sima palabra global. De nuevo, la ejecucin de esta instruccin
ajustara el STR, e i es el desplazamiento respecto de GBR. Otro ejemplo ms es LIT i (Literal
i), que significa coloca i en la pila.
Con el fin de simplificar, asumimos que la ejecucin del programa, una vez cargado en
memoria, inicia en la instruccin indicada en CBR; es decir, asumimos que el cargador carga el
programa a partir de esa localizacin. La herramienta TWS incluye un intrprete que hace las
veces de la mquina abstracta.
Formato de instrucciones
El formato de las instrucciones de la mquina abstracta es el siguiente: {etiqueta} [mnemnico
de la instruccin] [0, 1 o 2 operandos]
Donde la etiqueta es opcional, adems vemos que hay instrucciones que no manejan datos,
otras que manejan un slo dato y otras que manejan dos datos. Es decir, en el conjunto de
instrucciones encontramos instrucciones con 0, 1 o 2 campos de direccionamiento.
Conjunto de instrucciones
Las instrucciones que la mquina abstracta puede ejecutar son las siguientes:
De control del programa
NOP : Hacer nada
HALT : Detenerse (halt)

De transferencia de datos
LIT v : Cargar (Push) la Literal v en Local frame (Lf) de la memoria de datos.
LLV i : Cargar valor local (Load Local Value) i en Lf.
LGV i : Cargar valor global (Load Local Value) i en Lf.
SLV i : Almacena valor local i (Store Local Value i) en Lf.
SGV i : Almacena valor global i.
LLA i : Cargar Direccin Local i (Load Local Address i) en Lf.
LGA i : Cargar Direccin Global i (Load Global Address i) en Lf.
POP n : Extrae n valores (Pop n values).
DUP : Duplica el tope de la pila.
SWAP : Intercambia los dos valores superiores de la pila.
Aritmticas y lgicas
UOP i : Operacin unitaria i (UnaryOperation i): const X = Pop Lf.
Push (Unop(i,X)) en Lf
BOP i :Operacinbinaria i: constXr,Xl = Pop Lf, Pop Lf
Push (Binop(i,Xl,Xr)) en Lf
De control de flujo
CALL n : Llamada a una subrutina.
RTN n : Retorno de rutina.
GOTO L : I <- L Salto incondicional a L
COND L M: I <- if Pop Lf = True # Pop Stack. Si el valor es:
then L # Verdadero, salta a L
else M # Falso, salta a M.
if
CODEF :Push F onLf # Carga el punto de entrada.
SOS i : Llamada a la funcin i del sistema operativo
Donde
Unop(i,X) significa:
case i of
UNOT : not(X)
UNEG : -(X)
USUCC : X+1
UPRED : X-1
Binop(i,Xl,Xr) significa:
case i of
BAND : Xl and Xr
BOR : Xl or Xr
BPLUS : Xl + Xr
BMINUS : Xl - Xr
BMULT : Xl * Xr
BDIV : Xl div Xr
BMOD : Xl mod Xr
BEQ : Xl = Xr
BNE : Xl <>Xr
BLE : Xl <= Xr
BGE : Xl >= Xr
BLT : Xl <Xr
BGT : Xl >Xr
Llamadas al sistema
Para simplificar el manejo de los dispositivos de Entrada/Salida suponemos que tenemos
disponibles algunas llamadas al sistema operativo, a las cuales se accede por medio de la
instruccin SOS:
SOS (Sistema operativo) i significa:
case i of
TRACEX :Trace_Execution<- not TraceExecution
DUMPMEM: Dump_Memory

INPUT :readln(i)
Push i on Lf
INPUTC :readln(ch)
Push Ord(ch) on Lf
OUTPUT : write (Pop Lf)
OUTPUTC: write (Chr(Pop(Lf)))
OUTPUTL: writeln
EOF : if eof(input)
then Push True on Lf
else Push False on Lf
Vemos que la mquina abstracta puede ejecutar las cuatro operaciones aritmticas bsicas:
suma, resta, multiplicacin y divisin, adems la operacin mdulo; tambin puede ejecutar las
tres operaciones lgicas bsicas: NOT, ANDy OR; puede ejecutar saltos condicionales e
incondicionales. Cuenta con llamadas al sistema operativo para las operaciones de
Entrada/Salida y para funciones de depuracin.
Como sabemos, el compilador debe traducir del lenguaje de alto nivel a este conjunto
deinstrucciones. Es, por tanto, necesario entender cmo utilizar este lenguaje ensambladorpara
escribir programas en bajo nivel para la mquina abstracta. A continuacin presentamos un par
de ejemplos de traduccin de Tiny al ensamblador de la mquina abstracta.
Ejemplo 1
Vamos a mostrar la traduccin del siguiente programa en Tiny:
Programcopy:
{ Despliega en pantalla (eco) los primeros 10 nmeros ledos con input }
Var count: integer;
Begin
Count:=1;
While( count <= 10) do
Begin
Output(read);
Count := count + 1;
End
End copy.
El cdigo mquina para este programa se muestra abajo. Obviamente, los comentarios no son
generados por el generador de cdigo.
LIT 0 # Espaciopara Count
LIT 1 # Asigna 1
SGV 0 # Count := 1
L2 LGV 0 # Carga Count
LIT 10 # Carga 10
BOP BLE # POP, Compara. Push resultado T/F
COND L3 L4 # Pop stack, si V, ve a L3, sino, ve a L4.
L3 SOS INPUT # Llamada al SO. Lee y coloca en la pila
SOS OUTPUT # Llamada al SO. Saca de la pila y despliega
SOS OUTPUTL # Despliega un avance de lnea
LGV 0 # Carga Count
LIT 1 # Carga 1
BOP BPLUS # Smalos y guarda resultado en la pila
SGV 0 # Saca de la pila y almacena en Count
GOTO L2 # Regresa a L2
L4 HALT # Salta aqu cuando termines. Detnte.

Ejemplo 2
Con el fin de ayudar al entendimiento de esta mquina estudiaremos otro programa ejemplo,
escrito en el lenguaje Medium, que es el lenguaje intermedio para Tiny:
program fact:
var m: integer;
function fact(n: integer) : integer
begin
If n > 0 then
fact := n * fact( n 1 );
else
fact := 1;
m := m + 1;
end;
begin
m := 0;
output( fact( read ), m );
end fact.
El cdigo para la mquina abstracta es el siguiente:
LIT 0
GOTO L1
L2 LLV 1
LIT 0
BOP BGT
COND L3 L4
L3 LLV 1
LIT 0
LLV 1
LIT 1
BOP BMINUS
CODE L2
CALL 3
BOP BMULT
SLV 0
GOTO L5
L4 LIT 1
SLV 0
NOP
L5 LGV 0
LIT 1
BOP BPLUS
SGV 0
LLV 0
RTN 1
L1 LIT 0
SGV 0
LIT 0
SOS INPUT
CODE L2
CALL 1
SOS OUTPUT
LGV 0
SOS OUTPUT
SOS OUTPUTL
HALT
Es muy recomendable que traces con papel y lpiz la ejecucin de estos dos programas de
ejemplo para que entiendas mejor la programacin en bajo nivel de la mquina abstracta.

Bytecode
El bytecode un cdigo intermedio ms abstracto que el cdigo mquina. Habitualmente es
tratado como un archivo binario que contiene un programa ejecutable similar a un mdulo
objeto, que es un archivo binario producido por el compilador cuyo contenido es el cdigo
objeto o cdigo mquina .
El bytecode recibe su nombre porque usualmente cada cdigo de operacin tiene una longitud
de un byte, si bien la longitud del cdigo de las instrucciones vara. Cada instruccin tiene un
cdigo de operacin entre 0 y 255 seguido de parmetros tales como los registros o las
direcciones de memoria. Esta sera la descripcin de un caso tpico, si bien la especificacin de
bytecode depende ampliamente del lenguaje.
Como cdigo intermedio, se trata de una forma de salida utilizada por los implementadores de
lenguajes para reducir la dependencia respecto del hardware especfico y facilitar la
interpretacin. Menos frecuentemente se utiliza el bytecode como cdigo intermedio en un
compilador. Algunos sistemas, llamados traductores dinmicos o compiladores just-in-time
traducen el bytecode a cdigo mquina inmediatamente antes de su ejecucin para mejorar la
velocidad de ejecucin.
Los programas en bytecode suelen ser interpretados por un intrprete de bytecode (en general
llamado mquina virtual, dado que es anlogo a un ordenador). Su ventaja es su portabilidad:
el mismo cdigo binario puede ser ejecutado en diferentes plataformas y arquitecturas. Es la
misma ventaja que presentan los lenguajes interpretados. Sin embargo, como el bytecode es
en general menos abstracto, ms compacto y ms orientado a la mquina que un programa
pensado para su modificacin por humanos, su rendimiento suele ser mejor que el de los
lenguajes interpretados. A causa de esa mejora en el rendimiento, muchos lenguajes
interpretados, de hecho, se compilan para convertirlos en bytecode y despus son ejecutados
por un intrprete de bytecode. Entre esos lenguajes se encuentran Perl, Gambas, PHP y
Python. En el caso de Java se suele trasmitir como bytecode a la mquina receptora, que
utiliza un compilador just-in-time para compilar el bytecode en cdigo mquina nativo antes de
su ejecucin, ahorrando as procesos de interpretacin.
Son asimismo interesantes los denominados p-Codes, similares a bytecodes pero cuyos
cdigos de operacin pueden constar de ms de un byte y pueden ser variables en tamao,
como los opcodes de muchas CPUs. Estos cdigos trabajan a muy alto nivel, incluyendo
instrucciones del estilo de imprime esta cadena o borra la pantalla. Por ejemplo, BASIC
utiliza p-Code.

Potrebbero piacerti anche