1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani...

55
1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro

Transcript of 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani...

Page 1: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

1

Generazione di Codice Intermedio

Implementazione di Linguaggi 2A.A. 2004/2005

di Gualdani Alessandro

Page 2: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

2

Il generatore di codice intermedio nel compilatore

Scanner ParserType

checker

Generatore di codice

intermedio

Generatore di codice

Generatore di codice

intermedio

Interprete

Page 3: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

3

Introduzione

Sebbene un programma sorgente possaessere tradotto direttamente in codiceeseguibile, vi sono alcuni vantagginell’utilizzo di un codice intermedioindipendente dalla macchina: Retargeting un compilatore per

macchine diverse può essere facilmente creato

Ottimizzazioni possono essere applicate alla rappresentazione intermedia

Page 4: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

4

Tipi di rappresentazioni intermedie

AST (Abstract Syntax Tree) albero in cui un nodo rappresenta un operatore e i suoi figli rappresentano gli operandi

DAG (Directed Acyclic Graph) simile ad un AST tranne per il fatto che una sottoespressione comune ha più di un padre

Notazione postfissa è una linearizzazione di un AST: è una lista di nodi dell’albero in cui un nodo appare immediatamente dopo i suoi figli

Three address code (notazione a tre indirizzi) descritto in seguito

Page 5: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

5

Esempio (1/2)

Consideriamo il seguente esempio:a := b*-c + b*-c

:=

a +

* *

b - b -

c c

:=

a +

*

b -

c

AST DAG

Page 6: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

6

Esempio (2/2)

Notazione postfissaa b c - * b c - * + :=

Three address code

t1 := - ct2 := b * t1t3 := - ct4 := b * t3t5 := t2 + t4a := t5

t1 := - ct2 := b * t1t5 := t2 + t2a := t5

Corrispondente all’AST

Corrispondente al DAG

Page 7: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

7

Three address code

Il codice a tre indirizzi è una sequenza di istruzioni del tipo:

x := y op zdove x, y, z sono nomi, costanti o temporanei generati dal compilatore ed op è un operatore

Il nome “codice a tre indirizzi” deriva dal fatto che, di solito, ogni istruzione contiene tre indirizzi: due per gli operandi ed uno per il risultato

Page 8: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

8

Istruzioni del codice a tre indirizzi (1/3)

Le istruzioni sono simili al codice assembler possono avere etichette ci sono istruzioni (salti) per il controllo di

flusso

1. Comandi di assegnamento della forma x := y op z, dove op è un

operatore (binario) logico o aritmetico della forma x := op y, dove op è un

operatore unario copy statement x := y, dove il valore di y è

assegnato ad x

Page 9: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

9

Istruzioni del codice a tre indirizzi (2/3)

2. Salti incondizionato, goto L condizionato, if x relop y goto L, dove

relop è un operatore relazionale (<, =, >=, …)

3. Invocazioni/ritorni di procedura istruzioni param x, call p, n, return y

(opzionale); il loro uso tipico è nella sequenza

generata per l’invocazione di procedura p(x1, x2, …, xn)

param x1param x2…param xncall p, n

Page 10: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

10

Istruzioni del codice a tre indirizzi (3/3)

4. Assegnamenti indiciati della forma x := y[i], assegna alla variabile

x il valore nella locazione che si trova i unità dopo y

della forma x[i] := y, l’opposto dell’assegnazione del punto precedente

5. Assegnamenti di indirizzi e puntatori della forma x := &y, assegna ad x la

locazione di y della forma x := *y, assegna ad x il

contenuto della locazione di y della forma *x := y, assegna all’oggetto

puntato da x il valore di y

Page 11: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

11

Implementazione dei comandi a tre indirizzi

In un compilatore i codici a tre indirizzi possono essere implementati come record con campi per gli operatori e gli operandi

Possibili rappresentazioni: Quadruple Triple Triple indirette

Page 12: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

12

Implementazione dei comandi a tre indirizzi - Quadruple

Una quadrupla è un record con quattro campi op, arg1, arg2, resultop memorizza un codice interno per

l’operatorearg1 ed arg2 memorizzano il primo ed il

secondo operandoresult memorizza il risultato

dell’istruzione I contenuti di arg1, arg2, result

sono, di solito, puntatori alla symbol table

Page 13: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

13

Implementazione dei comandi a tre indirizzi - Triple

Una tripla è un record con tre campi op, arg1, arg2op memorizza un codice interno per

l’operatorearg1 ed arg2 memorizzano il primo ed il

secondo operando Per evitare di inserire nomi temporanei

