análisis semantico

Upload: miriam

Post on 08-Jan-2016

248 views

Category:

Documents


0 download

DESCRIPTION

La fase de análisis semántico obtiene su nombre por requerir información relativa al significado del lenguaje, que está fuera del alcance de la representativo de las gramáticas libres de contexto y los principales algoritmos existentes de análisis; es por ello por lo que se dice que captura la parte de la fase de análisis considerada fuera del ámbito de la sintaxis.

TRANSCRIPT

Tabla de Smbolos y Anlisis Semntico de Java y GCC

Grupo 10Tabla de Smbolos y Anlisis Semntico de Java y GCC200320831 Edwin Alexander Juan Vallejos2004-12874Julio Enrique Vivas Castillo

Introduccin

La fase de anlisis semntico obtiene su nombre por requerir informacin relativa al significado del lenguaje, que est fuera del alcance de la representatividad de las gramticas libres de contexto y los principales algoritmos existentes de anlisis; es por ello por lo que se dice que captura la parte de la fase de anlisis considerada fuera del mbito de la sintaxis.

As, la mayora de los compiladores utilizan una gramtica libre de contexto para describir la sintaxis del lenguaje y una fase de anlisis semntico posterior para restringir las sentencias que semnticamente no pertenecen al lenguaje.

1.2 Objetivos de la Tabla de Smbolos (TS)

Las Tablas de Smbolos (en adelante TS) son estructuras de datos que almacenan toda la informacin de los identificadores del lenguaje fuente.

Las misiones principales de la TS en el proceso de traduccin son:

Colaborar con las comprobaciones semnticas.

Facilitar ayuda a la generacin de cdigo.

La informacin almacenada en la TS depende directamente del tipo de elementos del lenguaje especfico a procesar y de las caractersticas de dicho lenguaje. Habitualmente los elementos del lenguaje que requieren el uso de la TS son los distintos tipos de identificadores del lenguaje (nombres de variables, de objetos, de funciones, de etiquetas, de clases, de mtodos, etc.).

La informacin relativa a un elemento del lenguaje se almacena en los denominados atributos de dicho elemento. Estos atributos tambin varan de un tipo de lenguaje a otro y de un elemento a otro. As ejemplos de atributos tales como nombre, tipo, direccin relativa en tiempo de ejecucin, dimensiones de los arrays, nmero y tipo de los parmetros de procedimientos, funciones y mtodos, tipos de acceso a los elementos de una clase (public, private, protected), etc. se recogen y se guardan en la TS.

Los atributos se obtienen unas veces directamente del anlisis del programa fuente, es decir, estn en forma explcita (por ejemplo en la seccin de declaraciones del programa fuente) y otras veces los atributos se obtienen de forma implcita a travs del contexto en el que aparece el elemento en el programa fuente.

En el proceso de compilacin se accede a la TS en unos determinados puntos que dependen inicialmente del nmero y la naturaleza de las pasadas del procesador de lenguaje y del propio lenguaje fuente a procesar.

En los traductores y compiladores, las TS existen nicamente en tiempo de compilacin, aunque en depuracin (debug) pueden estar almacenadas en disco y dar informacin en tiempo de ejecucin para identificar los smbolos que se deseen inspeccionar.

En los intrpretes contienen informacin en tiempo de ejecucin.

Las palabras reservadas no estn en la TS.

2 Contenidos de la TS

Una TS se puede definir como una estructura de datos organizada en funcin de los identificadores que aparecen en el programa fuente.

Aunque su nombre parece indicar una estructuracin en una tabla no es necesariamente sta la nica estructura de datos utilizada, tambin se emplean rboles, pilas, etc.

Lo que la estructura debe permitir es establecer un homomorfismo entre los mbitos de utilizacin de los smbolos en el programa fuente y el modo en que aparecen en las sucesivas bsquedas en la tabla. Para ello debe manejar diferentes contextos de bsqueda que imiten los diferentes tipos de bloques del lenguaje fuente que se compila.

