Etapas finales de un traductor - PowerPoint PPT Presentation

1 / 79
About This Presentation
Title:

Etapas finales de un traductor

Description:

Optimizador (puede ser opcional e ir en esta etapa o hasta despu s de haber ... Las proposiciones de tres direcciones se parece mucho al ensamblador, el cual es ... – PowerPoint PPT presentation

Number of Views:251
Avg rating:3.0/5.0
Slides: 80
Provided by: juancarlos5
Category:

less

Transcript and Presenter's Notes

Title: Etapas finales de un traductor


1
Etapas finales de un traductor
  • M.C. Juan Carlos Olivares Rojas

Noviembre 2009
2
Agenda
  • Generador de código intermedio (opcional)
  • Optimizador (puede ser opcional e ir en esta
    etapa o hasta después de haber generado la
    traducción)
  • Generador de código objeto.

3
Generación de Código Intermedio
  • Etapas Finales de un Traductor

4
Agenda
  • Lenguajes intermedios.
  • Notaciones.
  • Infija.
  • Postfija.
  • Prefija.
  • Representación de código intermedio.
  • Notación Polaca.
  • Codigo P.
  • Triplos y Cuádruplos.

5
Agenda
  • Esquemas de generación.
  • Expresiones.
  • Declaración de variables, constantes
  • Estatuto de asignación.
  • Estatuto condicional.
  • Estatuto de ciclos
  • Arreglos.
  • Funciones.

6
Código Intermedio
  • Es una etapa opcional en muchos casos que ayuda a
    simplificar la producción de código objeto
  • La administración de la memoria se da en esta
    etapa.
  • Se debe considerar tanto la memoria estática como
    dinámica, y en esta se utilizan generalmente
    pilas.

7
Generador de Cod. Intermedio
  • Los lenguajes intermedios generalmente tienen
    árboles de derivación más pequeños que su
    contraparte original.
  • Se puede representar un árbol sintáctico con un
    Grafo Dirigido Acíclico (GDA).
  • La notación postfija es una manera linealizada de
    representar un árbol sintáctico.

8
Generador Cod. Intermedio
  • a b-cb-c
  • abc -bc -
  • x y op z
  • xyz
  • t1yz
  • t2xt1

9
Lenguajes intermedios
  • Los lenguajes intermedios nos sirven para
    representar la producción final de nuestro
    lenguaje fuente.
  • Existen muchos lenguajes intermedios, la mayoría
    de ellos son una representación más simplificada
    del código original para facilitar la traducción
    hacia el código final.

10
Lenguajes Intermedios
  • Otros lenguajes intermedios sirven de base o como
    representación parcial de otros procesos.
  • Por ejemplo al compilar un programa en C en
    Windows o DOS, se produce un código objeto con
    extensión .obj para que posteriormente el
    enlazador cree finalmente el código executable
    .exe

11
Lenguajes Intermedios
  • En sistemas basados en Unix, también ocurre algo
    similar generándose un archivo .o y el executable
    a.out
  • Otros lenguajes intermedios famosos son los
    generados para la máquina virtual de Java el
    bytecode y para la máquina virtual de .NET el
    MISL para luego ejecutarse en tiempo de ejecución
    JIT (Just in Time)

12
Lenguajes Intermedios
  • Otros lenguajes intermedios se utilizan en
    sistemas distribuidos como RPC, CORBA y su IDL,
    etc.
  • En este caso estos lenguajes intermedios se
    encargan de enmascarar toda la heterogeneidad de
    las comunicaciones distribuidas en una computadora

13
Notaciones
  • Las notaciones sirven de base para expresar
    sentencias bien definidas.
  • El uso más extendido de las notaciones sirve para
    expresar operaciones aritméticas.
  • Las expresiones aritméticas se pueden expresar de
    tres formas distintas infija, prefija y postfija.

14
Notaciones
  • La diversidad de notaciones corresponde en que
    para algunos casos es más sencillo un tipo de
    notación.
  • Las notaciones también dependen de cómo se
    recorrerá el árbol sintáctico, el cual puede ser
    en inorden, preorden o postorden teniendo una
    relación de uno a uno con la notación de los
    operadores.

15
Infija
  • La notación infija es la más utilizada por los
    humanos por que es la más comprensible ya que
    ponen el operador entre los dos operandos. Por
    ejemplo ab-5.
  • No existe una estructura simple para representar
    este tipo de notación en la computadora por esta
    razón se utilizan otras notaciones.

16
Postfija
  • La notación postfija pone el operador al final de
    los dos operandos, por lo que la expresión queda
    ab5-
  • La notación posftfija utiliza una estructura del
    tipo LIFO (Last In First Out) pila, la cual es la
    más utilizada para la implementación.

17
Prefija
  • La notación prefija pone el operador primero que
    los dos operandos, por lo que la expresión
    anterior queda ab-5.
  • Esto se representa con una estructura del tipo
    FIFO (First In First Out) o cola.
  • Las estructuras FIFO son ampliamente utilizadas
    pero tienen problemas con el anidamiento
    aritmético.

18
Representación Cod Int.
  • Existen maneras formales para representar código
    intermedio.
  • Estas notaciones simplifican la traducción de
    nuestro código fuente a nuestro código objeto ya
    que ahorran y acotan símbolos de la tabla de
    símbolos

19
Código P
  • El código P hace referencia a máquinas que
    utilizan o se auxilian de pilas para generar
    código objeto.
  • En muchos caso la P se asociado a código portable
    el cual garantiza que el código compilado en una
    máquina se pueda ejecutar en otras.

20
Código P
  • Para garantizar la portabilidad del código se
    necesita que el lenguaje este estandarizado por
    algún instituto y que dicho código no tenga
    extensiones particulares.
  • También se recomienda la no utilización de
    características especiales exclusivas de alguna
    arquitectura de computadoras en particular.

21
Triplos
  • Las proposiciones de tres direcciones se parece
    mucho al ensamblador, el cual es un lenguaje
    intermedio más entendible para la máquina.
  • Las estructuras de control (if, switch, while,
    do-while, for) son realmente etiquetas goto
    disfrazadas.

22
Triplos
  • El problema de utilizar cuádruplos radica en que
    se tienen que colocar los valores temporales en
    la tabla de símbolo.
  • Con una estructura de tres campos se pueden
    omitir los valores temporales, dicha estructura
    recibe el nombre de triples y tiene los
    siguientes campos op, arg1 y arg2

23
Triplos
  • Generalmente el código que generan los triples
    recibe el nombre de código de dos direcciones,
    aunque en ocasiones puede variar.
  • Cuando se utilizan triples se ocupan punteros a
    la misma estructura de los triples.
  • b t1 t2 //cuádruplos
  • b (0) //triple

24
Triplos
  • Se debe tener en cuenta el proceso de asignación,
    de declaración, expresiones booleanas.
  • Las expresiones lógicas también pueden pasarse a
    código de tres direcciones, utilizando para ello
    expresiones en corto circuito.

25
Triplos
  • La evaluación de expresiones en corto circuito
    implica que se evalúan condiciones revisando
    valores anteriores por ejemplo, para el operador
    AND con una condición que se detecte como falsa
    toda la expresión es falsa, en el caso del
    operador OR si se encuentra una condición
    verdadera todo será verdadera
  • Cómo resuelven los compiladores las expresiones?
    Forma Normal disyuntiva

26
Triplos
  • La notación de tres direcciones es una forma
    abstracta de código intermedio.
  • Esta notación se puede implementar como registros
    con campos para el operador y operadores.

27
Intérpretes
  • Los interpretes generalmente utilizan este
    triplos para generar el código intermedio para
    ejecutarse una vez considerado la instrucción
    como válido.
  • En este sentido, un compilador es más difícil de
    implementar ya que tendrá que mantener todas las
    estructuras generadas que en muchas ocasiones
    serán cuadruplos.

28
Cuadruplos
  • Es una estructura tipo registro con cuatros
    campos que se llaman op, arg1, arg2 y resultado.
    OP tiene un código intermedio.
  • Los operadores unarios como x-y no utilizan
    arg2. Generalmente arg1, arg2 y resultado son
    valores de tipo puntero y apuntan a una entrada
    en la tabla de símbolos.

29
Esquemas de Generación
  • Los esquemas de generación son las estrategias o
    acciones que se deberán realizarse y tomarse en
    cuenta en el momento de generar código
    intermedio.
  • Los esquemas de generación dependen de cada
    lenguaje. Tomaremos algunos esquemas de
    generación del lenguaje C.

30
Expresiones
  • Para generar expresiones estas deben
    representarse de manera más simple y más literal
    para que su conversión sea más rápida.
  • Por ejemplo la traducción de operaciones
    aritméticas debe especificarse una por una, de
    tal forma que una expresión sea lo más mínimo
    posible.

31
Declaración de variables
  • Las declaraciones de variables y constantes deben
    separarse de tal manera que queden las
    expresiones una por una de manera simple.
  • Por ejemplo int a,b,c se descompone a int a int
    b intc respectivamente.

32
Estatutos de Asignación
  • Las operaciones de asignación deben quedar
    expresadas por una expresión sencilla, si está es
    compleja se debe reducir hasta quedar un operador
    sencillo.
  • Por ejemplo x ab/5 debe quedar de la forma y
    b/5 z ay xz.

33
Estatuto Condicional
  • Las condiciones deben expresarse de manera lo más
    sencilla posible de tal forma que puedan
    evaluarse en cortocircuito. Por ejemplo una
    instrucción como if (a b f!5 f30) se
    evalúa primero x (ab f!5)y x f30
    if (y)
  • Las instrucciones de decisión compleja como
    switch se reducen a una versión complejas de ifs

34
Estatuto de Ciclos
  • Los ciclos se descomponen en un ciclo genérico,
    por lo que ciclos while, for y do- while tienen
    la misma representación interna. En el caso de C,
    todo queda en forma de while.
  • Las condiciones lógicas también pueden ser
    evaluadas en cortocircuito y reducidas.

35
Arreglos
  • Los arreglos se descomponen en estructuras
    básicas de manejo de manera simple, así por
    ejemplo char aHola se reduce a a0H
    a1o a2l a3a a4\0

36
Funciones
  • Las funciones pueden reducir a en línea, lo que
    se hace es expander el código original de la
    función.
  • Las funciones se descomponen simplificando los
    parámetros de manera individual al igual que el
    valor de retorno.

37
Optimización
  • Etapas Finales del Proceso de Traducción

38
Agenda
  • Tipos de optimización.
  • Locales.
  • Bucles.
  • Globales.
  • De mirilla.
  • Costos.
  • Costo de ejecución.
  • Criterios para mejorar el código.
  • Herramientas para el análisis del flujo de datos.

39
Tipos de Optimización
  • Las optimizaciones pueden realizarse de
    diferentes formas. Las optimizaciones se realizan
    en base al alcance ofrecido por el compilador.
  • La optimización va a depender del lenguaje de
    programación y es directamente proporcional al
    tiempo de compilación es decir, entre más
    optimización mayor tiempo de compilación.

40
Tipos de Optimización
  • Como el tiempo de optimización es gran consumidor
    de tiempo (dado que tiene que recorrer todo el
    árbol de posibles soluciones para el proceso de
    optimización) la optimización se deja hasta la
    fase de prueba final.
  • Algunos editores ofrecen una versión de
    depuración y otra de entrega o final.

41
Tipos de Optimización
  • La optimización es un proceso que tiene a
    minimizar o maximizar alguna variable de
    rendimiento, generalmente tiempo, espacio,
    procesador, etc.
  • Desafortunamente no existen optimizador que hagan
    un programa más rápido y que ocupe menor espacio.

42
Tipos de optimización
  • La optimización se realiza reestructurando el
    código de tal forma que el nuevo código generado
    tenga mayores beneficios.
  • La mayoría de los compiladores tienen una
    optimización baja, se necesita de compiladores
    especiales para realmente optimizar el código.

43
Optimización Local
  • La optimización local se realiza sobre módulos
    del programa. En la mayoría de las ocasiones a
    través de funciones, métodos, procedimientos,
    clases, etc.
  • La característica de las optimizaciones locales
    es que sólo se ven reflejados en dichas secciones.

44
Optimización Local
  • La optimización local sirve cuando un bloque de
    programa o sección es crítico por ejemplo la
    E/S, la concurrencia, la rapidez y confiabilidad
    de un conjunto de instrucciones.
  • Como el espacio de soluciones es más pequeño la
    optimización local es más rápida

45
Optimización de Ciclos
  • Los ciclos son una de las partes más esenciales
    en el rendimiento de un programa dado que
    realizan acciones repetitivas, y si dichas
    acciones están mal realizadas, el problema se
    hace N veces más grandes.
  • La mayoría de las optimizaciones sobre ciclos
    tratan de encontrar elementos que no deben
    repetirse en un ciclo.

46
Optimización de Ciclos
  • Sea el ejemplo
  • while(a b)
  • int c a
  • c 5
  • En este caso es mejor pasar el int c a fuera
    del ciclo de ser posible.

47
Optimización de ciclos
  • El problema de la optimización en ciclos y en
    general radica es que muy difícil saber el uso
    exacto de algunas instrucciones. Así que no todo
    código de proceso puede ser optimizado.
  • Otros uso de la optimización pueden ser el
    mejoramiento de consultas en SQL o en
    aplicaciones remotas (sockets, E/S, etc.)

48
Optimización Global
  • La optimización global se da con respecto a todo
    el código.
  • Este tipo de optimización es más lenta pero
    mejora el desempeño general de todo programa.
  • Las optimizaciones globales pueden depender de la
    arquitectura de la máquina.

49
Optimización Global
  • En algunos casos es mejor mantener variables
    globales para agilizar los procesos (el proceso
    de declarar variables y eliminarlas toma su
    tiempo) pero consume más memoria.
  • Algunas optimizaciones incluyen utilizar como
    variables registros del CPU, utilizar
    instrucciones en ensamblador.

50
Optimización de Mirilla
  • La optimización de mirilla trata de estructurar
    de manera eficiente el flujo del programa, sobre
    todo en instrucciones de bifurcación como son las
    decisiones, ciclos y saltos de rutinas.
  • La idea es tener los saltos lo más cerca de las
    llamadas, siendo el salto lo más pequeño posible

51
Costos
  • Los costos son el factor más importante a tomar
    en cuenta a la hora de optimizar ya que en
    ocasiones la mejora obtenida puede verse no
    reflejada en el programa final pero si ser
    perjudicial para el equipo de desarrollo.
  • La optimización de una pequeña mejora tal vez
    tenga una pequeña ganancia en tiempo o en espacio
    pero sale muy costosa en tiempo en generarla.

52
Costos
  • Pero en cambio si esa optimización se hace por
    ejemplo en un ciclo, la mejora obtenida puede ser
    N veces mayor por lo cual el costo se minimiza y
    es benéfico la mejora.
  • Por ejemplo for(int i0 i lt 10000 i) si la
    ganancia es de 30 ms 300s

53
Costos de Ejecución
  • Los costos de ejecución son aquellos que vienen
    implícitos al ejecutar el programa.
  • En algunos programas se tiene un mínimo para
    ejecutar el programa, por lo que el espacio y la
    velocidad del microprocesadores son elementos que
    se deben optimizar para tener un mercado
    potencial más amplio.

54
Costos de Ejecución
  • Las aplicaciones multimedia como los videojuegos
    tienen un costo de ejecución alto por lo cual la
    optimización de su desempeño es crítico, la gran
    mayoría de las veces requieren de procesadores
    rápidos (e.g. tarjetas de video) o de mucha
    memoria.
  • Otro tipo de aplicaciones que deben optimizarse
    son las aplicaciones para dispositivos móviles.

55
Costos de Ejecución
  • Los dispositivos móviles tiene recursos más
    limitados que un dispositivo de cómputo
    convencional razón por la cual, el mejor uso de
    memoria y otros recursos de hardware tiene mayor
    rendimiento.
  • En algunos casos es preferible tener la lógica
    del negocio más fuerte en otros dispositivos y
    hacer uso de arquitecturas descentralizadas como
    cliente/servidor o P2P.

56
Criterios Mejora de Software
  • La mejor manera de optimizar el código es hacer
    ver a los programadores que optimicen su código
    desde el inicio, el problema radica en que el
    costo podría ser muy grande ya que tendría que
    codificar más y/o hacer su código mas legible.
  • Los criterios de optimización siempre están
    definidos por el compilador

57
Criterios de Optimización
  • Muchos de estos criterios pueden modificarse con
    directivas del compilador desde el código o de
    manera externa.
  • Este proceso lo realizan algunas herramientas del
    sistema como los ofuscadores para código móvil y
    código para dispositivos móviles.

58
Htas. Análisis Flujo Datos
  • Existen algunas herramientas que permiten el
    análisis de los flujos de datos, entre ellas
    tenemos los depuradores y desambladores.
  • La optimización al igual que la programación es
    un arte y no se ha podido sistematizar del todo.

59
Generación de Código Objeto
  • Juan Carlos Olivares Rojas

60
Agenda
  • Lenguaje máquina.
  • Características.
  • Direccionamiento.
  • Lenguaje ensamblador.
  • Características.
  • Almacenamiento.
  • Registros.
  • Distribución.
  • Asignación.
  • Administración de memoria.

61
Lenguaje Máquina
  • El lenguaje máquina sólo es entendible por las
    computadoras. Se basa en una lógica binaria de 0
    y 1, generalmente implementada por mecanismos
    eléctricos.
  • En general el lenguaje máquina es difícil de
    entender para los humanos por este motivo hacemos
    uso de lenguajes más parecidos a los lenguajes
    naturales.

62
Características
  • El lenguaje máquina realiza un conjunto de
    operaciones predeterminadas llamadas
    microoperaciones.
  • Las microoperaciones sólo realizan operaciones
    del tipo aritmética (,-,, /), lógicas (AND, OR,
    NOT) y de control (secuencial, decisión,
    repetitiva)

63
Características
  • El lenguaje máquina es dependiente del tipo de
    arquitectura. Así un programa máquina para una
    arquitectura intel x86 no se ejecutará en una
    arquitectura Power PC de IBM (al menos de manera
    nativa).
  • Algunos microprocesadores implementan más
    funcionalidades llamado CISC, pero son más lentos
    que los RISC ya que estos tienen registros más
    grandes.

64
Direccionamiento
  • Es la forma en como se accede a la memoria.
    Recordar que un programa no puede ejecutarse sino
    se encuentra en memoria principal.
  • La forma de acceder a la memoria depende del
    microprocesador, pero en general existen dos
    tipos de direccionamiento directo e indirecto.

65
Direccionamiento
  • El direccionamiento directo también recibe el
    nombre de direccionamiento absoluto y el acceso a
    las direcciones se hace de manera directa.
  • El direccionamiento indirecto también recibe el
    nombre de direccionamiento relativo y se basa a
    partir de una dirección genérica, generalmente el
    inicio del programa.

66
Direccionamiento
  • Para acceder a una dirección relativa se suma a
    la dirección base el número de espacios de
    memorias necesarias.
  • El direccionamiento relativo hace a los programas
    relocalizables e independientes.
  • Si la dirección base es el inicio de la memoria
    fija el direccionamiento pasa a ser un variante
    de direccionamiento absoluto.

67
Lenguaje Ensamblador
  • El ensamblador (del inglés assembler) es un
    traductor de un código de bajo nivel a un código,
    ejecutable directamente por la máquina para la
    que se ha generado.
  • Fue la primera abstracción de un lenguaje de
    programación, posteriormente aparecieron los
    compiladores.

68
Características
  • El programa lee un archivo escrito en lenguaje
    ensamblador y sustituye cada uno de los códigos
    mnemotécnicos por su equivalente código máquina.
  • Los programas se hacen fácilmente portables de
    máquina a máquina y el cálculo de bifurcaciones
    se hace de manera fácil.

69
Ensambladores
  • Ensambladores básicos. Son de muy bajo nivel, y
    su tarea consiste básicamente en ofrecer nombres
    simbólicos a las distintas instrucciones,
    parámetros y cosas tales como los modos de
    direccionamiento.

70
Ensambladores
  • Ensambladores modulares, o macro ensambladores.
    Descendientes de los ensambladores básicos,
    fueron muy populares en las décadas de los 50 y
    los 60, antes de la generalización de los
    lenguajes de alto nivel. Una macroinstrucción es
    el equivalente a una función en un lenguaje de
    alto nivel.

71
Almacenamiento
  • Una de las principales ventajas del uso del
    ensamblador, es que se encarga de administrar de
    manera transparente para el usuario la creación
    de memoria, las bifurcaciones y el paso de
    parámetros. Además nos permite acceder
    directamente a los recursos de la máquina para un
    mejor desempeño.

72
Registros
  • Los registros son la memoria principal de la
    computadora. Existen diversos registros de
    propósito general y otros de uso exclusivo.
  • Algunos registros de propósito general son
    utilizados para cierto tipo de funciones.
    Existen registros acumuladores, puntero de
    instrucción, de pila, etc.

73
Distribución
  • La distribución es el proceso en el que el
    programa generado puede ejecutarse en otras
    máquinas.
  • Con respecto al ensamblador, la mayoría del
    direccionamiento se hace relativo para que el
    programa sea relocalizable por un programa
    llamado cargador

74
Distribución
  • En el caso de programas compilados se necesitan
    de las librerías, si son estáticas se incluyen en
    el ejecutable por lo que el programa se hace
    gráfico, si son dinámicas no pero el programa es
    más pequeño.
  • Debido a la complejidad del software actual se
    necesitan de asistentes para poder instalar y
    ejecutar un programa

75
Asignación
  • La asignación de valores a variables se hace a
    través de un proceso de mover el contenido de
    memoria a registro, o de registro a memoria, pero
    nunca de memoria a memoria.
  • Cuando se trata de memoria dinámica se debe
    seguir el rastro de los datos

76
Administración memoria
  • La administración de la memoria e sun proceso hoy
    en día muy importante, de tal modo que su mal o
    buen uso tiene una acción directa sobre el
    desempeño de memoria.
  • En general un ensamblador tiene un administrador
    de memoria más limitado que un compilador.

77
Administración de Memoria
  • En la mayoría de los lenguajes de programación el
    uso de punteros no estaba vigilado por lo que se
    tienen muchos problemas con el uso de memoria.
    Los lenguajes más recientes controlan el uso de
    punteros y tienen un programa denominado
    recolector de basura que se encarga de limpiar la
    memoria no utilizada mejorando el desempeño.

78
Referencias
  • Aho (2006), et. al. Compiladores Principios y
    Técnicas. Segunda Edición.

79
Preguntas?
Write a Comment
User Comments (0)
About PowerShow.com