Está en la página 1de 61

Lección 5:

Generación De Código
1.  Introducción
2.  Tipos de Código Intermedio
3.  Declaraciones
4.  Expresiones y Asignación
5.  Estructuras de Control
6.  Procedimientos y Funciones

Lecturas: Scott, capítulo 9


Muchnick, capítulos 4, 6
Aho, capítulo 8
Fischer, capítulos 10, 11 , 12 , 13, 14
Holub, capítulo 6
Bennett, capítulo 4, 10
12048 - J. Neira - 1
1/6. Introducción
•  Código intermedio: •  Se busca:
interfaz entre ‘front-ends’ y –  transportabilidad
‘back-ends’ –  posibilidades de optimización
•  Debe ser:
–  abstracto
–  sencillo
•  No se tiene en cuenta:
–  modos de direccionamiento
–  tamaños de datos
–  existencia de registros
–  eficiencia de cada operación

¿por qué no generar el código


final directamente?
12048 - J. Neira - 2
Código Intermedio
•  Ventajas: •  Desventajas:
– Permite abstraer la má- – Implica una pasada
quina, separar operacio- más para el compilador
nes de alto nivel de su (no se puede utilizar el
modelo de una pasada,
implementación a bajo conceptualmente sim-
nivel. ple).
– Permite la reutilización – Dificulta llevar a cabo
de los front-ends y back- optimizaciones especí-
ends. ficas de la arquitectura
destino.
– Permite optimizaciones
generales. – Suele ser ortogonal a la
máquina destino, la tra-
ducción a una arquitec-
tura específica será más
larga e ineficiente.

12048 - J. Neira - 3
2/6. Tipos de Código Intermedio
•  AST (Abstract Syntax •  Ventajas: unificación de
Trees): forma condensada pasos de compilación
de árboles de análisis, con –  Creación del árbol y la tabla
sólo nodos semánticos y de símbolos
sin nodos para símbolos –  Análisis semántico
terminales (se supone que –  Optimización
el programa es sintáctica- –  Generación de código objeto
mente correcto).
•  Desventaja:
Arbol de análisis: –  espacio para almacenamiento
E AST:
opad E
T T
‘+’
P P opmul P id(A) ‘+’ T

id(A) id(B) ‘*’ id(C) id(B) ‘*’ id(C)

12048 - J. Neira - 4
ASTs
program gcd(input, output);
var i,j : integer;
begin
read(i,j);
while i <> j do
if i > j then i := i – j
else j := j – i;
writeln(i);
end.

12048 - J. Neira - 5
Tipos de Código Intermedio
•  DAG (Directed Acyclic Graphs): árboles sintácticos
concisos
DAG:
árbol sintáctico: E
E
‘+’
T ‘+’ T
T

id(B) ‘*’ id(C) id(B) ‘*’ id(C) id(B) ‘*’ id(C)

– Ahorran algo de espacio


– Resaltan operaciones duplicadas en el código
– Difíciles de construir
12048 - J. Neira - 6
Tipos de Código Intermedio
•  TAC (Three-Address •  Las operaciones más com-
Code): secuencia de plejas requieren varias ins-
instrucciones de la forma: trucciones:
dir 1 dir 2 dir 3 •  Este ‘desenrollado’ facilita
la optimización y genera-
resultado := operando1 op operando2 ción de código final.
–  operador: aritmético / lógico (a + b) x (c – (d / e))
–  operandos/resultado:
constantes, nombres,
temporales.

•  Se corresponde con ins-


trucciones del tipo:
a := b + c
12048 - J. Neira - 7
TAC
•  Ensamblador general y simplificado
para una máquina virtual: incluye
etiquetas, instrucciones de flujo de
control…
•  Incluye referencias explícitas a las
direcciones de los resultados
intermedios (se les da nombre).
•  La utilización de nombres permite la
reorganización (hasta cierto punto).
•  Algunos compiladores generan este
código como código final; se puede
interpretar fácilmente (UCSD
PCODE, Java).

•  Operadores:
CI generación optimización
muchos corto compleja compleja
pocos largo sencilla sencilla

