[Custom Thumbnail]
All the Code of the series can be found at the Github repository:
https://github.com/drifter1/compiler
case REF_NODE: /* identifier reference */
temp_ref = (AST_Node_Ref *) node;
/* if "simple" type */
int type = temp_ref->entry->st_type;
if(type == INT_TYPE || type == REAL_TYPE || type == CHAR_TYPE){
return temp_ref->entry->st_type;
}
/* if array */
else if(type == ARRAY_TYPE){
return temp_ref->entry->inf_type;
}
else if(type == POINTER_TYPE){
return INT_TYPE;
}
break;
...
case REL_NODE:
/* used in branch and loop conditions - not stored */
break;
case EQU_NODE:
/* used in branch and loop conditions - not stored */
break;
...
case IF_NODE:
temp_if = (struct AST_Node_If *) node;
//main_reg_allocation(temp_if->condition);
...
case ELSIF_NODE:
temp_elsif = (struct AST_Node_Elsif *) node;
//main_reg_allocation(temp_elsif->condition);
main_reg_allocation(temp_elsif->elsif_branch);
break;
case FOR_NODE:
temp_for = (struct AST_Node_For *) node;
//main_reg_allocation(temp_for->initialize);
//main_reg_allocation(temp_for->condition);
main_reg_allocation(temp_for->for_branch);
//main_reg_allocation(temp_for->increment);
break;
case WHILE_NODE:
temp_while = (struct AST_Node_While *) node;
//main_reg_allocation(temp_while->condition);
main_reg_allocation(temp_while->while_branch);
break;
....
for(i = 0; i < var_count - temp_count; i++){
for(j = 1; j < var_count; j++){
if(i < j){
insertEdge(i, j);
insertEdge(j, i);
}
}
}
char * GetRegisterName(int color, int isFloat){
char* regName;
regName = (char*) malloc(5 * sizeof(char));
if(isFloat == 0){
switch(color){
/* callee saved values */
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
sprintf(regName, "$s%d", color);
break;
/* caller saved temporaries */
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
sprintf(regName, "$t%d", color - 8);
break;
default:
fprintf(stderr, "Too many GP registers!\n");
exit(1);
}
}
else{
switch(color){
/* callee saved values */
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
sprintf(regName, "$f%d", color*2);
break;
default:
fprintf(stderr, "Too many FP registers!\n");
exit(1);
}
}
return regName;
}
void main_func_traversal(FILE *fp, AST_Node *node){
int i;
AST_Node_Declarations *temp_declarations;
AST_Node_Decl *temp_decl;
AST_Node_Arithm *temp_arithm;
AST_Node_Bool *temp_bool;
AST_Node_Rel *temp_rel;
AST_Node_Equ *temp_equ;
AST_Node_Ref *temp_ref;
AST_Node_Statements *temp_statements;
AST_Node_If *temp_if;
AST_Node_Elsif *temp_elsif;
AST_Node_For *temp_for;
AST_Node_While *temp_while;
AST_Node_Incr *temp_incr;
AST_Node_Assign *temp_assign;
AST_Node_Func_Call *temp_func_call;
AST_Node_Call_Params *temp_call_params;
/* temp variable ST entry */
list_t *entry;>
/* check if empty */
if(node == NULL){
return;
}
switch(node->type){
/* declarations case */
case DECLARATIONS:
/* nothing */
break;
/* declaration case */
case DECL_NODE:
/* nothing */
break;
/* left and right child cases */
case BASIC_NODE:
main_func_traversal(fp, node->left);
main_func_traversal(fp, node->right);
break;
case ARITHM_NODE:
temp_arithm = (struct AST_Node_Arithm *) node;
main_func_traversal(fp, node->left);
main_func_traversal(fp, node->right);
generate_arithm(fp, temp_arithm);
break;
case BOOL_NODE:
temp_bool = (struct AST_Node_Bool *) node;
main_func_traversal(fp, node->left);
main_func_traversal(fp, node->right);
generate_bool(fp, temp_bool);
break;
case REL_NODE:
temp_rel = (struct AST_Node_Rel *) node;
main_func_traversal(fp, node->left);
main_func_traversal(fp, node->right);
generate_rel(fp, temp_rel);
break;
case EQU_NODE:
temp_equ = (struct AST_Node_Equ *) node;
main_func_traversal(fp, node->left);
main_func_traversal(fp, node->right);
generate_equ(fp, temp_equ);
break;
/* reference case */
case REF_NODE:
temp_ref = (struct AST_Node_Ref *) node;
/* load value from memory to register */
generate_load(fp, temp_ref);
break;
/* constant case */
case CONST_NODE:
/* already managed in the various generation functions */
break;
/* statements case */
case STATEMENTS:
temp_statements = (struct AST_Node_Statements *) node;
for(i = 0; i statement_count; i++){
main_func_traversal(fp, temp_statements->statements[i]);
}
break;
/* the if case */
case IF_NODE:
temp_if = (struct AST_Node_If *) node;
main_func_traversal(fp, temp_if->condition);
main_func_traversal(fp, temp_if->if_branch);
if(temp_if->elseif_count > 0 ){
for(i = 0; i elseif_count; i++){
main_func_traversal(fp, temp_if->elsif_branches[i]);
}
}
if(temp_if->else_branch != NULL){
main_func_traversal(fp, temp_if->else_branch);
}
break;
/* the else if case */
case ELSIF_NODE:
temp_elsif = (struct AST_Node_Elsif *) node;
main_func_traversal(fp, temp_elsif->condition);
main_func_traversal(fp, temp_elsif->elsif_branch);
break;
/* for case */
case FOR_NODE:
temp_for = (struct AST_Node_For *) node;
main_func_traversal(fp, temp_for->initialize);
main_func_traversal(fp, temp_for->condition);
main_func_traversal(fp, temp_for->for_branch);
main_func_traversal(fp, temp_for->increment);
break;
/* while case */
case WHILE_NODE:
temp_while = (struct AST_Node_While *) node;
main_func_traversal(fp, temp_while->condition);
main_func_traversal(fp, temp_while->while_branch);
break;
/* assign case */
case ASSIGN_NODE:
temp_assign = (struct AST_Node_Assign *) node;
main_func_traversal(fp, temp_assign->assign_val);
break;
/* simple case */
case SIMPLE_NODE:
/* will be managed in another article */
break;
/* increment statement */
case INCR_NODE:
temp_incr = (AST_Node_Incr*) node;
/* will be covered in another article */
break;
/* function call case */
case FUNC_CALL:
temp_func_call = (struct AST_Node_Func_Call *) node;
if(temp_func_call->num_of_pars != 0){
for(i = 0; i num_of_pars; i++){
main_func_traversal(fp, temp_func_call->params[i]);
}
}
/* when function non-void */
if(temp_func_call->entry->inf_type != VOID_TYPE){
generate_func_call_res(fp, temp_func_call);
}
break;
case CALL_PARAMS:
temp_call_params = (struct AST_Node_Call_Params*) node;
/* parameters will be covered in another article */
break;
/* function declaration stuff */
case FUNC_DECLS:
case FUNC_DECL:
case RET_TYPE:
case DECL_PARAMS:
case RETURN_NODE:
/* can't occur in main */
break;
default: /* wrong choice case */
fprintf(stderr, "Error in node selection!\n");
exit(1);
}
}void generate_arithm(FILE *fp, AST_Node_Arithm *node);
void generate_bool(FILE *fp, AST_Node_Bool *node);
void generate_rel(FILE *fp, AST_Node_Rel *node);
void generate_equ(FILE *fp, AST_Node_Equ *node);
void generate_load(FILE *fp, AST_Node_Ref *node);
void generate_func_call_res(FILE *fp, AST_Node_Func_Call *node);
void generate_load(FILE *fp, AST_Node_Ref *node){
if(node->entry->st_type == REAL_TYPE){
fprintf(fp, "L.D %s, %s\n", GetRegisterName(node->entry->g_index, 1), node->entry->st_name);
}
else{
if(node->ref == 1){
fprintf(fp, "LA %s, %s($0)\n", GetRegisterName(node->entry->g_index, 0), node->entry->st_name);
}
else{
fprintf(fp, "LW %s, %s($0)\n", GetRegisterName(node->entry->g_index, 0), node->entry->st_name);
}
}
}
void generate_arithm(FILE *fp, AST_Node_Arithm *node){
...
/* operation */
switch(node->op){
case ADD:
/* code */
break;
case SUB:
/* code */
break;
case MUL:
/* code */
break;
case DIV:
/* code */
break;
case INC:
/* code */
break;
case DEC:
/* code */
break;
}
}
...
case INC:
/* check data type */
if (node->data_type == REAL_TYPE){
fprintf(fp, "LI.D $28, 1.0\n");
fprintf(fp, "ADD.D %s, %s, $28\n", GetRegisterName(node->g_index, 1), GetRegisterName(node->g_index, 1));
}
else{
fprintf(fp, "ADDI %s, %s, 1\n", GetRegisterName(node->g_index, 0), GetRegisterName(node->g_index, 0));
}
break;
case DEC:
/* check data type */
if (node->data_type == REAL_TYPE){
fprintf(fp, "LI.D $28, 1.0\n");
fprintf(fp, "SUB.D %s, %s, $28\n", GetRegisterName(node->g_index, 1), GetRegisterName(node->g_index, 1));
}
else{
fprintf(fp, "SUBI %s, %s, 1\n", GetRegisterName(node->g_index, 0), GetRegisterName(node->g_index, 0));
}
break;
...
if (expression_data_type(node->left) == REAL_TYPE){
float_op = 1;
if(node->left->type == CONST_NODE){
const_op = 1;
Operand1 = 3;
}
else{
Operand1 = 1;
}
}
else{
if(node->left->type == CONST_NODE){
const_op = 1;
Operand1 = 2;
}
else{
Operand1 = 0;
}
}
if(node->data_type == REAL_TYPE){
float_op = 1;
Result = 1;
}
if(float_op == 1){
if(const_op == 1){
if(Operand1 == 2 || Operand1 == 3){
temp_const = (AST_Node_Const *) node->left;
}
else{
temp_const = (AST_Node_Const *) node->right;
}
/* floating-point constant */
if(temp_const->const_type == REAL_TYPE){
fprintf(fp, "LI.D $f28, %.2f\n", temp_const->val);
}
else{
fprintf(fp, "LI.D $f28, %d.0\n", temp_const->val);
}
}
/* operand needs conversion */
if(Operand1 == 0){
fprintf(fp, "MTC1.D %s, $f30\n", GetRegisterName(getGraphIndex(node->left) , 0));
fprintf(fp, "CVT.D.W $f30, $f30\n");
}
else if(Operand2 == 0){
fprintf(fp, "MTC1.D %s, $f30\n", GetRegisterName(getGraphIndex(node->right) , 0));
fprintf(fp, "CVT.D.W $f30, $f30\n");
}
fprintf(fp, "ADD.D ");
/* check if result needs conversion */
if(Result == 0){
fprintf(fp, "$f26, ");
}
else{
fprintf(fp, "%s, ", GetRegisterName(node->g_index, 1));
}
switch(Operand1){
case 0:
fprintf(fp, "$f30 ");
break;
case 1:
fprintf(fp, "%s ", GetRegisterName(getGraphIndex(node->left) , 1));
break;
case 2:
case 3:
fprintf(fp, "$f28 ");
}
switch(Operand2){
case 0:
fprintf(fp, "$f30 ");
break;
case 1:
fprintf(fp, "%s ", GetRegisterName(getGraphIndex(node->right) , 1));
break;
case 2:
case 3:
fprintf(fp, "$f28 ");
}
fprintf(fp, "\n");
/* result needs type-conversion */
if(Result == 0){
fprintf(fp, "CVT.W.D $f26, $f26\n");
fprintf(fp, "MTC1 %s, $f26\n", GetRegisterName(node->g_index, 0));
}
}
else if(const_op == 1){
if(Operand1 != 0){
temp_const = (AST_Node_Const *) node->left;
fprintf(fp, "ADDI %s, %s, %d\n", GetRegisterName(node->g_index, 0), GetRegisterName(getGraphIndex(node->right), 0), temp_const->val);
}
if(Operand2 != 0){
temp_const = (AST_Node_Const *) node->right;
fprintf(fp, "ADDI %s, %s, %d\n", GetRegisterName(node->g_index, 0), GetRegisterName(getGraphIndex(node->left), 0), temp_const->val);
}
}
else{
fprintf(fp, "ADD %s, %s, %s\n", GetRegisterName(node->g_index, 0), GetRegisterName(getGraphIndex(node->left), 0), GetRegisterName(getGraphIndex(node->right), 0));
}.data
# variables
i: .word 0
val: .double 0.000000
res: .double 0.000000
# messages
.text
main:
L.D $f2, val
LI.D $f28, 1.0
ADD.D $f6, $f2 $f28
.data
# variables
i: .word 0
val: .double 2.500000
res: .space 80
# messages
.text
main:
LW $s0, i($0)
Relational Expression
L.D $f2, val
LW $s0, i($0)
Function Call result
LW $s2, res($0)
LW $s2, res($0)
.data
# variables
c: .byte 'c'
i: .word 0
p: .word 0
val: .double 2.500000
res: .double 0.500000, 1.500000, 2.500000, 3.500000, 4.500000, 5.500000
# messages
msg1: .asciiz "\n"
msg2: .asciiz "\n"
msg3: .asciiz "iteration: 3\n"
msg4: .asciiz " "
msg5: .asciiz "\n"
.text
main:
LA $s3, res($0)
LW $s0, i($0)
Relational Expression
LW $s0, i($0)
Relational Expression
LW $s0, i($0)
Equality Expression
LW $s0, i($0)
MULI $s5, $s0, 2
Function Call result
L.D $f4, val
LW $s0, i($0)
Function Call result
LW $s3, res($0)
L.D $f4, val
LW $s0, i($0)
Function Call result
LW $s3, res($0)
LW $s3, res($0)
LW $s4, p($0)
ADDI $t1, $s4, 1
LW $s0, i($0)
Equality Expression
L.D $f4, val
Equality Expression
Boolean Expression
LW $s0, i($0)
Relational Expression
LW $s0, i($0)
LW $s1, c($0)