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.