nella symbol table, un valore intermedio viene riferito mediante la posizione dell’istruzione che lo calcola

Page 14: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

14

Implementazione dei comandi a tre indirizzi – Triple indirette

Le istruzioni del codice a tre indirizzi vengono rappresentate mediante una lista di puntatori a triple

Ad es., si può usare un array statement con l’elenco dei puntatori alle triple, nell’ordine desiderato

Page 15: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

15

Implementazione dei comandi a tre indirizzi – Esempio (1/3)

Consideriamo l’assegnamentoa := b*-c + b*-c

le rappresentazioni a quadruple, triple e triple indirette sono le seguenti: Quadruple

op arg1 arg2 result

(0) - c t1

(1) * b t1 t2

(2) - c t3

(3) * b t3 t4

(4) + t2 t4 t5

(5) := t5 a

Page 16: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

16

Implementazione dei comandi a tre indirizzi – Esempio (2/3)

Triple

op arg1 arg2

(0) - c

(1) * b (0)

(2) - c

(3) * b (2)

(4) + (1) (3)

(5) := a (4)

Page 17: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

17

Implementazione dei comandi a tre indirizzi – Esempio (3/3)

Triple indirette

op arg1 arg2

(14) - c

(15) * b (14)

(16) - c

(17) * b (16)

(18) + (15) (17)

(19) := a (18)

statement

(0) (14)

(1) (15)

(2) (16)

(3) (17)

(4) (18)

(5) (19)

Page 18: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

18

Traduzione diretta dalla sintassi in three address code

Una regola (azione) semantica è assegnata ad ogni produzione

Si costruisce un AST e se ne effettua una visita depth-first per effettuare la traduzione in base alle regole semantiche

Nella fase di generazione del codice intermedio non è effettuata alcuna ottimizzazione

Page 19: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

19

DichiarazioniMan mano che si incontrano le dichiarazioniin una procedura o in un blocco, si alloca lospazio per la memoria: per ogni nome locale, si crea una entrata

nella symbol table con informazioni quali il tipo e l’indirizzo relativo per quel simbolo in memoria

nella generazione degli indirizzi si presuppone una particolare allocazione dei dati (nel seguito supporremo che gli indirizzi siano multipli di 4)

Page 20: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

20

Dichiarazioni in una procedura

Si utilizza una variabile globale offset per tener traccia del prossimo indirizzo di memoria libero

La procedura enter(name, type, offset) crea una nuova entrata nella symbol table per name, associandogli tipo type, a partire dall’indirizzo in offset

Il non terminale T possiede due attributi: type (nome del tipo) width (quantità di memoria necessaria per

allocare valori del tipo T)

Page 21: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

21

Dichiarazioni – Schema di traduzione

P { offset := 0 } D

D D ; D

D id : T { enter(id.name, T.type, offset); offset := offset + T.width }

T integer { T.type := integer; T.width := 4 }

T real { T.type := real; T.width := 8 }

T array [ num ] of T1 { T.type := array(num.val, T1.type);

T.width := num.valT1.width }

T T1 { T.type := pointer(T1.type);

T.width := 4 }

Page 22: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

22

Comandi di assegnamento

Attributi usati in seguito: id.name: attributo che memorizza il

nome dell’identificatore E.place: attributo (di

un’espressione E) che memorizza la variabile temporanea che contiene il valore dell’espressione

Page 23: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

23

Comandi di assegnamentoOperazioni usate in seguito: newtemp: funzione che restituisce

l’indirizzo di una nuova variabile temporanea

lookup(id.name): funzione che verifica se esiste un’entrata per id.name nella symbol table; in caso positivo restituisce il puntatore (indirizzo di memoria) all’identificatore, altrimenti ritorna nil

emit(“code”): è una procedura che genera il codice a tre indirizzi

Page 24: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

24

Assegnamento – Schema di traduzione

S id := E { p := lookup(id.name) if p nil then emit(p ‘:=‘ E.place) else error }

E E1 + E2 { E.place := newtemp; emit(E.place ‘:=‘ E1.place ‘+’ E2.place) }

E E1 * E2 { E.place := newtemp; emit(E.place ‘:=‘ E1.place ‘*’ E2.place) }

E - E1 { E.place := newtemp emit(E.place ‘:=‘ ‘-‘ E1.place) }

E ( E1 ) { E.place := E1.place }

E id { p := lookup(id.name) if p nil then E.place := p else error }

Page 25: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

25

Espressioni booleaneNei linguaggi di programmazione le espressionibooleane hanno il duplice scopo: di calcolare dei valori di verità di controllare il flusso di esecuzione in statement

quali, ad es., if o whileIn seguito considereremo espressioni booleane conla seguente grammatica:

