You are on page 1of 18

FACULTAD

INGENIERIA

E.A.P.

INGENIERIA DE SISTEMAS

TEMA

TIPOS DE COMPILADORES

DOCENTE

MARIN RODRIGUEZ WILLIAM JOEL

ASIGNATURA

: TEORIA DE LENGUAJE Y COMPILADORES

CICLO

: VII

ALUMNO(A)

:MUOZ PUMARRUMI KENIA SENOFIA

HUACHO PER

2012

Pgina 1

INTRODUCCIN DE COMPILADOR

Los primeros compiladores se realizaron programndolos directamente en lenguaje mquina o en ensamblador. Una vez que se dispone de un compilador, se pueden escribir nuevas versiones del compilador (u otros compiladores distintos) en el lenguaje que compila ese compilador. Actualmente existen herramientas que facilitan la tarea de escribir compiladores intrpretes informticos. Estas herramientas permiten generar el esqueleto del analizador sintctico a partir de una definicin formal del lenguaje de partida, especificada normalmente mediante una gramtica formal y barata, dejando nicamente al programador del compilador la tarea de programar las acciones semnticas asociadas.

Pgina 2

DEDICATORIA Quiero dedicarle este trabajo A Dios que me ha dado la vida y fortaleza para terminar este trabajo de investigacin, A mis Padres por estar ah cuando ms los necesit; en especial a mi madre por su ayuda, constante cooperacin y a mi profesor por su enseanza que nos brinda cada semana.

Pgina 3

COMPILADOR

Qu es un compilador?
Un compilador es un pequeo programa informtico, que se encarga de traducir (compilar) el cdigo fuente de cualquier aplicacin que se est desarrollando. En pocas palabras, es un software que se encarga de traducir el programa hecho en lenguaje de programacin, a un lenguaje de mquina que pueda ser comprendido por el equipo y pueda ser procesado o ejecutado por este.

Pgina 4

Caractersticas de un compilador
Generalmente un compilador se divide en dos partes: * Front End: parte que analiza el cdigo fuente, comprueba su validez, genera el rbol de derivacin y rellena los valores de la tabla de smbolos. Parte que suele ser independiente de la plataforma o sistema operativo para el que funcionar. * Back End: parte en donde se genera el cdigo mquina exclusivo para una plataforma a partir de lo analizado en el front end. Por lo general el resultado del back end no puede ser ejecutado directamente, se necesita pasar por un proceso de enlazado (linker). Existen varios tipos de compiladores: Compiladores cruzados, Compiladores optimizadores, Compiladores de una sola pasada, Compiladores de varias pasadas, Compiladores JIT (Just In Time). Intrpretes vs compiladores Cualquier lenguaje puede ser ejecutado tanto va intrprete o va compilador, pero algunos lenguajes suelen asociarse ms a una va que a la otra, y por esto son llamados "lenguajes interpretados" o "lenguajes compilados" respectivamente. Tambin puede darse que un programa contenga partes que son implementadas va intrprete y otras va compilador. Existen intrpretes que incluyen cierta "compilacin" en el medio. Son aquellos que compilan a un cdigo intermedio llamado bytecode, que es ms eficiente de ejecutar que hacerlo directamente desde el cdigo fuente. Desventaja de los intrpretes la principal desventaja de los intrpretes, es que cuando un programa es interpretado, suele ejecutarse ms lento que si el mismo programa estuviese compilado. Esto se debe a que el intrprete debe analizar cada sentencia en el programa en cada ejecucin (un anlisis en tiempo real). Tambin el acceso a variables es ms lento en un intrprete, porque mapear los identificadores para almacenar las localizaciones debe hacerse repetidas veces en tiempo real. Tipos de compiladores Existen varios tipos de compiladores, los cuales se adecuan a los requerimientos de los programadores. Podemos destacar los compiladores cruzados, compiladores optimizadores, compiladores de una sola pasada y de varias pasadas, compiladores JIT y los conocidos intrpretes, que traducen el cdigo del programa en tiempo real. Cada uno de estos compiladores, se adecua a un lenguaje en especfico o a varios. Algunos son de cdigo abierto, otros son de licencia propietaria. La versatilidad de

Pgina 5