Los smbolos se guardan en la tabla con su nombre y una serie de atributos opcionales que dependern del lenguaje y de los objetivos del procesador. Este conjunto de atributos almacenados en la TS para un smbolo determinado se define como registro de la tabla de smbolos (symbol-table record). Una forma de organizacin simple es imaginar la TS como una tabla con una serie de filas, cada fila contiene una lista de atributos que estn asociados a un identificador.

Las clases de atributos que aparecen en una TS dependen de la naturaleza del lenguaje de programacin para el cual est escrito el compilador. Por ejemplo, un lenguaje de programacin puede no tener tipos, entonces el atributo tipo no necesita aparecer en la tabla. Operaciones con la TS

Las dos operaciones que se llevan a cabo generalmente en las TS son las insercin y la bsqueda. La forma en que se realizan estas dos operaciones difiere levemente segn que las declaraciones del lenguaje a compilar sean explcitas o implcitas.

Otras operaciones son activar (set) y desactivar (reset) las tablas de los identificadores locales o automticos.

Lenguajes con declaraciones explcitas obligatorias

Las dos operaciones se realizan en puntos concretos del compilador. Es obvio que la operacin de insercin se realiza cuando se procesa una declaracin, ya que una declaracin es un descriptor inicial de los atributos de un identificador del programa fuente.

Si la TS est ordenada, es decir los nombres de las variables estn por orden alfabtico, entonces la operacin de insercin llama a un procedimiento de bsqueda para encontrar el lugar donde colocar los atributos del identificador a insertar. En tales casos la insercin lleva tanto tiempo como la bsqueda.

Si la TS no est ordenada, la operacin de insercin se simplifica mucho, aunque tambin se necesita un procedimiento de colocacin. Sin embargo la operacin de bsqueda se complica ya que debe examinar toda la tabla.

La operacin de bsqueda se lleva a cabo en todas las referencias de los identificadores, excepto en su declaracin. La informacin que se busca (por ejemplo: tipo, direccin en tiempo de ejecucin, etc.) se usa en la verificacin semntica y en la generacin de cdigo.

En las operaciones de bsqueda se detectan los identificadores que no han sido declarados previamente emitindose el mensaje de error correspondiente. En las operaciones de insercin se detectan los identificadores que ya han sido previamente declarados, emitindose, a su vez, el correspondiente mensaje de error.

3.1.2 Lenguajes con declaraciones implcitas de los

identificadores

Las operaciones insercin y bsqueda estn estrechamente unidas. Cualquier identificador que aparezca en el texto fuente deber ser tratado como una referencia inicial, ya que no hay manera de saber a priori si los atributos del identificador ya han sido almacenados en la TS.

As, cualquier identificador que aparezca en el texto fuente llama al procedimiento de bsqueda, que a su vez, llamar al procedimiento de insercin si el nombre del identificador no se encuentra en la TS. Todos los atributos asociados con un identificador declarado implcitamente se deducen del papel desempeado por el identificador en el programa.

Representacin OO de smbolos y tipos en compiladores

En los sistemas orientados a objetos aparecen nuevos problemas a la hora de implementar la tabla de smbolos que se estudian en los siguientes apartados.

En estos momentos hay dos lenguajes implicados que pueden ser orientados a objetos: el lenguaje a compilar y el lenguaje de implementacin del compilador, en este caso el lenguaje de implementacin de la propia tabla de smbolos (ver Figura 4-23).

A continuacin se considera que el lenguaje de implementacin es orientado a objetos, esto proporciona beneficios de implementacin de la TS. Todo lo estudiado en este apartado es aplicable para el caso de lenguajes fuente estructurados (tambin orientados a objetos). Queda fuera del alcance de este documento las TS de lenguajes OO implementados en lenguajes estructurados convencionales.

La doble jerarqua smbolo-tipo

Cuando estamos compilando un lenguaje orientado a objetos (OO), el esquema de tabla de smbolos debe representar en cierto modo el modelo del lenguaje fuente. En un esquema orientado a objetos tenemos una doble jerarqua:

Smbolos, que son todos aquellos identificadores que representan variables locales, atributos, campos de un registro, parmetros de un mtodo, etc.

