Compilation
2000-01
Exercices
Question
Remplacer dans le code engendré pour la conditionnelle le saut à une
instruction vide par un saut à la suite du code engendré.
Réponse
L'idée est de passer en paramètre à la fonction comp_inst
une étiquette de fin. Notons qu'il existe toujours au moins
une instruction dans le code engendré : l'instruction de sortie
(cf fonction ecrire_exit).
Convention : les commentaires introduits par (*>>>
signalent les ajouts principaux. Les morceaux de code inchangés ne
sont pas reproduits mais remplacés par [..].
Dans le fichier mips.ml :
on modifie la fonction
ecrire_exit pour lui passer en paramètre une étiquette.
let ecrire_exit fichier etiq =
begin etiqueter fichier etiq ;
output_string fichier "li $2, 10 \n" ;
etiqueter fichier marge ;
output_string fichier "syscall #exit\n \n"
end
;;
Dans le fichier gencode.ml :
on modifie la
fonction comp_inst. L'étiquette de fin est une
référence initialisée avec la valeur marge qui peut
être modifiée à l'occurence d'une instruction conditionnelle.
Dans le corps d'une boucle, l'étiquette de fin doit être confondue
avec l'étiquette du test de sortie (on ne sort d'une boucle qu'en
passant pas le test).
let rec comp_inst fichier etiq_deb etiq_fin =
function
[..]
| Composition (i1, i2) ->
begin (*>>> Generation d'une etiquette intermediaire *)
let etiq_mid = ref marge in
comp_inst fichier etiq_deb etiq_mid i1 ;
comp_inst fichier !etiq_mid etiq_fin i2
end
| Conditionnelle (testc, si_vrai, si_faux) ->
let etiqv = genetiq() in
begin (*>>> Calcul, si besoin, d'une nouvelle etiquette de fin *)
if !etiq_fin=marge then etiq_fin := genetiq();
comp_bool fichier etiq_deb etiqv testc;
comp_inst fichier marge etiq_fin si_faux ;
ecrire_jump fichier marge !etiq_fin "conditionnelle";
comp_inst fichier etiqv etiq_fin si_vrai ;
end
| Boucle (testb, corps) ->
let etiqd = genetiq() in
(*>>> L'etiquette de fin est l'etiquette du test *)
let etiqf = ref (genetiq()) in
begin
ecrire_jump fichier etiq_deb !etiqf "boucle";
comp_inst fichier etiqd etiqf corps ;
comp_bool fichier !etiqf etiqd testb
end
[..]
;;
Dans le fichier gencode.ml :
on modifie la
fonction comp_prog.
let comp_prog pm nomfich =
let fichier_mips = open_out nomfich in
begin
[..]
(*>>> Initialisation de l'etiquette de fin *)
let etiq_fin = ref marge in
comp_inst fichier_mips marge etiq_fin pm ;
(* Arreter le calcul *)
ecrire_exit fichier_mips !etiq_fin;
[..]
end
;;
This document was translated from LATEX by HEVEA.