unos los hace mucho ms populares que otros, pero a grandes rasgos, el escoger un determinado compilador depender de los requerimientos de cada usuario. Importancia de los compiladores La importancia de los compiladores radica en que, sin estos programas no existira ninguna aplicacin informtica, ya que son la base de la programacin en cualquier plataforma. Tipos de compiladores Esta clasificacin de los tipos de compiladores no es excluyente, por lo que puede haber compiladores que se adscriban a varias categoras:

Compiladores cruzados: generan cdigo para un sistema distinto del que estn funcionando. Compiladores optimizadores: realizan cambios en el cdigo para mejorar su eficiencia, pero manteniendo la funcionalidad del programa original. Compiladores de una sola pasada: generan el cdigo mquina a partir de una nica lectura del cdigo fuente. Compiladores de varias pasadas: necesitan leer el cdigo fuente varias veces antes de poder producir el cdigo mquina. Compiladores JIT (J ust In Time): forman parte de un intrprete y compilan partes del cdigo segn se necesitan. Compiladores incrementales: generan un cdigo objeto instruccin por instruccin (en vez de hacerlo para todo el programa) cuando el usuario teclea cada orden individual. El otro tipo de compiladores requiere que todos los enunciados o instrucciones se compilen conjuntamente. Compilador con montador: compilador que compila distintos mdulos de forma independiente y despus es capaz de enlazarlos. Autocompilador: compilador que est escrito en el mismo lenguaje que va a compilar. Evidentemente, no se puede ejecutar la primera vez. Sirve para hacer ampliaciones al lenguaje, mejorar el cdigo generado, etc. Metacompilador: es sinnimo de compilador de compiladores y se refiere a un programa que recibe como entrada las especificaciones del lenguaje para el que se desea obtener un compilador y genera como salida el compilador para ese lenguaje. Descompilador: realiza el proceso inverso a la compilacin, es decir pasa de lenguaje objeto a fuente. HotSpot: herramienta que incluye un compilador dinmico y una mquina virtual para interpretar los ByteCodes.

Pgina 6

Caractersticas principales
1. Compiladores cruzados:

Un compilador cruzado (cross compiler ) es aquel que genera cdigo ejecutable para una plataforma diferente a aquella en la que se ejecuta. Esta herramienta es til cuando quiere compilarse cdigo para una plataforma a laque no se tiene acceso, o cuando es incmodo o imposible compilar en dicha plataforma (como en el caso de los sistemas empotrados). Ejemplo: supongamos que queremos desarrollar aplicaciones para un telfono mvil, una PDA o una consola de videojuegos. Normalmente ser ms cmodo realizar el desarrollo en un PC y luego volcar el cdigo objeto en el dispositivo de destino. En estas situaciones, el compilador que usaremos en el PC es un caso de compilador cruzado. El sistema operativo Nachos se ejecuta sobre una mquina virtual basada en el procesador MIPS. Los programas de usuario deben estar escritos en cdigo mquina del MIPS. Afortunadamente, no necesitas escribir los programas de usuario en cdigo mquina o en ensamblador, sino que lo puedes hacer en lenguaje C. El compilador cruzado que viene con la instalacin de Nachos es capaz de traducir de C a cdigo del MIPS. El compilador cruzado que se distribuye con el Nachos es una versin del popular compilador GCC. Funciona sobre prcticamente cualquier versin de Linux. El NASM, que puede ensamblar, entre otro formatos, ELF (para sistemas UNIX) y COM (para DOS). ElNetwide Assembler o NASM, es un ensamblador libre para la plataforma Intelx86. Puede ser usado para escribir programas tanto de 16 bits como de 32 bits (IA-32). En el NASM, si se usan las bibliotecas correctas, los programas de 32 bits se pueden escribir de una manera tal para que sean portables entre cualquier sistema
2. Compiladores JIT(Just In Time):

Un JIT es un generador de cdigo que convierte los bytecodes Java en cdigo nativo de la mquina. Los programas Java invocados con un JIT generalmente se ejecutan ms rpido que cuando se ejecutan en bytecodes por el intrprete. Un paso adelante en el rendimiento del cdigo Java lo han representado los Compiladores Just-In-Time, que compilan el cdigo convirtindolo a cdigo mquina antes de ejecutarlo. Es decir, un compilador JIT va trasladando los ByteCodes al cdigo mquina de la plataforma segn los va leyendo, realizando un cierto grado de optimizacin. El resultado es que cuando el programa se ejecute, habr partes que no se ejecuten y que no sern compiladas, y el compilador JIT no perder el tiempo en optimizar cdigo que nunca se va a ejecutar. No obstante, los compiladores JIT no pueden realizar demasiadas