Tipos, que son todos los identificadores que representan tipos del lenguaje, entendidos aqu los tipos en un sentido amplio, esto es comprendiendo clases cuando se habla de lenguajes OO. (Ver [ORTIN04])

No es objetivo definir aqu lo que es un tipo y simplemente nos quedamos con el concepto de que en OO un tipo determina el tipo de mensajes que puede admitir un smbolo. Cuando dos smbolos son el mismo tipo se entiende que admite exactamente los mismos mensajes.

As pues el esquema de la tabla de smbolos consta de dos tablas:

Tabla de smbolos, que sirve para guardar una referencia a todos los smbolos que pueden ser accedidos desde el entorno actual.

Tabla de tipos, que es la que guarda la estructura de tipos definida en el programa fuente: las clases, las interfaces, los tipos bsicos, etc.

La jerarqua de smbolos

La jerarqua de smbolos describe todos los posibles smbolos que pueden aparecer en el cdigo fuente.

A partir de la tabla de smbolos se accede a estos smbolos (representado aqu por una agregacin, pero que en general ser una acceso algo ms complejo). Cada smbolo tiene tipo y debe poderse acceder a dicho tipo a travs del smbolo.

El mtodo de acceso puede ser representado como en este caso por una agregacin o tambin podra estar representado por una relacin cualificada por una cadena que identificara el nombre del smbolo. Este tipo de representacin puede ser implementada por medio de una tabla de acceso hash, de manera que, como en un diccionario, se localizase la entrada del smbolo por su nombre.

Este tipo de implementacin est recogida en la mayor parte de las bibliotecas de contenedores de los lenguajes orientados a objetos, map, hashmap, hashtable, etc. son algunos de los nombres habituales que recibe este tipo de contenedor dependiendo de los leguajes de implementacin.

SymbolTable + insert() : void + search() : Symbol + set() : void + reset() : void name Symbol - name: string - address: string Type +has type + getType() : + getName() : string + getAddress() : string LocalVar Field Atribute + getType() : + getName() : string + getType() : Type + getType() : + getName() : string + getAddress() : string + getName() : string + getAddress() : string + getAddress() : string Property Parameter + getType() : + getName() : string + getAddress() : string + getType() : Type + getName() : string + getAddress() : string Figura 4-26. Jerarqua de smbolos Obsrvese que en la Figura 4-26 se ha hecho un esquema muy genrico de tabla de smbolos que prev que cada uno de los posibles smbolos tenga un comportamiento y unas responsabilidades diferentes.

SymbolTable + insert() : void + search() : Symbol + set() : void + reset() : void name GenericSymbol Type - name: string - address: string +has type + getName() : string + getType() : Type + getAddress() : string Figura 4-27. Versin simplificada de la jerarqua de smbolos

La jerarqua de tipos

En paralelo a la jerarqua de smbolos tenemos una jerarqua de tipos donde pueden estar todos los tipos bsicos del lenguaje y los tipos definidos por el usuario (con typedef, clases, etc.).

Un esquema bastante general se puede ver en la Figura 4-28.

En este caso se tiene una tabla de tipos (TypeTable) que tiene guardados todos los tipos que aparecen durante la compilacin del cdigo fuente.

Al comenzar dicha compilacin estarn nicamente los tipos bsicos del sistema (los BuiltinType). En el momento en que el cdigo comienza a describir clases, arrays, mtodos, interfaces, etc. Va creando los nuevos tipos y metindolos en la tabla.

Hay que hacer notar que la clase BuiltinType representa a cada uno de los tipos bsicos.

TypeTable SymbolTable + insert() : void + search() : Type name name Type +has type Symbol +field +atribute +implements * BuiltInTypeArrayTypeClassTypeInterfaeTypeFunctionTypeRecordType PointerType +extends * +extends * * * name name name position +typename +type +contains +contains+method +contains +contains +method +return value +contains Atributes Atributes - access: int - access: int - static: boolean - static: boolean + getAccess() : int + getStatic() : boolean + getAccess() : int + getStatic() : boolean Figura 4-28. Jerarqua y tabla de tipos

Funcionamiento y acceso a la tabla de smbolos

Sea un lenguaje que tiene los tipos bsicos void, int y double y una estructura en clases similar al Java sin interfaces y con herencia simple.