12048 - J. Neira - 8
TAC
•  Variaciones sintácticas: (Aho)
1. Asignación:
x := y op z
x := op y
(Fischer) x := y
x[i] := y
(READI, A) x := y[i]
x := &y
(READI, B) x := *y
(GT, A, B, t1) *x := y
(JUMP0, t1, L1)
(ADDI, A, 5, C) 2. Saltos:
(JUMP, L2) goto L
(LABEL, L1) if x oprel y goto L
(ADDI, B, 5, C)
(LABEL, L2) 3. Procedimientos:
(SUBI,C, 1, t2) param x1
...
(MULTI, 2, t2, t3) param xn
(WRITEI, t3) call p, n
12048 - J. Neira - 9
Representaciones de TAC
Fuente:
a := b * c + b * d; •  Supuesta ventaja: es más
concisa.
•  Cuádruplas: el destino
suele ser una temporal. Falso: estadísticamente se
requieren más instrucciones.
(*, b, c, t1)
(*, b, d, t2)
(+, t1, t2, a)
•  Desventaja: el código ge-
•  Tripletas: sólo se repre- nerado es dependiente de
sentan los operandos la posición.
(1) (*, b, c)
(2) (*, b, d) Cierto: la dependencia posi-
(3) (+, (1), (2)) cional dificulta la optimización.
(4) (:=, (3), a)
12048 - J. Neira - 10
Representaciones de TAC
•  Tripletas Indirectas: + vector que indica el orden de
ejecución de las instrucciones.
a := (b * c + b * d) * b * c;

1 b * c 2 b * d 1 b * c
2 b * d 1 b * c 2 b * d
3 b * c 3 b * c 3 (1) + (2)
4 (1) + (2) 4 (1) + (2) 4 (3) * (1)
5 (4) * (3) 5 (4) * (3) 5 a := (4);
6 a := (5); 6 a := (5);

Reorganizar es Se puede com-


eficiente partir espacio
12048 - J. Neira - 11
RTL: register transfer language
d = (a + b) * c;

12048 - J. Neira - 12
Notación posfija
•  Polaca inversa, código de cero direcciones:
– notación matemática libre de paréntesis
– los operadores aparecen después de los operandos

Expresiones: a := b * c + b * c

1. E átomo ⇒ E ’
@a
2. E1 op E2 ⇒ E1’ E2’ op b
c
3. (E) ⇒ E’ mult
b
c
Asignación: mult
add
id := E ⇒ @id E’ asg asg
12048 - J. Neira - 13
Notación Postfija
•  Ventajas: •  Desventajas:
–  Código generado conciso. –  Código dependiente de la
–  No hacen falta temporales. posición.
–  Algunas optimizaciones –  solo efectiva si el ‘target’ es
sencillas. de pila.
–  Mantiene la estructura a := b * c + b * c
sintáctica.

@a b c mult dup add asg

a + b * c (a + b) * c

a a
E
b E b
id(A)‘+’ T c T ‘*’id(C) add
mult c
id(B)‘*’id(C) id(A)‘+’id(B)
12048 - J. Neira -
add mult 14
Generación de código intermedio
•  Consideración fundamental: generación de código
correcto. a := b * c

; Dirección de A.
INEFICIENCIA SRF 0 5
EN TIEMPO: INEFICIENCIA
; Acceso a B. EN ESPACIO:
¿hay alguna forma SRF 0 4
menos costosa de DRF ¿está b * c
hacer la ; Acceso a C. calculado
multiplicación? en algún sitio?
SRF 0 3
DRF
TMS
; Asignación.
ASG
•  Sin hacerse estas preguntas, es razonablemente sencillo.
12048 - J. Neira - 15
3/6. Procesamiento de declaraciones
Esencialmente se •  Declaración de variables:
trata de completar int sig, nivel = 0;
la tabla de símbolos void abrir_bloque()
{
... sig = INICIAL;
•  no se genera código (hay ++nivel;
}
excepciones).
void cerrar_bloque()
•  se limita a resolver proble- {
... nivel--;
mas relacionados con al- }
macenamiento de los obje- void crear_var (char *nom,
tos: int tipo)
{
.....
–  Espacio requerido
–  Lugar en la memoria simbolo->dir = sig;
–  Valor switch (tipo) {
case ENTERO :
sig += 2; break;
•  hay información explícita e case REAL :
sig += 4; break;
implícita en el fuente. ....
}
} Al final, sig indica el tamaño
12048 - J. Neira - del bloque de activación. 16
Ejemplo
Programa p;
entero i, j, m;
3 4 5
accion dato (ref entero d);
Principio 3
Fin
3 4 5
accion mcd(Val entero a, b; ref entero m);
entero r; 6

