UNIDAD 2 Generación de código intermedio Competencia específica de la unidad:
Aplicar las herramientas para desarrollar una máquina virtual que ejecute código intermedio a partir del código fuente de un lenguaje prototipo. Diseña mediante el uso de reglas semánticas dirigidas por sintaxis, un analizador semántico para un compilador. E código fuente puede ser traducido en su código de la máquina destino, entonces, !por qu" hemos de traducir el código fuente en un código intermedio que luego se traduce en su código de destino# $amos a ver las razones por las que n ecesitamos un código intermedio.
%i un compilador traduce traduce el idioma de origen a su ordenador ordenador de destino destino sin tener la opción de generar código intermedio, a continuación, en cada nueva máquina, una nativa del compilador completo es necesario. &ódigo 'ntermedio elimina la necesidad de un nuevo compilador completo para cada máquina de la sección de análisis mismo de todos los compiladores. a segunda parte del compilador, compilado r, s(ntesis, se modifica de acuerdo a la máquina de destino. Es más fácil de aplicar las modificaciones del código fuente para mejorar rendimiento del código mediante la aplicación de t"cnicas de optimización código el código intermedio. Representación intermedia
&ódigos intermedios puede ser representado en una variedad de formas ) tienen sus propios *eneficios. •
Alto nivel IR + Alto nivel de representación de código intermedio está mu) cerca de la
lengua de origen. ueden ser fácilmente generados desde el código fuente ) podemos aplicar fácilmente modificaciones de código para mejorar el rendimiento. ero para optimización de la máquina destino, es menos preferido. •
Bao Nivel IR + Este es cerca de la máquina de destino, lo que lo hace adecuado para
registro ) asignación de memoria, un conjunto de instrucciones selección, etc. es *ueno para optimizaciones dependientes de la máquina. &ódigo intermedio puede ser espec(fica para cada idioma -p. ej., código de *)tes de ava/ o independiente de la lengua -tres+código de dirección/. &ódigo 0hree+Address 1enerador de código intermedio reci*e la entrada de su predecesor, analizador semántico, en la forma de un ár*ol de sintaxis anotado. 2r*ol de sintaxis que luego se puede convertir en una representación lineal, por ejemplo, postfija notación. &ódigo intermedio tiende a ser código
independiente de la máquina. or lo tanto, generador de código supone que tiene n3mero ilimitado de almacenamiento en memoria -registro/ para generar el código. or ejemplo4 a 5 * 6 c 7 d8 El generador de código intermedio, tratar de dividir esta expresión en su*+expresiones ), a continuación, generar el código correspondiente. r9 5 c 7 d8 r: 5 * 6 r98 r; 5 r: 6 r98 a 5 r; < que se utilizan como registros en el programa de destino. =n código de dirección tiene un máximo de tres direcciones para calcular la expresión. =n código de dirección puede estar representado en dos formas 4 cuádruples ) triples. Cuadruplica
&ada instrucción cuadruplica exposición se divide en cuatro campos4 operador, arg9, arg:, ) resultado. El ejemplo anterior se representa a continuación cuadruplica en formato4 !p" $ % % &
Arg#
Arg2
Resultado
c * r: r;
d r9 r9
r9 r: r; a
'riples
&ada instrucción en triples presentación tiene tres campos 4 op, arg9, arg:.os resultados de las respectivas su*+expresiones son indicados por la posición de expresión. %imilitud con 0riples representan DA1 ) ár*ol de sintaxis. %on equivalentes a DA1 al tiempo que representan las expresiones. !p $ % % &
Arg#
Arg2
c d * ->/ -9/ ->/ -:/ 0riples ante el pro*lema de optimización código un inmovilismo mientras que, en la medida en que los resultados son posicionales ) cam*iar el orden o la posición de una expresión puede causar pro*lemas. Indirectos 'riples
Esta representación es una mejora so*re representación triples. %e usa punteros en lugar de su posición para almacenar los resultados. Esto permite a los optimizadores li*remente volver a colocar la su*+expresión para producir un código optimizado. Declaraciones =na varia*le o procedimiento tiene que ser declarado antes de que se pueda utilizar. Declaración implica asignación de espacio en la memoria ) la entrada de tipo ) nom*re de la ta*la de s(m*olos. =n programa puede ser codificada ) diseñado siguiendo la estructura de la
máquina destino en mente, pero es posi*le que no siempre se pueda convertir con precisión un código fuente para su idioma de destino. 0omando el conjunto del programa, como una colección de procedimientos ) su*+ procedimientos, es posi*le declarar que todos los nom*res locales en el procedimiento. Asignación de memoria se realiza de manera consecutiva ) nom*res son asignados a la memoria en la secuencia en la que se declara en el programa. odemos utilizar el desplazamiento varia*le ) ponerlo a cero ?offset 5 >@ que denotan la dirección *ase. a fuente lenguaje de programación ) la arquitectura del equipo de destino puede variar en la forma los nom*res se almacenan, por lo tanto se utiliza direccionamiento relativo. ientras que el primer nom*re se asigna memoria a partir de la posición de memoria > ?offset5 >@, el siguiente nom*re declaró despu"s, de*e ser asignada la memoria junto a la primera. (emplo:
0omamos el ejemplo de lenguaje de programación & en una varia*le de tipo entero se le asigna : *)tes de memoria ) una varia*le de tipo float se asigna B *)tes de memoria. int a8 float *8 Allocation process4 ?offset 5 >@ int a8 id.t)pe 5 int id.Cidth 5 : offset 5 offset 6 id.Cidth ?offset 5 :@ float *8 id.t)pe 5 float id.Cidth 5 B offset 5 offset 6 id.Cidth ?offset 5 @ ara entrar en este detalle en una ta*la de s(m*olos, un procedimiento entrar puede ser utilizado. Este m"todo puede tener la siguiente estructura4 enter-name, t)pe, offset/ Este procedimiento de*e crear una entrada en la ta*la de s(m*olos, de nombre de la variable, en su tipo ) el tipo de desplazamiento de dirección relativa en su área de datos. Código m)*uina
a aparición de los lenguajes de alto nivel mejoró la productividad de los programadores al li*erarlos de los detalles de *ajo nivel de la computadora que esta*an programando. El compilador es quien se encarga de realizar la conversión del código fuente en lenguaje de alto nivel al código máquina de la computadora que ejecutará el programa. or tanto, el compilador quien ahora maneja los detalles de *ajo nivel de la arquitectura a programar. Esto implica que el desarrollo del compilador requiere del conocimiento de los detalles de la arquitectura de la máquina destino. En este apartado conoceremos la computadora a*stracta que 0in) traduce sus programas. +a m)*uina a,stracta
En este apartado descri*imos la computadora para la cual el compilador de 0in) genera código o*jeto. Está diseñada para facilitar la traducción de un lenguaje similar al ascal a una arquitectura a*stracta. Esta computadora es un su*conjunto de la computadora Dream-Dream machine/ diseñada por ranF De
sin registros direccionales, por lo que carece de instrucciones como Gcarga registro H con IJ8 es decir, todas las instrucciones suponen que los datos están en la pila ) guardan los resultados en la pila. Además, se han eliminado algunas restricciones normales en las máquinas reales4 as instrucciones de ramificación no están limitadas a un determinado rango. 0odas las instrucciones tienen el mismo formato, ) no dos o tres formatos diferentes, como en la arquitectura 'A;:, por ejemplo. a computadora tiene tres memorias diferentes ) separadas entre s(4 • •
• • •
De código De datos De direcciones de retorno
os l(mites de cada tipo de memoria están indicados por una serie de registros. a siguiente figura ilustra estas memorias ) sus registros l(mite4 a memoria de código se considera de sólo+lectura. King3n programa puede saltar -*ranch/ fuera de su área de código, )a que todas sus instrucciones están confinadas al rango de direcciones limitado por los registros &L< ) &<. Ki el código ni las direcciones de retorno pueden modificarse ni copiarse, de*ido a que todas las lecturas ) escrituras a memoria están restringidas a realizarse entre los registros 1L< -1lo*al Lase
El formato de las instrucciones de la máquina a*stracta es el siguiente4 ?etiqueta@ Omnemónico de la instrucciónP O>, 9 o : operandosP Donde la etiqueta es opcional, además vemos que ha) instrucciones que no manejan datos, otras que manejan un sólo dato ) otras que manejan dos datos. Es decir, en el conjunto de instrucciones encontramos instrucciones con >, 9 o : campos de direccionamiento. Conunto de instrucciones
as instrucciones que la máquina a*stracta puede ejecutar son las siguientes4 De control del programa
KM 4 Qacer nada QA0 4 Detenerse -halt/
De transferencia de datos
'0 v 4 &argar -ush/ la iteral v en ocal frame -f/ de la memoria de datos. $ i 4 &argar valor local -oad ocal $alue/ i en f. 1$ i 4 &argar valor glo*al -oad ocal $alue/ i en f. %$ i 4 Almacena valor local i -%tore ocal $alue i/ en f. %1$ i 4 Almacena valor glo*al i. A i 4 &argar Dirección ocal i -oad ocal Address i/ en f. 1A i 4 &argar Dirección 1lo*al i -oad 1lo*al Address i/ en f. M n 4 Extrae n valores -op n values/. D= 4 Duplica el tope de la pila. %NA 4 'ntercam*ia los dos valores superiores de la pila. Aritm.ticas / lógicas
=M i 4 Mperación unitaria i -=nar)Mperation i/4 const H 5 op f. ush -=nop-i,H// en f LM i 4Mperación*inaria i4 constHr,Hl 5 op f, op f ush -Linop-i,Hl,Hr// en f De control de fluo
&A n 4 lamada a una su*rutina. <0K n 4
ara simplificar el manejo de los dispositivos de EntradaV%alida suponemos que tenemos disponi*les algunas llamadas al sistema operativo, a las cuales se accede por medio de la instrucción %M%4 %M% -%istema operativo/ i significa4 case i of 0
'K=0 4readln-i/ ush i on f 'K=0& 4readln-ch/ ush Mrd-ch/ on f M=0=0 4 Crite -op f/ M=0=0&4 Crite -&hr-op-f/// M=0=04 Criteln EM 4 if eof-input/ then ush 0rue on f else ush alse on f $emos que la máquina a*stracta puede ejecutar las cuatro operaciones aritm"ticas *ásicas4 suma, resta, multiplicación ) división, además la operación módulo8 tam*i"n puede ejecutar las tres operaciones lógicas *ásicas4 KM0, AKD) M<8 puede ejecutar saltos condicionales e incondicionales. &uenta con llamadas al sistema operativo para las operaciones de EntradaV%alida ) para funciones de depuración. &omo sa*emos, el compilador de*e traducir del lenguaje de alto nivel a este conjunto deinstrucciones. Es, por tanto, necesario entender cómo utilizar este lenguaje ensam*ladorpara escri*ir programas en *ajo nivel para la máquina a*stracta. A continuación presentamos un par de ejemplos de traducción de 0in) al ensam*lador de la máquina a*stracta. (emplo #
$amos a mostrar la traducción del siguiente programa en 0in)4 rogramcop)4 ? Despliega en pantalla -eco/ los primeros 9> n3meros le(dos con input @ $ar count4 integer8 Legin &ount4598 Nhile- count R5 9>/ do Legin Mutput-read/8 &ount 45 count 6 98 End End cop). El código máquina para este programa se muestra a*ajo. M*viamente, los comentarios no son generados por el generador de código. '0 > S Espaciopara &ount '0 9 S Asigna 9 %1$ > S &ount 45 9 : 1$ > S &arga &ount '0 9> S &arga 9> LM LE S M, &ompara. ush resultado 0V &MKD ; B S op stacF, si $, ve a ;, sino, ve a B. ; %M% 'K=0 S lamada al %M. ee ) coloca en la pila %M% M=0=0 S lamada al %M. %aca de la pila ) despliega %M% M=0=0 S Despliega un avance de l(nea 1$ > S &arga &ount '0 9 S &arga 9 LM L=% S %3malos ) guarda resultado en la pila %1$ > S %aca de la pila ) almacena en &ount 1M0M : S
(emplo 2
&on el fin de a)udar al entendimiento de esta máquina estudiaremos otro programa ejemplo, escrito en el lenguaje GediumJ, que es el lenguaje intermedio para 0in)4 program fact4 var m4 integer8 function fact-n4 integer/ 4 integer *egin 'f n U > then fact 45 n 7 fact- n X 9 /8 else fact 45 98 m 45 m 6 98 end8 *egin m 45 >8 output- fact- read /, m /8 end fact. El código para la máquina a*stracta es el siguiente4 '0 > 1M0M 9 : $ 9 '0 > LM L10 &MKD ; B ; $ 9 '0 > $ 9 '0 9 LM L'K=% &MDE : &A ; LM L=0 %$ > 1M0M Y B '0 9 %$ > KM Y 1$ > '0 9 LM L=% %1$ > $ > <0K 9 9 '0 > %1$ > '0 > %M% 'K=0 &MDE : &A 9 %M% M=0=0 1$ > %M% M=0=0 %M% M=0=0 QA0 Es mu) recomenda*le que traces con papel ) lápiz la ejecución de estos dos programas de ejemplo para que entiendas mejor la programación en *ajo nivel de la máquina a*stracta.
B/tecode
El *)tecode un código intermedio más a*stracto que el código máquina. Qa*itualmente es tratado como un archivo *inario que contiene un programa ejecuta*le similar a un módulo o*jeto, que es un archivo *inario producido por el compilador cu)o contenido es el código o*jeto o código máquina . El *)tecode reci*e su nom*re porque usualmente cada código de operación tiene una longitud de un *)te, si *ien la longitud del código de las instrucciones var(a. &ada instrucción tiene un código de operación entre > ) :YY seguido de parámetros tales como los registros o las direcciones de memoria. Esta ser(a la descripción de un caso t(pico, si *ien la especificación de *)tecode depende ampliamente del lenguaje. &omo código intermedio, se trata de una forma de salida utilizada por los implementadores de lenguajes para reducir la dependencia respecto del hardCare espec(fico ) facilitar la interpretación. enos frecuentemente se utiliza el *)tecode como código intermedio en un compilador. Algunos sistemas, llamados traductores dinámicos o compiladores just-in-time traducen el *)tecode a código máquina inmediatamente antes de su ejecución para mejorar la velocidad de ejecución. os programas en *)tecode suelen ser interpretados por un int"rprete de *)tecode -en general llamado máquina virtual, dado que es análogo a un ordenador/. %u ventaja es su porta*ilidad4 el mismo código *inario puede ser ejecutado en diferentes plataformas ) arquitecturas. Es la misma ventaja que presentan los lenguajes interpretados. %in em*argo, como el *)tecode es en general menos a*stracto, más compacto ) más orientado a la máquina que un programa pensado para su modificación 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 *)tecode ) despu"s son ejecutados por un int"rprete de *)tecode. Entre esos lenguajes se encuentran erl, 1am*as, Q ) )thon. En el caso de ava se suele trasmitir como *)tecode a la máquina receptora, que utiliza un compilador just+in+time para compilar el *)tecode en código máquina nativo antes de su ejecución, ahorrando as( procesos de interpretación. %on asimismo interesantes los denominados p+&odes, similares a *)tecodes pero cu)os códigos de operación pueden constar de más de un *)te ) pueden ser varia*les en tamaño, como los opcodes de muchas &=s. Estos códigos tra*ajan a mu) alto nivel, inclu)endo instrucciones del estilo de Zimprime esta cadena[ o Z*orra la pantalla[. or ejemplo, LA%'& utiliza p+&ode.