Pgina 7

optimizaciones, ya que hay cdigo que ellos no ven, as que aunque siempre son capaces de optimizar la parte de cdigo de inicializacin de un programa, hay otras partes que deben ser optimizadas, segn se van cargando, con lo cual, hay una cierta cantidad de tiempo que inevitablemente ha de perderse. Cmo Funcionan los Compiladores JIT? Los compiladores JIT se suministran como libreras nativas dependientes de la plataforma. Si existe la librera del compilador JIT, la JVM inicializa el JNI (Java Native Interface) para llamar a las funciones JIT disponibles en la librera en lugar de su funcin equivalente del intrprete. Se usa la clase java. lang. Compiler Para cargar la librera nativa y empezar la inicializacin dentro del compilador JIT Cuando la JVM llama a un mtodo Java, usa un mtodo llamante como especificado en el bloque mtodo del objeto class cargado. El compilador JIT usa su propio llamante. Las versin de Sun chequea el bit de acceso al mtodo por un valor ACC_MACHINE_COMPILED para notificarle al intrprete que el cdigo de este mtodo ya est compilado y almacenado en las clases cargadas. Por ejemplo, si desea calentar su aplicacin y saber que los mtodos clave en su aplicacin se han compilado, se puede llamar al mtodo Compiler. disable () despus de haber calentado su aplicacin y estar seguros de que la compilacin JIT no se ocurrir durante el resto de la ejecucin de la aplicacin. Se puede controlar la compilacin mtodo de dos maneras:

Especificar un conjunto de mtodos que se pueden compilar: Compiler.command ("{} <metodo specification> (compilacin)"); Donde <metodo specification> es una lista de todos los mtodos que se han cargado en este momento y debe ser compilado. <metodo specification> describe un mtodo de nombre completo. El asterisco indica que un partido de comodn. Por ejemplo, Si usted quiere compilar todos los mtodos que comienzan con java.lang.String que se han cargado ya, deber indicar: Compiler.command ("{*} java.lang.String (compilacin)"); Nota: Este comando compila no slo mtodos de la clase java.lang.String, sino tambin en la clase java.lang.StringBuffer, que puede no ser lo que usted quera. Si quieres compilar slo los mtodos de la clase java.lang.String, se especifica:

Pgina 8

Compiler.command ("{java.lang.String *.} (Compilacin)");

Especifica que todos los mtodos de la cola de compilacin debe ser compilado antes de la ejecucin de este hilo sigue: Compiler.command ("waitOnCompilationQueue"); Es posible que desee asegurarse de que la cola de compilacin estaba vaca antes de inhabilitar el compilador. Una tcnica tpica para compilar un conjunto de Mtodos y clases podran ser:

Compiler.enable (); / / asegurar compilador est activo Compiler.command ("{com.mycompany *.} (Compilacin)"); / / queue de seguridad de todos los mtodos que desee compilar Compiler.command ("waitOnCompilationQueue"); / / esperar a que todos esos mtodos son compilados Compiler.disable (); / / girar el compilador de

3. Compiladores optimizadores: Realizan cambios en el cdigo para mejorar su eficiencia, pero manteniendo la funcionalidad del programa original. Este tipo de compiladores mejora la eficiencia del programa objeto en ocupacin de memoria o en tiempo de ejecucin, realiza modificaciones sobre el cdigo intermedio para mejorar la eficiencia en velocidad y tamao. Entre las funciones que realiza se puede citar: Eliminacin de saltos consecutivos Eliminar el clculo de expresiones cuyo valor no se usa. Fundir en uno solo el clculo repetido de la misma expresin. Sacar de los lazos las expresiones cuyo valor no cambia en el lazo. Reducir el uso de memoria local reutilizando el espacio de una variable muerta.

Pgina 9

Tipos de optimizaciones

Las tcnicas utilizadas en la optimizacin se pueden dividir entre varios mbitos que pueden afectar a cualquier cosa, desde una sola instruccin a todo el programa. En trminos generales, las tcnicas de mbito local son ms fciles de aplicar que las globales pero que resultan en menores ganancias. Algunos ejemplos de los mbitos siguientes:
a) Optimizaciones de mirilla

