Files
compilateur-l/src/parcours.c
sylvain099 a791cdfe4b reparation
2016-03-25 10:01:32 +01:00

499 lines
12 KiB
C

#include <stdio.h>
#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 );
}
/*-------------------------------------------------------------------------*/