Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


Compilatori algoritmi generazione di codice, Dispense di Tecniche E Linguaggi Di Programmazione

Compilatori algoritmi generazione di codice

Tipologia: Dispense

2018/2019

Caricato il 20/10/2019

jack-pagoda
jack-pagoda 🇮🇹

5

(5)

40 documenti

1 / 43

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
Generazione Codice Intermedio
Front-end ® generazione codice intermedio
Vantaggi della rappresentazione intermedia (indipendente dal target):
1. Porting ® cambia solo il back-end
2. Ottimizzazione iniziale indipendente dal target
Tecnologie dei Linguaggi Artificiali 8. Generazione codice intermedio
1
Analizzatore
lessicale
programma
sorgente
Analizzatore
sintattico
rappresentazione
intermedia
Analizzatore
semantico
Symbol
Table
Generatore
codice int.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b

Anteprima parziale del testo

Scarica Compilatori algoritmi generazione di codice e più Dispense in PDF di Tecniche E Linguaggi Di Programmazione solo su Docsity!

Generazione Codice Intermedio

 Front-end ® generazione codice intermedio

 Vantaggi della rappresentazione intermedia (indipendente dal target):

1. Porting ® cambia solo il back-end

2. Ottimizzazione iniziale indipendente dal target

Analizzatore

lessicale

programma

sorgente

Analizzatore

sintattico

rappresentazione

intermedia

Analizzatore

semantico

Symbol

Table

Generatore

codice int.

Rappresentazione Intermedia

 Rappresentazione intermedia º struttura dati che rappresenta il programma sorgente durante

la traduzione (es: albero astratto + symbol table)

 Albero astratto

 Codice intermedio ® rappresentazione intermedia più vicina al codice target

 Svariate forme di codice intermedio: in generale ® linearizzazione dell'albero astratto

 Diversi livelli di astrazione

 Rappresentazioni tipiche

rappresentazione adeguata del programma sorgente

inadeguato per il programma target (es :cicli ® goto)

alto ® vicino all'albero astratto

basso ® vicino alla macchina target

Codice a tre indirizzi

P-code

¹ forme

Codice a Tre Indirizzi (ii)

 Esempio esteso: computazione del fattoriale x!

 Note:

 read / write : tradotte direttamente in istruzioni con un indirizzo

 if_false (due indirizzi): usato per tradurre if / repeat

 label (un indirizzo): può essere necessaria nella implementazione del codice a tre indirizzi

 halt (zero indirizzi): terminazione del programma

 Assegnamenti nel sorgente ® mappati su istruzioni di copiatura

read x; /* input of integer */ if x > 0 then fact := 1; repeat fact := fact * x; x := x – 1 until x = 0; write fact endif

read x t1 = x> if_false t1 goto L fact = 1 label L t2 = fact * x fact = t t3 = x – 1 x = t t4 = x== if_false t4 goto L write fact label L halt

fact := fact * x t2^ = fact^ *^ x fact = t

(anche se sufficiente unica istruzione ® ottimizzazione)

Codice a Tre Indirizzi (iii)

 Tipica rappresentazione

 Record (tipicamente):

 Possibile valore null per qualche indirizzo

" istruzione ® record di campi

codice completo

array

lista a puntatori di record

op addr1 addr2 addr

read x t1 = x> if_false t1 goto L fact = 1 label L t2 = fact * x fact = t t3 = x – 1 x = t t4 = x== if_false t4 goto L write fact label L halt

(rd, x, , ) (gt, x, 0, t1) (if_f, t1, L1, ) (asn, 1, fact, ) (lab, L2, , ) (mul, fact, x, t2) (asn, t2, fact, ) (sub, x, 1 , t3) (asn, t3, x, ) (eq, x, 0, t4) (if_f, t4, L2, ) (wri, fact, , ) (lab, L1, , ) (halt, , , )

P-code (ii)

Esempio 2:

 Nota: diversa semantica per

x := y + 1

lda x ; carica l'indirizzo di x lod y ; carica il valore di y ldc 1 ; carica la costante 1 adi ; somma sto ; memorizza la cima all'indirizzo sotto la cima e fa il pop di entrambi

lda ® caricamento dell'indirizzo ® lvalue

lod ® caricamento del valore ® rvalue

P-code (iii)

Esempio 3:

lda x ; carica indirizzo di x rdi ; leggi l'intero, memorizzalo all'indirizzo sulla cima e fai il pop lod x ; carica valore di x ldc 0 ; carica la costante 0 grt ; confronta i due valori, rimuovili, push del risultato booleano fjp L1 ; pop del valore booleano, salta a L1 se falso lda fact ; carica indirizzo di fact ldc 1 ; carica la costante 1 sto ; pop due valori, memorizzando il primo all'indirizzo dato dal secondo lab L2 ; definizione della label L lda fact ; carica indirizzo di fact lod fact ; carica valore di fact lod x ; carica valore di x mpi ; moltiplicazione sto ; pop due valori, memorizzando il primo all'indirizzo dato dal secondo lda x ; carica indirizzo di x lod x ; carica valore di x ldc 1 ; carica la costante 1 sbi ; sottrazione sto ; pop due valori, memorizzando il primo all'indirizzo dato dal secondo lod x ; carica valore di x ldc 0 ; carica la costante 0 equ ; test di uguaglianza fjp L2 ; pop valore booleano, salta a L2 se falso lod fact ; carica valore di fact wri ; stampa top, pop lab L1 ; definizione della label L stp ; termina l'esecuzione