Se trata de hacer un compilador de este tipo de cdigo y, en este caso, hacer la tabla de smbolos de dicho compilador y demostrar que es suficiente para todo el proceso de compilacin.

A partir de un cdigo se ir siguiendo toda la formacin de la tabla de smbolos y se podr comprobar cmo funciona el modelo.

Ejemplo:Sea el siguiente cdigo de ejemplo de un lenguaje sencillo que slo permite dos tipos bsicos (int y double) y un cdigo principal en que se pueden hacer lecturas, escrituras y expresiones:

1: int i;

2: float f;

3: main ()

4: {

5: int f;

6: read f;

7: i = f;

8: write i + 2;

9: }

Figura 4-42. AST del cdigo de ejemplo

Figura 4-45. Insertar una declaracin y referenciar un identificador

Figura 4-46. Estructura AST-TS resultante una vez terminada la visita de identificacin

Figura 4-48. rbol AST decorado resultante de la primera pasada del visitor

Representacin intermedia RTL

La mayor parte del trabajo realizado por el compilador se lleva a cabo sobre una representacin intermedia llamada lenguaje de transferencia de registros. En este lenguaje, las instrucciones que van a la salida se describen, una a una, en una forma algebraica que describe lo que la instruccin realiza.RTL est inspirado en las listas de Lisp. Este tiene una forma interna, hecha de estructuras que apuntan a otras estructuras y una forma textual que es utilizada para la descripcin de la mquina y las salidas de impresin al momento de depurar un programa. La forma textual usa parntesis anidados para indicar los apuntadores a la forma interna.

RTL para expresiones aritmticasA menos que se especifique lo contrario, todas las expresiones aritmticas deben ser vlidas para el modo m. Un operando es vlido para un modo m si tiene un modo m, o si es un const_int o const_double y m es un modo de la clase MODE_INT.

(plus:m x y)(ss_plus:m x y)(us_plus:m x y)

Estas tres expresiones, todas representan la suma de valores representados por x y y operados en el modo m. Difieren en si aceptan la operacin con o sin signo.

(minus:m x y)(ss_minus:m x y)(us_minus:m x y)

Estas operaciones representan la resta de y a x, operadas en el modo m. Similar a la adicin anterior. Manejo de la tabla de smbolosCuando cpplib encuentra un identificador, genera un cdigo hash para ste y lo guarda en la tabla hash. Por identificador nos referimos a tokens del tipo CPP_NAME; esto incluye identificadores en el sentido usual de C, adems palabras reservadas, nombres de directivas, nombre de macros y as sucesivamente. Por ejemplo, pragma, int, foo y __GNUC__ son todos identificadores y se les calcula el cdigo hash al momento de ser analizados lxicamente.Cada nodo en la tabla hash contiene informacin varia sobre el identificador que representa. Por ejemplo, su longitud y tipo. En cualquier momento, cada identificador cae en exactamente una de las tres categoras:MacrosEstos han sido declarados como macros, ya sea por medio de la lnea de comandos o por medio de #define. Unos pocos, tales como __TIME__ son parte del compilador (built-in) e ingresados en la tabla hash durante la inicializacin. El nodo hash para un macro normal apunta a una estructura con ms informacin acerca del macro, tal como, si es de tipo funcin, cuantos argumentos toma, y su expansin. Los macros que son parte del compilador estn marcados como especiales, y a cambio contienen una enumeracin indicando de los macros built-in es.Aserciones (asserts)Las Aserciones o afirmaciones se encuentran en un espacio de nombres separado al de los macros. Para asegurar esto, cpp de hecho agrega un caracter # antes de hacer el hash y meterlo en la tabla hash. Un nodo de asercin apunta a una cadena de respuestas a la asercin.VoidCualquier otro identificador cae en esta categora un identificador que no es un macro, o un macro que desde entonces ha sido indefinido con #undef. Cuando se preprocesa C++, esta categora tambin incluye operadores con nombre (named operadors) tal como xor. En las expresiones estos se comportan como los operadores que representan, pero en contextos donde la estructura del token es importante se escriben de forma diferente. Esta distincin en la forma de escribirlos es relevante cuando son operandos los operadores macro # y ##. Los nodos hash para los operadores con nombre estn marcados (flagged), ambos para poder distinguir la forma de escritura (spelling) y para prevenir que stos sean definidos como macros.