E E or E | E and E | not E | ( E ) | id relop id | true | false

dove: relop { <, >, =, , , } gli operatori and e or associano a sinistra ed or ha

precedenza minore di and e not

Page 26: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

26

Espressioni booleane – Metodi di rappresentazione

I principali metodi per rappresentare i valoridi un’espressione booleana sono:1. codificare true e false attraverso valori

interi (di solito 1 e 0) e valutare un’espressione booleana analogamente ad una aritmetica

2. rappresentare un’espressione booleana attraverso il flusso di controllo, cioè rappresentando il valore dell’espressione booleana mediante la posizione raggiunta nel programma

Page 27: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

27

Espressioni booleane – Rappresentazione numerica

Supponiamo true codificato con 1 e false con 0 Ad es. a or b and not c è rappresentata dal

seguente codice a tre indirizzi:

Una espressione relazionale come, ad es., a<b è equivalente all’istruzione condizionale if a<b then 1 else 0, che può essere tradotta nel seguente codice a tre indirizzi:

t1 := not ct2 := b and t1t3 := a or t2

100: if a<b goto 103101: t := 0102: goto 104103: t := 1104:

Page 28: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

28

Espressioni booleane – Rappresentazione numerica

Operazioni usate in seguito: nextstat: indirizzo della prossima

istruzione emit: incrementa nextstat dopo

aver prodotto il codice a tre indirizzi

Page 29: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

29

Espressioni booleane – Rappresentazione numerica – Schema di traduzione

E E1 or E2

{ E.place := newtemp; emit(E.place ‘:=‘ E1.place ‘or’ E2.place) }

E E1 and E2

{ E.place := newtemp; emit(E.place ‘:=‘ E1.place ‘and’ E2.place) }

E not E1 { E.place := newtemp; emit(E.place ‘:=‘ ‘not’ E1.place) }

E ( E1 ) { E.place := E1.place }

E id1 relop id2

{ E.place := newtemp; emit(‘if’ id1.place relop.op id2.place ‘goto’ nexstat+3);

emit(E.place ‘:=‘ ‘0’); emit(‘goto’ nexstat+2);

emit(E.place ‘:=‘ ‘1’) }

E true { E.place := newtemp; emit(E.place ‘:=‘ ‘1’) }

E false { E.place := newtemp; emit(E.place ‘:=‘ ‘0’) }

Page 30: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

30

Espressioni booleane – Rappresentazione attraverso il flusso di controllo

L’idea base è che la valutazione di una espressione produce due etichette: quella a cui si salta se l’espressione è vera e quella a cui si salta se l’espressione è falsa

Supponiamo, ad es., che l’espressione E sia della forma a<b; il codice a tre indirizzi è della forma:

dove E.true è l’etichetta a cui si salta se l’espressione è vera ed E.false è l’etichetta a cui si salta se l’espressione è falsa

if a<b goto E.truegoto E.false

Page 31: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

31

Espressioni booleane – Rappresentazione attraverso il flusso di controllo

Supponiamo ora che E sia della forma E1 or E2 Se E1 è vera, allora sappiamo immediatamente

che anche E è vera (così E1.true è lo stesso che E.true)

Se E1 è falsa, allora dobbiamo valutare E2 (così E1.false è l’etichetta della prima istruzione nel codice per E2; le uscite true e false di E2 sono le stesse di E)

Analoghe considerazioni si applicano alla traduzione E1 and E2

La traduzione di espressioni E della forma not E1 provoca solo uno scambio delle uscite true e false di E1 con quelle di E

Page 32: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

32

Espressioni booleane – Rappresentazione attraverso il flusso di controllo

Attributi ed operazioni usati in seguito: newlabel: funzione che ritorna una nuova

etichetta le espressioni booleane E hanno due

attributi, E.true ed E.false, che contengono le etichette (indirizzi) dove bisogna saltare se l’espressione è vera o falsa ed un attributo E.code che contiene il codice prodotto per valutarle

l’operatore || rappresenta la concatenazione di codice

Page 33: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

33

Espressioni booleane – Rappresentazione attraverso il flusso di controllo – Schema di traduzione

E E1 or E2

{ E1.true := E.true; E1.false := newlabel;

E2.true := E.true; E2.false := E.false;

E.code := E1.code || emit(E1.false‘:’) || E2.code }

E E1 and E2

{ E1.true := newlabel; E1.false := E.false;

E2.true := E.true; E2.false := E.false;

E.code := E1.code || emit(E1.true‘:’) || E2.code }

E not E1 { E1.true := E.false; E1.false := E.true;

E.code := E1.code }