Generalmente se realiza al final del proceso de compilacin despus de cdigo de mquina se ha generado. Esta forma de optimizacin examina unas pocas instrucciones adyacentes (como "mira a travs de una mirilla" en el cdigo) para ver si se puede sustituir por una sola instruccin o una secuencia ms corta de instrucciones. Por ejemplo, una multiplicacin de un valor de 2 puede ser ejecutado de manera ms eficiente por la izquierda por desplazamiento el valor o sumando el valor de a s mismo. (Este ejemplo es tambin un ejemplo de la reduccin de resistencia .)
Optimizaciones locales

stos slo tienen en cuenta la informacin local a un bloque bsico . Dado que los bloques bsicos no tienen control de flujo, estas optimizaciones necesita un anlisis muy poco (para ahorrar tiempo y reducir los requisitos de almacenamiento), pero esto tambin significa que ninguna informacin se conserva a travs de saltos.
Optimizaciones globales

Estos tambin son llamados "mtodos intraprocedimiento" y actuar en funciones enteras. Esto les da ms informacin para trabajar, pero a menudo hace clculos costosos necesarios. Peores supuestos de caso tienen que hacerse cuando se producen las llamadas a funciones o variables globales son accesibles (porque poca informacin sobre ellos est disponible).
b) Optimizaciones de ciclo

Estos actan sobre los estados que forman un bucle, tal como un bucle (por ejemplo, bucle invariante en el movimiento de cdigo ). Optimizaciones de ciclo puede tener un impacto significativo ya que muchos programas pasan una gran parte de su tiempo dentro de bucles.

Pgina 10

Optimizacin interprocedural, de todo el programa o el enlace de

tiempo Estos analizar todo el cdigo fuente de un programa. La mayor cantidad de informacin extrada significa que las optimizaciones pueden ser ms eficaces en comparacin a cuando slo tienen acceso a la informacin local (es decir, dentro de una sola funcin). Este tipo de optimizacin tambin puede permitir que las nuevas tcnicas a realizar. Por ejemplo la funcin de procesos en lnea , donde una llamada a una funcin se sustituye por una copia del cuerpo de la funcin.
Mquina de optimizacin de cdigo

Estos analizar la imagen tarea ejecutable del programa despus de todo de un cdigo mquina ejecutable ha sido vinculado . Algunas de las tcnicas que se pueden aplicar en un alcance ms limitado, tales como la compresin de macro (que ahorra espacio por el colapso de secuencias comunes de instrucciones), son ms eficaces cuando la imagen ejecutable de la tarea completa est disponible para el anlisis. 4. Compiladores de una sola pasada: Generan el cdigo mquina a partir de una nica lectura del cdigo fuente, es decir examina el cdigo fuente una vez, generando el cdigo o programa objeto. Una aproximacin al manejo de las TS se presenta en la Figura 3, donde el anlisis lxico, sintctico, semntico y la generacin de cdigo se realizan en una pasada, es decir, se explora el texto fuente sentencia a sentencia (o bloques de sentencias) realizndose los tres anlisis y la generacin de cdigo. Ventajas del compilador de una pasada Fue fcil de implementar Generaba poca actividad de entrada/salida El cdigo de un procedimiento se compila en memoria y se escribe como una unidad a la memoria secundaria Desventajas Limitaciones en la calidad del cdigo generado Mucha necesidad de memoria

Pgina 11

Pgina 12

Ejemplo de Pascal