Los identificadores iguales comparten el mismo nodo hash. Desde que cada token identificador, despus del anlisis lxico, contiene un puntero a su nodo hash, ste es usado para proveer una consulta rpida de informacin diversa. Por ejemplo, cuando se analiza sintcticamente una sentencia #define, CPP marca cada nodo hash del identificador de argumento con el ndice de ese argumento. Esto duplica la validacin de argumentos en una operacin O(1) para cada argumento. De forma similar, para cada identificador en la expansin del macro, se busca en la estructura para saber si es un argumento, y que argumento es, tambin es una operacin O(1). Adems, cada nombre de directiva, tal con endif, tiene una enumeracin de directiva asociada almacenada en su nodo hash, as que la bsqueda de la directiva tambin es una operacin O(1).Examinando la tabla de smbolosLos ejecutables pueden contener una tabla de smbolos. Esta tabla guarda la localizacin de funciones y variables por nombre, y puede ser mostrada con la ayuda del comando nm:$ nm a.out 08049f20 d _DYNAMIC 08049ff4 d _GLOBAL_OFFSET_TABLE_ 080484cc R _IO_stdin_used w _Jv_RegisterClasses 08049f10 d __CTOR_END__ 08049f0c d __CTOR_LIST__ 08049f18 D __DTOR_END__ 08049f14 d __DTOR_LIST__ 080484d8 r __FRAME_END__ 08049f1c d __JCR_END__ 08049f1c d __JCR_LIST__ 0804a014 A __bss_start 0804a00c D __data_start 08048480 t __do_global_ctors_aux 08048340 t __do_global_dtors_aux 0804a010 D __dso_handle w __gmon_start__ 0804847a T __i686.get_pc_thunk.bx 08049f0c d __init_array_end 08049f0c d __init_array_start 08048410 T __libc_csu_fini 08048420 T __libc_csu_init U __libc_start_main@@GLIBC_2.0 0804a014 A _edata 0804a01c A _end 080484ac T _fini 080484c8 R _fp_hw 08048298 T _init 08048310 T _start 0804a014 b completed.6625 0804a00c W data_start 0804a018 b dtor_idx.6627 080483a0 t frame_dummy 080483c4 T main U printf@@GLIBC_2.0

Entre los contenidos de la tabla de smbolos, la salida muestra que el inicio de la funcin main tiene el offset 080483c4. La mayora de smbolos son para uso interno por el compilador y el sistema operativo. Una letra T en la segunda columna indica una funcin que est definida en el archivo objeto, mientras que una U indica que una funcin est indefinida (y debera ser resuelta por medio de enlace contra otro archivo objeto.) El uso frecuente para el comando nm es verificar que una librera contiene la definicin de una funcin especfica, verificando que aparezca una T en la segunda columna seguido del nombre de la funcin.Optimizacin de cdigo con GCCGCC es un compilador de optimizacin. Provee de un amplio rango de opciones que intentan incrementar la velocidad, o reducir el tamao, de los archivos ejecutables que genera.La optimizacin es un proceso complejo. Para cada comando de alto nivel en el cdigo fuente generalmente existen muchas combinaciones de instrucciones de mquina que pueden ser utilizadas para lograr el resultado final apropiado. El compilador debe considerar estas posibilidades y escoger entre ellas.En general, cdigo diferente debe ser generado para diferentes procesadores, desde que casi cada uno utiliza lenguajes de ensamblador y mquina incompatibles. Cada tipo de procesador tambin tiene sus propias caractersticas, por ejemplo, algunos CPU's proveen un nmero de registros ms grande para almacenar resultados intermedios de clculos, mientras que otros deben almacenar y recuperar resultados intermedios de la memoria. El cdigo apropiado debe ser generado en cada caso.Adems, diferentes cantidades de tiempo se requieren para diferentes instrucciones, dependiendo de como sean ordenadas. GCC toma en cuenta todos estos factores en cuenta y trata de producir el ejecutable ms rpido para un sistema dado cuando se compila con optimizacin.Optimizacin a nivel de cdigoLa primer forma de optimizacin de cdigo usada por GCC ocurre a nivel de cdigo fuente, y no requiere conocimiento alguno sobre las instrucciones de mquina. Hay muchas tcnicas sobre optimizacin a nivel de cdigo fuente pero trataremos las ms comunes: eliminacin de subexpresiones comunes y funciones en-lnea.Eliminacin de subexpresiones comunesUno de los mtodos de optimizacin a nivel de cdigo que es fcil de entender envuelve el computo de una expresin en el cdigo fuente con pocas instrucciones, a modo de reutilizar resultados previamente calculados. Por ejemplo, la siguiente asignacin:x = cos(v)*(1+sin(u/2)) + sin(w)*(1-sin(u/2))puede ser reescrita con una variable t para eliminar una evaluacin extra el trmino sin(u/2)