Principio
Fin

Principio
Fin
12048 - J. Neira - 17
Declaración de Variables
•  ¿Y si se permite mezclar •  C: este problema no existe.
declaraciones de variables •  Pascal: muchos compilado-
y procedimientos? res lo prohíben.
procedure P; i.dir = 0
var i,j,k : integer;j.dir = 2
k.dir = 4•  Posible solución:
procedure Q; l.dir = 0
var l,m : integer; m.dir = 2
begin int sig[MAXANID], nivel = 0;
....
end; void abrir_bloque ()
var n : integer; {... sig[++nivel] = INICIAL;}

n.dir = 4 void cerrar_bloque ()


(¡igual { ... nivel--;}
que k!)
void crear_var (char *nom,
•  ¿Y si necesitas mantener int tipo)
{ ....
información sobre el tama- simbolo->dir = sig[nivel];
ño de cada bloque? ...
12048 - J. Neira -
} 18
Inicializadores, C:
•  extern y static: •  auto y struct:
–  Valor inicial por defecto: 0. –  Valor inicial por defecto:
–  Admiten sólo valores ninguno.
constantes. –  Admiten valores no
–  El inicializador se ejecuta una constantes.
sola vez. –  Se ejecutan c/vez que se
#include <stdio.h> activa el bloque.
/* ¿legal? */ int f()
int i = 1, {
/* ¿legal? */ /* ¿legal? */
j = i + 1, int i = 1,
/* ¿legal? */ /* ¿legal? */
j = i + 1,
m = 34 + 1, g(),
f(), /* ¿legal? */
/* ¿legal? */ k = g(i),
k = f(), /* ¿legal? */
/* ¿legal? */ n = f(),
l; l;
/* ¿legal? */
/* ¿legal? */ static int m = 1;
extern int n = 0; .....
12048 - J. Neira -
} 19
Esquema general, secuencial
%union {...
char *cadena;...
}
...

programa p; programa: tPROGRAMA tIDENTIFICADOR ';'


