Está en la página 1de 58

GENERACIÓN DE CÓDIGO INTERMEDIO

UNIDAD II

COMPILADORES TEORÍA E IMPLEMENTACION
JACINTO RUIZ CATALÁN  ALFAOMEGA

CONSTRUCCION DE COMPILADORES PRINCIPIOS Y PRACTICA
KENNETH C. LOUDEN  THOMSON EDITORES

TRADUCTORES Y COMPILADORES CON LEX YACC JFLEX CUP Y JAVACC
SERGIO GALVES ROJAS  MIGUEL ANGEL MORA MATA

 Analizar

una máquina virtual que ejecute código intermedio a partir del código fuente de un lenguaje prototipo.

2.1 Notaciones
2.1.1 Prefija  2.1.2 Infija  2.2.3 Postfija

2.2 Representaciones de código Intermedio.

  

2.2.1 Notación Polaca 2.2.2 Código P 2.2.3 Triplos 2.2.4 Cuádruplos.
2.3.1 2.3.2 2.3.3 2.3.4 2.3.5 2.3.6 Variables y constantes. Expresiones. Instrucción de asignación. Instrucciones de control. Funciones Estructuras

2.3 Esquema de generación.
     

Fases dependientes del lenguaje Fuente e independientes de la Maquina final

Fases independientes del lenguaje Fuente pero dependientes del código Intermedio y de la maquina final

CODIGO FUENTE

CODIGO INTERMEDIO

ANALISIS LEXICO

OPTIMIZACION DE CODIGO INTERMEDIO GENERACION DE CODIGO FINAL OPTIMIZACIÓN DE CODIGO FINAL

ANALISIS SINTACTICO ANALISIS SEMANTICO GENERACIÓN DE CODIGO INTERMEDIO

FRONT END

BACK END

CODIGO FINAL / EJECUTABLE

interpretable y  Obtención de código ejecutable.  Diferencia entre código código ejecutable nativo. . Diferencia entre código fuente y código ejecutable.

operador operando1 operando2 FORMATO DE INSTRUCCIÓN .Arquitectura básica de Von Neumann “En la memoria se almacena el programa y los datos necesarios para que éste opere” Instrucciones del procesador Son las instrucciones básicas que puede realizar la UCP. Todo ello conforma el “formato de instrucción”. Con ellas se construyen los programas que puede entender la UCP “código máquina” Cada instrucción básica “instrucción máquina” se especifica mediante un código de instrucción junto con la información sobre cómo obtener los operandos necesarios.

 Capaz de ejecutar millones de instrucciones MHz  .Unidad Central de Proceso CPU  Componente encargado de ejecutar las instrucciones que están en memoria principal.

EL PROCESADOR . Las instrucciones de los programas son almacenados en la memoria primaria. La primer tarea del CPU es leer una instrucción de la memoria.

 La unidad Prefetch le indica al bus que instrucción o conjunto de instrucciones tiene que leer (direcciones de memoria). EL PROCESADOR .  Prelectura de la instrucción desde la memoria principal.

 La Unidad de Decodificación toma las instrucciones leídas y las traslada a una forma adecuada para el procesamiento interno de CPU. operador operando1 operando2 EL PROCESADOR FORMATO DE INSTRUCCIÓN .

 La Unidad de Control coordina y organiza cuales elementos del CPU realizarán funciones. EL PROCESADOR .

 La Unidad Aritmético Lógica (Logic Unit) se encarga de ejecutar las operaciones correspondientes. Incluye registros de 32 o 64 bits generalmente. EL PROCESADOR .

 Creación y ejecución de programas en código nativo (Lenguaje C) Archivo de texto escrito por el programador .

(Java) Bite Code hola.class .Ejecución de código intermedio (interpretado)  Creación y ejecución de programas en código interpretado.

 Se . trata de representar de una manera formalizada las operaciones a llevar a cabo en un lenguaje más cercano a la máquina final. aunque no a una máquina concreta si no a una máquina abstracta. El código intermedio (CI) es la representación en un lenguaje sencillo de la secuencia real de las operaciones que se harán como resultado de las fases anteriores.

. Fácil de traducir al lenguaje objeto.  EJEMPLO Java Fácil de producir. Ventajas  del código intermedio    Aumenta la portabilidad del compilador de una máquina a otra. Reglas claras de construcción.

.

Pre .  Los prefijos. a Operando + Operador b Operando .Pos .In se refieren a la posición relativa del operador con respecto a los dos operandos. prefija y posfija. Las notaciones son una forma especial en la que se pueden expresar una expresión matemática y puedan ser de 3 formas: infija.

 Se evalúa de izquierda a derecha hasta que se encuentre el primer operador seguido inmediatamente de un par de operandos. 2+3  + 2 3  No requiere de paréntesis para indicar el orden de precedencia de operadores. La característica distintiva de esta notación es que coloca los operadores a la izquierda de sus operandos. .

 (3*6)/ (2+4) EVALUACIÓN LECTURA FINAL .

