génération de code intermédiaire code intermédiaire traduction des déclarations instructions...
TRANSCRIPT
![Page 1: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/1.jpg)
Génération de code intermédiaire
Code intermédiaire
Traduction des déclarations
Instructions d'affectation
Expressions booléennes
Appels de procédures
![Page 2: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/2.jpg)
Introduction
Constitue la fin de la partie frontale du compilateur
Indépendant de la machine cible
Avantages de séparer code intermédiaire et code final :
possibilité de réutiliser le générateur de code intermédiaire pour des machines différentes
possibilité d'améliorer le code intermédiaire indépendamment de la machine cible
Peut être incorporé à l'analyseur (traducteur)
... codefinal
analyseursyntaxique
contrôleur de types
générateur de code
intermédiaire
générateur de code
final
![Page 3: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/3.jpg)
Code intermédiaire
Les arbres syntaxiques sont déjà presque du code intermédiaire
Rappel : arbre syntaxique de a := b-4+c
-
+
id num 4
id
entrée pour b
entrée pour c
. .
. .
.
.
:= . .
id
entrée pour a
.
tmp1 := b - 4
tmp2 := tmp1 + c
a := tmp2
![Page 4: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/4.jpg)
Code intermédiaireRappel : une grammaire attribuée qui construit l'arbre syntaxique
d'une instruction d'affectation
S --> id = E S.ptr := makeNode('=',
makeLeaf(id, id.entry), E.ptr)
E --> E + E E.ptr := makeNode('+', E1.ptr, E2.ptr)
E --> E * E E.ptr := makeNode('*', E1.ptr, E2.ptr)
E --> - E E.ptr := makeNode(unaryMinus, E1.ptr)
E --> ( E ) E.ptr := E1.ptr
E --> id E.ptr := makeLeaf(id, id.entry)
![Page 5: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/5.jpg)
Code à trois adressesProche d'un langage d'assemblage
Utilise des noms symboliques (ex. add ou +) et des sauts
Forme générale : x := y op z
où op est un opérateur. Les trois adresses sont celles de x, y et z.
Instructions d'affectation
x := y op z x := op y
Instructions de saut
inconditionnel goto L
conditionnel if x relop y goto L
Instructions indicées
x := y [ i ] x [ i ] := y
![Page 6: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/6.jpg)
ExempleUne grammaire attribuée qui engendre du code à trois adresses
On utilise des noms temporaires pour l'évaluation des expressions
Attributs des noeuds E
E.place contient le nom lié à l'adresse qui contiendra la valeur de E à l'exécution
E.code contient une séquence d'instructions en code intermédiaire
Cette séquence est le résultat de la traduction de E
newtemp() engendre un nouveau nom temporaire à chaque appel
gen() engendre une instruction de code à trois adresses
L'opérateur || représente la concaténation
![Page 7: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/7.jpg)
Exemple : expressionsS --> id = E S.code := E.code || gen(id.place, ':=', E.place) ;
E --> E + E E.place := newtemp() ;
E.code := E1.code || E2.code ||
gen(E.place, ':=', E1.place, '+', E2.place) ;
E --> E * E E.place := newtemp() ;
E.code := E1.code || E2.code ||
gen(E.place, ':=', E1.place, '*', E2.place) ;
E --> - E E.place := newtemp() ;
E.code := E1.code ||
gen(E.place, ':=', unaryMinus, E1.place) ;
E --> ( E ) E.place := E1.place ; E.code := E1.code ;
E --> id E.place := id.place ; E.code := ' ' ;
![Page 8: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/8.jpg)
Exemple : contrôle
S --> while ( E ) S S.begin := newlabel() ;
S.after := newlabel() ;
S.code := gen(S.begin, ':') || E.code ||
gen('if', E.place, '=', '0', 'goto', S.after) ||
S1.code || gen('goto', S.begin) ||
gen(S.after, ':') ||
newlabel() engendre une nouvelle étiquette d'instruction à chaque appel
Les étiquettes d'instructions servent de cible pour les sauts
![Page 9: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/9.jpg)
Code à trois adressesL'implémentation du code à trois adresses peut se faire par
quadruplets
op, arg1, arg2, résultat
op arg1 arg2 résultat
(0) unaryMinus c t1
(1) * b t1 t2
(2) unaryMinus c t3
(3) * b t3 t4
(4) + t2 t4 t5
(5) := t5 a
![Page 10: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/10.jpg)
Code à trois adressesou par triplets
op, arg1, arg2
en utilisant les noms des triplets comme nom du résultat
op arg1 arg2
(0) unaryMinus c
(1) * b (0)
(2) unaryMinus c
(3) * b (2)
(4) + (1) (3)
(5) := a (4)
![Page 11: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/11.jpg)
Traduction des déclarations
On suppose que les déclarations sont groupées au début des fonctions
Adresses relatives liées aux noms locaux : variable deplct
Attributs des noeuds T (type)
T.type représente le type simple ou complexe (expression de type)
T.taille représente la place mémoire occupée par les objets du type
Schéma de traduction
![Page 12: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/12.jpg)
Traduction des déclarationsP --> { sommet := new Env() ; deplct := 0 ; } D
D -->
D --> T id ; { sommet.mettre(id.name, T.type, deplct) ;
deplct += T.taille ; } D
T --> B { t := B.type ; w := B.taille ;
C { T.type := C.type ; T.taille := C.taille ; }
B --> int { T.type := entier ; T.taille := 4 ; }
B --> float { T.type := flottant ; T.taille := 8 ; }
C --> { C.type := t ; C.taille := w ; }
C --> [ num ] C {C.type := tableau(num.val, C1.type) ;
C.taille := num.val * C1.taille ; }
![Page 13: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/13.jpg)
Table des symboles
Mémorise les informations sur les identificateurs contenus dans le programme
À un instant donné de la compilation, et donc à un point donné du code source, la table des symboles indique ce qui est connu sur chaque identificateur du programme dans cet environnement
Le contenu de la table des symboles évolue pendant la compilation
Quand on entre dans une boucle, on ajoute de nouvelles variables locales, et on les enlève quand on sort
![Page 14: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/14.jpg)
Table des symboles
Entrées de la table des symboles
Correspondent à des déclarations
Si un même nom est déclaré plusieurs fois, il a plusieurs entrées
Opérations sur la table des symboles
- consultation de l'entrée correspondant à un identificateur
- insertion d'une nouvelle entrée
- empiler/dépiler un bloc d'entrées correspondant à un bloc du code source
On peut voir chaque bloc d'entrées comme une table de symboles séparée
![Page 15: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/15.jpg)
Traduction des déclarationsUne grammaire plus complète avec les fonctions emboîtées
(comme en Pascal) ou les blocs (comme en C)
On construit une table des symboles séparée pour chaque fonction en-tête 0
a
x
readarray
exchange
quicksort
sort
en-têtereadarray en-têteexchange
en-tête
k
v
partition
quicksort
en-tête
i
j
partition
![Page 16: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/16.jpg)
Traduction des déclarationsnew Env() crée une nouvelle table des symboles et renvoie un
pointeur sur elle
Env.empiler(table) empile une table terminée
table.mettre(nom, type, deplct) crée une entrée dans table
On utilise deux piles parallèles :
Env pour les tables des blocs
Depl pour les déplacements correspondants
![Page 17: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/17.jpg)
Traduction des déclarationsP --> M BlocM --> ε sommet = null ; deplct = 0 ;Bloc --> { N D ; S } sommet = Env.depiler() ;
deplct= Depl.depiler() ;N --> ε Env.empiler(sommet) ; sommet = new Env
;Depl.empiler(deplct) ; deplct = 0 ;
D --> T id ; sommet.mettre(id.name, T.type, deplct) ;deplct +=T.type ;
DD --> εS --> S IS --> εI --> Bloc
![Page 18: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/18.jpg)
Traduction des déclarationsP --> M D ; S addWidth(top(tables), top(offsets) ;
pop(tables) ; pop(offsets) ;M --> ε t := makeTable(0) ;
push(t, tables) ; push(0, offsets) ;D --> D ; DD --> id ( ) { N D ; S }
t := top(tables) ; addWidth(t, top(offsets));pop(tables) ; pop(offsets) ;enterFunc(top(tables, id.name, t) ;
D --> T identer(top(tables), id.name, T.type, top(offsets)) ;top(offsets) +=T.type ;
N --> ε t := makeTable(top(tables)) ;push(t, tables) ; push(0, offsets) ;
![Page 19: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/19.jpg)
Traduction des déclarationsOn peut ajouter les types structures ou classes
T --> struct { L D } T.type := structure(sommet) ;T.taille := deplct ;sommet = Env.depiler() ; deplct= Depl.depiler() ;
L --> ε Env.empiler(sommet) ; sommet = new Env() ;
Depl.empiler(deplct) ; deplct = 0 ;
![Page 20: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/20.jpg)
Traduction des déclarationsOn peut ajouter les types enregistrements, dont la traduction
est très semblable à celle des déclarations de fonctions
T --> struct { L D }T.type := struct(top(tables)) ;T.width := top(offsets);pop(tables) ; pop(offsets) ;
L --> ε t := makeTable(0) ;push(t, tables) ; push(0, offsets) ;
![Page 21: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/21.jpg)
Affectations
Un schéma de traduction pour traduire les affectations
Le schéma crée et utilise des noms temporaires
lookup(name) consulte la table des symboles
emit() écrit une instruction de code à trois adresses
L'ordre des instructions correspond à l'ordre dans lequel elles ont été écrites
![Page 22: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/22.jpg)
S --> id = E p := lookup(id.name) ;
if (p) emit(p, ':=', E.place) else error() ;
E --> E + E E.place := newtemp() ;
emit(E.place, ':=', E1.place, '+', E2.place) ;
E --> E * E E.place := newtemp() ;
emit(E.place, ':=', E1.place, '*', E2.place) ;
E --> - E E.place := newtemp() ;
emit(E.place, ':=', unaryMinus, E1.place) ;
E --> ( E ) E.place := E1.place ;E --> id p := lookup(id.name) ;
if (p) E.place := p else error() ;
![Page 23: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/23.jpg)
Affectations
Adaptation au cas où les fonctions emboîtées sont autorisées
On peut utiliser la grammaire précédenteP --> D ; SD --> D ; DD --> id ( ) { D ; S }D --> T id
Il faut raffiner la fonction lookup()
On consulte d'abord la table de la fonction en cours en utilisant la pile de tables (nom local)
Si le nom n'est pas local, on consulte la table de la fonction englobante, etc.
![Page 24: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/24.jpg)
Adressage des éléments de tableaux
L'adresse de a[i] est
base + (i - low) w
où low est la borne inférieure des indices, base l'adresse relative du début du tableau et w la taille des éléments
En séparant la partie qui peut être calculée à la compilation
i w + base - low w
Dans une instruction de code à trois adresses x := y [ z ],
base - low w correspond à y et i w à z
En langage C, a[i] est équivalent à *(a+i) et low = 0
L'expression se réduit à
i w + base
![Page 25: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/25.jpg)
Tableaux à plusieurs dimensionsLes éléments peuvent être rangés
- ligne par ligne comme en C et en Pascal (exemple ci-dessous)
- colonne par colonne comme en Fortrana[0][0]
a[0][1]
a[0][2]
a[1][0]
a[1][1]
a[1][2]
a[i][j] j = 0 j = 1 j = 2
i = 0 base base+w base+2w
i = 1 base+3w base+4w base+5w
C'est le dernier indice qui varie le plus vite
![Page 26: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/26.jpg)
Tableaux à plusieurs dimensionsDans un tableau à deux dimensions rangé ligne par ligne, les i1
premières lignes contiennent (i1 - low1) n2 éléments, où n2 est le nombre des valeurs possibles de i2
Adresse de a[i1][i2] :
base + ((i1 - low1) n2 + i2 - low2) w
En séparant la partie qui peut être calculée à la compilation
(i1 n2 + i2) w + base - (low1 n2 + low2) w
On généralise à k dimensions
((...((i1 n2 + i2) n3 + i3)...) nk + ik) w
+ base - ((...(low1 n2 + low2) n3 + low3)...) nk + lowk) w
La deuxième ligne peut être calculée à la compilation
![Page 27: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/27.jpg)
Tableaux à plusieurs dimensions
En C, la deuxième ligne de la formule se réduit à
+ base
Pour traduire les références de tableau, on engendre le code qui calcule la première ligne
ek w
avec ek= (...((i1 n2 + i2) n3 + i3)...) nk + ik
On utilise la récurrence :
e1 = i1
ek= ek-1 nk + ik
![Page 28: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/28.jpg)
Tableaux à plusieurs dimensions
Une grammaire simple :
L --> id [ Elist ] | id
Elist --> Elist ] [ E | E
mais l'attribut donnant nk sera hérité : il est obtenu à partir du nom du tableau et transmis de haut en bas par les noeuds Elist
Une version où l'attribut est synthétisé :
L --> Elist ] | id
Elist --> Elist ] [ E | id [ E
L'attribut donnant nk obtenu à partir du nom du tableau peut être transmis de bas en haut par les noeuds Elist
![Page 29: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/29.jpg)
TableauxS --> L = E
E --> E + E
E --> ( E )
E --> L
L --> Elist ]
L --> id
Elist --> Elist ] [ E
Elist --> id [ E
Attributs
L.place est l'entrée dans la table des symboles (contient l'adresse du tableau)
L.offset contient l'adresse relative de l'élément dans le tableau
![Page 30: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/30.jpg)
S --> L = E if (L.offset)
emit(L.place, '[', L.offset, ']', ':=', E.place) ;
else emit(L.place, ':=', E.place) ;
E --> E + E ...
E --> ( E ) ...
E --> L if (L.offset) {
E.place := newtemp() ;
emit(E.place, ':=', L.place, '[', L.offset, ']', ) ; }
else E.place = L.place ;
![Page 31: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/31.jpg)
L --> Elist ] L.place := newtemp() ; L.offset := newtemp() ;
emit(L.place, ':=', const(Elist.array)) ;
emit(L.offset, ':=', width(Elist.array), '*',
Elist.place) ;
L --> id L.place := id.place ; L.offset := 0 ;
Elist --> Elist ] [ E t := newtemp() ; m := Elist1.ndim + 1 ;
emit(t, ':=', Elist1.place, '*',
limit(Elist1.array, m)) ;
emit(t, ':=', t, '+', E.place) ; Elist.ndim := m ;
Elist.array := Elist1.array ; Elist.place := t ;
Elist --> id [ E Elist.ndim := 1 ; Elist.array := id.place ;
Elist.place := E.place ;
const() donne l'adresse du tableau connue à la compilation
width() donne w limit() donne nm
![Page 32: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/32.jpg)
Expressions booléennes
Les expressions booléennes sont souvent employées dans des conditions d'instructions de contrôle : if, while, for
Grammaire
E --> E or E | E and E | not E | ( E ) | id relop id | true | false
Méthodes de traduction
1. Comme les expressions arithmétiques
2. Par sauts (évaluation paresseuse)
![Page 33: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/33.jpg)
Évaluation arithmétique0 représente faux, 1 représente vrai
Code source
b or x < y
Code intermédiaire
100 : t := b
101 : if x < y goto 104
102 : u := 0
103 : goto 105
104 : u := 1
105 : v:= t or u
Si b vaut vrai, on exécute quand même les instructions 101 et 105
![Page 34: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/34.jpg)
Évaluation paresseuse
On évite de calculer toutes les sous-expressions quand ce n'est pas nécessaire
Dès qu'on peut déduire la valeur de l'expression à partir de la valeur d'une sous-expression, on fait un saut pour court-circuiter la fin
Première version
On suppose qu'on sait vers quelles étiquettes il faut sauter quand on a trouvé la valeur de E : E.vrai si la valeur est vraie, E.faux si elle est fausse
![Page 35: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/35.jpg)
Évaluation paresseuse
Dans le code intermédiaire qui traduit E, certaines instructions peuvent contenir un saut inconditionnel vers E.vrai ou vers E.faux
E
E.vrai E.faux
E
E
E.vrai E.faux
E
E
E.vrai E.faux
E --> E and E E --> E or E
E.vrai E.faux E.vrai E.faux
![Page 36: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/36.jpg)
ExempleCode source a < b or c < d and e < f
Code intermédiaire
if a < b goto Evrai
goto E1
E1: if c < d goto E2
goto Efaux
E2: if e < f goto Evrai
goto Efaux
Difficulté si on ne connaît pas la valeur de Evrai et Efaux
![Page 37: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/37.jpg)
RéalisationProblème
En général, les instructions cibles E.vrai et E.faux sont engendrées après la traduction de E
Solutions1. Opérer en deux passesPremière passe : les étiquettes sont des noms temporaires
Deuxième passe : on les remplace par les adresses des instructions
2. Reprise arrièreDans E.vrai, on ne met plus le nom de l'instruction cible, mais la
liste des sauts vers l'instruction cibleQuand on engendre ces sauts, on les laisse incompletsDès qu'on connaît le numéro de l'instruction cible, on les complète
![Page 38: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/38.jpg)
Reprise arrière : exemple
100 : if a < b goto
101 : goto 102
102 : if c < d goto 104
103 : goto
104 : if e < f goto
105 : goto
E.v={100,104}E.f={103,105}
E.v={100}E.f={101} or
and
a < b
M.next=102
E.v={104}E.f={103,105}
E.v={102}E.f={103}
c < d
M.next=104E.v={104}E.f={105}
e < f
ε
ε
![Page 39: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/39.jpg)
Reprise arrière
makeList(i) crée une nouvelle liste chaînée d'instructions de saut contenant seulement i
merge(p, q) concatène deux listes chaînées d'instructions
backpatch(p, i) complète les instructions de saut contenues dans la liste p en leur donnant pour cible l'instruction i
E.vrai contient la liste des sauts incomplets qui doivent être exécutés dès qu'on sait que E est vraie
De même pour E.faux
E.vrai et E.faux seront des attributs synthétisés
![Page 40: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/40.jpg)
Grammaire
On ajoute à la grammaire précédente un marqueur M qui sert à sauvegarder le numéro de la prochaine instruction dans un attribut M.next
Ce numéro est conservé dans next, mis à jour par emit()
E --> E or M E E --> E and M E
E --> not EE --> ( E )
E --> id relop id E --> true
E --> falseM --> ε
![Page 41: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/41.jpg)
Schéma de traductionE --> E or M E backpatch(E1.f, M.next) ; E.f := E2.f ;
E.v := merge(E1.v, E2.v) ;
E --> E and M E backpatch(E1.v, M.next) ; E.v := E2.v ;
E.f := merge(E1.f, E2.f) ;
E --> not E E.v := E1.f ; E.f := E1.v ;
E --> ( E ) E.v := E1.v ; E.f := E1.f ;
E --> id relop id E.v := makeList(next) ;
emit('if', id1.place, relop, id2.place, 'goto') ;
E.f := makeList(next) ; emit('goto') ;
E --> true E.v := makeList(next) ; emit('goto') ;
E --> false E.f := makeList(next) ; emit('goto') ;
M --> ε M.next = next ;
![Page 42: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/42.jpg)
Instructions de contrôle
S --> if ( E ) S | if ( E ) S else S | while ( E ) S
E.code
S1.code
si-alors
...
...
E.v E.f
si-alors-sinon
...
...
E.v E.fE.code
S1.code
goto
S2.code
...
E.code
S1.code
goto
tant que
...
E.v E.f
...
...
![Page 43: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/43.jpg)
Instructions de contrôleS --> if ( E ) S | if ( E ) S else S | while ( E ) S | { L } | A
L --> L ; S | S
A représente une affectation
Une instruction S peut contenir des sauts vers la première instruction à exécuter après S
Ces sauts sont engendrés incomplets et listés dans S.suivant
De même pour L et L.suivant
On ajoute des marqueurs M et N
![Page 44: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/44.jpg)
Schéma de traductionS --> if ( E ) M S backpatch(E.v, M.next) ;
S.suivant := merge(E.f, S1.suivant) ;
M --> ε M.next := next ;
S --> while ( M E ) M S backpatch(E.v, M2.next) ;
backpatch(S1.suivant, M1.next) ;
S.suivant := E.f ; emit('goto', M1.next) ;
S --> if ( E ) M S else N S backpatch(E.v, M.next) ;
backpatch(E.f, N.next) ;
S.suivant := merge(S1.suivant, N.suivant,
S2.suivant) ;
N --> ε N.suivant := makeList(next) ; emit('goto') ;
N.next := next ;
![Page 45: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/45.jpg)
Schéma de traduction
S --> { L } S.suivant := L.suivant ;
S --> A S.suivant := makelist() ;
L --> L ; M S backpatch(L.suivant, M.next) ;
L.suivant := S.suivant ;
L --> S L.suivant := S.suivant ;
![Page 46: Génération de code intermédiaire Code intermédiaire Traduction des déclarations Instructions d'affectation Expressions booléennes Appels de procédures](https://reader030.vdocuments.site/reader030/viewer/2022012906/551d9da5497959293b8d6df5/html5/thumbnails/46.jpg)
ExempleCode source while (a < b) if (c < d) x = y + z ;
Code intermédiaire
100 : if a < b goto 102
101 : goto 107
102 : if c < d goto 104
103 : goto 100
104 : t := y + z
105 : x := t
106 : goto 100
107 :