t = sin(u/2)x = cos(v)*(1+t) + sin(w)*(1-t)Esta forma de reescritura es llamada eliminacin de subexpresiones comunes (o common subexpression elimination, CSE) y es realizada automticamente cuando la optimizacin est habilitada. La eliminacin de subexpresiones comunes es poderosa, porque puede simultneamente incrementar la velocidad y reducir el tamao del cdigo.Funciones en-lnea

Otro tipo de optimizacin a nivel de cdigo es el llamado reemplazo de funciones en-lnea, el cual incrementa la eficiencia de funciones llamadas frecuentemente.Ya sea que una funcin es usada, cierta cantidad de tiempo extra es requerido para que el CPU pueda realizar la llamada: ste debe almacenar los argumentos de la funcin en los registros apropiados y localidades de memoria, saltar al inicio de la funcin, comenzar a ejecutar el cdigo, en entonces retornar al punto original de ejecucin cuando la llamada a la funcin est completa. Este trabajo adicional se conoce como gasto de llamada a funcin (o, function-call overhead). Este tipo de optimizacin elimina este gasto adicional al reemplazar llamadas a auna funcin por el cdigo de la funcin en s (tambin conocido como, colocar el cdigo en-lnea.)En muchos casos, el costo de llamar a una funcin es una parte considerable del tiempo total de ejecucin de un programa. Puede volverse significativo solo cuando hay funciones que contienen un nmero relativamente bajo de instrucciones, y estas funciones cuentan por una fraccin sustancial del tiempo de ejecucin, en este caso el costo se vuelve una gran proporcin del tiempo total de ejecucin.Poner en lnea siempre es favorable si hay un solo punto de invocacin de una funcin. Tambin es incondicionalmente mejor si la invocacin de una funcin requiere ms instrucciones (memoria) que mover el cuerpo de la funcin en-lnea. Esta optimizacin tambin pude facilitar optimizaciones ms precisas, tales como eliminacin de subexpresiones comunes, por medio de la unin de varias funciones separadas en una funcin ms grande.La siguiente funcin sq(x) es un ejemplo tpico de una funcin que podra beneficiarse de la optimizacin en-lnea. sta computa x^2, el cuadrado de su argumento x:

