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
mult
3. (E) ⇒ E’ 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 E
b 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
INEFICIENCIA SRF 0 5
EN INEFICIENCIA
INEFICIENCIA
ENTIEMPO:
TIEMPO: ; Acceso a B. EN
ENESPACIO:
ESPACIO:
¿hay
SRF 0 4
¿hayalguna
algunaforma
forma ¿está
menos
menoscostosa
costosade
de
DRF ¿estább**cc
hacer ; Acceso a C. calculado
calculado
hacerlala en
multiplicación?
multiplicación? SRF 0 3 enalgún
algúnsitio?
sitio?
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 int sig[MAXANID], nivel = 0;
begin
....
end; void abrir_bloque ()
{... sig[++nivel] = INICIAL;}
var n : integer;
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? */
m = 34 + 1, j = i + 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 = $3;
$$.cod = code (STC, $1); 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>;

;; nn yy oo dependen
dependen de
de la
la declaración
declaración
SRF
SRF nn oo
;; código
código para
para expresión
expresión11
...
...
;; límite
límite inferior
inferior
STC
STC 44
SBT
SBT
;; tamaño
tamaño (en
(en este
este caso
caso sobra)
sobra)
STC
STC 11
TMS
TMS
PLUS
PLUS
;; código
código para
para expresión
expresión22
...
...
ASG
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] := ...;

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
Paraun
unoperador
operadorn-ario:
n-ario:
a*b + c*d - e*f + 10
1.
1. Generar
Generarcódigo
códigopara
paraeva-
eva-
+ luar
luarlos
losoperandos
operandos1..n,
1..n,al-
al-
macenando
macenandolos losresultados
resultados
- 10 en
enlocalizaciones
localizacionestempo-
tempo-
rales-
rales-
+ *
2.
2. Generar
Generarcódigo
códigopara
paraeva-
eva-
* * e f luar
luarel
eloperador,
operador,utilizando
utilizando
los
losoperandos
operandosalmacena-
almacena-
a b c d dos
dosenenlas
lasnnlocalizaciones
localizaciones
temporales
temporalesyyalmacenando
almacenando
a b * c d * + e f * - 10 + elelresultado
resultadoen
enotra
otralocali-
locali-
zación
zacióntemporal.
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
- 10 ;variable D
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
‘registerallocation
allocationproblem’
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.
t5 := t4 + 10; 1. cc == 00
00
2.
2. Para
Paragenerar
generarun
unnuevo
nuevo
t0 := A * B; 11 nombre
nombretemporal,
temporal,utilizar
utilizar
tc,eeincrementar
incrementar ccen
t1 := C * D; 22 tc, en1. 1.
t0 := t0 + t1; 11
t1 := E * F; 22 3.
3. Cuando
Cuandoaparezca
aparezcaun
un
t0 := t0 - t1; 11 nombre
nombretemporal
temporalcomo
como
t0 := t0 + 10; 11 operando,
operando,decrementar
decrementar cc
12048 - J. Neira -
en
en1.
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
; recuperar K que todas las compo-
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;
4 5. parámetro por referencia
q (k); utilizado como argumento
q (l); 5
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