Un ejemplo de tal construccin es la declaracin de avance en Pascal . Pascal exige que los procedimientos se haya declarado o definido completamente antes de su uso. Esto ayuda a un compilador de una pasada con su tipo de cheques : llamar a un procedimiento que no ha sido declarada en cualquier parte es un claro error. Declaraciones adelantadas ayudar mutuamente recursivas procedimientos llamar directamente entre s, a pesar de la regla de declarar, antes de usar: function odd(n : integer ) : boolean ; begin if n = 0 then odd := false else if n < 0 then odd := even(n + 1) { Compiler error: 'even' is not defined } else odd := even(n - 1) end ; function even(n : integer ) : boolean ; begin if n = 0 then even := true else if n < 0 then even := odd(n + 1) else even := odd(n - 1) end ; Mediante la adicin de una declaracin de avance para la funcin even antes de la funcin odd , el compilador de una pasada se dijo que habr una definicin de even ms tarde en el programa. function even(n : integer ) : boolean ; forward ; function odd(n : integer ) : boolean ; { Et cetera } function even(n : integer ) : boolean ; forward ; function odd(n : integer ) : boolean ; { Et cetera } 5. Compiladores de varias pasadas: En un compilador de varias pasadas, tal como el de la Figura 4, la tabla de smbolos (TS) se crea durante el anlisis lxico y sintctico (pasada 1). En los compiladores modernos la TS se crea durante el primer recorrido del rbol AST, una vez creado ste mediante el analizador sintctico (pasada 2). Cuando un compilador comienza a traducir un programa fuente, la TS est vaca o contiene unas pocas entradas para las funciones incorporadas (las palabras reservadas habitualmente son almacenadas en una tabla aparte y usadas exclusivamente por el analizador lxico).El analizador lxico separa el programa fuente en tokens que compara con las palabras reservadas. Si el token comparado no es una palabra reservada se asume que es un identificador y durante el sintctico (fase sintctica) se aade a ella. Si el token comparado se encuentra en la TS, el analizador sintctico accede directamente al ndice que identifica a dicho identificador reconocido anteriormente, en caso contrario, el analizador sintctico introduce dicho smbolo en la TS. Segn avanza la compilacin, slo se aade una entrada para cada identificador nuevo, pero se explora la Tabla una vez por cada nueva aparicin de un identificador.

Pgina 13

6. Compiladores incrementales: Generan un cdigo objeto instruccin por instruccin (en vez de hacerlo para todo el programa) cuando el usuario teclea cada orden individual. El otro tipo de compiladores requiere que todos los enunciados o instrucciones se compilen conjuntamente. Es aquel que compila un programa en el que si despus se descubren errores, en vez de corregir el programa fuente y compilarlo por completo, se compilan solo las modificaciones. Lo ideal es que solo se recompilen aquellas partes que contenan los errores, y que el cdigo generado se reinserte con cuidado en el OBJ generado cuando se encontraron los errores. Sin embargo esto es muy difcil. En general puede hacer a muchos

Pgina 14

niveles, por ejemplo, si se nos olvida un ; se genera un OBJ transitorio. Si se pone el ; que falta y se recompila, un compilador incremental puede funcionar a varios niveles: A nivel de carcter: Se recompila el ; A nivel de sentencia: Si el ; faltaba en la lnea 100 slo se compila la lnea100. A nivel de bloque: Si el ; faltaba en un procedimiento o bloque solo se compila ese bloque. A nivel de Fichero: Si tenemos 15 ficheros y solo se modifica 1(al que le faltaba el ;), compilo ese fichero y luego se enlazan todos juntos. Lo ideal es que se hiciese a nivel de instruccin, pero lo normal es encontrarlo a nivel de fichero. 7. Autocompilador: Compilador que est escrito en el mismo lenguaje que va a compilar. Evidentemente, no se puede ejecutar la primera vez. Sirve para hacer ampliaciones al lenguaje, mejorar el cdigo generado, etc. Cuando se extiende entre muchas mquinas diferentes el uso de un compilador, y ste se desea mejorar, el nuevo compilador se escribe con el antiguo, de manera que pueda ser compilado por todas esas mquinas diferentes, y d como resultado un compilador ms potente de ese mismo lenguaje. 8. Metacompilador: Es un compilador de compiladores y se refiere a un programa que recibe como entrada las especificaciones del lenguaje para el que se desea obtener un compilador y genera como salida el compilador para ese lenguaje Un metacompilador o generador de parsers es una herramienta que, a partir de la especificacin de un lenguaje, construye un programa o analizador que es capaz de reconocer secuencias o elementos de dicho lenguaje. En general, la especificacin del lenguaje abarca tanto el aspecto lxico como el sintctico, y son los que permiten la construccin del parser, mientras que el aspecto semntico del lenguaje se deja en manos del usuario, para que lo ensamble una vez obtenido el parser. El desarrollo de los metacompiladores se encuentra con la dificultad de unir la generacin de cdigo con la parte de anlisis. Lo que s se han desarrollado son generadores de analizadores lxicos y sintcticos. Por ejemplo, los conocidos: LEX: generador de analizadores lxicos YACC: generador de analizadores sintcticos, desarrollados para UNIX. Los inconvenientes que tienen son que los analizadores que generan no son muy eficientes.

