#include <stdio.h> #include<assert.h> #include "mcc/dynamic_array.h" #include "mcc/symbol_table.h" #include "mcc/symbol_table_print.h" #include "mcc/tac.h" static const char *tac_type(enum mcc_tac_operation type) { switch (type) { case MCC_TAC_BOOL: case MCC_TAC_BOOL_LITERAL: case MCC_TAC_NOT: case MCC_TAC_AND: case MCC_TAC_OR: case MCC_TAC_LOAD_BOOL: case MCC_TAC_STORE_BOOL: case MCC_TAC_EQ_BOOL: case MCC_TAC_IDENTIFIER_BOOL: case MCC_TAC_PARAM_BOOL: case MCC_TAC_PARAM_POP_BOOL: case MCC_TAC_NEQ_BOOL: return "bool"; case MCC_TAC_INT: case MCC_TAC_INT_LITERAL: case MCC_TAC_MINUS_INT_BIN: case MCC_TAC_PLUS_INT: case MCC_TAC_MUL_INT: case MCC_TAC_DIV_INT: case MCC_TAC_LOAD_INT: case MCC_TAC_EQ: case MCC_TAC_NEQ: case MCC_TAC_GT: case MCC_TAC_LT: case MCC_TAC_LTEQ: case MCC_TAC_IDENTIFIER_INT: case MCC_TAC_PARAM_INT: case MCC_TAC_PARAM_POP_INT: case MCC_TAC_GTEQ: return "int"; case MCC_TAC_FLOAT: case MCC_TAC_IDENTIFIER_FLOAT: case MCC_TAC_FLOAT_LITERAL: case MCC_TAC_MINUS_FLOAT_UN: case MCC_TAC_PLUS_FLOAT: case MCC_TAC_MINUS_FLOAT_BIN: case MCC_TAC_MUL_FLOAT: case MCC_TAC_DIV_FLOAT: case MCC_TAC_PARAM_FLOAT: case MCC_TAC_PARAM_POP_FLOAT: case MCC_TAC_LOAD_FLOAT: case MCC_TAC_STORE_FLOAT: case MCC_TAC_LT_FLOAT: case MCC_TAC_LTEQ_FLOAT: case MCC_TAC_GT_FLOAT: case MCC_TAC_GTEQ_FLOAT: case MCC_TAC_EQ_FLOAT: case MCC_TAC_NEQ_FLOAT: return "float"; case MCC_TAC_STRING: case MCC_TAC_IDENTIFIER_STRING: case MCC_TAC_STRING_LITERAL: case MCC_TAC_PARAM_STRING: case MCC_TAC_PARAM_POP_STRING: case MCC_TAC_LOAD_STRING: case MCC_TAC_STORE_STRING: return "string"; case MCC_TAC_JMP: case MCC_TAC_JMP_FALSE: case MCC_TAC_LABEL: case MCC_TAC_CALL: case MCC_TAC_RETURN: case MCC_TAC_FUNCTION_END: case MCC_TAC_UNKNOWN: return "untyped"; case MCC_TAC_PARAM_POP_BOOL_ARR: case MCC_TAC_PARAM_BOOL_ARR: return "bool_array"; case MCC_TAC_PARAM_POP_INT_ARR: case MCC_TAC_PARAM_INT_ARR: return "int_array"; case MCC_TAC_PARAM_POP_STRING_ARR: case MCC_TAC_PARAM_STRING_ARR: return "string_array"; case MCC_TAC_PARAM_POP_FLOAT_ARR: case MCC_TAC_PARAM_FLOAT_ARR: return "float_arr"; } return "ERROR"; } void tac_print(struct mcc_tac *tac, FILE *out) { fprintf(out,"------------------------------\n"); fprintf(out,"- TAC -\n"); fprintf(out,"------------------------------\n"); for (int i = 0; i < tac->tac_entries->size ; i++) { struct mcc_tac_entry *entry = tac->tac_entries->arr[i]; const char *op_type = tac_type(entry->tac_op); switch (entry->tac_op) { // Assignment case MCC_TAC_BOOL: case MCC_TAC_IDENTIFIER_BOOL: case MCC_TAC_BOOL_LITERAL: case MCC_TAC_INT: case MCC_TAC_IDENTIFIER_INT: case MCC_TAC_INT_LITERAL: case MCC_TAC_FLOAT: case MCC_TAC_IDENTIFIER_FLOAT: case MCC_TAC_FLOAT_LITERAL: case MCC_TAC_STRING: case MCC_TAC_IDENTIFIER_STRING: case MCC_TAC_STRING_LITERAL: fprintf(out,"%s = %s (%s)\n", entry->result, entry->arg1, op_type); break; // Unary case MCC_TAC_MINUS_INT_UN: case MCC_TAC_MINUS_FLOAT_UN: fprintf(out,"%s = -%s (%s)\n", entry->result, entry->arg1, op_type); break; case MCC_TAC_NOT: fprintf(out,"%s = !%s (%s)\n", entry->result, entry->arg1, op_type); break; // Binary case MCC_TAC_PLUS_INT: case MCC_TAC_PLUS_FLOAT: fprintf(out,"%s = %s + %s (%s)\n", entry->result, entry->arg1, entry->arg2, op_type); break; case MCC_TAC_MINUS_INT_BIN: case MCC_TAC_MINUS_FLOAT_BIN: fprintf(out,"%s = %s - %s (%s)\n", entry->result, entry->arg1, entry->arg2, op_type); break; case MCC_TAC_MUL_INT: case MCC_TAC_MUL_FLOAT: fprintf(out,"%s = %s * %s (%s)\n", entry->result, entry->arg1, entry->arg2, op_type); break; case MCC_TAC_DIV_INT: case MCC_TAC_DIV_FLOAT: fprintf(out,"%s = %s / %s (%s)\n", entry->result, entry->arg1, entry->arg2, op_type); break; case MCC_TAC_LT: case MCC_TAC_LT_FLOAT: fprintf(out,"%s = %s < %s (%s)\n", entry->result, entry->arg1, entry->arg2, op_type); break; case MCC_TAC_GT: case MCC_TAC_GT_FLOAT: fprintf(out,"%s = %s > %s (%s)\n", entry->result, entry->arg1, entry->arg2, op_type); break; case MCC_TAC_LTEQ: case MCC_TAC_LTEQ_FLOAT: fprintf(out,"%s = %s <= %s (%s)\n", entry->result, entry->arg1, entry->arg2, op_type); break; case MCC_TAC_GTEQ: case MCC_TAC_GTEQ_FLOAT: fprintf(out,"%s = %s >= %s (%s)\n", entry->result, entry->arg1, entry->arg2, op_type); break; case MCC_TAC_AND: fprintf(out,"%s = %s && %s (%s)\n", entry->result, entry->arg1, entry->arg2, op_type); break; case MCC_TAC_OR: fprintf(out,"%s = %s || %s (%s)\n", entry->result, entry->arg1, entry->arg2, op_type); break; case MCC_TAC_EQ: case MCC_TAC_EQ_FLOAT: case MCC_TAC_EQ_BOOL: fprintf(out,"%s = %s == %s (%s)\n", entry->result, entry->arg1, entry->arg2, op_type); break; case MCC_TAC_NEQ: case MCC_TAC_NEQ_FLOAT: case MCC_TAC_NEQ_BOOL: fprintf(out,"%s = %s != %s (%s)\n", entry->result, entry->arg1, entry->arg2, op_type); break; // params case MCC_TAC_PARAM_BOOL: case MCC_TAC_PARAM_INT: case MCC_TAC_PARAM_FLOAT: case MCC_TAC_PARAM_STRING: fprintf(out,"param_push %s (%s)\n", entry->arg1, op_type); break; case MCC_TAC_PARAM_POP_BOOL: case MCC_TAC_PARAM_POP_INT: case MCC_TAC_PARAM_POP_FLOAT: case MCC_TAC_PARAM_POP_STRING: fprintf(out,"param_pop %s (%s)\n", entry->arg1, op_type); break; // load case MCC_TAC_LOAD_BOOL: case MCC_TAC_LOAD_INT: case MCC_TAC_LOAD_FLOAT: case MCC_TAC_LOAD_STRING: fprintf(out,"load %s[%s] %s (%s)\n", entry->arg1, entry->arg2, entry->result, op_type); break; // store case MCC_TAC_STORE_BOOL: case MCC_TAC_STORE_INT: case MCC_TAC_STORE_FLOAT: case MCC_TAC_STORE_STRING: fprintf(out,"store %s[%s] %s (%s)\n", entry->result, entry->arg2, entry->arg1, op_type); break; // IR operations case MCC_TAC_JMP: fprintf(out,"jump %s (%s)\n", entry->result, op_type); break; case MCC_TAC_JMP_FALSE: fprintf(out,"jumpfalse %s %s (%s)\n", entry->arg1, entry->result, op_type); break; case MCC_TAC_LABEL: fprintf(out,"\n"); fprintf(out,"label %s (%s)\n", entry->result, op_type); break; case MCC_TAC_VARIABLE_DECLARATION: fprintf(out,"declaration %s\n", entry->arg1); break; case MCC_TAC_CALL: fprintf(out,"call %s %s (%s)\n", entry->result, entry->arg1, op_type); break; case MCC_TAC_RETURN: case MCC_TAC_FUNCTION_END: fprintf(out,"return (%s)\n", op_type); break; case MCC_TAC_FUNCTION_START: fprintf(out, "\n\nfunction %s start \n", entry -> arg1); break; default: fprintf(out,"ERROR\n"); } } }