E ( E1 ) { E1.true := E.true; E1.false := E.false;

E.code := E1.code }

E id1 relop id2

{ E.code := emit(‘if’ id1.place relop.op id2.place ‘goto’ E.true) || emit(‘goto’ E.false) }

E true { E.code := emit(‘goto‘ E.true) }

E false { E.code := emit(‘goto‘ E.false) }

Page 34: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

34

Comandi per il controllo del flusso

La grammatica che consideriamo è la seguente:S if E then S1

| if E then S1 else S2

| while E do S1

le espressioni booleane E vengono tradotte mediante rappresentazione attraverso il flusso di controllo

la traduzione degli statement S consente di controllare il flusso in base all’istruzione che deve seguire il codice S.code: viene realizzato attraverso l’attributo S.next che contiene l’etichetta della prima istruzione da eseguire dopo il codice per S

Page 35: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

35

Comandi per il controllo del flusso if E then S1

Nella traduzione dello statement S if E then S1, una nuova etichetta E.true viene creata e “attaccata” alla prima istruzione generata per lo statement S1

Il codice per E genera un salto all’etichetta E.true se E è vera ed un salto a S.next se E è falsa (quindi l’etichetta E.false è in corrispondenza della prossima istruzione da eseguire cioè S.next)

E.code

S1.codeE.true:

E.false:

to E.true

to E.false

Page 36: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

36

Comandi per il controllo del flusso if E then S1 else S2

Nella traduzione dello statement S if E then S1 else S2 si salta alla prima istruzione di S1 se E è vera, alla prima istruzione di S2 se E è falsa

S.next, come nello statement S if E then S1, rappresenta l’etichetta della prima istruzione da eseguire dopo aver eseguito il codice per S

E.code

S1.codeE.true:

E.false:

to E.true

to E.false

goto S.next

S2.codeS.next:

Page 37: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

37

Comandi per il controllo del flusso while E do S1

Nella traduzione dello statement S while E do S1, una nuova etichetta S.begin è creata ed “attaccata” alla prima istruzione generata per E ed un’altra E.true per la prima istruzione per S1

Il codice per E genera un salto ad E.true se E è vera, ad S.next se E è falsa (cioè E.false “punta” ad S.next)

Dopo l’esecuzione del codice per S1 si effettua un salto ad S.begin per valutare l’espressione booleana

E.code

S1.codeE.true:

E.false:

to E.true

to E.false

goto S.begin

S.begin:

Page 38: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

38

Comandi per il controllo del flusso Schema di traduzione

S if E then S1

{ E.true := newlabel; E.false := S.next; S1.next := S.next;

S.code := E.code || emit(E.true‘:’) || S1.code }

S if E then S1 else S2

{ E.true := newlabel; E.false := newlabel; S1.next := S.next;

S2.next := S.next;

S.code := E.code || emit(E.true‘:’) || S1.code ||

emit(‘goto’ S.next) || emit(E.false’:’) || S2.code }

S while E do S1

{ S.begin := newlabel; E.true := newlabel; E.false := S.next; S1.next := S.begin;

S.code := emit(S.begin‘:’) || E.code || emit(E.true’:’) || S1.code ||

emit(‘goto’ S.begin) }

Page 39: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

39

Invocazioni di procedureConsideriamo una semplice grammatica perinvocare procedure:

S call id ( Elist )Elist Elist, E | E

Quando si genera il codice a tre indirizzi per le procedure, è necessario valutare le espressioni degli argomenti quindi fare seguire la lista di parametri; per far ciò: si utilizza una coda (variabile globale queue) in

cui i valori delle espressioni Elist vengono inseriti la routine che implementa l’invocazione emette

una istruzione param per ogni elemento della coda

Page 40: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

40

Invocazioni di procedure Schema di traduzione

S call id ( Elist )

{ t := 0;

for each item p on queue do emit(‘param’ p); t := t+1;

emit(‘call’ id.place, t)

}

Elist Elist, E { append E.place to the end of queue }

Elist E { initialize queue to contain only E.place }

Page 41: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

41

Backpatching (1/2)

Il modo più semplice per implementare le traduzioni finora presentate è quello di usare due passate:

1. prima si costruisce un albero sintattico per l’input

2. poi si effettua una visita depth-first dell’albero, calcolando le traduzioni date nella definizione

Page 42: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

42

Backpatching (2/2)

Il problema principale nel generare codice per le espressioni booleane e per il controllo di flusso in una singola passata è dato dal fatto che potremmo non conoscere l’etichetta argomento di una goto quando l’istruzione è generata

