diff --git a/Codes_en_COREC/tests/test4.corec b/Codes_en_COREC/tests/test4.corec index 61dfdca1f8f58b40f0d62f39f42e558822de8a7c..1985bf0aed5aaee1c95504c5c9ff029a2095b8bd 100644 --- a/Codes_en_COREC/tests/test4.corec +++ b/Codes_en_COREC/tests/test4.corec @@ -5,39 +5,29 @@ prog Test4 { Loc : (array,6), (float,1), float=3.0 Rec : { array = 2; + array[1] = 2; + array[2] = 2; + array[3] = 2; - array += float; - printstr("Attendu 4.00"); + array += 2; array[1] -= 2; - printstr("Attendu 2.00"); array[2] /= 2; - printstr("Attendu 1.00"); array[3] *= 2; - printstr("Attendu 2.00"); - + printstr("Expected : 4.0 0.0 1.0 4.0 0.0 0.0 \nObtained : "); print(array); array[1] = array[0] + float; - printstr("Attendu 5.00 :"); - array[2] = array[0] - float; - printstr("Attendu 2.00 :"); - + array[2] = array[2] - float; array[3] = array[0] / float; - printstr("Attendu 0.66 :"); array[4] = array[0] * float; - printstr("Attendu 2.00 :"); - + printstr("Expected : 4.0 7.0 -2.0 1.3333334 12.0 0.0 \nObtained : "); print(array); array[2] = array[0] + array[1]; - printstr("Attendu 4.00 :"); array[3] = array[0] - array[1]; - printstr("Attendu 0.00 :"); array[4] = array[0] / array[1]; - printstr("Attendu 1.00 :"); array[5] = array[0] * array[1]; - printstr("Attendu 4.00 :"); - + printstr("Expected : 4.0 7.0 11.0 -3.0 0.5714286 28.0 \nObtained : "); print(array) } } diff --git a/Codes_en_COREC/tests/test5.corec b/Codes_en_COREC/tests/test5.corec index ebb5b5e0c464540d7b3174a976ada21c55917621..053feb414d1e408b549a6db6c2bd8061607c643f 100644 --- a/Codes_en_COREC/tests/test5.corec +++ b/Codes_en_COREC/tests/test5.corec @@ -8,11 +8,15 @@ prog Test6 { f2 = 1.3; f1 += f2*2; + printstr("Expected : 1.2 + 1.3 * 2 = 3.8\nObtained : 1.2 + 1.3 * 2 = "); + print(f1); + f2 = f2*2; + printstr("Expected : 1.3 * 2 = 2.6\nObtained : "); + print(f2); f1 /= f2+f2*4; - - print(f1); - print(f2) + printstr("Expected : 3.8 / (2.6 + 2.6 * 4) = 0.29230767\nObtained : "); + print(f1) } } } diff --git a/Codes_en_COREC/tests/test6.corec b/Codes_en_COREC/tests/test6.corec index ef6219ddc415afaa14820fdffd3ab5701d2e783f..afa9e3475772cec4ff7d189a88dcb56dd3d45570 100644 --- a/Codes_en_COREC/tests/test6.corec +++ b/Codes_en_COREC/tests/test6.corec @@ -2,29 +2,27 @@ prog Test6 { def Main{ - Loc : a=2, (2Darray,3,3), (3Darray,a,a,a)//, 3Darray[0,0,0] = 0 //BUG HERE + Loc : a=2, (array2D,3,3), (array3D,a,a,a)//, array3D[0,0,0] = 0 //BUG HERE Rec : { - 2Darray[0,0] = 0; - 2Darray[0,1] = 1; - 2Darray[0,2] = a; - 2Darray[1,0] = 3.0; - 2Darray[1,1] = 4.5; - 2Darray[1,2] = 5; + array2D[0,0] = 0; + array2D[0,1] = 1; + array2D[0,2] = a; + array2D[1,0] = 3.0; + array2D[1,1] = 4.5; + array2D[1,2] = 5; - print(2Darray); + print(array2D); - 3Darray[0,0,0] = 0; - 3Darray[0,0,1] = 1; - 3Darray[0,1,0] = a; - 3Darray[0,1,1] = 3; - 3Darray[1,0,0] = 4; - 3Darray[1,0,1] = 5; - 3Darray[1,1,0] = 6; - 3Darray[1,1,1] = 7; + array3D[0,0,0] = 0; + array3D[0,0,1] = 1; + array3D[0,1,0] = a; + array3D[0,1,1] = 3; + array3D[1,0,0] = 4; + array3D[1,0,1] = 5; + array3D[1,1,0] = 6; + array3D[1,1,1] = 7; - print(3Darray); - printstr("Expected a = 2\nReal a = "); - print(a); + print(array3D); printstr("Fini") } } diff --git a/README.md b/README.md index 8c38f7524adbfc9e73d245b20dbb1a934376ce7b..931fa201543d3bbd56e08f5e75f78fb3867a5cef 100644 --- a/README.md +++ b/README.md @@ -37,19 +37,19 @@ sudo apt install bison ## Implemented Features ### 1. branch test1 -- Definition of local variable in the loc section of functions. **(TO DO :TRANSLATE IN MIPS but do not do here the float value)** -- Affectation of integer value. **(TO DO :TRANSLATE IN MIPS but do not do here the float value)** -- Print and printstr functions. **(TO DO :TRANSLATE IN MIPS)** +- Definition of local variable in the loc section of functions. * +- Affectation of integer value. +- Print and printstr functions. ### 2. branch test2 -- Operation on variable (except arrays) -> (+,-,*,/). **(TO DO :TRANSLATE IN MIPS)** -- Assignement operation on variable (except arrays) -> (+=,-=,*=,/=). **(TO DO :TRANSLATE IN MIPS)** +- Operation on variable (except arrays) -> (+,-,*,/). +- Assignement operation on variable (except arrays) -> (+=,-=,*=,/=). ### 3. branch test3 -- Affectation and definition of local 1D array. **(TO DO :TRANSLATE IN MIPS)** +- Affectation and definition of local 1D array. ### 4. branch test4 -- Operation with and on local 1D array. **(TO DO :TRANSLATE IN MIPS)** -- print function works on array. **(TO DO :TRANSLATE IN MIPS)** +- Operation with and on local 1D array. +- print function works on array. ### 5. branch test5 -- float value as singleton array. **(TO DO :TRANSLATE IN MIPS)** +- float value as singleton array. - Cast integer in float if integer affectation to arrays or multiplication of a float and an integer. (Implicit) ### 6. branch test6 - Affectation multi dimensional array. **(TO DO :TRANSLATE IN MIPS)** diff --git a/corec.l b/corec.l index 572b155d1560e7587af83f2d14141284e99f275a..ff6f3aa3fb40e335c1593fb3089909b6dbe29359 100644 --- a/corec.l +++ b/corec.l @@ -63,13 +63,21 @@ in {return in_dom;} "/" {return divide;} "%" {return mod;} -([0-9]*[[:alpha:]]+|[[:alpha:]])[[:alnum:]]* { +[[:alpha:]][[:alnum:]]* { if ( yyleng > 63 ) - fprintf(stderr,"Error at line %u: Identifier '%s' too long (> 31), truncated.\n",lineNumber,yytext); + fprintf(stderr,"Error at line %u: Identifier '%s' too long (> 63), truncated.\n",lineNumber,yytext); strncpy(yylval.strval,yytext,63); yylval.strval[64] = '\0'; - return ID; + return ID1; } +[0-9]*[[:alpha:]]+[[:alnum:]]* { + if ( yyleng > 63 ) + fprintf(stderr,"Error at line %u: Identifier '%s' too long (> 63), truncated.\n",lineNumber,yytext); + strncpy(yylval.strval,yytext,63); + yylval.strval[64] = '\0'; + return ID2; + } + ["]([^"]|[\\]["])*["] { if ( yyleng > 1023 ) fprintf(stderr,"Error at line %u: Identifier '%s' too long (> 1023), truncated\n",lineNumber,yytext); diff --git a/corec.y b/corec.y index 997990cd431ff27c4695c97a4fadcd2e6183b1f7..d63de70b16d9762ecbdf5c083706dacf50afa81a 100644 --- a/corec.y +++ b/corec.y @@ -73,7 +73,8 @@ void exit_safely(){ %token out %token inout -%token <strval> ID +%token <strval> ID1 +%token <strval> ID2 %token <strval> chaine %token <intval> entier %token <floatval> flottant @@ -123,6 +124,7 @@ void exit_safely(){ %type <ptrValE> E T F CALL %type <ptrArray> ARRAYREF %type <opaff> OPAFF +%type <opaff> OPREL %% @@ -149,8 +151,8 @@ LFONC : | %empty ; FONC : - // Declaration of a function ID - def ID + // Declaration of a function ID1 + def ID1 { struct symbol* id = symtable_get(SYMTAB,$2,symb_scope_function); if ( id != NULL ){ @@ -175,7 +177,7 @@ LDECL : | DECL ; DECL : // Section Loc declaration of arguments - ID + ID1 { // Declare a variable without affectation struct symbol* id = symtable_get(SYMTAB,$1,symb_scope_function); @@ -185,47 +187,47 @@ DECL : // Section Loc declaration of arguments } id = symtable_put_loc(SYMTAB,$1,symb_scope_function); } - | ID aff E + | ID1 aff E { // Declare a variable with affectation of value struct symbol* id = symtable_get(SYMTAB,$1,symb_scope_function); // Errors detection if($3.ptr->kind == CONSTANT_FLOAT){ // Float = array - if(id == NULL){ // Test if the variable ID is already declare + if(id == NULL){ // Test if the variable ID1 is already declare fprintf(stderr, "Error at line %u in function '%s': Try to declare variable '%s' as a float (array of dimension and lenght 1) but the size isn't declare. You may prefer to do this : '(%s,1), '%s'=%0.2f'.\n",lineNumber,symb_scope_function->u.name,$1,$1,$1,$3.ptr->u.value_float); exit_safely(); } - else if(id->kind != ARRAY){ // Test if the variable ID isn't an array (cannot affect an array value (float) to a non array variable) + else if(id->kind != ARRAY){ // Test if the variable ID1 isn't an array (cannot affect an array value (float) to a non array variable) fprintf(stderr, "Error at line %u in function '%s': Try assigning at variable '%s' a float value (an array of dimension and lenght 1) but '%s' isn't an array.\n",lineNumber,symb_scope_function->u.name,$1,$1); exit_safely(); } } else if($3.ptr->kind == ARRAY || $3.isEArray){ // Affectation is an array - if(id == NULL){ // Test if the variable ID is already declare + if(id == NULL){ // Test if the variable ID1 is already declare fprintf(stderr, "Error at line %u in function '%s': Try to declare variable '%s' as an integer but the affectation value is an array.\n",lineNumber,symb_scope_function->u.name,$1); exit_safely(); } - else if(id->kind != ARRAY){ // Test if ID isn't an array + else if(id->kind != ARRAY){ // Test if ID1 isn't an array fprintf(stderr, "Error at line %u in function '%s': Try assigning an array variable '%s' to a non array type variable '%s'.\n",lineNumber,symb_scope_function->u.name,$3.ptr->u.arr.name,$1); exit_safely(); } } else{ // Test if affectation value isn't a float and array - if (id != NULL){ // Test if the variable ID is already declare + if (id != NULL){ // Test if the variable ID1 is already declare fprintf(stderr, "Error at line %u in function '%s': Variable '%s' is already declared.\n",lineNumber,symb_scope_function->u.name,$1); exit_safely(); } - // Create a local variable name = ID in the scope of the 'symb_scope_function' + // Create a local variable name = ID1 in the scope of the 'symb_scope_function' id = symtable_put_loc(SYMTAB,$1,symb_scope_function); } - if(id->kind == ARRAY){ // Handle if ID is an implicit array(array -> array[0]) (ID is already declare, not by symtable_put_loc three instructions above) + if(id->kind == ARRAY){ // Handle if ID1 is an implicit array(array -> array[0]) (ID1 is already declare, not by symtable_put_loc three instructions above) struct symbol* const_0 = symtable_const_int(SYMTAB,0); gencode(CODE,AFF_ARRAY,id,const_0,$3.ptr); } - else // ID isn't an array + else // ID1 isn't an array gencode(CODE,COPY,id,$3.ptr,NULL); } | // Array declaration @@ -257,15 +259,15 @@ DECL : // Section Loc declaration of arguments size = tabArrayDim[0]; } else{ //ND arrays, except 1D array, require temporary operation struct symbol* tmpPair; - struct symbol* tmpImpair = newtemp(SYMTAB); + struct symbol* tmpImpair = newtemp(SYMTAB,INTEGER); gencode(CODE,BOP_MULT,tmpImpair,tabArrayDim[0],tabArrayDim[1]); // Init (case 2D array) for(unsigned int i=2;i<$2.dim;i++){ if(i%2 == 0){ - tmpPair = newtemp(SYMTAB); + tmpPair = newtemp(SYMTAB,INTEGER); gencode(CODE,BOP_MULT,tmpPair,tmpImpair,tabArrayDim[i]); } else{ - tmpImpair = newtemp(SYMTAB); + tmpImpair = newtemp(SYMTAB,INTEGER); gencode(CODE,BOP_MULT,tmpImpair,tmpPair,tabArrayDim[i]); } } @@ -283,8 +285,8 @@ DECL : // Section Loc declaration of arguments } ; -ARRAY : // Array declaration shape (ID, length_dim1, length_dim2, ..., length_dimN) - left_parenthesis ID comma DLIST right_parenthesis +ARRAY : // Array declaration shape (ID1, length_dim1, length_dim2, ..., length_dimN) + left_parenthesis ID1 comma DLIST right_parenthesis { $$.dim = $4.dim; strcpy($$.name,$2); @@ -336,7 +338,7 @@ ARGLIST : ; ELTARG : ARRAY - | ID + | ID1 ; DOM : @@ -349,7 +351,7 @@ DOMLIST : | D ; D : - ID in_dom left_bracket E double_period E right_bracket + ID1 in_dom left_bracket E double_period E right_bracket ; REC : @@ -377,7 +379,7 @@ I : COND | AFFECTATION // Affectation of variables | CALL // Call of functions or variables - | read_f left_parenthesis ID right_parenthesis // Read + | read_f left_parenthesis ID1 right_parenthesis // Read | print left_parenthesis {isPrintCall = 1;} CALL right_parenthesis // Print variable (printing out var of functions ins't implement yet) { gencode(CODE,CALL_PRINT,$4.ptr,NULL,NULL); @@ -422,8 +424,8 @@ AFFECTATION : // Compute the Arrays [+-/*] E and store it in a temporary variable struct symbol* tmp1; struct symbol* tmp2; - tmp1 = newtemp(SYMTAB); - tmp2 = newtemp(SYMTAB); + tmp1 = newtemp(SYMTAB,FLOAT); + tmp2 = newtemp(SYMTAB,FLOAT); // Copy in a temporary var the value of ARRAYREF gencode(CODE,COPY_ARRAY,tmp1,$1.ptr1,$1.ptr2); @@ -459,7 +461,7 @@ AFFECTATION : // Copy the tmp2 in the array memory gencode(CODE,AFF_ARRAY,$1.ptr1,$1.ptr2,tmp2); } - | ID OPAFF E // Assignement operation of E to ID + | ID1 OPAFF E // Assignement operation of E to ID1 { struct symbol* tmpArr; struct symbol* id = symtable_get(SYMTAB,$1,symb_scope_function); @@ -469,14 +471,14 @@ AFFECTATION : fprintf(stderr, "Error at line %u in function '%s': Variable '%s' is not declared, neither as an argument, nor as a local variable.\n",lineNumber,symb_scope_function->u.name,$1); exit_safely(); } - else if(id->kind == ARRAY){ // Handle if ID is an implicit array(array -> array[0]) + else if(id->kind == ARRAY){ // Handle if ID1 is an implicit array(array -> array[0]) if($3.ptr->kind == CONSTANT_INT){ // Cast t = symtable_const_double(SYMTAB,(float)$3.ptr->u.value_int); } else{ t = $3.ptr; } - tmpArr = newtemp(SYMTAB); + tmpArr = newtemp(SYMTAB,FLOAT); struct symbol* const_0 = symtable_const_int(SYMTAB,0); gencode(CODE,COPY_ARRAY,tmpArr,id,const_0); } @@ -489,9 +491,13 @@ AFFECTATION : tmpArr = id; } - // Compute the ID [+-/*] E and store it in a temporary variable + // Compute the ID1 [+-/*] E and store it in a temporary variable + enum var_type ty = INTEGER; + if(ISFLOAT(t) || ISFLOAT(tmpArr)) + ty = FLOAT; struct symbol* tmp; - tmp = newtemp(SYMTAB); + + tmp = newtemp(SYMTAB,ty); switch($2.opnum){ case 1: @@ -521,7 +527,7 @@ AFFECTATION : } // Copy the temp in the variable - if(id->kind == ARRAY){ // Handle if ID is an implicit array(array -> array[0]) + if(id->kind == ARRAY){ // Handle if ID1 is an implicit array(array -> array[0]) struct symbol* const_0 = symtable_const_int(SYMTAB,0); gencode(CODE,AFF_ARRAY,id,const_0,tmp); } @@ -542,7 +548,7 @@ AFFECTATION : // id index E gencode(CODE,AFF_ARRAY,$1.ptr1,$1.ptr2,t); } - | ID aff E // Affectation of A to ID + | ID1 aff E // Affectation of A to ID1 { struct symbol* id = symtable_get(SYMTAB,$1,symb_scope_function); @@ -557,7 +563,7 @@ AFFECTATION : exit_safely(); } - if(id->kind == ARRAY){ // Handle if ID is an implicit array(array -> array[0]) + if(id->kind == ARRAY){ // Handle if ID1 is an implicit array(array -> array[0]) struct symbol* t; if($3.ptr->kind == CONSTANT_INT){ // Cast t = symtable_const_double(SYMTAB,(float)$3.ptr->u.value_int); @@ -574,11 +580,11 @@ AFFECTATION : ; CALL : - ID left_parenthesis LCALL right_parenthesis // Call of functions + ID1 left_parenthesis LCALL right_parenthesis // Call of functions { $$.ptr = NULL; } - | ID // Call variables + | ID1 // Call variables { struct symbol* id = symtable_get(SYMTAB,$1,symb_scope_function); if ( id == NULL ){ @@ -586,13 +592,13 @@ CALL : exit_safely(); } - if(id->kind == ARRAY && !isPrintCall){ // If ID is an implicit array and we isn't in a print, we add [0] after ID : ID[0] + if(id->kind == ARRAY && !isPrintCall){ // If ID1 is an implicit array and we isn't in a print, we add [0] after ID1 : ID1[0] $$.isEArray = 1; - $$.ptr = newtemp(SYMTAB); + $$.ptr = newtemp(SYMTAB,FLOAT); struct symbol* const_0 = symtable_const_int(SYMTAB,0); gencode(CODE,COPY_ARRAY,$$.ptr,id,const_0); } - else // Else if we are in a print with an array or we just a normal variable, we just call ID + else // Else if we are in a print with an array or we just a normal variable, we just call ID1 $$.ptr = id; isPrintCall = 0; @@ -609,9 +615,9 @@ PRECINST : mod entier %prec formatmod ; ARRAYREF : // Array indexing - ID left_bracket ELIST right_bracket // ID[...] + ID1 left_bracket ELIST right_bracket // ID1[...] { - // $$.ptr1 -> The ID symbol + // $$.ptr1 -> The ID1 symbol // $$.ptr2 -> The index symbol struct symbol* id = symtable_get(SYMTAB,$1,symb_scope_function); @@ -638,7 +644,7 @@ ARRAYREF : // Array indexing struct symbol* kIndex1Dpair; struct symbol* kIndex1Dimpaire; - index=newtemp(SYMTAB); + index=newtemp(SYMTAB,INTEGER); for(unsigned int k=0;k<$3.dim;k++){ // Get K+1dim index struct symbol* kIndexND = tabArrayDim[k]; @@ -661,21 +667,21 @@ ARRAYREF : // Array indexing struct symbol* tmpPair; struct symbol* tmpImpair; if(k%2==0){ - tmpPair = newtemp(SYMTAB); + tmpPair = newtemp(SYMTAB,INTEGER); tmpImpair; gencode(CODE,BOP_MULT,tmpPair,id->u.arr.size[k+1],id->u.arr.size[k+2]); } else{ tmpPair; - tmpImpair = newtemp(SYMTAB); + tmpImpair = newtemp(SYMTAB,INTEGER); gencode(CODE,BOP_MULT,tmpImpair,id->u.arr.size[k+1],id->u.arr.size[k+2]); } for(unsigned int j=k+3;j<$3.dim;j++){ id->u.arr.size[j]; if(j%2 == 0){ - tmpPair = newtemp(SYMTAB); + tmpPair = newtemp(SYMTAB,INTEGER); gencode(CODE,BOP_MULT,tmpPair,tmpImpair,id->u.arr.size[j]); } else{ - tmpImpair = newtemp(SYMTAB); + tmpImpair = newtemp(SYMTAB,INTEGER); gencode(CODE,BOP_MULT,tmpImpair,tmpPair,id->u.arr.size[j]); } } @@ -692,7 +698,7 @@ ARRAYREF : // Array indexing gencode(CODE,COPY,index,kIndexND,NULL); } } else{ - kIndex1Dpair = newtemp(SYMTAB); + kIndex1Dpair = newtemp(SYMTAB,INTEGER); if(shift!=NULL){ gencode(CODE,BOP_MULT,kIndex1Dpair,kIndexND,shift); } else{ @@ -701,7 +707,7 @@ ARRAYREF : // Array indexing gencode(CODE,BOP_PLUS,index,index,kIndex1Dpair); } } else{ - kIndex1Dimpaire = newtemp(SYMTAB); + kIndex1Dimpaire = newtemp(SYMTAB,INTEGER); if(shift!=NULL){ gencode(CODE,BOP_MULT,kIndex1Dimpaire,kIndexND,shift); } else{ @@ -768,8 +774,11 @@ ELIST : // Indexing list E : E plus T { - $$.ptr = newtemp(SYMTAB); - if($1.ptr->kind == CONSTANT_INT && ($3.ptr->kind == CONSTANT_FLOAT || $3.ptr->kind == ARRAY)){ // If a float is T, then need to cast E to a float to do float+float => $$ E the result is array + enum var_type ty = INTEGER; // by default result is an integer + if(ISFLOAT($1.ptr) || ISFLOAT($3.ptr)) // check if one of the operand is a float + ty = FLOAT; // since one operand is a float the result is a float + $$.ptr = newtemp(SYMTAB,ty); + if($1.ptr->kind == CONSTANT_INT && ($3.ptr->kind == CONSTANT_FLOAT || $3.ptr->kind == ARRAY || $3.ptr->kind == NAME_FLOAT)){ // If a float is T, then need to cast E to a float to do float+float => $$ E the result is array $$.isEArray = 1; struct symbol* t = symtable_const_double(SYMTAB,(float)$1.ptr->u.value_int); gencode(CODE,BOP_PLUS,$$.ptr,t,$3.ptr); @@ -783,7 +792,10 @@ E : } | E sub T { - $$.ptr = newtemp(SYMTAB); + enum var_type ty = INTEGER; // by default result is an integer + if(ISFLOAT($1.ptr) || ISFLOAT($3.ptr)) // check if one of the operand is a float + ty = FLOAT; // since one operand is a float the result is a float + $$.ptr = newtemp(SYMTAB,ty); if($1.ptr->kind == CONSTANT_INT && ($3.ptr->kind == CONSTANT_FLOAT || $3.ptr->kind == ARRAY)){ $$.isEArray = 1; struct symbol* t = symtable_const_double(SYMTAB,(float)$1.ptr->u.value_int); @@ -798,7 +810,10 @@ E : } | sub E %prec usub { - $$.ptr = newtemp(SYMTAB); + enum var_type ty = INTEGER; // by default result is an integer + if(ISFLOAT($2.ptr)) // check if the operand is a float + ty = FLOAT; // since the operand is a float the result is a float + $$.ptr = newtemp(SYMTAB,ty); gencode(CODE,UOP_MINUS,$$.ptr,$2.ptr,NULL); } | T @@ -811,7 +826,10 @@ E : T : T mult F { - $$.ptr = newtemp(SYMTAB); + enum var_type ty = INTEGER; // by default result is an integer + if(ISFLOAT($1.ptr) || ISFLOAT($3.ptr)) // check if one of the operand is a float + ty = FLOAT; // since one operand is a float the result is a float + $$.ptr = newtemp(SYMTAB,ty); if($1.ptr->kind == CONSTANT_INT && ($3.ptr->kind == CONSTANT_FLOAT || $3.ptr->kind == ARRAY)){ $$.isEArray = 1; struct symbol* t = symtable_const_double(SYMTAB,(float)$1.ptr->u.value_int); @@ -826,7 +844,10 @@ T : } | T divide F { - $$.ptr = newtemp(SYMTAB); + enum var_type ty = INTEGER; // by default result is an integer + if(ISFLOAT($1.ptr) || ISFLOAT($3.ptr)) // check if one of the operand is a float + ty = FLOAT; // since one operand is a float the result is a float + $$.ptr = newtemp(SYMTAB,ty); if($1.ptr->kind == CONSTANT_INT && ($3.ptr->kind == CONSTANT_FLOAT || $3.ptr->kind == ARRAY)){ $$.isEArray = 1; struct symbol* t = symtable_const_double(SYMTAB,(float)$1.ptr->u.value_int); @@ -841,7 +862,10 @@ T : } | T mod F { - $$.ptr = newtemp(SYMTAB); + enum var_type ty = INTEGER; // by default result is an integer + if(ISFLOAT($1.ptr) || ISFLOAT($3.ptr)) // check if one of the operand is a float + ty = FLOAT; // since one operand is a float the result is a float + $$.ptr = newtemp(SYMTAB,ty); if($1.ptr->kind == CONSTANT_INT && ($3.ptr->kind == CONSTANT_FLOAT || $3.ptr->kind == ARRAY)){ $$.isEArray = 1; struct symbol* t = symtable_const_double(SYMTAB,(float)$1.ptr->u.value_int); @@ -874,7 +898,7 @@ F : | ARRAYREF { - $$.ptr = newtemp(SYMTAB); + $$.ptr = newtemp(SYMTAB,FLOAT); gencode(CODE,COPY_ARRAY,$$.ptr,$1.ptr1,$1.ptr2); } | entier @@ -889,6 +913,36 @@ F : COND : E OPREL E ternary_then B ternary_else B + { + /* + switch($2.opnum){ + case 1: + gencode(CODE,OPREL_LT,tmp,tmpArr,t); + break; + + case 2: + gencode(CODE,OPREL_GT,tmp,tmpArr,t); + break; + + case 3: + gencode(CODE,OPREL_LE,tmp,tmpArr,t); + break; + + case 4: + gencode(CODE,OPREL_GE,tmp,tmpArr,t); + break; + + case 5: + gencode(CODE,OPREL_EQ,tmp,tmpArr,t); + break; + + default: + fprintf(stderr, "BUG\n"); + break; + + } + */ + } ; B : BLOCKINST @@ -896,11 +950,30 @@ B : ; OPREL : inf + { + $$.opnum = 1; + } | sup + { + $$.opnum = 2; + } | inf_equal + { + $$.opnum = 3; + } | sup_equal + { + $$.opnum = 4; + } | equal + { + $$.opnum = 5; + } ; + +ID : + ID1 + | ID2 %% diff --git a/docs/projet_sujet.pdf b/docs/projet_sujet.pdf index 71d84338e4ba5bdec7b89196bd3505b8b2e05420..36e8b3cd243df404de318a4fec1a317b2c940d6f 100644 Binary files a/docs/projet_sujet.pdf and b/docs/projet_sujet.pdf differ diff --git a/lib.c b/lib.c index de783eed76521df3d65f8c753da54edcbfeab324..75ba887464219c7def19014bec4894b4359b7b35 100644 --- a/lib.c +++ b/lib.c @@ -114,6 +114,16 @@ struct symbol* symtable_put_name(struct symtable * t, const char * id) ++ (t->size); return s; } +struct symbol* symtable_put_name_float(struct symtable * t, const char * id) +{ + if(t->size==t->capacity) + symtable_grow(t); + struct symbol *s = &(t->symbols[t->size]); + s->kind = NAME_FLOAT; + strcpy(s->u.name,id); + ++ (t->size); + return s; +} struct symbol* symtable_put_chaine(struct symtable * t, const char * chaine) { @@ -166,32 +176,49 @@ struct symbol* symtable_put_array(struct symtable * t, const char* var_name, uns return s; } +struct symbol *newtemp(struct symtable * t, enum var_type ty) +{ + struct symbol* s; + name_t name; + sprintf(name,"t%d",t->temporary); + if(ty == INTEGER) + s = symtable_put_name(t,name); + else if( ty == FLOAT) + s = symtable_put_name_float(t,name); + else + fprintf(stderr,"wrong var_type given, or do not exist yet\n"); + ++ (t->temporary); + return s; +} + void symtable_dump(struct symtable * t, FILE* fout) { unsigned int i; for ( i=0 ; i<t->size; i++ ) { - if(t->symbols[i].kind==CONSTANT_INT) - fprintf(fout,"# %p = %ld\n",&(t->symbols[i]),t->symbols[i].u.value_int); - else if(t->symbols[i].kind==CONSTANT_FLOAT) - fprintf(fout,"# %p = %0.2f\n",&(t->symbols[i]),t->symbols[i].u.value_float); - else if(t->symbols[i].kind==NAME) - fprintf(fout,"# %p = %s\n",&(t->symbols[i]),t->symbols[i].u.name); - else if(t->symbols[i].kind==NAME_LOC) - fprintf(fout,"# %p = %s (in the scope of the '%s' function)\n",&(t->symbols[i]),t->symbols[i].u.name,t->symbols[i].scope_function); - else if(t->symbols[i].kind==CHAIN) - fprintf(fout,"# %p = %s\n",&(t->symbols[i]),t->symbols[i].u.chaine); - else if(t->symbols[i].kind==ARRAY){ - fprintf(fout,"# %p = (%s,",&(t->symbols[i]),t->symbols[i].u.arr.name); - if(t->symbols[i].u.arr.size[0]->kind == NAME_LOC || t->symbols[i].u.arr.size[0]->kind == NAME) - fprintf(fout,"%s",t->symbols[i].u.arr.size[0]->u.name); + if(t->symbols[i].kind==CONSTANT_INT) + fprintf(fout,"# %p = %ld\n",&(t->symbols[i]),t->symbols[i].u.value_int); + else if(t->symbols[i].kind==CONSTANT_FLOAT) + fprintf(fout,"# %p = %0.2f\n",&(t->symbols[i]),t->symbols[i].u.value_float); + else if(t->symbols[i].kind==NAME) + fprintf(fout,"# %p = %s (INTEGER)\n",&(t->symbols[i]),t->symbols[i].u.name); + else if(t->symbols[i].kind==NAME_FLOAT) + fprintf(fout,"# %p = %s (FLOAT)\n",&(t->symbols[i]),t->symbols[i].u.name); + else if(t->symbols[i].kind==NAME_LOC) + fprintf(fout,"# %p = %s (in the scope of the '%s' function type : INTEGER)\n",&(t->symbols[i]),t->symbols[i].u.name,t->symbols[i].scope_function); + else if(t->symbols[i].kind==CHAIN) + fprintf(fout,"# %p = %s\n",&(t->symbols[i]),t->symbols[i].u.chaine); + else if(t->symbols[i].kind==ARRAY){ + fprintf(fout,"# %p = (%s,",&(t->symbols[i]),t->symbols[i].u.arr.name); + if(t->symbols[i].u.arr.size[0]->kind == NAME_LOC || t->symbols[i].u.arr.size[0]->kind == NAME || t->symbols[i].u.arr.size[0]->kind == NAME_FLOAT) + fprintf(fout,"%s",t->symbols[i].u.arr.size[0]->u.name); else if(t->symbols[i].u.arr.size[0]->kind == CONSTANT_INT) - fprintf(fout,"%ld",t->symbols[i].u.arr.size[0]->u.value_int); + fprintf(fout,"%ld",t->symbols[i].u.arr.size[0]->u.value_int); else if(t->symbols[i].u.arr.size[0]->kind == CONSTANT_FLOAT) - fprintf(fout,"%0.2f",t->symbols[i].u.arr.size[0]->u.value_float); + fprintf(fout,"%0.2f",t->symbols[i].u.arr.size[0]->u.value_float); else{ - printf("BUG array size kind:%d\n",t->symbols[i].u.arr.size[0]->kind); - exit(1); + printf("BUG array size kind:%d\n",t->symbols[i].u.arr.size[0]->kind); + exit(1); } fprintf(fout,") (in the scope of the '%s' function)\n",t->symbols[i].scope_function); } @@ -247,16 +274,6 @@ void gencode(struct code * c, ++ (c->nextquad); } -struct symbol *newtemp(struct symtable * t) -{ - struct symbol* s; - name_t name; - sprintf(name,"t%d",t->temporary); - s = symtable_put_name(t,name); - ++ (t->temporary); - return s; -} - static void symbol_dump(struct symbol* s, FILE* fout) { switch ( s->kind ) @@ -264,6 +281,9 @@ static void symbol_dump(struct symbol* s, FILE* fout) case NAME: fprintf(fout,"%s",s->u.name); break; + case NAME_FLOAT: + fprintf(fout,"%s",s->u.name); + break; case CONSTANT_INT: fprintf(fout,"%ld",s->u.value_int); break; @@ -428,9 +448,11 @@ void code_mips_dump(struct symtable * t, struct code * c, FILE* fout){ fprintf(fout,"\t_%s: .word 0\n",t->symbols[i].u.name); } else if(t->symbols[i].kind == NAME){ - fprintf(fout,"\t_%s: .word 0\n",t->symbols[i].u.name); + fprintf(fout,"\t%s: .word 0\n",t->symbols[i].u.name); + } + else if(t->symbols[i].kind == NAME_FLOAT){ + fprintf(fout,"\t%s: .float 0\n",t->symbols[i].u.name); } - // this prevent the declaration fo some temp necessary but is also necessary to allocat the memory tab TODO resolve this issue else if (t->symbols[i].kind == ARRAY){ fprintf(fout,"\t_%s: .word 0\n",t->symbols[i].u.name); } @@ -452,22 +474,22 @@ void code_mips_dump(struct symtable * t, struct code * c, FILE* fout){ switch (c->quads[i].kind) { case BOP_PLUS: - print_bop_plus(c,fout,i); + print_bop_plus(c,t,fout,i); break; case BOP_MINUS: - print_bop_minus(c,fout,i); + print_bop_minus(c,t,fout,i); break; case BOP_MULT: - print_bop_mult(c,fout,i); + print_bop_mult(c,t,fout,i); break; case BOP_DIV: - print_bop_div(c,fout,i); + print_bop_div(c,t,fout,i); break; case BOP_MOD: - print_bop_mod(c,fout,i); + print_bop_mod(c,t,fout,i); break; case UOP_MINUS: - print_uop_minus(c,fout,i); + print_uop_minus(c,t,fout,i); break; case COPY_ARRAY: print_copy_array(t,c,fout,i); @@ -509,8 +531,10 @@ void code_free(struct code * c) } void free_exit(int code, struct code* c, struct symtable* t, FILE* fname){ - code_free(c); - symtable_free(t); + if( c != NULL) + code_free(c); + if( t != NULL) + symtable_free(t); if(fname!=NULL){fclose(fname);} exit(code); } @@ -526,65 +550,162 @@ void print_main_def(FILE* fout){ } // -------- ARITHMETIC RELATED -------- - -void print_bop_plus(struct code * c, FILE* fout,int i) +void print_bop_plus(struct code * c, struct symtable* t, FILE* fout,int i) { - //Check if we have variable names or just integers for sym2 and sym3 - print_nameOrInteger(c,fout,i,0b110); - //Do the operation and save result in wanted variable - fprintf(fout,"\tadd $t0, $t0, $t1\n"); - fprintf(fout,"\tsw $t0, _%s\n",c->quads[i].sym1->u.name); + #ifdef LIBDEBUG + fprintf(fout,"%s# start of x + y section\n",tabulation); + #endif + if(ISFLOAT(c->quads[i].sym2) || ISFLOAT(c->quads[i].sym3) ) + { // float minus + load_float_bop_macro("$f0","$f1","$t0",c->quads[i].sym2,c->quads[i].sym3,t,fout); + fprintf(fout,"%sadd.s $f2, $f0, $f1\n",tabulation); + load_addr_macro("$t0",c->quads[i].sym1,t,fout); + fprintf(fout,"%sswc1 $f2, 0($t0)\n",tabulation); + } else { // integer minus + //Check if we have variable names or just integers + print_nameOrInteger(c,fout,i,0b110); + //Do the operation and save result in wanted variable + fprintf(fout,"%sadd $t0, $t0, $t1\n",tabulation); + fprintf(fout,"%ssw $t0, %s\n",tabulation,c->quads[i].sym1->u.name); + } + #ifdef LIBDEBUG + fprintf(fout,"%s# end of x + y section\n",tabulation); + #endif } -void print_bop_minus(struct code * c, FILE* fout,int i) + +void print_bop_minus(struct code * c, struct symtable* t, FILE* fout,int i) { - //Check if we have variable names or just integers - print_nameOrInteger(c,fout,i,0b110); - //Do the operation and save result in wanted variable - fprintf(fout,"\tsub $t0, $t0, $t1\n"); - fprintf(fout,"\tsw $t0, _%s\n",c->quads[i].sym1->u.name); + #ifdef LIBDEBUG + fprintf(fout,"%s# start of x - y section\n",tabulation); + #endif + if(ISFLOAT(c->quads[i].sym2) || ISFLOAT(c->quads[i].sym3) ) + { // float minus + load_float_bop_macro("$f0","$f1","$t0",c->quads[i].sym2,c->quads[i].sym3,t,fout); + fprintf(fout,"%ssub.s $f2, $f0, $f1\n",tabulation); + load_addr_macro("$t0",c->quads[i].sym1,t,fout); + fprintf(fout,"%sswc1 $f2, 0($t0)\n",tabulation); + } else { // integer minus + //Check if we have variable names or just integers + print_nameOrInteger(c,fout,i,0b110); + //Do the operation and save result in wanted variable + fprintf(fout,"%ssub $t0, $t0, $t1\n",tabulation); + fprintf(fout,"%ssw $t0, %s\n",tabulation,c->quads[i].sym1->u.name); + } + #ifdef LIBDEBUG + fprintf(fout,"%s# end of x - y section\n",tabulation); + #endif } -void print_bop_mult(struct code * c, FILE* fout,int i) +void print_bop_mult(struct code * c, struct symtable* t, FILE* fout,int i) { - //Check if we have variable names or just integers for sym2 and sym3 - print_nameOrInteger(c,fout,i,0b110); - //Do the operation and save result in wanted variable - fprintf(fout,"%smul $t0, $t0, $t1\n",tabulation); - fprintf(fout,"%ssw $t0, _%s\n",tabulation,c->quads[i].sym1->u.name); + #ifdef LIBDEBUG + fprintf(fout,"%s# start of x * y section\n",tabulation); + #endif + if(ISFLOAT(c->quads[i].sym2) || ISFLOAT(c->quads[i].sym3) ) + { // float multiplication + load_float_bop_macro("$f0","$f1","$t0",c->quads[i].sym2,c->quads[i].sym3,t,fout); + fprintf(fout,"%smul.s $f2, $f0, $f1\n",tabulation); + load_addr_macro("$t0",c->quads[i].sym1,t,fout); + fprintf(fout,"%sswc1 $f2, 0($t0)\n",tabulation); + } else { // integer multiplication + //Check if we have variable names or just integers for sym2 and sym3 + print_nameOrInteger(c,fout,i,0b110); + //Do the operation and save result in wanted variable + fprintf(fout,"%smul $t0, $t0, $t1\n",tabulation); + fprintf(fout,"%ssw $t0, %s\n",tabulation,c->quads[i].sym1->u.name); + } + #ifdef LIBDEBUG + fprintf(fout,"%s# end of x * y section\n",tabulation); + #endif } -void print_bop_div(struct code * c, FILE* fout,int i) +void print_bop_div(struct code * c, struct symtable* t, FILE* fout,int i) { - //Check if we have variable names or just integers for sym2 and sym3 - print_nameOrInteger(c,fout,i,0b110); - //Do the operation and save result in wanted variable - fprintf(fout,"%sdiv $t0, $t0, $t1\n",tabulation); - fprintf(fout,"%ssw $t0, _%s\n",tabulation,c->quads[i].sym1->u.name); + #ifdef LIBDEBUG + fprintf(fout,"%s# start of x / y section\n",tabulation); + #endif + if(ISFLOAT(c->quads[i].sym2) || ISFLOAT(c->quads[i].sym3) ) + { // float division + load_float_bop_macro("$f0","$f1","$t0",c->quads[i].sym2,c->quads[i].sym3,t,fout); + fprintf(fout,"%sdiv.s $f2, $f0, $f1\n",tabulation); + load_addr_macro("$t0",c->quads[i].sym1,t,fout); + fprintf(fout,"%sswc1 $f2, 0($t0)\n",tabulation); + } else { // integer division + //Check if we have variable names or just integers for sym2 and sym3 + print_nameOrInteger(c,fout,i,0b110); + //Do the operation and save result in wanted variable + fprintf(fout,"%sdiv $t0, $t0, $t1\n",tabulation); + fprintf(fout,"%ssw $t0, %s\n",tabulation,c->quads[i].sym1->u.name); + } + #ifdef LIBDEBUG + fprintf(fout,"%s# end of x / y section\n",tabulation); + #endif } -void print_bop_mod(struct code * c, FILE* fout,int i) +void print_bop_mod(struct code * c, struct symtable* t, FILE* fout,int i) { - //Check if we have variable names or just integers for sym2 and sym3 - print_nameOrInteger(c,fout,i,0b110); - //Do the operation and save result in wanted variable - fprintf(fout,"%sdiv $t0, $t0, $t1\n",tabulation); - fprintf(fout,"%smfhi $t0\n",tabulation); - fprintf(fout,"%ssw $t0, _%s\n",tabulation,c->quads[i].sym1->u.name); + #ifdef LIBDEBUG + fprintf(fout,"%s# start of x %% y section\n",tabulation); + #endif + if(ISFLOAT(c->quads[i].sym2) || ISFLOAT(c->quads[i].sym3) ) + { // float modulo + load_float_bop_macro("$f0","$f1","$t0",c->quads[i].sym2,c->quads[i].sym3,t,fout); + // get the quotient + fprintf(fout,"%sdiv.s $f2, $f0, $f1\n",tabulation); + // floor it down + fprintf(fout,"%sfloor.w.s $f3, $f2 \n",tabulation); + // the above operation turned it into the integer format we need to turn it back to a float + fprintf(fout,"%scvt.s.w $f3, $f3 \n",tabulation); + // we now multiply divisor and the obtained quotient + fprintf(fout,"%smul.s $f4, $f3, $f1\n",tabulation); + // we substract this to the dividend we obtain the remainder of the division hence we have the mod + fprintf(fout,"%ssub.s $f5, $f0, $f4\n",tabulation); + load_addr_macro("$t0",c->quads[i].sym1,t,fout); + fprintf(fout,"%sswc1 $f5, 0($t0)\n",tabulation); + } else { // integer modulo + //Check if we have variable names or just integers for sym2 and sym3 + print_nameOrInteger(c,fout,i,0b110); + //Do the operation and save result in wanted variable + fprintf(fout,"%sdiv $t0, $t0, $t1\n",tabulation); + fprintf(fout,"%smfhi $t0\n",tabulation); + fprintf(fout,"%ssw $t0, %s\n",tabulation,c->quads[i].sym1->u.name); + } + #ifdef LIBDEBUG + fprintf(fout,"%s# end of x %% y section\n",tabulation); + #endif } -void print_uop_minus(struct code * c, FILE* fout,int i) +void print_uop_minus(struct code * c, struct symtable* t, FILE* fout,int i) { - fprintf(fout,"%slw $t0, _%s\n",tabulation,c->quads[i].sym1->u.name); - //Check if we have variable names or just integers - if(c->quads[i].sym2->kind == NAME || c->quads[i].sym2->kind == NAME_LOC) - fprintf(fout,"%slw $t1, _%s\n",tabulation,c->quads[i].sym2->u.name); - else if(c->quads[i].sym2->kind == CONSTANT_INT) - fprintf(fout,"%sli $t1, %ld\n",tabulation,c->quads[i].sym2->u.value_int); + #ifdef LIBDEBUG + fprintf(fout,"%s# start of -x section\n",tabulation); + #endif + if(ISFLOAT(c->quads[i].sym2)) + { // float uop minus + if(!ISFLOAT(c->quads[i].sym2)) + { // if sym2 is an integer convert it to a float and store it in $f0 + convert_int_to_float("$f0","$t0",c->quads[i].sym2,t,fout); + } else { // store it in $f0 + load_symbol_macro("$f0","$t0",c->quads[i].sym2,t,fout); + } + fprintf(fout,"%sneg.s $f1, $f0\n",tabulation); + load_addr_macro("$t0",c->quads[i].sym1,t,fout); + fprintf(fout,"%sswc1 $f1, 0($t0)\n",tabulation); + } else { + //Check if we have variable names or just integers + if(c->quads[i].sym2->kind == NAME || c->quads[i].sym2->kind == NAME_LOC) + fprintf(fout,"%slw $t0, %s\n",tabulation,c->quads[i].sym2->u.name); + else if(c->quads[i].sym2->kind == CONSTANT_INT) + fprintf(fout,"%sli $t0, %ld\n",tabulation,c->quads[i].sym2->u.value_int); - //Do the operation and save result in wanted variable - fprintf(fout,"%ssub $t0, $t0, $t1\n",tabulation); - fprintf(fout,"%ssw $t0, _%s\n",tabulation,c->quads[i].sym1->u.name); + //Do the operation and save result in wanted variable + fprintf(fout,"%sneg $t1, $t0\n",tabulation); + fprintf(fout,"%ssw $t1, %s\n",tabulation,c->quads[i].sym1->u.name); + } + #ifdef LIBDEBUG + fprintf(fout,"%s# end of -x section\n",tabulation); + #endif } // -------- PRINT RELATED -------- @@ -595,11 +716,11 @@ void print_print(struct symtable * t,struct code * c, FILE* fout,int i) case ARRAY: // TODO + WIP solution temporaire, quand les fonctions seront implémentés à remplacer par une fonction pour éviter le code spaghetti // putting the array size in $t2 - load_symbol_macro("$t2",c->quads[i].sym1->u.arr.dim1size,t,fout); + load_symbol_macro("$t2","NULL",c->quads[i].sym1->u.arr.dim1size,t,fout); // to avoid doing a mult at each iterations we multiply the size by 4 (each elements need a 4 bytes incrementation) fprintf(fout,"%smul $t0, $t2, 4\n",tabulation); // putting array address in $t1 - load_symbol_macro("$t1",c->quads[i].sym1,t,fout); + load_symbol_macro("$t1","NULL",c->quads[i].sym1,t,fout); fprintf(fout,"%sli $t2, 0\n",tabulation); @@ -615,7 +736,7 @@ void print_print(struct symtable * t,struct code * c, FILE* fout,int i) // load the current float element in the fprintf(fout,"%slwc1 $f0, ($t3)\n",tabulation); // function that print the asked register - print_reg("f0",fout,1); + print_reg("f0",fout,FLOAT); // macro that print a space fprintf(fout,"%sSPACE\n",tabulation); // increment to next address @@ -649,13 +770,13 @@ void print_printstr(struct symtable * t, struct code * c, FILE* fout,int i) } -void print_reg(char * reg,FILE * fout, int type){ - switch(type) { - case 0: +void print_reg(char * reg,FILE * fout, enum var_type ty){ + switch(ty) { + case INTEGER: fprintf(fout,"%smove $a0, $%s\n",tabulation,reg); fprintf(fout,"%sli $v0, 1\n",tabulation); break; - case 1: + case FLOAT: fprintf(fout,"%smov.s $f12, $%s\n",tabulation,reg); fprintf(fout,"%sli $v0, 2\n",tabulation); break; @@ -683,13 +804,13 @@ void print_copy_array(struct symtable * t, struct code * c, FILE* fout,int i) exit(1); } // adress of the array element we want to copy - load_tab_addr_macro("$t0", 1, 2, c->quads[i].sym2,c->quads[i].sym3,t,fout); + load_tab_addr_macro("$t0", "$t1", "$t2", c->quads[i].sym2,c->quads[i].sym3,t,fout); // adress of the place we want to copy the array element in load_addr_macro("$t1",c->quads[i].sym1,t,fout); - // load in $t2 what's inside the array element - fprintf(fout,"%slw $t2, ($t0)\n",tabulation); + // load in $f0 what's inside the array element + fprintf(fout,"%slwc1 $f0, ($t0)\n",tabulation); // store it in the destination - fprintf(fout,"%ssw $t2, ($t1)\n",tabulation); + fprintf(fout,"%sswc1 $f0, ($t1)\n",tabulation); #ifdef LIBDEBUG fprintf(fout,"%s# end of copy_array section\n",tabulation); @@ -708,7 +829,7 @@ void print_allocate_array(struct symtable * t, struct code * c, FILE* fout,int i // number for the sbrk primitive call fprintf(fout,"%sli $v0, 9\n",tabulation); // based on the type of the var indicating the size of the array we do different operations to end up with the nb of bytes we should allocate is $a0 - load_symbol_alloc_macro("$a0",0,c->quads[i].sym1->u.arr.dim1size,t,fout); + load_symbol_alloc_macro("$a0","$t0",c->quads[i].sym1->u.arr.dim1size,t,fout); // call sbrk fprintf(fout,"%ssyscall\n",tabulation); // save the allocated array ptr returned in $v0 by syscall in the assigned .data var @@ -730,9 +851,9 @@ void print_aff_array(struct symtable * t, struct code * c, FILE* fout,int i) } // V alternative, effectue directement le*4 en calcul vu qu'on devrait passer par un load immediate dans tout les cas // fprintf(fout,"%sla $t0, %s\n",tabulation,c->quads[i].sym1->u.name); - load_tab_addr_macro("$t0", 1, 2, c->quads[i].sym1,c->quads[i].sym2,t,fout); - load_symbol_macro("$t1",c->quads[i].sym3,t,fout); - fprintf(fout,"%ssw $t1, ($t0)\n",tabulation); + load_tab_addr_macro("$t0", "$t1", "$t2", c->quads[i].sym1,c->quads[i].sym2,t,fout); + load_symbol_macro("$f0","$t2",c->quads[i].sym3,t,fout);// sym3 is a float so the tmp register will be + fprintf(fout,"%sswc1 $f0, ($t0)\n",tabulation); #ifdef LIBDEBUG fprintf(fout,"%s# end of aff_array section\n",tabulation); #endif @@ -778,22 +899,23 @@ void print_nameOrInteger(struct code * c, FILE* fout,int i,int sym) // -------- MACROS -------- -void load_symbol_alloc_macro(char * dest, int tmp_used, struct symbol * sym, struct symtable * t, FILE* fout){ + +void load_symbol_alloc_macro(char * dest, char * tmp_used, struct symbol * sym, struct symtable * t, FILE* fout){ if(sym->kind == CONSTANT_INT) // var = 3 // in this case the value is a constant int we can do a load immediate in $a0 with value*4 fprintf(fout,"%sli %s, %ld\n",tabulation,dest,(sym->u.value_int)*4); // in other cases we need to load the value from the label of the corresponding symbol else if( sym->kind == NAME || sym->kind == NAME_LOC ) { // var = 4*3 - fprintf(fout,"%slw $t%d, _%s\n",tabulation,tmp_used,(sym->u.name)); + fprintf(fout,"%slw %s, %s\n",tabulation,tmp_used,(sym->u.name)); } else { // array[4] = array[5]+3*4 - fprintf(fout,"%slw $t%d, temp%d\n",tabulation,tmp_used,indice_temp(t,sym)); + fprintf(fout,"%slw %s, temp%d\n",tabulation,tmp_used,indice_temp(t,sym)); } // if we don't have a CONST INT we loaded the nb of int/floats we want to stock in the array, in this case if(sym->kind != CONSTANT_INT) - fprintf(fout,"%ssll %s, $t%d, 2\n",tabulation,dest,tmp_used); + fprintf(fout,"%ssll %s, %s, 2\n",tabulation,dest,tmp_used); } -void load_symbol_macro(char * dest, struct symbol * sym, struct symtable * t, FILE* fout){ +void load_symbol_macro(char * dest, char * tmp_used, struct symbol * sym, struct symtable * t, FILE* fout){ if(sym->kind == CONSTANT_INT) // var = 3 // in this case the value is a constant int we can do a load immediate in $a0 with value*4 fprintf(fout,"%sli %s, %ld\n",tabulation,dest,(sym->u.value_int)); @@ -805,41 +927,72 @@ void load_symbol_macro(char * dest, struct symbol * sym, struct symtable * t, FI fprintf(fout,"%slw %s, temp_float\n",tabulation,dest); } // in other cases we need to load the value from the label of the corresponding symbol - else if( sym->kind == NAME || sym->kind == ARRAY) { // var = 4*3 - fprintf(fout,"%slw %s, _%s\n",tabulation,dest,(sym->u.name)); + else if( sym->kind == NAME || sym->kind == NAME_LOC || sym->kind == ARRAY) { // var = 4*3 + fprintf(fout,"%slw %s, %s\n",tabulation,dest,(sym->u.name)); + } else if (sym->kind == NAME_FLOAT || sym->kind == CONSTANT_FLOAT) { + if( sym->kind == NAME_FLOAT ) + fprintf(fout,"%sla %s, %s\n",tabulation,tmp_used,(sym->u.name)); + else + fprintf(fout,"%sla %s, temp%d\n",tabulation,tmp_used,indice_temp(t,sym)); + fprintf(fout,"%slwc1 %s, 0(%s)\n",tabulation,dest,tmp_used); } else { // array[4] = array[5]+3*4 fprintf(fout,"%slw %s, temp%d\n",tabulation,dest,indice_temp(t,sym)); } } -void load_tab_addr_macro(char * dest,int tmp_used1, int tmp_used2, struct symbol * sym_addr, struct symbol * sym_index, struct symtable * t, FILE* fout){ - fprintf(fout,"%slw $t%d, _%s\n",tabulation,tmp_used2,sym_addr->u.name); +void load_tab_addr_macro(char * dest,char * tmp_used1, char * tmp_used2, struct symbol * sym_addr, struct symbol * sym_index, struct symtable * t, FILE* fout){ + fprintf(fout,"%slw %s, %s\n",tabulation,tmp_used2,sym_addr->u.name); if(sym_index->kind == CONSTANT_INT) // put into dest the addr of array[index] element - fprintf(fout,"%saddi %s, $t%d, %ld\n",tabulation,dest,tmp_used2,(sym_index->u.value_int)*4); + fprintf(fout,"%saddi %s, %s, %ld\n",tabulation,dest,tmp_used2,(sym_index->u.value_int)*4); // in other cases we need to load the value from the label of the corresponding symbol else if( sym_index->kind == NAME || sym_index->kind == NAME_LOC || sym_index->kind == ARRAY) { - fprintf(fout,"%slw $t%d, _%s\n",tabulation,tmp_used1,(sym_index->u.name)); + fprintf(fout,"%slw %s, %s\n",tabulation,tmp_used1,(sym_index->u.name)); } else { - fprintf(fout,"%slw $t%d, temp%d\n",tabulation,tmp_used1,indice_temp(t,sym_index)); + fprintf(fout,"%slw %s, temp%d\n",tabulation,tmp_used1,indice_temp(t,sym_index)); } if (sym_index->kind != CONSTANT_INT){ // if not CONSTANT_INT wasn't yet multiplied by 4 - fprintf(fout,"%ssll $t%d, $t%d, 2\n",tabulation,tmp_used1,tmp_used1); - fprintf(fout,"%sadd %s, $t%d, $t%d\n",tabulation,dest,tmp_used2,tmp_used1); + fprintf(fout,"%ssll %s, %s, 2\n",tabulation, tmp_used1, tmp_used1); + fprintf(fout,"%sadd %s, %s, %s\n",tabulation, dest, tmp_used2, tmp_used1); } } void load_addr_macro(char * dest, struct symbol * sym, struct symtable * t, FILE* fout) { - if( sym->kind == NAME || sym->kind == NAME_LOC || sym->kind == ARRAY){ - fprintf(fout,"%sla %s, _%s\n",tabulation,dest,sym->u.name); + if( sym->kind == NAME || sym->kind == NAME_FLOAT || sym->kind == NAME_LOC || sym->kind == ARRAY){ + fprintf(fout,"%sla %s, %s\n",tabulation,dest,sym->u.name); } else fprintf(fout,"%sla %s, temp%d\n",tabulation,dest,indice_temp(t,sym)); } +void convert_int_to_float(char * dest,char * tmp, struct symbol * sym, struct symtable * t, FILE* fout) +{ + load_addr_macro(tmp,sym,t,fout); + fprintf(fout,"%slw %s, 0(%s)\n",tabulation,tmp,tmp); + fprintf(fout,"%smtc1 %s, %s\n",tabulation,tmp,dest); + // we convert the integer to a float + fprintf(fout,"%scvt.s.w %s, %s\n",tabulation,dest,dest); // the value in dest now is a float +} + + + +void load_float_bop_macro(char * dest1, char* dest2, char * tmp, struct symbol * sym1, struct symbol * sym2, struct symtable * t, FILE* fout){ + if(!ISFLOAT(sym1)) + { // if sym2 is an integer convert it to a float and store it in $f0 + convert_int_to_float(dest1,tmp,sym1,t,fout); + } else { // store it in $f0 + load_symbol_macro(dest1,tmp,sym1,t,fout); + } + if(!ISFLOAT(sym2)) + { // if sym2 is an integer convert it to a float and store it in $f1 + convert_int_to_float(dest2,tmp,sym2,t,fout); + } else { // store it in $f1 + load_symbol_macro(dest2,tmp,sym2,t,fout); + } +} void print_macros(FILE* fout){ fprintf(fout,"\n# MACROS definition\n\n"); @@ -863,6 +1016,8 @@ void print_SPACE_macro(FILE* fout){ fprintf(fout,"\tsyscall\n"); fprintf(fout,".end_macro\n"); } + + // ETC FEEL FREE TO ADD MORE SECTIONS // -------- DEBUG RELATED -------- diff --git a/lib.h b/lib.h index a9426d98523e5fbfb6e4f0c55fa744669cfd703d..e4930c1e4208fd28e333b0b2f058f23dfdad3ee3 100644 --- a/lib.h +++ b/lib.h @@ -9,6 +9,7 @@ extern struct symbol* symb_scope_function; #define INDENT_BUF 1024 // make each section of MIPS code more clear comment to disable #define LIBDEBUG +#define ISFLOAT(X) ( X->kind == CONSTANT_FLOAT || X->kind == ARRAY || X->kind == NAME_FLOAT ) /* TABLE DES SYMBOLES */ @@ -22,8 +23,14 @@ struct array { struct symbol* dim1size; }; +enum var_type{ + INTEGER, // -> the var is an INTEGER + FLOAT // -> the var is a FLOAT +}; + enum kind{ NAME, // -> use the name attribut in the union u + NAME_FLOAT, // -> use the name attribut in the union u CONSTANT_INT, // -> use the value_int attribut in the union u CONSTANT_FLOAT, // -> use the value_float attribut in the union u CHAIN, // -> use the chaine attribut in the union u @@ -41,8 +48,9 @@ struct symbol { float value_float; struct array arr; } u; - // * (! only sets with variable kind : NAME_LOC, ARRAY) - name_t scope_function; // -> Name of the function where locals variables (NAME_LOC, ARRAY) are defined. + // * (! only sets with variable kind : NAME_LOC_INT, NAME_LOC_FLOAT, ARRAY) + name_t scope_function; // -> Name of the function where locals variables (NAME_LOC, NAME_LOC_FLOAT, ARRAY) are defined. + }; // Store the symbol table @@ -61,13 +69,17 @@ struct symbol* symtable_const_int(struct symtable * t, long int v); // Add a symbol in the table of a float (CONSTANT_FLOAT) struct symbol* symtable_const_double(struct symtable * t, float v); // Add a symbol in the table of a function (NAME) -struct symbol* symtable_put_name(struct symtable * t, const char * s); +struct symbol* symtable_put_name(struct symtable * t, const char * id); +// Add a symbol in the table of a function (NAME_FLOAT) +struct symbol* symtable_put_name_float(struct symtable * t, const char * id); // Add a symbol in the table of a chaine of caracters (CHAIN) struct symbol* symtable_put_chaine(struct symtable * t, const char * chaine); -// Add a symbol in the table of a local variable (defined but isn't initialized) (NAME_LOC) +// Add a symbol in the table of a local variable (defined but isn't initialized) (NAME_LOC_INT and NAME_LOC_FLOAT) struct symbol* symtable_put_loc(struct symtable * t, const char * var_name, struct symbol* func_id); // Add a symbol in the table of a local array (defined but isn't initialized) (ARRAY) struct symbol* symtable_put_array(struct symtable * t, const char* var_name, unsigned int dim, struct symbol** arrayDim, struct symbol* dim1size, struct symbol* func_id); +// Add to the symtable a temporary function which is used to transform multiples addresses instruction to a group of 3 addresses instructions (uses NAME kind) +struct symbol* newtemp(struct symtable * t,enum var_type ty); // Get a pointer of a symbol with attribut name in the symtable (if 's' isn't in the table, return NULL) // (func_id is used for the scope of function on the local variable) @@ -91,7 +103,7 @@ void symtable_free(struct symtable * t); * COPY_ARRAY -> tmp=sym1 array=sym2 element=sym3 -> tmp= array[element] */ struct quad { - enum quad_kind { BOP_PLUS, BOP_MINUS, BOP_MULT, BOP_DIV, BOP_MOD, UOP_MINUS, COPY, COPY_ARRAY, ALLOCATE_ARRAY, AFF_ARRAY, DEF_MAIN, DEF_FUNCTION, CALL_PRINT, CALL_PRINTSTR} kind; + enum quad_kind { BOP_PLUS, BOP_MINUS, BOP_MULT, BOP_DIV, BOP_MOD, UOP_MINUS, COPY, COPY_ARRAY, ALLOCATE_ARRAY, AFF_ARRAY, DEF_MAIN, DEF_FUNCTION, CALL_PRINT, CALL_PRINTSTR, CONDITION, OPREL_LT, OPREL_GT, OPREL_LE, OPREL_GE, OPREL_EQ} kind; struct symbol* sym1; struct symbol* sym2; struct symbol* sym3; @@ -114,9 +126,6 @@ void gencode(struct code * c, struct symbol* s2, struct symbol* s3); -// Add to the symtable a temporary function which is used to transform multiples addresses instruction to a group of 3 addresses instructions (uses NAME kind) -struct symbol *newtemp(struct symtable * t); - // Display in the 'fout' output file the intermediate code (in commentary) void code_dump(struct code * c, FILE* fout); // Display in the 'fout' output file the mips code @@ -138,22 +147,22 @@ void print_main_def(FILE* fout); // -------- ARITHMETIC RELATED -------- // add the BOP plus arithmetic operation TODO explain in more details -void print_bop_plus(struct code * c, FILE* fout,int i); +void print_bop_plus(struct code * c, struct symtable* t, FILE* fout,int i); // add the BOP minus arithmetic operation TODO explain in more details -void print_bop_minus(struct code * c, FILE* fout,int i); +void print_bop_minus(struct code * c, struct symtable* t, FILE* fout,int i); // add the BOP mult arithmetic operation TODO explain in more details -void print_bop_mult(struct code * c, FILE* fout,int i); +void print_bop_mult(struct code * c, struct symtable* t, FILE* fout,int i); // add the BOP div arithmetic operation TODO explain in more details -void print_bop_div(struct code * c, FILE* fout,int i); +void print_bop_div(struct code * c, struct symtable* t, FILE* fout,int i); // add the BOP modulo arithmetic operation TODO explain in more details -void print_bop_mod(struct code * c, FILE* fout,int i); +void print_bop_mod(struct code * c, struct symtable* t, FILE* fout,int i); // add the UOP minus arithmetic operation TODO explain in more details -void print_uop_minus(struct code * c, FILE* fout,int i); +void print_uop_minus(struct code * c, struct symtable* t, FILE* fout,int i); // -------- PRINT RELATED -------- @@ -164,10 +173,10 @@ void print_print(struct symtable * t, struct code * c, FILE* fout,int i); void print_printstr(struct symtable * t, struct code * c, FILE* fout,int i); /** @brief print_reg make MIPS code to print the register's value, no LF and no SPACE - * only the register's value type = 0 => int | type = 1 => float everything else is considered as an int TODO update this + * var_type is the type we wanna print, either FLOAT or INTEGER * TODO think about deleting type and just checking if the first reg character is an f if no other cases than int and floats */ -void print_reg(char * reg,FILE * fout, int type); +void print_reg(char * reg,FILE * fout, enum var_type ty); // -------- FUNCTIONS RELATED -------- @@ -198,21 +207,34 @@ void print_nameOrInteger(struct code * c, FILE* fout,int i,int sym); /** @brief load_symbol_alloc_macro load a symbol used for an sbrk allocation ( multiply it's value by 4) */ -void load_symbol_alloc_macro(char * dest, int tmp_used, struct symbol * sym, struct symtable * t, FILE* fout); +void load_symbol_alloc_macro(char * dest, char * tmp_used, struct symbol * sym, struct symtable * t, FILE* fout); /** @brief load_symbol_macro load a symbol value into the dest register + * tmp_used register is only used if the sym is a float the register won't be changed unless you load a float + * since floats should be loaded in $f register if you should always know the type when calling this function + * thus if the type is anything else than a FLOAT (CONSTANT_FLOAT / NAME_FLOAT) you can put a dummy value in tmp_used, + * Convention : use NULL so if you have an error it will be clearly visible in the MIPS code (won't assemble) */ -void load_symbol_macro(char * dest, struct symbol * sym, struct symtable * t, FILE* fout); +void load_symbol_macro(char * dest, char * tmp_used, struct symbol * sym, struct symtable * t, FILE* fout); /** @brief load_tab_addr_macro given a symbol adress and a symbol index put the addr of array[n] element in dest * tmp_used1 and tmp_used2 won't be saved so ensure nothing that should be saved is in */ -void load_tab_addr_macro(char * dest, int tmp_used1, int tmp_used2, struct symbol * sym_addr, struct symbol * sym_index, struct symtable * t, FILE* fout); +void load_tab_addr_macro(char * dest, char * tmp_used1, char * tmp_used2, struct symbol * sym_addr, struct symbol * sym_index, struct symtable * t, FILE* fout); /** @brief load_addr_macro put the memory adress of sym into the dest register */ void load_addr_macro(char * dest, struct symbol * sym, struct symtable * t, FILE* fout); +/** @brief convert an int to a float, the dest register must be a $f[0-31] register + */ +void convert_int_to_float(char * dest,char * tmp, struct symbol * sym, struct symtable * t, FILE* fout); + +/** @brief load the two operand required for a binary operation into dest1 and dest2 + * convert them if needed + */ +void load_float_bop_macro(char * dest1, char* dest2, char * tmp, struct symbol * sym1, struct symbol * sym2, struct symtable * t, FILE* fout); + /** @brief Macro printer only print the LF and SPACE macros for the moment * should be called between .data and .text segments */