double sq (double x){ return x * x;}Esta funcin es pequea, as que el costo de llamarla es comparable con el tiempo que toma ejecutar una multiplicacin sencilla calculada por la misma funcin. Si esta funcin s usada dentro de un bucle, tal como el que aparece a continuacin, entonces la llamada a funcin podra volverse substancial:for (i = 0; i < 1000000; i++) { sum += sq (i + 0.5); }Utilizando este tipo de optimizacin reemplaza el cuerpo del bucle con el cuerpo de la funcin, resultando en el siguiente cdigo:for (i = 0; i < 1000000; i++) { double t = (i + 0.5); /* variable temporal */ sum += t * t; }Eliminando la llamada a la funcin y realizando la multiplicacin en-lnea permite que el bucle se ejecute a la mxima eficiencia. GCC selecciona funciones para optimizar por este mtodo usando un nmero pruebas heursticas, tales como examinar que la funcin candidata sea pequea. Como optimizacin que es, se lleva a cabo solo dentro de cada archivo objeto. La palabra reservada inline puede ser usada para pedir que explcitamente una funcin especfica sea reemplazada por su contenido, incluyendo su uso en otros archivosSchedulingste es el nivel ms bajo de optimizacin, en el cual el compilador tenermina la mejor forma de ordenar instrucciones individuales. La mayora de CPUs permiten que una o ms instrucciones nuevas comiencen a ejecutarse antes que otras hayan finalizado. Muchos CPUs tambin soportan pipelining, donde mltiples instrucciones se ejecutan en paralelo en el mismo CPU.Cuando esta optimizacin est habilitada, las instrucciones deben ser ordenadas de tal manera que permita que los resultados estn disponibles para ser utilizados por instrucciones posteriores en el momento indicado, y para que permitan una ejecucin mxima en paralelo. sta optimizacin mejora la velocidad de un ejecutable sin incrementar su tamao, pero requiere de memoria adicional y ms tiempo en el proceso de compilacin (debido a su complejidad).Niveles de optimizacinA modo de controlar el tiempo de compilacin y la utilizacin de memoria por el compilador, y el costo-beneficio entre velocidad y espacio para el ejecutable resultante, GCC provee un rango de niveles de optimizacin general, numerados de 0 a 3, adems de las opciones individuales para tipos especficos de optimizacin.-O0 u omitir la opcin -O (default)En este niel de optimizacin GCC no realiza ninguna optimizacin y compila el cdigo fuente de la forma ms directa posible. Cada comando en el cdigo fuente es convertido directamente a las instrucciones correspondientes en el archivo ejecutable, sin reordenamiento. Esta es la mejor opcin a usar cuando de depura un programa y es la default si no se indica nivel de optimizacin alguno.-O1 o -OEste nivel habilita la mayora de formas comunes de optimizacin que no implican operaciones relacionadas con costo-beneficio de velocidad-espacio. Con esta opcin los ejecutables resultantes deberan ser ms pequeos y rpidos que con -O0. Las optimizaciones ms costosas, tales como paralelismo en la ejecucin de instrucciones no se utilizan en este nivel. Compilar con la opcin -O1 puede tomar menos tiempo que compilar con -O0, debido a las cantidades reducidas de datos que necesitan ser procesados despus de la optimizaciones sencillas realizadas.-O2Esta opcin habilita ms optimizaciones, adems de las ya utilizadas por -O1. Estas optimizaciones adicionales incluyen el paralelismo en la ejecucin de instrucciones. Solo las optimizaciones que no requieren clculo de costo-beneficio entre espacio-velocidad son utilizadas para que el ejecutable no aumente en tamao. El compilador tomar ms tiempo para compilar programas y requerir ms memoria que si se utilizara -O1. Esta opcin es generalmente la mejor eleccin para la implantacin de un programa, porque provee la optimizacin mxima sin incrementar el tamao del ejecutable. Es el nivel de optimizacin por default para los lanzamientos de paquetes GNU.-O3Esta opcin habilita optimizaciones ms costosas, tales como funciones en-lnea, adems de las optimizaciones de los niveles ms bajos -O2 y -O1. La optimizacin -O3 puede incrementar la velocidad del ejecutable resultante, pero puede tambin incrementar su tamao. Bajo algunas circunstancias donde estas optimizaciones no son favorables, esta opcin podra hacer que el programa sea ms lento.-Os Esta opcin selecciona optimizaciones que reducen el tamao de un ejecutable. El objetivo de esta opcin es producir el ejecutable ms pequeo posible, para sistemas restringidos en cuanto a memoria o espacio en disco. En Algunos casos un ejecutable ms pequeo tambin se ejecutar ms rpido, debido a un mejor uso de cach.Es importante recordar que un beneficio de la optimizacin en los niveles ms altos debe ser evaluada junto con el costo. El costo de optimizar incluye mayor complejidad en el momento de depurar, y requerimientos mayores de tiempo y mejora durante la compilacin. Para la mayora de propsitos est bien si se utiliza -O0 para depurar, y -O2 para desarrollo e implantacin.