Se non si vogliono effettuare due passate, un modo per ovviare al problema è: tener traccia di una lista di istruzioni goto con

l’indirizzo del salto lasciato (temporaneamente) non specificato

riempire gli argomenti del salto quando l’indirizzo viene generato

Questa tecnica si chiama backpatching

Page 43: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

43

Argomenti non trattati

Dichiarazioni con procedure annidate [1, §8.2]

Dichiarazione di record [1, §8.2] Indirizzamento di elementi in un array

[1, §8.3] Conversioni di tipo all’interno di

assegnamenti [1, §8.3] Istruzione case [1, §8.5]

Page 44: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

44

Un’altra rappresentazione intermedia

Michael Franz e Thomas Kistler hanno realizzato una rappresentazione intermedia che coniuga la portabilità del codice con le ridotte dimensioni in termini di spazio occupato

La rappresentazione intermedia da loro proposta va sotto il nome di slim binaries

Page 45: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

45

Slim Binaries

Page 46: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

46

Introduzione I file oggetto contengono una

rappresentazione intermedia compatta La codifica degli slim binaries è basata

sull’osservazione che parti differenti di un programma sono spesso simili le une alle altre; queste similarità vengono sfruttate utilizzando un algoritmo di compressione predittivo che consente di codificare le sottoespressioni ricorrenti in un programma in modo efficiente dal punto di vista dello spazio

La generazione di codice macchina per la specifica architettura viene effettuata on-the-fly

Page 47: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

47

Schema di compressione Lo schema di compressione adattivo

codifica l’input utilizzando un dizionario

Inizialmente il dizionario consiste di un piccolo numero di operazioni primitive

(quali assignment, addition e multiplication)

un piccolo numero di data item che appaiono nel programma che si sta processando (ad es. integer i, procedure P)

Page 48: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

48

Generazione della rappresentazione intermedia

La traduzione da codice sorgente inrappresentazione intermedia si compone didue fasi:1. si fa il parsing del codice sorgente e si

costruisce un AST ed una symbol table; dopo la fase di parsing, la symbol table viene scritta sullo slim binary (servirà per inizializzare i data symbol del dizionario e per informazioni di tipo per il generatore di codice)

2. l’AST è attraversato e codificato in una sequenza di simboli del dizionario

Page 49: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

49

Esplicitazione della Fase 2 (1/2)

L’encoder processa interi sottoalberi dell’AST alla volta e per ognuno ricerca nel dizionario una sequenza di simboli che esprima lo stesso significato Es. la chiamata di procedura P(i+1) può essere

rappresentata dalla combinazione delle operazioni procedure call e addition e dai data symbol procedure P, variable i e constant 1

Dopo la codifica di una sottoespressione, il dizionario è aggiornato usando adattività e predizioni euristiche: ulteriori simboli che descrivono variazioni dell’espressione appena codificata sono aggiunti al dizionario e simboli che si riferiscono a scope lessicali chiusi sono rimossi

Page 50: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

50

Esplicitazione della Fase 2 (2/2)

Es. dopo aver codificato l’espressione i+1, i simboli i-plus-something e something-plus-one potrebbero essere aggiunti; supponiamo di incontrare più avanti nel processo di codifica l’espressione (simile) i+j: questa potrebbe essere rappresentata utilizzando solo due simboli i-plus-something e j.

Page 51: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

51

Traduzione da codice sorgente in slim binary

Page 52: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

52

Slim binaries come moduli software

Gli slim binaries possono essere integrati in un ambiente che supporti i moduli software, con caricamento dinamico

Un modulo esporta funzionalità attraverso la propria interfaccia ed importa funzionalità attraverso l’interfaccia di altri moduli

Possibilità di sostituire un modulo con un altro che fornisce la stessa interfaccia

La generazione del codice eseguibile avviene come parte del processo di caricamento dinamico ed in modo trasparente all’utente

Page 53: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

53

Confronto tra Slim Binaries e codice nativo (spazio occupato)

Page 54: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

54

Aree di applicazione degli slim binaries

Realizzazione di sistemi estendibili mediante aggiunta di moduli software

Un’unica versione per ogni componente, adatta a qualsiasi piattaforma; facilità di download da un server viste le ridotte dimensioni

Riduzione dello spazio dei programmi rispetto alle versioni native

Page 55: 1 Generazione di Codice Intermedio Implementazione di Linguaggi 2 A.A. 2004/2005 di Gualdani Alessandro.

55

Bibliografia

[1] A.V. Aho, R. Sethi, J.D. Ullman Compilers

Principles, Techniques, and ToolsAddison-Wesley

[2] M. Franz, T. KistlerSlim BinariesDicembre 1997