read x; /* input of integer */ if x > 0 then fact := 1; repeat fact := fact * x; x := x – 1 until x = 0; write fact endif

Codice Intermedio come Attributo Sintetizzato

 Esempio: Subset delle espressioni C (assegnamenti come espressioni)

 P-code (A = { pcode }):

 GA più semplice (non necessario generare nomi per temporanei)

 Necessaria una “ store non distruttiva ” per supportare gli assegnamenti come espressioni ® stn

 Semantica di stn:

expr ® id = expr | term term ® term + factor | factor factor ® ( expr ) | num | id

Assunzione: id e num con attributo lessicale lexval = stringa di caratteri

Memorizza il valore all'indirizzo sottostante (come sto)

Lascia il valore in cima alla pila

Scarta l'indirizzo

Produzione Regole semantiche expr 1 ® id = expr 2 expr^1 .pcode = “lda” ||^ id .lexval^ ++^ expr^2 .pcode ++ “stn” expr ® term expr.^ pcode^ = term.^ pcode term 1 ® term 2 + factor term 1 .pcode = term 2 .pcode ++ factor .pcode ++ “adi” term ® factor term .pcode = factor .pcode factor ® ( expr ) factor .pcode = expr .pcode factor ® num factor .pcode = “ldc” || num. lexval factor ® id factor .pcode = “lod” || id. lexval

|| = concatenazione con spazio ++ = concatenazione con newline

Codice Intermedio come Attributo Sintetizzato (ii)

 Esempio (P-code):

(x = x + 3) + 4

expr

term

term factor

factor

( expr )

num 4

id x

=^ expr

term

term factor

factor (^) num 3 id x

Nodes P-code 10, 8 (^) lod x 9 ldc 3

7, 6

lod x ldc 3 adi

lda x lod x ldc 3 adi stn (^3) ldc 4

lda x lod x ldc 3 adi stn ldc 4 adi

Codice Intermedio come Attributo Sintetizzato (iv)

(x = x + 3) + 4

expr

term

term factor

factor

( expr )

num 4

id x

=^ expr

term

term factor

factor (^) num 3 id x

Nodes qcode name 10,8 x 9 3 3 4 7, 6 t1^ =^ x +^3 t

5, 4, 2

t1 = x + 3 x = t1 t

t1 = x + 3 x = t t2 = t1 + 4

t

Codice Intermedio come Attributo Sintetizzato (v)

 Note (su generazione di codice come computazione di un attributo sintetizzato)

 Mostra chiaramente le relazioni fra

 Non pratico, perché:

1. Concatenazione di stringhe

2. Meglio generare piccoli frammenti di codice e scrivere su file (o su strutture dati)

3. In generale: generazione di codice dipende pesantemente da attributi ereditati ®

complicazione nella GA

frammenti di codice

sotto-alberi sintattici

molte operazioni di copiatura

spreco di memoria

azioni semantiche che non aderiscono alla sintesi di attributi in post-ordine

Necessarie tecniche più dirette (pratiche) di generazione di codice non basate su GA

Generazione Pratica di Codice (ii)

 Se LHS complessa ® necessario un altro (primo) figlio

expr ® id = expr | term term ® term + factor | factor factor ® ( expr ) | num | id

typedef enum {PLUS, ASSIGN, NUM, ID} Symbol;

typedef struct t_node { Symbol symbol; struct t_node *p1, *p2; char lexeme; / for id , num */ } Node;

typedef Node *Pnode;

(x = x + 3) + 4

x= (^4)

x (^3)

Nota: Identificatore di assegnamento

memorizzato nel nodo corrispondente

(per albero astratto)

symbol p1 p2 lexeme

Generazione Pratica di Codice (iii)

void genCode(Pnode p) { char code[MAXCODE]; /* massima lunghezza di una linea di Pcode */

switch (p>symbol) { case PLUS: genCode(p>p1); gencode(p>p2); emit("adi"); break ; case ASSIGN: sprintf(code, "lda %s", p>lexeme); emit(code); genCode(p>p1); emit("stn"); break ; case NUM: sprintf(code, "ldc %s", p>lexeme); emit(code); break ; case ID: sprintf(code, "lod %s", p>lexeme); emit(code); break ; } }

symbol p1 p2 lexeme

x= (^4)

x (^3)

Estensione di P-code per la Computazione degli Indirizzi

 Introduzione di nuove istruzioni per esprimere ¹ modi di indirizzamento

 ind

 ixa

top(stack) =

= integer

addr =
+

pop()

push(*addr)

top a^^ ind^ i top^ *(a + i)

top(stack) =

subtop(stack) = <base-addr>

= scale factor

addr = <base-addr> + ( * )

pop(), pop()

push(addr)

(indirect load)

(indexed address)

a top i

ixa s (^) top a + (s * i)

Generazione di Codice per Manipolazione di Array

 Elementi di array: memorizzati sequenzialmente

 Indirizzo di un elemento: computato mediante

 Computazione dell'indirizzo:

1. "Normalizzazione" dell'indice (quando l'indice non inizia con 0 ) ® indice normalizzato

2. Moltiplicazione dell'indice normalizzato per il fattore di scala = sizeof(elem) ® indice scalato

3. Indirizzo = indirizzo base + indice scalato (al punto 2)

offset = funzione lineare del valore dell'indice

int a[SIZE], i, j; … a[i+1] = a[j*2] + 3;

indirizzo integer comunque ® necessario computare prima l'indirizzo

indirizzo base dell'array