/*36+24 EVALUACIÓN .

EVALUACIÓN (3*6)/ (2+4) 4 2 + 6 3 * / LECTURA FINAL /*36+24 + ) ) E / ) / * / E .

/*36+24 EVALUACIÓN 3 2 6 6 18 6 3 4 4 6 6 6 2+4 3*6 18/6 .

Hijo_derecho expexp op exp|num / * + (3*6)/ (2+4) /*36+24 4 3 6 2 . Hijo_izquierdo. Nodo.

 Es la notación común de fórmulas aritméticas y lógicas. . en la cual se escriben los operadores entre los operandos en que están actuando: 2+2  No es tan simple de analizar por las computadoras. como la notación prefija o la notación postfija. aunque muchos lenguajes de programación la utilizan debido a su familiaridad.

Nodo. Hijo_izquierdo. Hijo_derecho expexp op exp|num (3*6)/ (2+4) / * + 3*6 / 2+4 3 6 2 4 .

. lo que optimiza los procesos a la hora de programar. S=A+B*C S A B C * + =  Su principio es el de evaluar los datos directamente cuando se introducen y manejarlos dentro de una estructura LIFO (Last In First Out).Se refiere a que el operador ocupa la posición después de los operandos.

 (3*6)/ (2+4) EVALUACIÓN LECTURA FINAL .

36*24+/ EVALUACIÓN .

 (3*6)/ (2+4) 2 4 + / EVALUACIÓN 3 6 * LECTURA FINAL 36*24+/ + * ( ( E / ( / ( / E .

36*24+/ EVALUACIÓN 4 6 3 3 18 2 18 2 18 6 18 3 3*6 4+2 18/6 .

Nodo expexp op exp|num / * + (3*6)/ (2+4) 36*24+/ 4 3 6 2 . Hijo_izquierdo. Hijo_derecho.

 Generación    de código: Simple No utiliza registros  Optimización Es difícil de reordenar ya que hay que considerar el contenido de la pila (Polaca Inversa)  Interpretación  rápida Es muy fácil de interpretar ya que solo necesita una pila Si. ya que todos los procesadores implementan una pila.  Transportable:  .

.

lo que optimiza los procesos.Su principio es el de evaluar los datos directamente cuando se introducen y manejarlos dentro de una estructura LIFO (Last In First Out).  if <cond> then <instr1> else <instr2>   No se puede traducir a <cond> <instr1> <instr2> If Código generado <cond> Salta Si falso Etiqueta1 <Instr1> Salta Etiqueta2 Etiqueta1: <Instr2> .

. Es una especificación de una Unidad Central de Procesamiento donde las instrucciones están diseñadas a ser ejecutadas por software (interpretadas) en lugar de Hardware.

. El código P comenzó como un código ensamblador objetivo estándar producido por varios compiladores Pascal en la década de 1970.  Fue diseñado para una maquina de pila hipotética la idea era hacer que los compiladores de Pascal se transportaran fácilmente.

) que posteriormente se trasladarán a direcciones reales en el mapa físico de memoria.En la creación de código intermedio se utilizan instrucciones simbólicas para representar los datos (variables. etc. . parámetros.

 El compilador debe generar un nombre temporal para guardar los valores calculados por cada instrucción.Cada instrucción de tres direcciones tiene a lo sumo un operador.  Algunas instrucciones de "tres direcciones" tiene menos de tres operadores.  .

Cuádruplos  Triplos  .

//Supongamos que x representa un entero Pasos para generar el CI  R1= valor (x)  R2= valor (1)  R3= R1 + R2  x=R3 • • • • CARGAR x null R1 CARGAR 1 null R2 SUMAR R1 R2 R3 CARGAR R3 null x CODIGO DE TRES DIRECCIONES CÓDIGO DE TRES DIRECCIONES .Ejemplo: x=x+1.

CARGAR 0 null 10000 CARGAR 10000 null 9000 CARGAR 9000 null 10001 CARGAR 1 null 10002 SUMAR 10001 10002 10003 CARGAR 10003 null 9000 posteriormente se trasladarán a direcciones reales en el mapa físico de memoria CÓDIGOS DE TRES DIRECCIONES int x main(){ x=0. x=x+1. } CI • CARGAR x null R1 • CARGAR 0 null R1 • CARGAR 1 null R2 • SUMAR R1 R2 R3 • CARGAR R3 null x .

MULTIPLICAR..n EL CI es muy próximo a un lenguaje ensamblador . DIVIDIR  OR.OTROS ARGUMENTOS DEL CI  RESTAR.x n).x 2. AND  MAYOR.. DISTINTO  ETIQUETA  Salto incondicional SALTAR_ETIQUETA null null etiq  Saltos condicionales SALTAR_CONDICION  op1 null etiq //SOLO SI ES FALSA IMPRIMIR_ENTERO 7 null null  IMPRIMIR_CADENA cad null null  Llamada al procedimiento p(x 1..      param x1 .. MENOR (Si se cumple coloca 1 en el res)  IGUAL... param xn Call p.

If a<b then x=b CARGAR A NULL R1 CARGAR B NULL R2 MAYOR R1 R2 R3 SALTAR_CONDICION R3 E1 E1 NULL NULL E1 CÓDIGOS DE TRES DIRECCIONES .

(2)) . Y.<operador> . <operando1>. Z) 3 (+. X) 2( +. W. (1). <operando2> El resultado se asocia al número de tripleta  Ejemplo: W*X+(Y+Z) 1( *.

. Y) 2 (Saltar si falso. (5)) 7. Y. 7) 5 (+. X. (=. . Z. . (1). X) 4 (Saltar. 5) 3 (=. 1) 6. Z.. Control de flujo: IF X>Y THEN Z=X ELSE Z=Y+1 1 (>..

SI FALSO .

.

(1) 2.EJERCICIO: A=B+C*D/E F=C*D Operaciones 1. A. (2) 3. C. (1) . (4) 5. D (2) /. F. B (2) (4) =. (5)  Tripletas (1) *. (3) (5) =. (1). E (3) +. (1) 6. (3) 4.

queda implícito y asociado a dicho terceto  Inconvenientes   La optimización supone mover tripletas y hay que recalcular las referencias .Los cuartetos son la herramienta más general  Inconvenientes   Ocupan demasiado espacio  Requieren muchas variables auxiliares para almacenar los resultados intermedios Los tercetos resuelven este problema suprimiendo el operando del resultado.

.

int y = 0. x=x-1. } } CARGAR 10 null 10001 CARGAR 0 null 10002 ETIQUETA null null BUCLE_1 CARGAR 10001 null 10003 CARGAR 0 null 10004 MAYOR 10003 10004 10005 SALTAR_CONDICION 10005 null FIN_BUCLE_1 CARGAR 10002 null 10006 CARGAR 10001 null 10007 SUMAR 10006 10007 10008 CARGAR 10008 null 10002 CARGAR 10001 null 10009 CARGAR 1null 10010 RESTAR 10009 10010 10011 CARGAR 10011 null 10001 SALTAR_ETIQUETA null null BUCLE_1 ETIQUETA null null FINBUCLE_1 IMPRIMIR_CADENA cadena1 null null . main(){ while(x>0){ y =y+x. } print(“Si leer”). }else{ print(“No leer”).int x = 10. if(x==0 && y>54){ print(“Si leer”).

int x = 10. main(){ while(x>0){ y =y+x. if(x==0 && y>54){ print(“Si leer”). CARGAR 10001 null 10013 CARGAR 0 null10014 IGUAL 10013 10014 10015 CARGAR 10002 null 10016 CARGAR 54 null10017 MAYOR 10016 10017 10018 AND 10015 10018 10019 SALTAR_CONDICION 10019 null ELSE_1 IMPRIMIR_CADENA cadena2 null null ETIQUETA null null ELSE_1 IMPRIMIR_CADENA cadena3 null null x=x-1. } } . } print(“Si leer”). }else{ print(“No leer”). int y = 0.

while (x*2<y){ while(y>x*4){ x=x+1. int y=20.int x=10. } } CARGAR 10 null 10001 CARGAR 20 null 10002 ETIQUETA null null BUCLE_1 CARGAR 10001 null 10003 CARGAR 2 null 10004 MULTIPLICAR 10003 10004 10005 CARGAR 10002 null 10006 MENOR 10005 10006 10007 SALTAR_CONDICION 10007 null FIN_BUCLE_1 ETIQUETA null null BUCLE_2 CARGAR 10002 null 10008 CARGAR 10001 null 10009 CARGAR 4 null 10010 MULTIPLICAR 10009 10010 10011 MAYOR 10008 10011 10012 SALTAR_CONDICION 10012 null FIN_BUCLE_2 CARGAR 10001 null 10013 CARGAR 1 null 10014 SUMAR 10013 10014 10015 CARGAR 10001 null 10015 SALTAR_ETIQUETA null null BUCLE_2 SALTAR_ETIQUETA null null BUCLE_1 ETIQUETA null null FIN_BUCLE_2 ETIQUETA null null FIN_BUCLE_1 .

if(y>1){ print(y). y=x*32. } } } } .int x=1-12. x=(32/12)*y. if(x>7){ while(y>0){ y=y-1. TAREA int y=x*32 CUADRUPLOS main(){ Y TRIPLOS x=1-12.

LOUDEN  THOMSON EDITORES   TRADUCTORES Y COMPILADORES CON LEX YACC JFLEX CUP Y JAVACC SERGIO GALVES ROJAS  MIGUEL ANGEL MORA MATA  . COMPILADORES TEORÍA E IMPLEMENTACION JACINTO RUIZ CATALÁN  ALFAOMEGA   CONSTRUCCION DE COMPILADORES PRINCIPIOS Y PRACTICA KENNETH C.

GENERACIÓN DE CÓDIGO INTERMEDIO. UNIDAD II .