... {
principio inicio_generacion_codigo ();
... $<cadena>$ = nueva_etiqueta ();
fin generar (ENP, $<cadena>$);
}
declaracion_variables
declaracion_acciones
{
comentario (sprintf(msg,
ENP L0 "Comienzo de %s", $2.nombre));
... etiqueta($<cadena>4);
; Comienzo de p }
L0: bloque_instrucciones
... {
; Fin de p comentario (sprintf(msg,
LVP "Fin de %s", $2.nombre));
generar (LVP);
fin_generacion_codigo();
}
12048 - J. Neira - 20
Esquema general, AST
%union {...
LISTA cod;
}
...
%type <cod> bloque_instrucciones
%type <cod> declaracion_acciones
programa: tPROGRAMA tIDENTIFICADOR ';'
programa p; declaracion_variables
... declaracion_acciones
principio bloque_instrucciones
...
fin {
char *lenp = newlabel(), msg[100];
$$ = code (ENP, lenp);
concatenar (&($$), $5);
ENP L0 sprintf(msg, "Comienzo de %s“,...);
... comment (&($$), msg);
; Comienzo de p label(&($$), lenp);
L0: concatenar (&($$), $6);
... sprintf(msg, "Fin de %s",...);
; Fin de p comment (&($$), msg);
LVP emit (&($$), LVP);
dumpcode ($$, fich_sal);
}
12048 - J. Neira - 21
4/6. Expresiones y Asignación

x[i, j] := a*b + c*d - e*f + 10;

•  De los operandos: •  Instrucciones generadas


–  Acceso a datos
–  Determinar su localización
»  Variables simples
–  Efectuar conversiones
»  Registros
implícitas
»  Vectores

•  De los operadores: –  Manipulación de datos


–  Respetar su precedencia »  Conversiones
–  Respetar su asociatividad »  Operaciones
–  Respetar orden de evaluación
(si definido) –  Flujo de control
–  Determinar interpretación »  Validación de subrangos
correcta (si sobrecargado) »  Operadores complejos
12048 - J. Neira - 22
Algunas dificultades
•  Orden de evaluación de los •  Método de evaluación de
operandos: los operadores:
push(pop() - pop()); push (pop() and pop());
¿Implementa correctamente SBT? ¿Implementa AND
¿Es relevante en el caso de PLUS? correctamente en PASCAL?

a[i] = i++;
¿el valor del subíndice es el push (pop() && pop());
anterior o actual valor de i? ¿Implementa AND
correctamente en C?
FRAMES[pop()] = pop();
¿Corresponde a ASG o ASGI?
En C, el operador && se evalúa
En C, ni la suma ni la asignación tienen por corto circuito y por lo
predefinido un orden de evaluación. tanto de izquierda a derecha.
12048 - J. Neira - 23
Operandos: acceso a nombres (sec)
•  La información esencial debe obtenerse de la tabla
de símbolos. factor :
constante : TIDENT
TTRUE {
generar (SRF, ?, ?);
{ generar (DRF);
generar (STC, 1); /* ¿parametro? */
} }
| TFALSE | TIDENT
{ {
generar (STC, 0); generar (SRF, ?, ?);
} /* ¿parametro? */
}
| TENTERO '[' expresion ']'
{ {
generar (STC, $1); /* ?tamano? */
} generar (DRF);
| TCARACTER }
{ | TIDENT '(' args ')'
generar (STC, $1); {
generar (OSF, ?, ?, ?);
} }
; .....
;
12048 - J. Neira - 24
Operandos: acceso a nombres (AST)
•  La información esencial debe obtenerse de la tabla
de símbolos. factor :
constante : TIDENT
TTRUE {
$$.cod = code (SRF,?,?);
{ emit (&($$.cod), DRF);
$$.cod = code (STC, 1); /* ¿parametro? */
} }
| TFALSE | TIDENT '[' expresion ']'
{ {
$$.cod = code (STC, 0); $$.cod = code (SRF, ?, ?);
} /* ¿parametro? */
concatenar (&($$.cod),
| TENTERO $3.cod);
{ /* ?tamano? */
$$.cod = code (STC, $1); emit (&($$), (DRF);
} }
| TCARACTER | TIDENT '(' args ')'
{ {
$$.cod = code (STC, $1); $$.cod = $3;
emit (&($$.cod),OSF,?,?,?);
} }
; .....
;
12048 - J. Neira - 25
Vectores
•  Componentes almacenadas
de forma contigua

V[1] V[2] V[3] V[4] V[5]

•  En C:
•  Vectores de dimensión defi-
nida en compilación, des- i x tamaño
plazamiento de V[i]:
•  se reduce a aritmética de
punteros:
(i – lim_inf) x tamaño
v[i]
es equivalente a
*(v + i)
12048 - J. Neira - 26
Procesamiento de Vectores
•  Dada var v : array[4..8] of integer;
v[<expresión1>] := <expresión2>;

; n y o dependen de la declaración
SRF n o
; código para expresión1
...
; límite inferior
STC 4
SBT
; tamaño (en este caso sobra)
STC 1
TMS
PLUS
; código para expresión2
...
ASG
¿o sea que el límite superior no sirve?
12048 - J. Neira - 27
Procesamiento de Vectores
•  Dada var v : array[-3..5] of boolean;
if v[<expresión>] then ...;
; n y o dependen de la declaración
SRF n o
; código para expresión
...
?? ¿qué hacer aquí?
??
STC -3
GTE
JMF ... ; procedimiento de error
STC 5
LTE
JMF ... ; procedimiento de error
; límite inferior
STC -3
SBT
; tamaño
STC 1
TMS
PLUS
DRF
JMF ...
12048 - J. Neira - 28
Matrices contiguas por filas, v1
entero v[2..5,3..7,1..8];
....
v[2,3,1] := ...;
v[5,7,8] := ...; ¿dirección?
v[3,4,5] := ...;

0
159
4 40 52 105 105
5 8
8 1 264 105
157 105
12048 - J. Neira - 29
Formulación alternativa, v2

entero v[2..5,3..7,1..8];
....
v[2,3,1] := ...;
v[5,7,8] := ...; ¿dirección?
105 v[3,4,5] := ...;

2 5 3
4
13 32 19
5
105 264 157
8
0 159 52
12048 - J. Neira - 30
Matrices: generación de código, v2
factor : TIDENT
{
int nivel = ..., /* nivel sint. */
int offset = ....; /* dir en BA */
generar (SRF, nivel, offset);
/* ¿par x ref? */
}
cn '[' lista_indices ']’
{
int t = ...; /* Tamaño elems */
int c = ...; /* Parte constante */
generar (STC, c);
dn generar (SBT);
generar (STC, t);
addr generar (TMS);
generar (PLUS);
generar (DRF);
}
;
12048 - J. Neira - 31
Matrices: generación de código, v2
%union { ..... int i; ..... }
%type <i> lista_indices
%%
lista_indices: expresion e1
{
c1 = e1 $$ = 1;
}
| lista_indices ',' ci-1
{
int s_i, i;
i = $1 + 1;
s_i = ...,
ci-1 si generar (STC, s_i); si
generar (TMS);
}
expresion ei
{
ci = ci-1 si + ei generar (PLUS);
$$ = $1 + 1;
}
;
12048 - J. Neira - 32
¿y porqué no...?
{% int i; %}
%%
lista_indices: expresion e1
{
c1 = e1 i = 1;
}
| lista_indices ',' ci-1
{
int s_i, i;
i = i + 1;
s_i = ...,
generar (STC, s_i); si
ci-1 si generar (TMS);
}
expresion e
{ i
ci = ci-1 si + ei generar (PLUS);
}
;
entero v[1..10], w[1..3, 1..4, 1..5, 1..6];
....
w[v[1], v[2], v[3], v[4]] := ...;
12048 - J. Neira - 33
Ejemplo: para v[3,4,5]

; v ; v
SRF n o v1 SRF n o v2
; e_1 ; e_1
STC 3 STC 3
; m_1 ; s_ 2
STC 40 STC 5
TMS TMS
PLUS ; e_2
; e_2 STC 4
STC 4 PLUS
; m_2 ; s_3
STC 8 STC 8
TMS TMS
PLUS ; e_3
; e_3 STC 5
STC 5 PLUS
; m_3 ; fin de los indices
STC 1 ; c
TMS STC 105
PLUS SBT
; fin de los indices PLUS
; c
STC 105
SBT ¿cuál es más eficiente?
12048 - J. Neira - 34
Operadores
•  Algoritmo recursivo: comenzando en la raíz del
árbol sintáctico:
Para un operador n-ario:
a*b + c*d - e*f + 10
1.  Generar código para eva-
+ luar los operandos 1..n, al-
macenando los resultados
- 10 en localizaciones tempo-
rales-
+ *
2.  Generar código para eva-
* * e f luar el operador, utilizando
los operandos almacena-
a b c d dos en las n localizaciones
temporales y almacenando
a b * c d * + e f * - 10 + el resultado en otra locali-
zación temporal.
12048 - J. Neira - 35
Operadores Aritméticos (sec)
%union { ... int instr; ... }
%type <instr> op_ad op_mul
%%
expr_simple : termino
| '+' termino
| '-' termino
{ generar (NGI); }
| expr_simple op_ad termino
{ generar ($2); }
;
op_ad : '+' { $$ = PLUS; }
| '-' { $$ = SBT; }
;
termino : factor
| termino op_mul factor
{ generar ($2); }
;
op_mul : '*' { $$ = TMS; }
| TDIV { $$ = DIV; }
| TMOD { $$ = MOD; }
;
Los operadores lógicos se tratan
12048 - J. Neira - de forma similar, excepto.... 36
Corto circuito: or else
•  Implica operaciones de control de flujo:

A or else B  if A then true else B

A A
JMT T JMF F
B STC 1
JMP Fin JMP Fin
T: STC 1 F: B
Fin: Fin:

A v v f f A v v f f
B v f v f B v f v f
Instr. a+2 a+2 a+b a+b Instr. a+3 a+3 a+b a+b
+2 +2 +1 +1
12048 - J. Neira - 37
Corto circuito: and then

A and then B  if A then B else false

A A
JMF F JMT T
B STC 0
JMP Fin JMP Fin
F: STC 0 T: B
Fin: Fin:

A v v f f A v v f f
B v f v f B v f v f
Instr. Instr.

12048 - J. Neira - 38
Siguiente problema....
•  ¿qué hacer con los •  Máquinas de pila:
resultados intermedios? ;variable A
SRF 0 3 DRF
a*1b +1 c*2d - e*3f +2 10 ;variable B
SRF 0 4 DRF
;*1: A * B
TMS
+ ;variable C
SRF 0 5 DRF
;variable D
- 10 SRF 0 6 DRF
;*2:C * D
+ TMS
* ;+1:(A*B)+(C*D)
PLUS
;variable E
* * e f SRF 0 7 DRF
;variable F
SRF 0 8 DRF
a b c d ;*3:E * F
TMS
;-:((A*B)+(C*D))-(E*F)
Depende del tipo de SBT
STC 10
código intermedio ;+2:(((A*B)+(C*D))-(E*F))+10
12048 - J. Neira -
PLUS 39
TAC: Variables temporales
•  Se supone disponible una cantidad ilimitada de variables

a*1b +1 c*2d - e*3f +2 10

t0 := A * B;
t1 := C * D;
t2 := t0 + t1;
t3 := E * F;
t4 := t2 - t3;
t5 := t4 + 10;

‘register allocation problem’

•  Al traducir este código intermedio para una arquitectura


destino, se utilizarán registros en lo posible, de lo contrario
posiciones de memoria.
12048 - J. Neira - 40
Código de tres direcciones
•  Se utiliza un generador de nombres temporales:
char *newtemp ()
{
static int c = 0;
char *m = malloc (5);
sprintf (m, "t%d", c++);
return m;
}

•  Las expresiones tienen como atributo el nombre de


la variable en la que quedan almacenadas.
%{
extern char *newtemp();
%}
%union {...char *place;...}
%type <place> TIDENT expresion
%type <place> expresion_simple termino factor
12048 - J. Neira - 41
Código de tres direcciones
expresion : simple { strcpy ($$, $1); }
;
simple : termino { strcpy ($$, $1); }
| '+' termino { strcpy ($$, $2);}
| '-' termino
{
strcpy ($$, newtemp());
tac ("%s := -%s;\n",$$, $2);
}
| simple '+' termino
{
strcpy ($$, newtemp());
tac("%s := %s + %s;\n",$$, $1, $3);
}
| simple '-' termino
{
strcpy ($$, newtemp());
tac("%s := %s - %s;\n",$$, $1, $3);
}
;
factor : TIDENT { strcpy ($$, $1); }
| '(' expresion ')‘ { strcpy ($$, $2); }
| TENTERO { sprintf ($$, "%d", $1);}
;
12048 - J. Neira - 42
Reutilización de temporales
•  Una vez que una variable •  Al traducir el código inter-
temporal aparece como medio, en lo posible se uti-
operando, deja de utilizar- lizarán registros (habrá una
se. cantidad limitada); de lo
t0 := A * B; contrario, posiciones de
t1 := C * D; memoria.
t2 := t0 + t1; •  Reducción de temporales
t3 := E * F; requeridas:
t4 := t2 - t3; 1.  c = 0
t5 := t4 + 10;
0 2.  Para generar un nuevo
t0 := A * B; 1 nombre temporal, utilizar
t1 := C * D; 2 tc, e incrementar c en 1.
t0 := t0 + t1; 1
t1 := E * F; 2 3.  Cuando aparezca un
t0 := t0 - t1; 1 nombre temporal como
t0 := t0 + 10; 1 operando, decrementar c
12048 - J. Neira -
en 1. 43
5/6. Estructuras de Control
•  Sin consideraciones de eficiencia, la generación de
código es relativamente sencilla:
•  Ejemplo 1: repetir INSTR:
; <instr>
<instr>
; <exp>
hasta <exp>
JMF INSTR
repetir: tREPETIR
{
$<instr>$ = nueva_etiqueta();
etiqueta ($<instr>$);
}
lista_instrucciones
tHASTA_QUE expresion
{
generar (JMF, $<instr>2);
}
;
12048 - J. Neira - 44
Selección (sec)

si <exp> seleccion: tSI expresion


ent {
<instr1> $<sino>$ = nueva_etiqueta();
si_no generar (JMF, $<sino>$);
}
<instr2> tENT lista_instrucciones
fsi {
$<fin>$ = nueva_etiqueta();
generar (JMP,$<fin>$);
etiqueta ($<sino>3);
}
; <exp> resto_seleccion tFSI
JMF SINO {
; <instr1> etiqueta($<fin>6);
JMP FIN }
;
SINO: resto_seleccion:
; <instr2> | tSI_NO lista_instrucciones
FIN: ;

12048 - J. Neira - 45
Optimalidad
•  La generación de código puede no ser óptima:

; exp
SRF n o
DRF
STC 1
EQ
JMF L0
si i = 1 ; l1
ent i := i + 1; SRF n o
fsi SRF n o
DRF
STC 1
PLUS
ASG
JMP L1
L0:
L1:

12048 - J. Neira - 46
Selección (AST)
seleccion:
tSI expresion
; <exp> tENT lista_instrucciones
JMF SINO resto_seleccion tFSI
; <instr1> {
JMP FIN char *lsino = newlabel(),
SINO: *lfin = newlabel();
; <instr2> $$ = $2.cod;
FIN: emit (&($$), JMF, lsino);
concatenar (&($$), $4);
if (longitud_lista($5)) {
emit (&($$), JMP, lfin);
; <exp> label (&($$), lsino);
JMF SINO concatenar (&($$), $5);
; <instr1> label (&($$), lfin);
SINO: }
else label (&($$), lsino);
}
;
resto_seleccion:
{ $$ = newcode();}
| tSI_NO lista_instrucciones
12048 - J. Neira - { $$ = $2}; 47
Selección múltiple
; caso
; exp
; exp1
EQ
JMF EXP2
caso <exp> ; instr1
JMP FIN
<exp1> : <instr1> ; EXP2:
... ...
<expn> : <instrn> ; EXPn:
dlc <instr> ; expn
fcaso EQ
JMF DLC
; instrn
JMP FIN
¿problemas? DLC:
; dlc
; instr
FIN:

12048 - J. Neira - 48
Selección múltiple
; caso
; exp
DUP
; exp1
equivale a: EQ
JMF EXP2
si <exp> = <exp1> ; instr1
ent <instr1> JMP FIN
si_no si <exp> = <exp2> EXP2:
ent <instr2> ...
.... EXPn:
si_no si <exp> = <expn> DUP
ent <instrn> ; expn
EQ
si_no <instr> JMF DLC
fsi ; instrn
... JMP FIN
fsi DLC:
; dlc
; instr
FIN:
POP
12048 - J. Neira - 49
Mientras que (sec)
EXP:
mq <exp> hacer ; <exp>
<instr> JMF FIN
fmq ; <instr>
JMP EXP
FIN:
mientras_que: tMQ
{
$<exp>$ = nueva_etiqueta();
etiqueta ($<exp>$);
}
expresion
{
$<fin>$ = nueva_etiqueta();
generar (JMF, $<fin>$);
}
instr tFMQ
{
generar (JMP, $<exp>2);
etiqueta($<fin>4);
}
; -
12048 - J. Neira 50
Mientras que (AST)
JMP COND
BLOQUE:
mq <exp> hacer ; <bloque>
<bloque> COND:
fmq ; <exp>
JMT BLOQUE

mientras_que: tMQ expresion bloque tFMQ


{
char *lcond = newlabel(),
*lbloque = newlabel();
$$ = code (JMP, lcond);
label (&($$), lbloque);
concatenar( &($$), $3);
label (&($$), lcond);
concatenar (&($$), $2);
emit (&($$), JMT, lbloque);
}

12048 - J. Neira - 51
6/6. Procedimientos y Funciones
Declaraciones:
• Recuperar los argumentos
• Generar el código del procedimiento/función
• Devolver el valor resultado (funciones)

accion q (val entero i; ref booleano t);


entero j;
booleano f;
accion r (ref entero j);
entero i;
principio
q (i, t);
r (j)
fin
principio Invocaciones:
q (j, f); • Apilar los argumentos
r (i)
fin • Ejecutar la invocación
12048 - J. Neira - 52
Argumentos
•  Los argumentos se transmiten a través del stack
accion p(val entero i;
ref booleano k;
val caracter c);
..........
p (a,b,d);

; recuperar C
; recuperar K
; apilar A ; recuperar I
; apilar B JMP P
; apilar D ...
; invocar P P:
OSF s l a ; accion P
...
12048 - J. Neira -
CSF 53
Invocación de Procedimientos
•  Cuando se evalúan las ex-
p (n+1, presiones correspondien-
b, tes a los argumentos, éstos
entacar(c+1)); van almacenándose en la
pila.
•  Al crear el BA del procedi-
SRF nn on miento, debe respetarse el
DRF tamaño del bloque actual
STC 1 •  El cambio de nivel es la
PLUS diferencia entre el nivel
SRF nb ob actual y el invocado.
DRF
SRF nc oc •  La dirección del procedi-
DRF miento o función se deter-
STC 1 mina al introducir el símbolo
PLUS en la tabla.
OSF s l a
12048 - J. Neira - 54
Invocación de Procedimientos
•  Los parámetros ref requie- •  Para los parámetros ref
ren la dirección de la elimino la última instruc-
varia-ble referenciada; ción de código generado
expresion genera código por expresion
para obtener el valor de la
variable.
SRF nn on SRF nn on
n+1 DRF DRF
STC 1 STC 1
PLUS PLUS
SRF nb ob SRF nb ob
b DRF
SRF nc oc SRF nc oc
entacar(c+1) DRF DRF
STC 1 STC 1
PLUS PLUS
OSF s l a OSF s l a
12048 - J. Neira - 55
Declaración de procedimientos
•  Evitar el posible código ; accion Q
; recuperar args Q
de procedimientos y JMP Q
; accion R
funciones locales ; recuperar args R
JMP R
R:
accion q (...); ; codigo de R
CSF
Q:
accion r (...); ; código de Q
principio CSF
...
fin
; accion R
principio ; recuperar args R
... R:
fin ; codigo de R
CSF
; accion Q
; recuperar args Q
Q:
; código de Q
CSF
12048 - J. Neira - 56
Recuperar los argumentos
•  Los parámetros por va- •  Los parámetros por
lor/referencia se copia se tratan como
tratan de forma variables locales:
separada: – Todos se recuperan al
– Todos se recuperan al inicio
inicio, unos son valores – Los que son S o E/S se
y otros son direcciones devuelven al final
– Ninguno se devuelve al
final.
•  Los argumentos de tipo
; recuperar C
SRF 0 5 vector pueden requerir
ASGI que todas las compo-
; recuperar K
SRF 0 4
ASGI nentes sean almacena-
; recuperar I das en la pila y luego
SRF 0 3
ASGI recuperadas.
12048 - J. Neira - 57
Utilización de parámetros
programa p; 1.  valor de un parámetro por
entero i, j; referencia
accion q(ref entero m); 2.  dirección de un parámetro
principio por referencia
escribir (m); 1
m := 0 2 3.  valor de un parámetro por
fin valor y otro por referencia
accion r(val entero k; 4.  parámetro por valor utiliza-
ref entero l); do como argumento a
principio parámetro por referencia
escribir (k, l); 3
l := 0; 5.  parámetro por referencia
q (k); 4
q (l); 5 utilizado como argumento
fin a parámetro por referencia
principio 6.  variables utilizadas como
r (i, j); 6 parámetros por valor y re-
fin ferencia respectivamente
12048 - J. Neira - 58
Código que debe ser generado
ENP L0 SRF 0 4 ; L
; accion Q 3 DRF
SRF 0 3 ;rec. M DRF
ASGI WRT 1
JMP L1 SRF 0 4 ; L
L1: SRF 0 3 ; M DRF
1 DRF STC 0
DRF ASG
WRT 1 SRF 0 3 ; K
SRF 0 3 ; M 4 OSF 5 1 1 ; Q
2 DRF SRF 0 4 ; L
STC 0 5 DRF
ASG OSF 5 1 1 ; Q
CSF CSF
; accion R ; ppal P
SRF 0 4 ;rec. L L0: SRF 0 3 ; I
ASGI DRF
SRF 0 3 ;rec. K 6 SRF 0 4 ; J
ASGI OSF 5 0 13 ; R
JMP L2 LVP
L2: SRF 0 3 ; K
3 DRF
WRT 1
12048 - J. Neira - 59
Y para funciones.....
•  Versión C:
; recuperar parametros
funcion mcd( SRF 0 4 ; B
val entero a,b) ASGI
dev entero; SRF 0 3 ; A
entero r; ASGI
JMP MCD
principio ; codigo de mcd
r := a mod b; MCD:
mq r <> 0 ...
a := b; ...
b := r; ; dejar resultado en
r := a mod b ; la pila
fmq; SRF 0 4
dev (b); DRF
CSF
fin CSF

12048 - J. Neira - 60
Y para funciones.....
•  Versión Pascal:
; recuperar parámetros
SRF 0 5 ; B
funcion mcd( ASGI
val entero a, b) SRF 0 4 ; A
dev entero; ASGI
entero r; JMP MCD
; código de mcd
principio MCD:
r := a mod b; ...
mq r <> 0 ...
SRF 0 3 ; MCD
a := b; SRF 0 5 ; B
b := r; DRF
r := a mod b ASG
fmq; ; dejar resultado en
; la pila
mcd := b; SRF 0 3 ; MCD
fin DRF
CSF

12048 - J. Neira - 61

También podría gustarte