#include #include "parcours.h" #include "syntabs.h" #include "util.h" int nbArg = 0; int nbvariableLocalFonc = 0; int contexte = C_VARIABLE_GLOBALE; int adresseGlobalCourante = 0; int adresseLocaleCourante = 0; int adresseArgumentCourant = 0; int afficheMips = 0; int creg = 0; extern dico_ dico; int tagindice = 0; void new_tag(char * tmp){ sprintf(tmp,"e%d",tagindice ); ++tagindice; } void printMips( const char * msg ) { if(afficheMips) printf("%s\n", msg); } int newReg() { return creg++%10; } void debutFunc() { printMips("subi $sp, $sp, 4"); printMips("sw $fp, 0($sp)"); printMips("move $fp, $sp"); printMips("subi $sp, $sp, 4"); printMips("sw $ra, 0($sp)"); } void finFuncreturn(int bool){ printMips("lw $ra, 0($sp)"); printMips("addi $sp, $sp, 4"); printMips("lw $fp, 0($sp)"); printMips("addi $sp, $sp, 4"); if(!bool){ printMips("addi $sp, $sp, 4 #ignore valeur de retour"); } printMips("jr $ra"); } void finFunc() { finFuncreturn(0); } void empile(char *reg) { if(afficheMips) { printf("subi $sp, $sp, 4\n"); printf("sw %s, 0($sp)\n", reg); } } void depile(char *reg) { if(afficheMips) { printf("lw %s, 0($sp)\n", reg); printf("addi $sp, $sp, 4\n"); } } /*-------------------------------------------------------------------------*/ void parcours_table(n_prog *n) { printMips(".data"); parcours_l_dec(n->variables); printMips(".text"); printMips("__start:"); printMips("jal main"); printMips("li $v0, 10"); printMips("syscall"); parcours_l_dec(n->fonctions); int id = rechercheExecutable("main"); if(id < 0 || dico.tab[id].complement != 0) { printf("Fonction main non trouvé\n"); affiche_dico(); exit(1); } } /*-------------------------------------------------------------------------*/ void parcours_l_instr(n_l_instr *n) { if(n) { parcours_instr(n->tete); parcours_l_instr(n->queue); } } /*-------------------------------------------------------------------------*/ void parcours_instr(n_instr *n) { if(n) { if(n->type == blocInst) parcours_l_instr(n->u.liste); else if(n->type == affecteInst) parcours_instr_affect(n); else if(n->type == siInst) parcours_instr_si(n); else if(n->type == tantqueInst) parcours_instr_tantque(n); else if(n->type == faireInst) parcours_instr_faire(n); else if(n->type == pourInst) parcours_instr_pour(n); else if(n->type == appelInst) parcours_instr_appel(n); else if(n->type == retourInst) parcours_instr_retour(n); else if(n->type == ecrireInst) parcours_instr_ecrire(n); } } /*-------------------------------------------------------------------------*/ void parcours_instr_si(n_instr *n) { parcours_exp(n->u.si_.test); int iRegistre = 0; char tmp[250]; char registre[250]; char faux[256]; char suite[256]; new_tag(faux); new_tag(suite); sprintf(registre,"$t%d",iRegistre); depile(registre); sprintf(tmp,"beq %s $zero %s", registre,faux); printMips(tmp); parcours_instr(n->u.si_.alors); sprintf(tmp,"j %s",suite); printMips(tmp); sprintf(tmp,"%s:",faux); printMips(tmp); if(n->u.si_.sinon) { parcours_instr(n->u.si_.sinon); } sprintf(tmp,"%s:",suite); printMips(tmp); } /*-------------------------------------------------------------------------*/ void parcours_instr_tantque(n_instr *n) { char tmp[256]; char etiquette[256]; char fin[256]; char registre[250]; new_tag(etiquette); new_tag(fin); sprintf(tmp,"%s:",etiquette); printMips(tmp); parcours_exp(n->u.tantque_.test); int iRegistre = 0; sprintf(registre,"$t%d",iRegistre); depile(registre); sprintf(tmp,"beq %s $0 %s", registre,fin); printMips(tmp); parcours_instr(n->u.tantque_.faire); sprintf(tmp,"j %s",etiquette); printMips(tmp); sprintf(tmp,"%s:",fin); printMips(tmp); } /*-------------------------------------------------------------------------*/ void parcours_instr_faire(n_instr *n) { parcours_instr(n->u.faire_.faire); parcours_exp(n->u.faire_.test); } /*-------------------------------------------------------------------------*/ void parcours_instr_pour(n_instr *n) { parcours_instr(n->u.pour_.init); char tmp[250]; char etiquette[256]; char fin[256]; char registre[250]; new_tag(etiquette); new_tag(fin); sprintf(tmp,"%s:",etiquette); printMips(tmp); parcours_exp(n->u.pour_.test); int iRegistre = 0; sprintf(registre,"$t%d",iRegistre); depile(registre); sprintf(tmp,"beq %s $zero %s", registre, fin); printMips(tmp); parcours_instr(n->u.pour_.faire); parcours_instr(n->u.pour_.incr); sprintf(tmp,"j %s",etiquette); printMips(tmp); sprintf(tmp,"%s:",fin); printMips(tmp); } /*-------------------------------------------------------------------------*/ void parcours_instr_affect(n_instr *n) { char var[256]; char tmp[250]; char registre[250]; parcours_exp(n->u.affecte_.exp); parcours_var(n->u.affecte_.var,var); int iRegistre = 0; sprintf(registre,"$t%d",iRegistre); depile(registre); sprintf(tmp,"sw %s, %s",registre, var); printMips(tmp); } /*-------------------------------------------------------------------------*/ void parcours_instr_appel(n_instr *n) { parcours_appel(n->u.appel); } /*-------------------------------------------------------------------------*/ void parcours_appel(n_appel *n) { char tmp[250]; int id = rechercheExecutable(n->fonction); if(id < 0) { printf("Fonction %s introuvable\n", n->fonction); affiche_dico(); exit(1); } printMips("subi $sp, $sp, 4 #Val Retour"); int nbArg = parcours_l_exp(n->args); if(dico.tab[id].complement != nbArg) { printf("Nombre Argument différent pour l'appel à %s\n", n->fonction); affiche_dico(); exit(1); } sprintf(tmp,"jal %s",n->fonction); printMips(tmp); int i = nbArg * 4; if(i != 0) { sprintf(tmp,"addi $sp, $sp, %d #désalocation des arguments",i); printMips(tmp); } } /*-------------------------------------------------------------------------*/ void parcours_instr_retour(n_instr *n) { char tmp[250]; char exec[250]; int returnAdress = 4 * (nbArg + 1); parcours_exp(n->u.retour_.expression); int iRegistre = 0; sprintf(tmp,"$t%d",iRegistre); depile(tmp); sprintf(exec,"sw %s %d($fp) #Adresse de retour",tmp , returnAdress); printMips(exec); sprintf(tmp,"addi $sp, $sp %d # desallocation variables locales",nbvariableLocalFonc * 4); printMips(tmp); finFuncreturn(1); } /*-------------------------------------------------------------------------*/ void parcours_instr_ecrire(n_instr *n) { parcours_exp(n->u.ecrire_.expression); char tmp[250]; int iRegistre = 0; sprintf(tmp,"$t%d",iRegistre); depile(tmp); sprintf(tmp, "move $a0, $t%d",iRegistre); printMips(tmp); printMips("li $v0, 1"); printMips("syscall"); printMips("li $a0, '\\n'"); printMips("li $v0, 11"); printMips("syscall"); } /*-------------------------------------------------------------------------*/ int parcours_l_exp(n_l_exp *n) { if(n){ parcours_exp(n->tete); return 1 + parcours_l_exp(n->queue); } return 0; } /*-------------------------------------------------------------------------*/ void parcours_exp(n_exp *n) { if(n->type == varExp) parcours_varExp(n); else if(n->type == opExp) parcours_opExp(n); else if(n->type == intExp) parcours_intExp(n); else if(n->type == appelExp) parcours_appelExp(n); else if(n->type == lireExp) parcours_lireExp(n); } /*-------------------------------------------------------------------------*/ void parcours_varExp(n_exp *n) { char var[256]; char tmp[256]; parcours_var(n->u.var, var); int iRegistre = 0; sprintf(tmp, "lw $t%d, %s", iRegistre, var); printMips(tmp); sprintf(tmp, "$t%d", iRegistre); empile(tmp); } /*-------------------------------------------------------------------------*/ void parcours_opExp(n_exp *n) { char tmp[256]; int iRegistre = 0; int iRegistre2 = 1; int iRegistre3 = 2; if(n->u.opExp_.op == plus) { parcours_exp(n->u.opExp_.op1); parcours_exp(n->u.opExp_.op2); sprintf(tmp, "$t%d", iRegistre3); depile(tmp); sprintf(tmp, "$t%d", iRegistre2); depile(tmp); sprintf(tmp,"add $t%d, $t%d, $t%d",iRegistre, iRegistre2, iRegistre3); printMips(tmp); } else if(n->u.opExp_.op == moins){ parcours_exp(n->u.opExp_.op1); parcours_exp(n->u.opExp_.op2); sprintf(tmp, "$t%d", iRegistre3); depile(tmp); sprintf(tmp, "$t%d", iRegistre2); depile(tmp); sprintf(tmp,"sub $t%d, $t%d, $t%d",iRegistre, iRegistre2, iRegistre3); printMips(tmp); } else if(n->u.opExp_.op == fois) { parcours_exp(n->u.opExp_.op1); parcours_exp(n->u.opExp_.op2); sprintf(tmp, "$t%d", iRegistre3); depile(tmp); sprintf(tmp, "$t%d", iRegistre2); depile(tmp); sprintf(tmp,"mult $t%d, $t%d", iRegistre2, iRegistre3); printMips(tmp); sprintf(tmp,"mflo $t%d",iRegistre); printMips(tmp); } else if(n->u.opExp_.op == divise) { parcours_exp(n->u.opExp_.op1); parcours_exp(n->u.opExp_.op2); sprintf(tmp, "$t%d", iRegistre3); depile(tmp); sprintf(tmp, "$t%d", iRegistre2); depile(tmp); sprintf(tmp,"div $t%d, $t%d", iRegistre2, iRegistre3); printMips(tmp); sprintf(tmp,"mflo $t%d",iRegistre); printMips(tmp); } else if(n->u.opExp_.op == egal){ parcours_exp(n->u.opExp_.op1); parcours_exp(n->u.opExp_.op2); sprintf(tmp, "$t%d", iRegistre3); depile(tmp); sprintf(tmp, "$t%d", iRegistre2); depile(tmp); char etiquette[256]; new_tag(etiquette); sprintf(tmp,"li $t%d, 1",iRegistre); printMips(tmp); sprintf(tmp,"beq $t%d, $t%d %s",iRegistre2, iRegistre3, etiquette); printMips(tmp); sprintf(tmp,"li $t%d, 0",iRegistre); printMips(tmp); sprintf(tmp,"%s:", etiquette); printMips(tmp); } else if(n->u.opExp_.op == diff) { parcours_exp(n->u.opExp_.op1); parcours_exp(n->u.opExp_.op2); sprintf(tmp, "$t%d", iRegistre3); depile(tmp); sprintf(tmp, "$t%d", iRegistre2); depile(tmp); char etiquette[256]; new_tag(etiquette); sprintf(tmp,"li $t%d, 0",iRegistre); printMips(tmp); sprintf(tmp,"beq $t%d, $t%d %s",iRegistre2, iRegistre3, etiquette); printMips(tmp); sprintf(tmp,"li $t%d, 1",iRegistre); printMips(tmp); sprintf(tmp,"%s:", etiquette); printMips(tmp); }else if(n->u.opExp_.op == inf){ parcours_exp(n->u.opExp_.op1); parcours_exp(n->u.opExp_.op2); sprintf(tmp, "$t%d", iRegistre3); depile(tmp); sprintf(tmp, "$t%d", iRegistre2); depile(tmp); char etiquette[256]; new_tag(etiquette); sprintf(tmp,"li $t%d, 1",iRegistre); printMips(tmp); sprintf(tmp,"blt $t%d, $t%d %s",iRegistre2, iRegistre3, etiquette); printMips(tmp); sprintf(tmp,"li $t%d, 0",iRegistre); printMips(tmp); sprintf(tmp,"%s:", etiquette); printMips(tmp); }else if(n->u.opExp_.op == infeg){ parcours_exp(n->u.opExp_.op1); parcours_exp(n->u.opExp_.op2); sprintf(tmp, "$t%d", iRegistre3); depile(tmp); sprintf(tmp, "$t%d", iRegistre2); depile(tmp); char etiquette[256]; new_tag(etiquette); sprintf(tmp,"li $t%d, 1",iRegistre); printMips(tmp); sprintf(tmp,"ble $t%d, $t%d %s",iRegistre2, iRegistre3, etiquette); printMips(tmp); sprintf(tmp,"li $t%d, 0",iRegistre); printMips(tmp); sprintf(tmp,"%s:", etiquette); printMips(tmp); }else if(n->u.opExp_.op == ou){ char faux1[256]; char faux2[256]; char vrai[256]; char empile[256]; new_tag(faux1); new_tag(faux2); new_tag(vrai); new_tag(empile); parcours_exp(n->u.opExp_.op1); sprintf(tmp, "$t%d", iRegistre2); depile(tmp); sprintf(tmp,"beq $zero, $t%d, %s",iRegistre2, faux1); printMips(tmp); sprintf(tmp,"j %s",vrai); printMips(tmp); sprintf(tmp,"%s :",faux1); printMips(tmp); parcours_exp(n->u.opExp_.op2); sprintf(tmp, "$t%d", iRegistre3); depile(tmp); sprintf(tmp,"or $t%d, $zero, $t%d",iRegistre, iRegistre3); printMips(tmp); sprintf(tmp,"j %s",empile); printMips(tmp); sprintf(tmp, "%s :", vrai); printMips(tmp); sprintf(tmp,"move $t%d $t%d",iRegistre, iRegistre2); printMips(tmp); sprintf(tmp,"%s : ", empile); printMips(tmp); } else if(n->u.opExp_.op == et) { char fin[256]; char faux[256]; new_tag(fin); new_tag(faux); parcours_exp(n->u.opExp_.op1); sprintf(tmp, "$t%d", iRegistre2); depile(tmp); sprintf(tmp,"beq $zero, $t%d, %s",iRegistre2,faux); printMips(tmp); sprintf(tmp, "$t%d", iRegistre2); empile(tmp); parcours_exp(n->u.opExp_.op2); sprintf(tmp, "$t%d", iRegistre3); depile(tmp); sprintf(tmp, "$t%d", iRegistre2); depile(tmp); sprintf(tmp,"beq $zero, $t%d, %s", iRegistre3, faux); printMips(tmp); sprintf(tmp,"and $t%d, $t%d, $t%d",iRegistre, iRegistre2, iRegistre3); printMips(tmp); sprintf(tmp,"j %s", fin); printMips(tmp); sprintf(tmp," %s :",faux); printMips(tmp); sprintf(tmp,"li $t%d 0",iRegistre); printMips(tmp); sprintf(tmp ," %s :",fin); printMips(tmp); } else if(n->u.opExp_.op == non) { parcours_exp(n->u.opExp_.op1); sprintf(tmp, "$t%d", iRegistre3); depile(tmp); sprintf(tmp,"not $t%d $t%d",iRegistre,iRegistre3); printMips(tmp); } else if(n->u.opExp_.op == cond) { char tmp[256]; char faux[256]; char empile[256]; new_tag(faux); new_tag(empile); parcours_exp(n->u.opExp_.op1); sprintf(tmp, "$t%d", iRegistre2); depile(tmp); sprintf(tmp,"beq $t%d, $zero %s",iRegistre2, faux); printMips(tmp); parcours_exp(n->u.opExp_.op2); sprintf(tmp, "$t%d", iRegistre); depile(tmp); sprintf(tmp,"j %s", empile); printMips(tmp); sprintf(tmp, "%s :", faux); printMips(tmp); parcours_exp(n->u.opExp_.op3); sprintf(tmp, "$t%d", iRegistre); depile(tmp); sprintf(tmp, "%s :", empile); printMips(tmp); } sprintf(tmp, "$t%d", iRegistre); empile(tmp); } /*-------------------------------- -----------------------------------------*/ void parcours_intExp(n_exp *n) { int iRegistre = 0; char tmp[256]; sprintf(tmp, "li $t%d, %d", iRegistre, n->u.entier); printMips(tmp); sprintf(tmp, "$t%d", iRegistre); empile(tmp); } /*-------------------------------------------------------------------------*/ void parcours_lireExp(n_exp *n) { printMips("li $v0 5"); printMips("syscall"); int iRegistre = 0; char tmp[256]; sprintf(tmp, "move $t%d, $v0", iRegistre); printMips(tmp); sprintf(tmp, "$t%d", iRegistre); empile(tmp); } /*-------------------------------------------------------------------------*/ void parcours_appelExp(n_exp *n) { parcours_appel(n->u.appel); } /*-------------------------------------------------------------------------*/ void parcours_l_dec(n_l_dec *n) { if( n ){ parcours_dec(n->tete); parcours_l_dec(n->queue); } } /*-------------------------------------------------------------------------*/ void parcours_dec(n_dec *n) { if(n){ if(n->type == foncDec) { parcours_foncDec(n); } else if(n->type == varDec) { parcours_varDec(n); } else if(n->type == tabDec) { parcours_tabDec(n); } } } /*-------------------------------------------------------------------------*/ void parcours_foncDec(n_dec *n) { char tmp[256]; sprintf(tmp, "%s :", n->nom); printMips(tmp); debutFunc(); int i = rechercheExecutable(n->nom); if( i >= 0) { printf("Fonction %s déjà déclaré\n", n->nom); affiche_dico(); exit(1); } int id = ajouteIdentificateur(n->nom, contexte, T_FONCTION, 0, -1); entreeFonction(); contexte = C_ARGUMENT; parcours_l_dec(n->u.foncDec_.param); int j = 0; for(int i = dico.sommet - 1; i >= 0; i--){ if(dico.tab[i].classe != C_ARGUMENT) break; j++; } nbArg = j; i = id; int nbvariableLocale = 0; dico.tab[id].complement = j; contexte = C_VARIABLE_LOCALE; parcours_l_dec(n->u.foncDec_.variables); while (i+1 < dico.sommet && (dico.tab[i+1].classe == C_VARIABLE_LOCALE || dico.tab[i+1].classe == C_ARGUMENT)){ if(dico.tab[i+1].classe == C_VARIABLE_LOCALE) ++nbvariableLocale; ++i; } nbvariableLocalFonc = nbvariableLocale; parcours_instr(n->u.foncDec_.corps); sprintf(tmp,"addi $sp, $sp %d # desallocation variables locales",nbvariableLocale * 4); printMips(tmp); affiche_dico(); sortieFonction(); finFunc(); } /*-------------------------------------------------------------------------*/ void parcours_varDec(n_dec *n) { if(rechercheDeclarative(n->nom) >= 0) { printf("Variable %s déjà déclaré\n", n->nom); affiche_dico(); exit(1); } if (contexte == C_VARIABLE_GLOBALE) { ajouteIdentificateur(n->nom, contexte, T_ENTIER, adresseGlobalCourante, -1); char tmp[250]; sprintf(tmp, "$%s: .space 4", n->nom); printMips(tmp); adresseGlobalCourante += 4; } else if (contexte == C_VARIABLE_LOCALE) { printMips("subi $sp, $sp, 4"); ajouteIdentificateur(n->nom, contexte, T_ENTIER, adresseLocaleCourante, -1); adresseLocaleCourante += 4; } else if (contexte == C_ARGUMENT) { ajouteIdentificateur(n->nom, contexte, T_ENTIER, adresseArgumentCourant, -1); adresseArgumentCourant += 4; } else { printf("Wtf ? %s\n", n->nom); affiche_dico(); exit(1); } } /*-------------------------------------------------------------------------*/ void parcours_tabDec(n_dec *n) { char texte[100]; // Max. 100 chars nom tab + taille sprintf(texte, "%s[%d]", n->nom, n->u.tabDec_.taille); if(rechercheDeclarative(n->nom) >= 0) { printf("Tableau %s déjà déclaré\n", n->nom); affiche_dico(); exit(1); } if (contexte == C_VARIABLE_GLOBALE) { ajouteIdentificateur(n->nom, contexte, T_TABLEAU_ENTIER, adresseGlobalCourante, n->u.tabDec_.taille); char tmp[250]; sprintf(tmp, "$%s: .space %d", n->nom, 4*n->u.tabDec_.taille); printMips(tmp); adresseGlobalCourante += 4*n->u.tabDec_.taille; } else { printf("Wtf ? %s\n", n->nom); affiche_dico(); exit(1); } } /*-------------------------------------------------------------------------*/ void parcours_var(n_var *n , char * var) { if(n->type == simple) { parcours_var_simple(n, var); } else if(n->type == indicee) { parcours_var_indicee(n, var); } } /*-------------------------------------------------------------------------*/ void parcours_var_simple(n_var *n, char * var) { int i = rechercheExecutable(n->nom); if( i < 0) { printf("Variable %s non déclaré\n", n->nom); affiche_dico(); exit(1); } else if (dico.tab[i].type == T_TABLEAU_ENTIER) { printf("Indice tableau %s est attendu\n", n->nom); affiche_dico(); exit(1); } if(dico.tab[i].classe == C_VARIABLE_GLOBALE) { sprintf(var, "$%s", n->nom); } else if (dico.tab[i].classe == C_ARGUMENT) { int adress = dico.tab[i].adresse; int result = 4 * nbArg - adress; sprintf(var, "%d($fp) #variable argument %s",result,n->nom); } else if (dico.tab[i].classe == C_VARIABLE_LOCALE){ int adresse = -1 *(8 + dico.tab[i].adresse); sprintf(var, "%d($fp) #variable locale", adresse); } } /*-------------------------------------------------------------------------*/ void parcours_var_indicee(n_var *n, char * var) { int i = rechercheExecutable(n->nom); if( i < 0) { printf("Tableau %s non déclaré\n", n->nom); affiche_dico(); exit(1); } else if (dico.tab[i].type == T_ENTIER) { printf("%s n'est pas un Tableau\n", n->nom); affiche_dico(); exit(1); } parcours_exp( n->u.indicee_.indice ); depile ("$t4"); printMips("add $t4,$t4,$t4"); printMips("add $t4,$t4,$t4"); sprintf(var,"$%s($t4)",n->nom); } /*-------------------------------------------------------------------------*/