Pgina 15

9. Descompilador: Pasa de un cdigo mquina (o programa de salida) al lenguaje que lo gener (programa fuente). Cada descompilador trabaja con un lenguaje de alto nivel concreto. Es una operacin casi imposible, porque al cdigo mquina casi siempre se le aplica una optimizacin. Por eso lo que hay suelen ser desensambladores, ya que existe una biseccin entre cada instruccin mquina y cada instruccin ensamblador. Se utilizan especialmente cuando el cdigo mquina ha sido generado con opciones de depuracin, y contiene informacin adicional de ayuda a la depuracin de errores (puntos de ruptura, opciones de visualizacin de variables, etc.). Tambin se emplea cuando el compilador original no gener cdigo mquina puro, sino pseudocdigo (para ejecutarlo a travs de un pseudointrprete). Algunas de las caractersticas que debe buscar en el programa descompilado: Todas las variables se declaran en la parte superior del programa, incluso indicadores. El cdigo fuente generado las siguientes prcticas estndar de sangra. Algunas caractersticas, como AutoPage y definiciones de nombres, se pierden en el tiempo de compilacin. El cdigo original usado START: como una etiqueta, mientras que el cdigo descompilado utilizado CL6: como una etiqueta. Los nombres de etiquetas se pierden en el tiempo de compilacin. El programa original utiliza un comando goto para saltar al principio: etiqueta, mientras que el programa descompilado rodea el bloque con una estructura de repeticin / loop. Esta es slo una manera de que el cdigo descompilado es mayor que el cdigo original. La compilacin del programa descompilado va a generar un programa que an funcionalmente idntico al programa original. Etiquetas Keyproc se conservan. Indicadores predefinidos y variables del sistema, como ERR y encontr, se mantienen en el programa descompilado. El margen de la izquierda del cdigo descompilado comienza en la columna 22. Esto deja espacio para rtulos e indicadores sobre la lnea. Este mtodo de formato hace que sea ms fcil de leer grandes programas descompilacin.

Pgina 16

10. HotSpot: La ltima tendencia en lo que a compilacin e intrpretes se refiere. Lo ltimo en que trabaja un es HotSpot, una herramienta que incluye un compilador dinmico y una mquina virtual para interpretar los ByteCodes, tal como se muestra en la figura siguiente, situada a la izquierda de la pgina. Cuando se cargan los ByteCodes producidos por el compilador por primera vez, stos son interpretados en la mquina virtual. Cuando ya estn en ejecucin, el profiler Mantiene informacin sobre el rendimiento y selecciona el mtodo sobre el que se va a realizar la compilacin. Los mtodos ya compilados se almacenan en un cach en cdigo mquina nativo. Cuando un mtodo es invocado, esta versin en cdigo mquina nativo es la que se utiliza, en caso de que exista; en caso contrario, los ByteCodes son reinterpretados. La funcin control que muestra el diagrama es como un salto indirecto a travs de la memoria que apunta tanto al cdigo mquina como al interpretado, aunque Sun no ha proporcionado muchos detalles sobre este extremo.

Pgina 17

BIBLIOGRAFIA

http://translate.google.com.pe/translate?hl=es&langpair=en|es&u=http://en.wikip edia.org/wiki/Compiler_optimization http://translate.google.com.pe/translate?hl=es&langpair=en|es&u=http://en.wikip edia.org/wiki/Compiler_optimization http://translate.google.com.pe/translate?hl=es&langpair=en|es&u=http://en.wikip edia.org/wiki/One-pass_compiler http://wiki.answers.com/Q/Difference_between_single_pass_compiler_ http://livedocs.adobe.com/flex/3/html/compilers_20.html http://www.decompile.com/dataflex/decompiler/source.htm http://javarevisited.blogspot.com/2011/11/hotspot-jvm-options-java-exam http://wiki.answers.com/Q/Difference_between_single_pass_compiler_and_multi_ pass_compiler#ixzz28bo5n2Vb http://javarevisited.blogspot.com/2011/11/hotspot-jvm-options-javaexamples.html#ixzz28bsoClbL

Pgina 18

You might also like