#include #include "parcours.h" #include "syntabs.h" #include "util.h" 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,"a%d\n",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 finFunc() { printMips("lw $ra, 0($sp)"); printMips("addi $sp, $sp, 4"); printMips("lw $fp, 0($sp)"); printMips("addi $sp, $sp, 4"); printMips("jr $ra"); } void empile(char *reg) { if(afficheMips) { printf("subu $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("addu $sp, $sp, 4\n"); } } /*-------------------------------------------------------------------------*/ void parcours_table(n_prog *n) { printMips(".data"); parcours_l_dec(n->variables); printMips(".text"); 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) { //TODOOOOOOOOOOOOOOOOOOOOOOOOOO /*int iRegistre = newReg(); char e[250]; new_tag(&e); printMips("li $t%d, -1",iRegistre);*/ parcours_exp(n->u.si_.test); parcours_instr(n->u.si_.alors); if(n->u.si_.sinon){ parcours_instr(n->u.si_.sinon); } } /*-------------------------------------------------------------------------*/ void parcours_instr_tantque(n_instr *n) { parcours_exp(n->u.tantque_.test); parcours_instr(n->u.tantque_.faire); } /*-------------------------------------------------------------------------*/ 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); parcours_exp(n->u.pour_.test); parcours_instr(n->u.pour_.faire); parcours_instr(n->u.pour_.incr); } /*-------------------------------------------------------------------------*/ void parcours_instr_affect(n_instr *n) { char var[256]; parcours_var(n->u.affecte_.var,&var); parcours_exp(n->u.affecte_.exp); int iRegistre = newReg(); char tmp[250]; char registre[250]; sprintf(registre,"$t%d",iRegistre); depile(registre); sprintf(tmp,"sw $t%d, %s ",iRegistre, var); printMips(tmp); } /*-------------------------------------------------------------------------*/ void parcours_instr_appel(n_instr *n) { parcours_appel(n->u.appel); } /*-------------------------------------------------------------------------*/ void parcours_appel(n_appel *n) { int id = rechercheExecutable(n->fonction); if(id < 0) { printf("Fonction %s introuvable\n", n->fonction); affiche_dico(); exit(1); } 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); } } /*-------------------------------------------------------------------------*/ void parcours_instr_retour(n_instr *n) { parcours_exp(n->u.retour_.expression); } /*-------------------------------------------------------------------------*/ void parcours_instr_ecrire(n_instr *n) { parcours_exp(n->u.ecrire_.expression); char tmp[250]; int iRegistre; iRegistre = newReg(); sprintf(tmp,"$t%d",iRegistre); depile(tmp); sprintf(tmp, "move $a0, $t%d",iRegistre); printMips(tmp); printMips("li $v0, 1"); 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]; parcours_var(n->u.var, &var); char tmp[256]; int iRegistre = newReg(); sprintf(tmp, "lw $t%d, %s", iRegistre, var); printMips(tmp); sprintf(tmp, "$t%d", iRegistre); empile(tmp); } /*-------------------------------------------------------------------------*/ void parcours_opExp(n_exp *n) { int iRegistre = newReg(); int iRegistre2 = newReg(); int iRegistre3 = newReg(); parcours_exp(n->u.opExp_.op1); parcours_exp(n->u.opExp_.op2); char tmp[256]; sprintf(tmp, "$t%d", iRegistre3); depile(tmp); sprintf(tmp, "$t%d", iRegistre2); depile(tmp); if(n->u.opExp_.op == plus) { sprintf(tmp,"add $t%d, $t%d, $t%d",iRegistre, iRegistre2, iRegistre3); printMips(tmp); } else if(n->u.opExp_.op == moins){ sprintf(tmp,"sub $t%d, $t%d, $t%d",iRegistre, iRegistre2, iRegistre3); printMips(tmp); } else if(n->u.opExp_.op == fois) { 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) { sprintf(tmp,"div $t%d, $t%d", iRegistre2, iRegistre3); printMips(tmp); sprintf(tmp,"mflo $t%d",iRegistre); printMips(tmp); } sprintf(tmp, "$t%d", iRegistre); empile(tmp); } /*-------------------------------- -----------------------------------------*/ void parcours_intExp(n_exp *n) { int iRegistre = newReg(); 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 = newReg(); 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++; } dico.tab[id].complement = j; contexte = C_VARIABLE_LOCALE; parcours_l_dec(n->u.foncDec_.variables); parcours_instr(n->u.foncDec_.corps); finFunc(); affiche_dico(); sortieFonction(); } /*-------------------------------------------------------------------------*/ 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: .word", n->nom); printMips(tmp); adresseGlobalCourante += 4; } else if (contexte == C_VARIABLE_LOCALE) { printMips("subbi $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 { sprintf(var, "%d", n->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 ); } /*-------------------------------------------------------------------------*/