Tiempo de Compilación Tiempo de Ejecución Programa fuente Datos de entrada Secuencia de caracteres Máquina abstracta Compilador Secuencia de símbolos Datos de entrada Parser Analizador semántico Máquina real Datos de entrada Código Programa objeto Datos de salida Descripción del comportamiento de un programa dependiente de máquina (implementación) Programa objeto Compiladores ( 04/11/2003 08:24) Datos de salida Descripción del comportamiento de un programa independiente de máquina pero fácil de implementar (implementación interpretada) Tabla de símbolos Generador de código - 6.1 - Programa objeto Árbol sintáctico Árbol sintáctico con atributos Compiladores ( 04/11/2003 08:24) Datos de salida Descripción abstracta del comportamiento de un programa Scanner ORGANIZACIÓN DE LA MEMORIA EN TIEMPO DE EJECUCIÓN Programa fuente - 6.2 - Compiladores ( 04/11/2003 08:24) - 6.3 - 1 Máquinas Abstractas y Paradigmas de Programación Máquina Abstracta • Con una máquina abstracta se define el ámbito de ejecución de los programas La arquitectura de la máquina abstracta depende de la forma de ejecución. – Recursos necesarios para ejecutar un programa – – – – Segmento de código Segmento de datos estático Pila Heap (memoria dinámica) • Registros del procesador – – – – Contador del programa Apuntador a la pila Acumulador Etc. – – – – Control de flujo Operaciones aritméticas Comparaciones Guardar y recuperar datos de memoria Etc. Compiladores ( 04/11/2003 08:24) Segmento de código Segmento de datos Pila Heap Pila bloques de memoria direccionados por apuntadores Segmento de código Pila de argumentos Pila de contexto Heap variables globales y estáticas código máquina, constantes y literales (solo lectura) • Lenguajes lógicos – – – – - 6.4 - B SP Libre • Lenguajes funcionales • Instrucción del código máquina – – – – – variables locales y resultados intermedios • Lenguajes imperativos • Organización de la memoria – – – – Organización de Memoria de un Programa Imperativo Heap Segmento de datos estáticos Segmento de código PC Segmento de código Pila de backtracking Trail Pila para la unificación Compiladores ( 04/11/2003 08:24) - 6.5 - Compiladores ( 04/11/2003 08:24) - 6.6 - 2 Asignación estática de memoria Direcciones Simbólicas y Linkado • Las variables cuyo tiempo de vida es todo el programa se guardan en el segmento de datos estático – – – – variables globales variables static campos static de clases etc. • El acceso se realiza por dirección absoluta de memoria. • La asignación de direcciones se puede realizar mediante un apuntador a la base del segmento que se incrementa con el tamaño de cada variable • Problema: en la compilación separada no se conoce el tamaño de los segmentos Fin • Un fichero objeto es una secuencia de trozos de segmento con – – – – • Los datos compuestos son – – – – una o más direcciones simbólicas un tamaño un tipo de segmento: código, datos, etc. opcionalmente un contenido struct union array conjunto • Para acceder a su contenido se necesita • Una librería es un conjunto de ficheros objeto • El linkeador se encarga de – Dirección base de la variable – Desplazamiento para acceder a una de sus componentes – juntar todos los trozos de segmento de los ficheros objeto incluyendo los que sean necesarios de las librerías – Transformar las direcciones simbólicas en direcciones absolutas de memoria • Ejemplo: struct { int a; double b; char c; } v; &v.c &v.b var3 var2 Base Compiladores ( 04/11/2003 08:24) Datos Compuestos &v.a var1 - 6.7 - Compiladores ( 04/11/2003 08:24) - 6.8 - Compiladores ( 04/11/2003 08:24) &v+12: &v+11: &v+10: &v+9: &v+8: &v+7: &v+6: &v+5: &v+4: &v+3: &v+2: &v+1: &v+0: c b a - 6.9 - 3 Struct y Union Struct y Union • Datos compuestos con desplazamiento conocido en tiempo de compilación • union (superposición de campos) • struct (sin superposición de campos) struct { tipo1 c1; tipo2 c2; ... tipon cn; } var; c1,c2,...,cn &var. c1=&var+sizeof(tipo1)+ sizeof(tipo2)+...+ sizeof(tipon-1) &var. c2=&var+sizeof(tipo1) • Alinear un dato supone que su dirección base ha de ser un múltiplo de una cierta potencia de 2. • Los datos se alinean para acelerar su acceso o por limitaciones de direccionamiento del procesador. • Ejemplo union { tipo1 c1; tipo2 c2; ... tipon cn; } var; – struct y union de C – record de PASCAL cn Alineación sizeof(tipon) c2 sizeof(tipo2) c1 sizeof(tipo1) &var. c1= &var. c2 = ...= &var. cn max {sizeof(tipo1), sizeof(tipo2),..., sizeof(tipon) } &v.c &v.b &var. c1=&var+0 Compiladores ( 04/11/2003 08:24) struct { char a; int b; int c; } v; &v.a - 6.10 - Compiladores ( 04/11/2003 08:24) - 6.11 - Compiladores ( 04/11/2003 08:24) &v+11: &v+10: &v+9: &v+8: &v+7: &v+6: &v+5: &v+4: &v+3: &v+2: &v+1: &v+0: c b Espacio ocupado en un array a - 6.12 - 4 Arrays ⎛a ⎜ 1,1 ⎜ a2 ,1 ⎜ ⎝ a3,1 a1,2 a2 ,2 a1,3 a2 , 3 a 3, 2 a 3, 3 Conjuntos a1,4 ⎞ ⎟ a2 ,4 ⎟ a3,4 ⎠⎟ • Conjunto de escalares – Memoria: a , a , a , a , a , a , a – Cálculo del desplazamiento 1, 2 1, 3 1, 4 2 ,1 • a: conjunto de (rojo, azul, verde) • 3 bits (rojo bit 0, azul bit 1, verde bit 2) 2 ,2 2 ,3 , a2 , 4 , a3,1 , a3, 2 , a3, 3 , a3, 4 n n j =1 l = j +1 desp (i1 , i2 ,..., in ) = sizeof (elementos) ∑ (i j − min j ) ∏ ( maxl − minl + 1) • Guardada por columnas (primero varían los índices de la izquierda) – Memoria: a , a , a , a , a , a , a – Cálculo del desplazamiento 1,1 2 ,1 3,1 1, 2 2 ,2 • Para la ejecución de un programa imperativo se necesita una pila porque se realiza un "recorrido" por su árbol sintáctico • En la pila se guarda – se utiliza un bit por elemento que puede contener el conjunto. Ejemplo • Guardada por filas (primero varían los índices de la derecha) 1,1 Asignación de la Pila 3, 2 1, 3 , a2 , 3 , a3, 3 , a1, 4 , a2 , 4 , a3, 4 n j −1 j =1 l =1 desp(i1 , i2 ,..., in ) = sizeof ( elementos) ∑ (i j − min j )∏ ( maxl − minl + 1) – Las operaciones entre conjuntos son – Resultados intermedios de la evaluación de expresiones – Bloques de activación de funciones • union -> or de bits • intersección -> and de bits – El bit que representa la presencia o ausencia de un elemento se calcula • • • • • desp(i)=i / 8 (división entera) • bit(i)=i % 8 (i modulo 8) – En el análisis semántico hay que tratar como caso especial el conjunto vacío variables locales enlaces estático, dinámico, display posición de retorno valor de retorno – Bloques de activación de excepciones – Bloques de salto no local • Complejidad para n dimensiones – -n 1sumas – n multiplicaciones Compiladores ( 04/11/2003 08:24) - 6.13 - Compiladores ( 04/11/2003 08:24) - 6.14 - Compiladores ( 04/11/2003 08:24) - 6.15 - 5 Evaluación de Expresiones (I) Evaluación de Expresiones (II) • Una expresión se puede representar como un árbol donde – Las operaciones son nodos internos del árbol, y cada una de ellas tiene por hijos sus operandos – Los literales son las hojas del árbol – Ejemplo: a*b+c*d - e Evaluación de Expresiones (III) • Organización de memoria • El recorrido del árbol en postorden se transforma en código de la siguiente forma – Una pila que crece hacia las direcciones inferiores de memoria – SP es el apuntador a la cabeza de la pila – Los operandos se ponen en la pila – Las operaciones cogen los operandos de la pila y dejan el resultado en esta • Instrucciones – Poner en la pila un literal • Ejemplo: a*b+c*d-e • PushLit número – Postorden a b * c d * + e– Código --SP; *SP= número; + PushGVar &a PushGVar &b OperBin * PushGVar &c PushGVar &d OperBin * OperBin + PushGVar &e OperBin - – Poner en la pila una variable global e • PushGVar dirección * a * b c --SP; *SP= *dirección; d – Operaciones binarias • La expresión se evalúa mediante un recorrido en postorden del árbol • OperBin operación *(SP+1)=*(SP+1) operación *SP; ++SP; a b * c d * + e- – Operaciones unarias • OperUna operación *SP= operación (*SP); Compiladores ( 04/11/2003 08:24) - 6.16 - Compiladores ( 04/11/2003 08:24) - 6.17 - Compiladores ( 04/11/2003 08:24) - 6.18 - 6 Bloque/Registro de Activación de una Función (I) Bloque/Registro de Activación de una Función (II) • Las funciones cumplen que la última que ha empezado ha ejecutarse es la primera en acabar su ejecución. Por lo tanto, la información necesaria para ejecutar las funciones se puede guardar en una pila • Cuando se llama a una función se necesita crear el espacio para la siguiente información – Posición de retorno, o sea donde ha de continuar la ejecución al salir de la función – Argumentos de la función – Valor de retorno – Variables de la función – Base del bloque de activación, o sea dirección a partir de la cual se guardan los datos necesarios para la ejecución de la función. Bloque de Activación de una Función C • Los argumentos van en orden inverso para poder implementar las funciones con número de argumentos variable (printf) • Para acelerar las llamadas, el valor de retorno va en un registro del procesador. Valor de retorno Argumentos PC de retorno Enlace dinámico B Argumenton Argumenton-1 .... Argumento2 Argumento1 Variables locales SP PC de retorno • El registro de activación de un procedimiento no contiene el valor de retorno. Enlace dinámico B Variables locales SP Compiladores ( 04/11/2003 08:24) - 6.19 - Compiladores ( 04/11/2003 08:24) - 6.20 - Compiladores ( 04/11/2003 08:24) - 6.21 - 7 Instrucciones para Llamar a Funciones Bloque de Activación de una Función PASCAL Código para Llamar una Función C – Llamar a una dirección de memoria • Call dirección --SP; *SP=PC+1; PC=dirección; – Retornar de función • Ret PC=*SP; ++SP; – Crear enlace dinámico y reservar espacio para las variables locales • Link tamaño --SP; *SP=B; B=SP; SP=SP - tamaño; – Eliminar el espacio de las variables locales y recuperar B • Unlink SP=B + 1; B=*B; – Eliminar los Argumentos • Add SP tamaño SP=SP + tamaño; Código que llama a la función Código de la Función Calculo del Argumenton Calculo del Argumenton-1 ... Calculo del Argumento2 Calculo del Argumento1 Call &Fun Add SP tamaño argumentos Push VR Link tamaño variables • El enlace estático o el display se utiliza para poder acceder a las variables locales de otras funciones Código del cuerpo de la función Valor de retorno Pop RV Unlink Ret Argumento1 Argumento2 .... Argumenton-1 Argumenton • El código que realiza la llamada no necesita saber el espacio ocupado por las variables locales de la función. • Al final de la llamada a una función queda en la pila su valor de retorno. Enlace estático o display PC de retorno Enlace dinámico B – Registro del Valor de Retorno VR • Push RV Variables locales --SP;*SP=RV; • Pop RV SP RV=*SP; ++SP; Compiladores ( 04/11/2003 08:24) - 6.22 - Compiladores ( 04/11/2003 08:24) - 6.23 - Compiladores ( 04/11/2003 08:24) - 6.24 - 8 Funciones/Procedimientos Anidados en PASCAL nivel 0 Procedure P1; Var V1:integer; nivel 1 Procedure P2; Var V2:integer; Nivel 2 Procedure P3 Var V3:integer; Nivel 3 Begin End; Begin End; Procedure P4; Var V4:integer; Nivel 2 Begin End; Begin End; Procedure P5 Var V5:integer; Nivel 1 Begin End; Código para Llamar una Función PASCAL Enlace Estático Código que llama a la función Código de la Función Add SP -tamaño valor de retorno Calculo del Argumento1 Calculo del Argumento2 ... Calculo del Argumenton-1 Calculo del Argumenton Cálculo del EE/Display Call &Fun Add SP tamaño argumentos+ tamaño EE/Display Link tamaño variables Código del cuerpo de la función Unlink Ret • El código que realiza la llamada no necesita saber el espacio ocupado por las variables locales de la función. • Al final de la llamada a una función queda en la pila su valor de retorno. • El enlace estático de un bloque de activación de una función apunta al bloque de activación de la función donde se ha definido. • El enlace dinámico apunta al bloque de activación de la función que ha llamado Procedure P1; Var V1:integer; Procedure P2; Var V2:integer; Begin End; Procedure P4; Var V4:integer; Begin End; Begin End; P1 ED PC EE P4 ED PC EE P2 ED PC EE P1 ED PC EE Secuencia de llamadas P1->P4->P2->P1 Compiladores ( 04/11/2003 08:24) - 6.25 - Compiladores ( 04/11/2003 08:24) - 6.26 - Compiladores ( 04/11/2003 08:24) - 6.27 - 9 Instrucciones para el Bloque de Activación con Enlace Estático – Crear enlace estático/display Cálculo del Enlace Estático Display • El enlace estático se calcula a partir de diferencias de nivel • Enlace estático de un nuevo bloque de activación • PushEE nivel ee=B; for (i= nivel;i>0; --i) ee=ee->ee; --SP; *SP=ee; – Acceder a variable local por enlace estático • PushEEVar nivel,desp ee=B; for (i= nivel;i>0; --i) ee=ee->ee; --SP; *SP=*(ee+ desp); • PopEEVar nivel,desp ee=B; for (i= nivel;i>0; --i) ee=ee->ee; *(ee+ desp)=*SP; ++SP; • El display es la agrupación de la lista de enlaces estáticos en un array DifNivel= nivel llamada - nivel función+1 EE=B for i=1 to DifNivel do EE=EE - >EE; • Enlace estático de una variable DifNivel= nivel variable - nivel código EE=B for i=1 to DifNivel do EE=EE - >EE; ED PC EE ED PC ED PC EE ED PC ED PC EE ED PC ED PC EE ED PC ED PC EE ED PC Enlaces estáticos Compiladores ( 04/11/2003 08:24) - 6.28 - Compiladores ( 04/11/2003 08:24) - 6.29 - Compiladores ( 04/11/2003 08:24) Display - 6.30 - 10 Instrucciones para el Bloque de Activación con Display Creación del Display Acceder a una Variable por Display • El display de un nuevo bloque de activación se crea por copia del anterior modificado – Crear display • Push B --SP; *SP=B; • Puntero del display de una variable DifNivel= nivel variable - nivel código – DifNivel==0 DifNivel= nivel llamada - nivel función+1 – Acceder a variable local por display B+desp Valor de retorno • PushDispVar nivel,desp --SP; *SP=*(B[nivel]+ desp); • PopDispVar nivel,desp *(B[nivel]+ desp)=*SP; ++SP; • PushBVar desp --SP; *SP=*(B+ desp); • PopBVar desp *(B+ desp)=*SP; ++SP; DifNivel==0 •Copiar display •Añadir B – DifNivel>0 Argumentos B[DifNivel+1]+desp display anterior B PC de retorno ED Valor de retorno Argumentos B ... Variables locales DifNivel>0 Copiar display menos los últimos DifNivel apuntadores display anterior DifNivel EE3 EE2 EE1 PC de retorno ED Valor de retorno Argumentos display nuevo B+4 B+3 B+2 B+1 B Variables locales PC de retorno ED B Variables locales Compiladores ( 04/11/2003 08:24) - 6.31 - Compiladores ( 04/11/2003 08:24) - 6.32 - Compiladores ( 04/11/2003 08:24) - 6.33 - 11