El documento trata sobre la generación de código intermedio en los compiladores. Explica que el código intermedio facilita la optimización, aumenta la portabilidad del compilador y divide el proceso de compilación en fases. Describe diferentes representaciones intermedias como RPN, código P y códigos de tres direcciones, y explica cómo se generan tercetos y tercetos indirectos a partir del análisis semántico.
Tinciones simples en el laboratorio de microbiología
Generación código intermedio 2
1. Generación de código. Procesadores de
Lenguaje I
Generación de Código Intermedio
Proceso de Síntesis
„ Lenguaje Intermedio
„ Generación de Código
Ventajas del código intermedio
„ Facilitar la fase de optimización
„ Aumentar la portabilidad del compilador de una máquina a otra
Š Se puede utilizar el mismo analizador para diferentes generadores
Š Se pueden utilizar optimizadores independientes de la máquina
„ Facilitar la división en fases del proyecto
Fuente Scanner Parser
Generador
de
Código
TDS
LI Objeto
Generación de código. Procesadores de
Lenguaje I
Generación de Código Intermedio
„ Aumentar la portabilidad del compilador de una máquina a otra
Š Se puede utilizar el mismo analizador para diferentes generadores
Š Se pueden utilizar optimizadores independientes de la máquina
Generador
de
Código Intemedio
Optimización
independiente
de máquina
C
Pascal
Ada
C++
Java
Intel X
Dec-Alpha
Motorola
N+M vs N*M
front-ends
back-ends
2. Generación de código. Procesadores de
Lenguaje I
Fase de Análisis
Err
ors
position := initial + rate * 60
lexical analyzer
id1 := id2 + id3 * 60
syntax analyzer
id2l
id3
+
*
semantic analyzer
:=
id1
60
:=
id1
id2l
id3
+
*
inttoreal
intermediate code generator
60
Symbol
Table
position ....
initial ….
rate….
Generación de código. Procesadores de
Lenguaje I
Fase de Síntesis
Err
ors
intermediate code generator
temp1 := inttoreal(60)
temp2 := id3 * temp1
temp3 := id2 + temp2
id1 := temp3
code optimizer
temp1 := id3 * 60.0
id1 := id2 + temp1
final code generator
MOVF id3, R2
MULF #60.0, R2
MOVF id2, R1
ADDF R1, R2
MOVF R1, id1
Symbol Table
position ....
initial ….
rate….
3 address code
3. Generación de código. Procesadores de
Lenguaje I Tipos de representaciones
intermedias
La representación del código intermedio depende
de la máquina objeto:
„ 0-direcciones: código para máquinas de pila (código P)
„ 2-direcciones: códigos para máquinas con operaciones
sobre registros de memoria
„ 3-direcciones: código para máquinas de arquitectura
RISC
En todo caso, añade un recorrido descendente
adicional para generar el código final
Generación de código. Procesadores de
Lenguaje I Tipos de representaciones
intermedias
Propiedades:
„ Fácil de producir en el análisis semántico
„ Fácil de traducir a código máquina real
„ Instrucciones simples y concisas, de fácil optimización
Tipos
„ Árboles de Sintaxis Abstracta
„ Notación Polaca Inversa (RPN)
„ Código P
„ Códigos de tres direcciones
Š Cuartetos
Š Tercetos
Š Tercetos Indirectos
4. Generación de código. Procesadores de
Lenguaje I Representaciones intermedias:
RPN
Notación Polaca Inversa (RPN)
„ Los operadores van después de los operandos
Š S = A + B * C → S A B C * + =
„ Ventajas
Š Facilidad para generar código a partir de ella
Š Es la notación más sencilla para el lenguaje intermedio
„ Inconvenientes
Š El código es difícil de entender
Š Poca flexibilidad
Š No es útil para optimización de código
Generación de código. Procesadores de
Lenguaje I
Representaciones intermedias: P
Código P
„ Extensión RPN para máquina completa (etiquetas, saltos)
„ Razones históricas (intérpretes Pascal)
„ Primer caso de máquina virtual
Š Todas las operaciones toman como argumentos la pila
Š Cargar/almacenar: lod, lda, ldc, sto
Š Aritmética: adi, sbi, mpi
Š Saltos: ujp, fjp, lab
„ Similares ventajas e inconvenientes (es un CI muy
próximo a un lenguaje ensamblador)
5. Generación de código. Procesadores de
Lenguaje I
Representaciones intermedias: P
Ejemplos Código P
Ejemplo 2:
if cond then x=3
Codigo P
lod cond // carga cond
fjp L1 // si falso salta a L1
lda x // carga direccion x
ldc 3 // carga constante 3
sto // almacena tope en inf
lab L1 // etiqueta L1
1
y
&x
…
cond
…
Ejemplo 1:
x:=y+1
Codigo P
lda x // carga direccion x
lod y // carga valor y
ldc 1 // carga constante 1
adi // suma 2 pos pila
sto // almacena tope en inf.
3
&x
…
Generación de código. Procesadores de
Lenguaje I
Árboles de Sintaxis Abstracta
Son árboles de derivación en los que no existe
información superflua
Cada nodo hoja representa un operando y cada no-hoja
un operador
Ejemplos
Árbol ASA S:=A+B*C IF A<B THEN X:=B A[I]:=B
E
E
T
F
A
T
F
B
+
+
A B
:=
S +
A *
B C
IF
< :=
A B X B
:=
[ ] B
A I
6. Generación de código. Procesadores de
Lenguaje I
Códigos de Tres Direcciones
Sentencias del estilo x = y op z
„ Cada línea de código tiene un operador y hasta
tres direcciones
„ Es una representación lineal del ASA
„ Uso generoso de variable temporales
„ Directamente relacionado con evaluación de
expresiones
Ejemplo: a = b*(c+d) se traduce a:
tmp1 = c+d
tmp2 = b*tmp1
a = tmp2
Generación de código. Procesadores de
Lenguaje I
Códigos de Tres Direcciones
Ejemplos (relacionar con ASA)
Ejemplo 1:
a=b*-c+4
Codigo 3 direcciones
t1=-c
t2=b*t1
t3=4
t4=t3+t2
a=t4
Ejemplo 2:
if cond then then_statements
else
else_statements;
end if;
Codigo 3 direcciones
t1 = cond
iff t1 else_label
codigo para ““then_statements””
goto endif_label
else_label:
codigo para ““else_statements””
endif_label:
7. Generación de código. Procesadores de
Lenguaje I Instrucciones en Código 3
direcciones
Asignaciones: x:=y op z (op aritmético o lógico)
Asignaciones 1 argumento x:= op y
Copia x:=y
Salto incondicional: goto L (L etiqueta)
Salto condicional gotoc x L frecuente.: iff x L (if false)
Salto condicional if x relop y goto L
Etiquetas: label L
Llamada a subrutina:
param x1
...
param xn
call p,n
ret
Asignaciones indexadas
x:=y[i]
x[i]=y
Asignaciones con punteros
x:=&y, x:=*y, *x:=y
Generación de código. Procesadores de
Lenguaje I
Códigos de 3 direcciones
Cada línea de código tiene un operador y hasta tres direcciones
Tipos: Cuartetos, Tercetos, Tercetos Indirectos
Cuartetos
„ Se representan por cuatro valores:
(<OPERADOR>,<Operando1>,<Operando2>,<Resultado>)
„ Ejemplos
Expresión Cuartetos Otra representación
S:=A+B*C * B C T1 (*, B, C, T1)
+ A T1 T2 (+, A, T1, T2)
:= T2 S (:=,T2, , S )
IF A<B THEN X:=B < A B E1 (<, A, B, E1)
IFF E1 E2 (IFF, E1, , E2 )
:= B X (:=, B, , X )
LABEL E2 (LABEL, , , E2)
8. Generación de código. Procesadores de
Lenguaje I
Implementación de código 3
direcciones
Implementación con cuartetos
„ 4 campos: (op,y,z,x) para x=y op z
„ Campos se anulan si no se necesitan, ej.: (rd,x,,)
Implementación con tercetos
„ El cuarto elemento siempre es un temporal
„ En lugar de nombrarlo, utilizar el propio índice del
terceto
Ejemplo: a = b+(c*d)
[cuartetos] [tercetos]
1. (mul,c,d,t1) 1: (mul,c,d)
2. (add,b,t1,t2) 2: (add,b,(1))
3. (:=,a,t2,_) 3: (:=,a,(2))
Generación de código. Procesadores de
Lenguaje I
Tercetos
Los cuartetos son la herramienta más general
Inconvenientes
„ Ocupan demasiado espacio
„ Requieren muchas variables auxiliares para
almacenar los resultados intermedios
Los tercetos resuelven este problema
suprimiendo el operando del resultado, queda
implícito y asociado a dicho terceto
(<OPERADOR>, <Operando1>, <Operando2>)
„ Hacen referencia a otro terceto
„ Son equivalentes a Árboles de Sintaxis Abstracta
9. Generación de código. Procesadores de
Lenguaje I
Tercetos y Tercetos Indirectos
Ejemplos
Expresión Tercetos
S:=A+B*C 1 (*, B, C)
2 (+, A, (1))
3 (:=, 2, S)
IF A<B THEN X:=B 1 (<, A, B)
2 (IFF,(1),(4))
3 (:=, B, X)
4 (,,)
Los Tercetos Indirectos son análogos a los anteriores
pero en lugar de ejecutarse secuencialmente se ejecutan
según un vector llamado SECUENCIA
„ Son más fáciles de optimizar
„ Ocupan menos memoria, el mismo terceto aparece una vez
Generación de código. Procesadores de
Lenguaje I
Tercetos Indirectos, Ejemplos
Expresión Tercetos Ind.
S:=A+B*C 1 (*, B, C)
X:=A+B*C 2 (+, A, (1))
3 (:=, (2), S)
4 (:=, (2), X)
VE=(1, 2, 3, 1, 2, 4)
WHILE X<B DO X:=X+1 1 (<, X, B)
2 (gotoc, (1), (4))
3 (goto, , (7))
4 (+, X, 1)
5 (:=, (4), X)
6 (goto, , (1))
7 (, , )
VE=(1, (2, 3, 4, 5, 6)+, 7)
10. Generación de código. Procesadores de
Lenguaje I
Generación de Código Intermedio:
Declaraciones
Definición de atributos con CI (sintetizado) + acciones
semánticas
Construcción explícita de la tabla de símbolos
„ Se crean entradas para cada variable según su tipo
„ Reserva de espacio en función del tipo empleado
Š offset es una variable global con dirección de la tabla actual
Š T.tipo, T.ancho: atributos que caracterizan cada entrada en
la tabla
Simplificación: tabla de un solo procedimiento
„ Extensiones para declaraciones en procedimientos y
ámbitos anidados
Generación de código. Procesadores de
Lenguaje I
Declaraciones (1 procedimiento)
Producciones Reglas semánticas
P→ {offset=0}
D
D→D; D
D→id: T {ponerTabla(id.lex, T.tipo, offset)
offset=offset+T.ancho}
T→integer {T.tipo=integer
T.ancho=4}
T→real {T.tipo=real
T.ancho=8}
T→array[num]
of T {T0.tipo=array(num.lex, T1.tipo)
T0.ancho=num.lex*T1.ancho}
T→↑T {T0.tipo=pointer(T1.tipo)
T0.ancho=4}
11. Generación de código. Procesadores de
Lenguaje I
Tercetos para Expresiones
Se construyen nombres temporales para los nodos interiores del
árbol sintáctico
Se calcula el valor del no terminal E en el lado izquierdo de E→E+E
dentro de un nuevo temporal t: E1 a t1; E2 a t2; t= t1+t2
„ E.lugar, es el nombre que contendrá el valor de E (“lugar” en TS)
„ E.código, es la secuencia instrucciones de tres direcciones para E
„ La función tempnuevo() devuelve una secuencia de nombres distintos
t1, t2, , t3,... en sucesivas llamadas
„ Las variables tienen el nombre id.lex, y se accede a su declaración en
la tabla de símbolos como lookup(id.lex) (detectar errores)
„ gen(.) genera código de tres direcciones
El número de temporales podría optimizarse posteriormente
Generación de código. Procesadores de
Lenguaje I
Asignaciones y Aritmética
Producciones Regla Semántica
S→ id := E {p=lookup(id.lex);
if (p!=null) S.código := E.código || gen(p ’:=’ E.lugar)}
E→ E+E {E0.lugar := tempnueva();
E0.código := E1.código || E2.código ||
gen(E0.lugar ´:=´ E1.lugar ´+´ E2.lugar)}
E→ E*E {E0.lugar := tempnueva();
E0.código := E1.código || E2.código ||
gen(E.lugar ´:=´ E1.lugar ´*´ E2.lugar)}
E→ -E {E0.lugar := tempnueva();
E0.código := E1.código || gen(E0.lugar´:=menosu´ E1.lugar)}
E→ (E) {E0.lugar := E1.lugar;
E0.código := E1.código}
E→ id {p=lookup(id.lex), if (p!=null) E.lugar := p;}
12. Generación de código. Procesadores de
Lenguaje I
Conversiones de Tipos
Producciones Regla Semántica
S→ id := E {p=lookup(id.lex);
S.código := E.código || gen(p ’:=’ E.lugar)}
E→ E+E {E0.lugar := tempnuevo();
if (E1.tipo=integer and E2.tipo=integer) then
c=gen(E0.lugar ´:=´ E1.lugar ´+´ E2.lugar)
E0.tipo=int
if (E1.tipo=real and E2.tipo=real) then
c=gen(E0.lugar ´:=´ E1.lugar ´+´ E2.lugar)
E0.tipo=real
if (E1.tipo=integerl and E2.tipo=real) then
c=gen(E0.lugar ´:=inttoreal´ E1.lugar ´+´ E2.lugar)
E0.tipo=real
if (E1.tipo=real and E2.tipo=integer) then
c=gen(E0.lugar ´:=l´ E1.lugar ´+ inttoreal´ E2.lugar)
E0.tipo=real}
E0.código := E1.código || E2.código ||c
….
Ej.: x:=y+i*j
t1:=multi(i,j)
t3:=inttoreal t1
t2:=addr(y, t3)
x:=t2
Generación de código. Procesadores de
Lenguaje I
Evaluación de Declaraciones y
Expresiones
Ej.: a: int; c: real;
a=0;c=a*4.0+1;
P
c
real
Código
Intermedio:
t1:=0
a:=t1
t2:=inttoreal a
t3:= t2 *4.0
t4:= t3+1
c:=t4
Ds
Ds D
Ds D
id
(a)
id
(c)
T
(int)
T
(real)
λ
Ss
S Ss
a
entero
id S Ss
(a)
E
(0)
:
=
=E
E E
id
(c)
(1)
+
* E
(4)
E
(a)
λ
:
100
104
TS
;
13. Generación de código. Procesadores de
Lenguaje I
Evaluación de Declaraciones y
Expresiones
Con atributo código: concatenar atributos sintetizados
a: int; c: real;
a=0;c=a*4.0+1;
t1:=0
a:=t1
t2:=inttoreal a
t3:= t2 *4
t4:= t3+1
c:=t4
Ss
S Ss
=
id S Ss
(a)
E
(0)
id
(c)
= E
E E
(1)
+
* E
(4)
E
(a)
λ
t1:=0
a:=t1
t2:=inttoreal a
t3:= t2 *4
t4:= t3+1
c:=t4
t2:=inttoreal a
t3:= t2 *4
t4:= t3t +1 2:=inttoreal a
t3:= t2 *4
Generación de código. Procesadores de
Lenguaje I
Evaluación de Declaraciones y
Expresiones
Sin atributo código: escribir código globalmente
a: int; c: real;
a=0;c=a*4.0+1;
t1:=0
a:=t1
t2:=inttoreal a
t3:= t2 *4
t4:= t3+1
c:=t4
Ss
S Ss
=
id S Ss
(a)
E
(0)
id
(c)
c:=t4
= E
E E
(1)
+
* E
(4)
E
(a)
λ
t1:=0
a:=t1
t4:= t3+1
t2:=inttoreal a
t3:= t2 *4
Salida global
14. Generación de código. Procesadores de
Lenguaje I
CGI sin utilizar atributo código
Producciones Regla Semántica
S→ id := E {p=lookup(id.lex);
if (p!=null) emitir(p ’:=’ E.lugar)}
E→ E+E {E0.lugar := tempnuevo();
emitir(E0.lugar ´:=´ E1.lugar ´+´ E2.lugar)}
E→ E*E {E0.lugar := tempnuevo;
emitir(E0.lugar ´:=´ E1.lugar ´*´ E2.lugar)}
E→ -E {E0.lugar := tempnuevo();
emitir(E0.lugar´:=menosu´ E1.lugar)}
E→ (E) {E0.lugar := E1.lugar;}
E→ id {p=lookup(id.lex), if (p!=null) E.lugar := p;}
Generación de código. Procesadores de
Lenguaje I
Literales numéricos
Dos posibilidades:
„ estricta (lugar es una dirección de memoria)
„ lugar es un texto
Producciones Regla Semántica
a) E→ num {E.lugar := nuevatemp(); emitir(E.lugar ’:=’ num.lex)}
b) E→ num {E.lugar := num.lex)}
a=3+b+7+c tmp1=3
tmp2=tmp1+b
tmp3=7
tmp4=tmp2+tmp3
tmp5=tmp4+c
a=tmp5
tmp1=3+b
tmp2=tmp1+7
tmp3=tmp2+c
a=tmp3
15. Generación de código. Procesadores de
Lenguaje I
Expresiones con Arrays (1D)
Suponiendo almacenamiento secuencial, las direcciones se calculan
desde la dirección base (dirección en memoria) con desp. lineal:
„ a[i+1]:: dir_base(a)+(i+1)*sizeof(a)
E0→id [E1] {p=lookup(id.lex)
E0.lugar=tempnuevo()
t=tempnuevo()
gen(t ’=’ E1.lugar ’*’ size(p))
gen(E0.lugar ’=p[’ t ’]’ )
}
S→id [E1]=E2 {p=lookup(id.lex)
t=tempnuevo()
gen(t ’=’ E1.lugar ’*’ size(p))
gen(’ p[’ t ’]=’ E2.lugar)
}
También puede hacerse con indirecciones (punteros)
a=p[i] t1=&p;
t2=t1+i;
a=*t2
Ejemplo:
a[i+1]=a[j+2]+3;
t1=j+2
t2=t1*size(a)
t3=a[t2];
t4=t3+3
t5=i+1
t6=t5*size(a)
a[t6]=t4
Generación de código. Procesadores de
Lenguaje I
Evaluación de Arrays (1D)
Sin atributo código: escribir código globalmente
a[i+1]=a[j+2]+3;
S
id
(a) t1:=i+1
t5:= t1*size(a)
a[t5]:=t4
E E
E + E
t2:=j+2
Salida global
[ ]
id
(i)
num
(1)
=
E
E + E
id
(a)
[ ]
id
(j)
num
(2)
Ejemplo:
a[i+1]=a[j+2]+3;
t1:=i+1
t2:=j+2
t3:=t2*size(a)
t4:=a[t3]
t5:= t1*size(a)
a[t5]:=t4
t3:=t2*size(a)
t4:=a[t3]
16. Generación de código. Procesadores de
Lenguaje I
Expresiones con registros y punteros
Registros
„ Los registros tienen campos con desplazamiento fijo
typedef struct cplx{
double real;
double imag;
cplx.real
cplx.imag
};
„ código 3 dir independiente: función “offset (tipo,campo)” en la TS
E→id “.” id {
E.lugar=tempnuevo();
t1=tempnuevo();
t2=tempnuevo();
gen(t1 ’=&’ id1.lex)
gen(t2 ‘=’ t1 +offset(’ id1.lex ’ ,’id2.lex ’)’);
gen(E.lugar ’=*’ t2);
}
Punteros tienen traducción directa
„ i=*x;
„ *x=i;
…
…
base de cplx
desplaz. campo “imag”
Generación de código. Procesadores de
Lenguaje I
Expresiones con registros y punteros
Combinaciones de punteros y registros
cplx *c1, *c2;
…
c1 ->real=c2->imag;
E→id “->” id {
…
cplx.real
cplx.imag
…
E.lugar=tempnuevo();
t=tempnuevo();
gen(t ‘=’ id1 +offset(’ id1.lex ’ ,’id2.lex ’)’);
gen(E.lugar ’=*’ t);
}
base de cplx
desplaz. campo “imag”
17. Generación de código. Procesadores de
Lenguaje I
Expresiones con registros y punteros
Ejemplos
cplx *c1, *c2;
…
c1 ->real=c2->imag;
…
cplx.real
cplx.imag
…
base de cplx
desplaz. campo “imag”
Ejemplo:
num.real=num.imag;
t2=&num
t3=t1+offset(num,imag)
t1=*t1
t4=&num
t5=t4+offset(num,real)
*t5=t1
Ejemplo:
c1->real= c2-> num.imag;
t2=c1+offset(c1,imag)
t3=*t2
t4=c2+offset(c2,real)
*t4=t3
Generación de código. Procesadores de
Lenguaje I
Evaluación de Arrays Multi-dimensionales
Un array se accede como un bloque
de posiciones consecutivas. Si empieza
en 0:
w base
„ posicion a[i]: base+i*w
Matriz 2 dimensiones (por filas): A[i1][i2]
„ posicion: base+(i1*n2+i2)*w
a[i]
…
A[0][0] … A[0][i2] …
… … … …
A[i1][0] … A[i1][i2] …
Generalización a k dimensiones: A[i1][i2]…[ik]
„ posicion: base+((…((i1*n2+i2)*n3+i3)…)*nk+ik )*w
„ Ecuación recurrente:
Š e1=i1
Š em=em-1*nm+im
a[1]
a[0]
… … … …
n2
i2
i1
18. Generación de código. Procesadores de
Lenguaje I
Evaluación de Arrays Multi-dimensionales
“E” representa la evaluación de una expresión, “L” el acceso a una
variable
„ L.offset es distinto de null si L es un acceso con desplazamiento (array
según instrucción de código intermedio)
„ L.lugar es la posición de comienzo
El símbolo recurrente “Lista” efectúa el cálculo de posición de los índices
con la ecuación recursiva:
„ Lista0::=Lista1 , E
„ Lista.lugar almacena el valor em
„ Lista.ndim es la dimensión (Lista0.ndim= Lista1.ndim+1)
„ Al terminar el último índice hay que multiplicar por w
El tipo array mantiene sus propiedades, en la tabla de símbolos: id.lex
tiene asociada una dirección: Lista.array
„ Tamaño total: ancho (Lista.array)
„ Límite de una dimensión: limite(Lista.array, m)
Generación de código. Procesadores de
Lenguaje I
Evaluación de Arrays Multi-dimensionales
Producciones Regla Semántica
S→ L := E {if (L.offset == null) gen(L.lugar’=‘ E.lugar
else gen(L.lugar ‘[‘ L.offset ‘]=’E.lugar}
E→ L {if (L.offset == null) gen(E.lugar’=‘ L.lugar
else E.lugar=tempnuevo(); gen(E.lugar ‘=‘L.lugar ‘[‘ L.offset ‘]’)}
E→ num {E.lugar=tempnuevo(); gen(E.lugar ‘=‘ num.val)}
L→ id {p=lookup(id.lex), L.lugar := p, L.offset=null}
L→ Lista] {L.lugar= tempnuevo();
L.offset= tempnuevo();
gen(L.lugar ´:=´ base(Lista.array) )
gen(L.offset ‘=‘ Lista.lugar ‘*’ ancho (Lista.array))}
Lista→Lista][E {t= tempnuevo(), m=Lista1.ndim+1
gen(t ‘=‘ Lista1.lugar ‘*’ limite(Lista1.array,m))
gen(t ‘=‘ t ‘+’ E.lugar)
Lista0.array=Lista1.array
Lista0.lugar=t, Lista0.ndim=m}
Lista→id [E {p=lookup(id.lex), Lista.array= p
Lista.lugar=E.lugar
Lista.ndim=1}
19. Generación de código. Procesadores de
Lenguaje I
Evaluación de Arrays Multi-dimensionales
Ej.: x:=M[3][1] (M de tipo array{[0…4]x[0…4],int})
S1
L1 := E1
Lista1
Lista2 [ E3
num (1)
]
L2
id [ E2
(M)
num (3)
id
(x)
]
• base
• limite(i)
• ancho
celda
Código
Intermedio:
t1:=3
t2:=1
t3:=t1*5
t3:=t3+ t2
t4:=base(M)
t5:=t3*4
t6:=t4[t5]
x:=t6
Generación de código. Procesadores de
Lenguaje I
S1: /S1->L1=E1/
L1: L1.lugar=x /L1->id/
L1.offset=null
E1: /E1->L2/
L2: /L2->Lista1]/
Lista1: /Lista1->Lista2][E3/
Lista2: /Lista2->E2]/
E2: E2.lugar=t1 /E2->num/
t1=3
Lista2.lugar=t1
Lista2.ndim=1
Lista2.array=M
E3: E3.lugar=t2 /E3->num/
t2=1
Lista1.lugar=t3
m=2
t3= t1*5 (*lista2*limite(M,1)*)
t3= t3+t2 (*suma indice E3*)
Lista1.array=M
Lista1.lugar=t3
Lista1.ndim=m
L2.lugar= t4
L2.offset=t5
t4=base(M)
t5=t3*ancho(M) (*lista1*ancho*)
E1.lugar=t6
t6=t5[t5]
x=t6
t1:=3
t2:=1
t3:=t1*5
t3:=t3+ t2
t4:=base(M)
t5:=t3*4
t6:=t4[t5]
x:=t6
20. Generación de código. Procesadores de
Lenguaje I
GCI para Expresiones Booleanas
Dos posibilidades:
„ Valores numéricos (0,1) …
„ Etiquetas para control de flujo
Con valores numéricos: E toma un valor aritmético,
instrucciones de salto en función del valor
if (a<b) x=1
t1=a<b
iff t1 L1
x:=1
L1 …
Con etiquetas: una expresión booleana tiene directamente las
etiquetas, que son posiciones destino de control de flujo:
E.true, E.false (evaluación en cortocircuito)
„ Son atributos heredados
if (a<b) x=1
if a < b goto L1
goto L2
L1 x:=1
L2 …
E, a<b, tiene un
atributo: t1
E, a<b, tiene tres
atributos: L1, L2, código
Generación de código. Procesadores de
Lenguaje I
GCI para Expresiones Booleanas
Ejemplos:
if E then S1 else S2
Codigo 3 direcciones
Código de evaluación de E
(hacia qué etiqueta salto)
E.true:
Código para S1
goto ‘‘Seguir’’
E.false:
Código para S2
Seguir:
…siguientes instrucciones
while (E) S
Codigo 3 direcciones
Comienzo:
Código de evaluación de E
(hacia qué etiqueta salto)
E.true:
Código para S
goto ‘‘Comienzo’’
E.false:
…siguientes instrucciones
22. Generación de código. Procesadores de
Lenguaje I
GCI- Condiciones Booleanas
Evaluación “en cortocircuito”
Producción Regla Semántica
E:=‘true’ {E.codigo = gen (‘goto’ E.true)}
E:=‘false’ {E.codigo = gen (‘goto’ E.false)}
E:=id1 relop id2 {E.code=gen(‘if’ id1.lugar ‘relop’ id2.lugar ’goto’ E.true)||
gen(‘goto’ E.false)}
E0:=E1´or´ E2 {E1.false= newlabel()
E1.true= E0.true
E2.true= E0.true
E2.false= E0.false
E0.codigo= E1.codigo || gen(E1.false ‘:’) || E2.codigo}
E0:=E1´and´ E2 {E1.true= newlabel()
E1.false= E0.false
E2.true= E0.true
E2.false= E0.false
E0.codigo= E1.codigo || gen(E1.true ‘:’) || E2.codigo}
E0:=(E1) {E1.false= E0.false
E1.true= E0.true
E1.code= E0.code}
Generación de código. Procesadores de
Lenguaje I
GCI- Condiciones Booleanas
Evaluación “en cortocircuito”. Ejemplo:
if (B) S:
codigo de B
Lt0:
código de S
Lf0:
…
Ejemplo:
if (a<(b+32) || (b>0 && a>0))
x=1
t1=b+32
if a < t1 goto Lt0
if b > 0 goto L1
goto Lf0
Label L1:
if a > 0 goto Lt0
goto Lf0
Label Lt0
x=1
Labl Lf0
…
23. Generación de código. Procesadores de
Lenguaje I
GCI- Estructuras de control
CONDICIONAL: S-> if (B) S else S
E0
true B false
label B.true:
S1
goto S.next:
label B.false:
S2
label S.next:
Generación de código. Procesadores de
Lenguaje I
GCI- Estructuras de control
BUCLE: S-> while (B) do S
E0
label inicio:
true B false
label B.true:
S
goto inicio
label S.next:
24. Generación de código. Procesadores de
Lenguaje I
GCI- Sentencias Condicionales
Atributo heredado S.next: instrucción continuación
„ Problema: etiquetas desconocidas a priori (idem)
Producción Regla Semántica
S:=if E then S1 {E.true= newlabel()
E.false= S0.next
S1.next= S0.next
S0.codigo=E.codigo||gen(E.true ‘:’)||S1.codigo}
S0:=if E then S1 else S2 {E.true= newlabel()
E.false= newlabel()
S1.next= S0.next
S2.next= S0.next
S0.codigo=E.codigo||gen(E.true ‘:’)||S1.codigo||
gen(‘goto’ S0.next||gen(E.false ‘:’)||S2.codigo}
S0:= while E do S1 {begin = newlabel()
E.true= newlabel()
E.false= S0.next
S1.next= begin
S0.codigo=gen(begin ‘:’)||E.codigo|| gen(E.true ‘:’)||
S1.codigo||gen(‘goto’ begin)}
Generación de código. Procesadores de
Lenguaje I
GCI- Condicionales sin atrib código
Atributo heredado S.next: instrucción continuación
Producción Regla Semántica
S0:=if {E.true= newlabel(); E.false= S0.next}
E then {emitir(‘label ’ E.true ‘:’); S1.next= S0.next;}
S1
S0:=if {E.true= newlabel(); E.false= newlabel()}
E then {emitir(‘label ’ E.true ‘:’); S1.next= S0.next}
S1 else {emitir(‘label ’ E.false ‘:’); S2.next= S0.next}
S2
S0:= while {begin = newlabel(); E.true= newlabel();
E.false= S0.next; emitir(‘label ’ begin ‘:’);}
E do {S1.next= begin; emitir(‘label ’ E.true ‘:’); }
S1
25. Generación de código. Procesadores de
Lenguaje I
Ejemplo control de flujo
while s<K do
if a>b
s=s+a
else
s=s-a
S1
while E1
do S2
if E2
S3 else S4
id >
(a)
id
(b)
id >
(s)
id
(K)
Código 3
direcciones
L1: if s<K goto L2
goto L0
L2: if a>b goto L3
goto L4
L3: t1=s+a
s=t1
goto L0
L4: t2=s-a
s=t2
goto L1
L0: …
Generación de código. Procesadores de
Lenguaje I
-
S1.next=L0 (**)
S1: /S1->while E1 do S2/
S1.next=L0
begin=L1
E1.true=L2
E1.false=L0
E1: /E1->id op id/
E1.codigo=if s<K goto L2
goto L0
S2.next=L0
S2: /S2->if E2 then S3 else S4/
E2.true=L3
E2.false=L4
E2: /E2->id op id/
E2.codigo=if a>b goto L3
goto L4
goto L0
S3.next=L1
S3: /S3->s=s+a/
S3.codigo=t1=s+a
s=t1
S4.next=L0
S4: /S4->s=s-a/
S4.codigo=t2=s+a
s=t2
S2.codigo=
S1.codigo=
if a>b goto L3
goto L4
L3: t1=s+a
s=t1
goto L0
L4: t2=s-a
s=t2
L1: if s<K goto L2
goto L0
L2: if a>b goto L3
goto L4
L3: t1=s+a
s=t1
goto L0
L4: t2=s-a
s=t2
goto L1
L0: …
26. Generación de código. Procesadores de
Lenguaje I
Relleno con retroceso (back-patching)
El código intermedio para control de flujo usa saltos a etiquetas
“futuras”
„ No es problema en CI puesto que se tratan como nombres
„ En el código final hay que transformarlas en direcciones
Una solución es diferir su ajuste final a una pasada posterior
„ Implementación sencilla: archivo temporal
goto target
...
goto target
...
target: mov foobar,r1
Tabla
target
…
goto target
….
goto target
…
target: mov foobar, r1
backpatch list
(lista enlazada)
Código
Generación de código. Procesadores de
Lenguaje I
Traducción de llamadas a funciones
Es el aspecto más dependiente del entorno de ejecución
„ Difícil de generalizar a código intermedio
Dos aspectos básicos
„ Declaración de función/procedimiento (o definición)
„ Llamada de función/procedimiento
El código intermedio define el punto de entrada y el punto de
retorno de la función
„ Definición
Instrucción de entrada
<código del cuerpo de la función>
Instrucción de salida
„ Llamada
Instrucción de comienzo de cálculo de parámetros
<código del cálculo de parámetros>
Instrucción de llamada
27. Generación de código. Procesadores de
Lenguaje I
GCI para llamadas a funciones
Instrucciones 3 direcciones
param x entryf
call f, n return x
Código P
mst ent f
cup ret
Ej.:
int f(int x, int y)
{return x+y+1;}
f(2+3,4);
entry f
t1=x+y
t2=t1+1
return t2
t1=2+3
param t1
param 4
call f 2
ent f
lod x
lod y
adi
ldc 1
adi
ret
mst
ldc 2
ldc 3
adi
ldc 4
cup f
Código 3-dir Código P
Generación de código. Procesadores de
Lenguaje I
Llamadas a funciones dentro de
expresiones
Producciones Regla Semántica
S→ id := E {p=lookup(id.lex);
if (p!=null) emitir(p ’:=’ E.lugar)}
E→ E+E {E0.lugar := tempnuevo();
emitir(E0.lugar ´:=´ E1.lugar ´+´ E2.lugar)}
…
E→ id {p=lookup(id.lex), if (p!=null) E.lugar := p;}
E → id(lista) {para cada elemento p en lista.pila
emitir(‘param ‘ p)
emitir(‘call’ id.lugar)}
…
28. Generación de código. Procesadores de
Lenguaje I
Ejemplo con funciones y expresiones
Sin atributo código: escribir código globalmente
a=0;c=1+f(2,4*a);
t1:=0
a:=t1
t2:=4*a
param t2
param 1
t3=call f 2
t4:= 1+t3
c:=t4
S
id
(c)
= E
+
E E
(1)
id ( lista
(f)
param t2
param 1
t3=call f 2
t2:=4*a
c:=t4
)
, lista
E
E
(4)
* E
(a)
E
(1)
t2
t2 1
t4=1+t3