Generacin de cdigo basada en la arquitectura de la mquina objetivoSe muestra el cdigo en ensamblador generado al ejecutar gcc con la opcin -S y la opcin -march seguida del identificador de la arquitectura respectiva:gcc -march=i386 -S programa.c gcc -march=nocona -S programa.c gcc -march=core2 -S programa.cComparacin de los cdigos en ensamblador utilizando Meld:

EjemplosEl siguiente programa ser utilizado para demostrar los efectos de los diferentes niveles de optimizacin:

#include

doublepowern (double d, unsigned n){ double x = 1.0; unsigned j;

for (j = 1; j programa.preprocesado

y luego leyendo el archivo programa.preprocesado.

Fase 2: Compilacin

En esta fase GCC transforma el cdigo C en cdigo ensamblador, propio del procesador que utilizamos en nuestra mquina Linux (x86, MIPS, Sparc, PPC, Alpha, ) Por ello es necesario que en caso de compilar el GCC se le indique para que arquitectura generar cdigo.

Se puede generar cdigo ensamblador desde el cdigo C preprocesado con la ayuda del programa cc1, o con un parmetro especial del GCC:

cc1 programa.preprocesado

o bien, gcc -S programa.preprocesado

Esto generar el cdigo ensamblador para nuestra mquina en el archivo de salida, programa.s.

Fase 3: Ensamblado

En esta fase, el compilador transforma el cdigo ensamblador a cdigo mquina binario que pueda entender nuestro procesador. Esto se puede realizar con el comando as:

as -o programa.o programa.s

Lo cual generar la salida objeto programa.o

Fase 4: Enlazado

En nuestro cdigo fuente generalmente aparecen llamadas a funciones como printf, fgets, fopen, etc. Estas funciones ya se encuentran compiladas y ensambladas en las libreras que se pueden encontrar en directorios como /lib, /usr/lib, /usr/local/lib. Lo que debe hacerse es aadir dinmica o estticamente estos binarios a nuestro cdigo ya compilado y ensamblado. Este proceso se denomina Enlazado o linkado.

Hay dos tipos principales de enlazado:

Enlazado esttico: Los binarios de las libreras se aaden a nuestros binarios compilados.

Enlazado dinmico: Esto no aade los binarios de las libreras a nuestro binario, ms bien, har que nuestro programa cargue en memoria la librera en el momento que la necesite. Esto permite que nuestro programa no aumente mucho en tamao.

El enlazado lo hace el programa ld donde a nuestro binario se le aade las libreras correspondientes a las funciones que llamamos, y a una serie de rutinas de inicializacin y salida.

Por ejemplo, el siguiente comando enlaza nuestro programa con las libreras requeridas:

ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o programa.o -z relro /usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/crt1.o /usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/crti.o /usr/lib/gcc/i486-linux-gnu/4.3.2/crtbegin.o -L/usr/lib/gcc/i486-linux-gnu/4.3.2 -L/usr/lib/gcc/i486-linux-gnu/4.3.2 -L/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/i486-linux-gnu/4.3.2/../../.. programa.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i486-linux-gnu/4.3.2/crtend.o /usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/crtn.o Aunque todo este proceso est englobado por el GCC, ya que GCC es un front-end de los programas cpp, cc1, as y ld.

As todo el proceso anterior se puede simplificar en un solo comando:

gcc -o programa programa.c

Si se cuenta con varias libreras que se desean usar, se puede indicar por medio de la directiva -l. Por ejemplo, para enlazar la librera con funciones matemticas (libm.so) se indica con -lm.

Si se cuenta con mdulos, es decir, otros archivos fuente que queremos aadir, primero debern ser compilador todos por separado como sigue:

gcc -c codigo_principal.cgcc -c modulo1.cgcc -c modulo2.c

Obteniendo los archivos codigo_principal.o, modulo1.o, modulo2.o, etc para el ejemplo anterior.

Y luego sern enlazados creando el archivo ejecutable de la siguiente manera:

gcc -o programa codigo_principal.o modulo1.o modulo2.o

Obteniendo as el ejecutable programa.