-
Clemens Paumgarten authoredClemens Paumgarten authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
tac.c 9.79 KiB
#include <stdlib.h>
#include <assert.h>
#include "mcc/tac.h"
#include "mcc/tac_string_builder.h"
// --------------------------------------------- Error Collector
// struct mcc_tac_error_collector *mcc_tac_new_error_collector() {
// struct mcc_tac_error_collector *ec = malloc(sizeof(*ec));
// if (ec == NULL) return NULL;
// ec -> errors = mcc_create_dynamic_array(MCC_TAC_ERROR_SIZE);
// return ec;
// }
// int mcc_tac_add_error(struct mcc_tac_error_collector *ec, struct mcc_tac_error *e) {
// assert(ec);
// assert(e);
// return mcc_add_to_array(ec -> errors, e);
// }
// struct mcc_tac_error *mcc_tac_new_error(struct mcc_ast_source_location *sloc, enum mcc_tac_error_type error_type) {
// struct mcc_tac_error *e = malloc(sizeof(*e));
// e -> sloc = sloc;
// e -> error_type = error_type;
// return e;
// }
// --------------------------------------------- TAC Object
struct mcc_tac *mcc_tac_new(struct mcc_tac *prev_tac, struct mcc_symbol_table *st) {
struct mcc_tac *tac = malloc(sizeof(*tac));
if(!tac) {
return NULL;
}
tac->prev = prev_tac;
tac->next = NULL;
if(prev_tac != NULL) {
prev_tac->next = tac;
}
tac->tac_entries = mcc_create_dynamic_array(MCC_TAC_ENTRY_SIZE);
tac->temporary_count = 0;
mcc_tac_new_label_string(tac);
tac->label_count = 0;
tac->root_table = st;
tac->current_symbol_table = st;
tac->current_symbol_index = 0;
tac->funcion_counter = 0;
return tac;
}
struct mcc_tac_entry *mcc_tac_new_entry(
enum mcc_tac_operation tac_op,
char *arg1,
char *arg2,
char *result
) {
struct mcc_tac_entry *te = malloc(sizeof(*te));
te->tac_op = tac_op;
te->arg1 = arg1;
te->arg2 = arg2;
te->result = result;
return te;
}
int mcc_tac_add_entry(struct mcc_tac *tac, struct mcc_tac_entry *te) {
return mcc_add_to_array(tac->tac_entries, te);
}
int mcc_tac_create_and_add_new_entry(
enum mcc_tac_operation tac_op,
char *arg1_temp,
char *arg2_temp,
char *result_temp,
struct mcc_tac *tac) {
// this way every string is stored in heap, easier to free
char *arg1 = NULL;
char *arg2 = NULL;
char *result = NULL;
if (arg1_temp != NULL) {
arg1 = malloc(sizeof(arg1_temp));
*arg1 = *arg1_temp;
}
if (arg2_temp != NULL) {
arg2 = malloc(sizeof(arg2_temp));
*arg2 = *arg2_temp;
}
if (result_temp != NULL) {
result = malloc(sizeof(result));
*result = *result;
}
struct mcc_tac_entry *te = mcc_tac_new_entry(tac_op, arg1, arg2, result);
return mcc_tac_add_entry(tac, te);
}
int mcc_tac_create_and_add_new_entry_temp(
enum mcc_tac_operation tac_op,
char *arg1,
char *arg2,
struct mcc_tac *tac) {
char *result = mcc_tac_new_temporary_string(tac);
struct mcc_tac_entry *te = mcc_tac_new_entry(tac_op, arg1, arg2, result);
return mcc_tac_add_entry(tac, te);
}
void mcc_tac_delete_entry(void *te) {
struct mcc_tac_entry *tac_entry = (struct mcc_tac_entry *) te;
free(tac_entry);
}
void mcc_tac_delete(struct mcc_tac *tac) {
if(tac->next != NULL) {
mcc_tac_delete(tac->next);
}
mcc_delete_array(tac->tac_entries, mcc_tac_delete_entry);
free(tac);
}
// --------------------------------------------------------------------- Conversion of AST Types to IR-Operation Types
enum mcc_tac_operation mcc_convert_ast_type_to_tac_literal(enum mcc_ast_data_type type) {
switch(type) {
case MCC_AST_DATA_TYPE_INT:
return MCC_TAC_INT;
case MCC_AST_DATA_TYPE_BOOL:
return MCC_TAC_BOOL;
case MCC_AST_DATA_TYPE_FLOAT:
return MCC_TAC_FLOAT;
case MCC_AST_DATA_TYPE_STRING:
return MCC_TAC_STRING;
default:
break;
}
return MCC_TAC_UNKNOWN;
}
enum mcc_tac_operation mcc_convert_ast_type_to_tac_ident(enum mcc_ast_data_type type) {
switch(type) {
case MCC_AST_DATA_TYPE_INT:
return MCC_TAC_IDENTIFIER_INT;
case MCC_AST_DATA_TYPE_BOOL:
return MCC_TAC_IDENTIFIER_BOOL;
case MCC_AST_DATA_TYPE_FLOAT:
return MCC_TAC_IDENTIFIER_FLOAT;
case MCC_AST_DATA_TYPE_STRING:
return MCC_TAC_IDENTIFIER_STRING;
default:
break;
}
return MCC_TAC_UNKNOWN;
}
enum mcc_tac_operation mcc_convert_ast_type_to_tac_param_push(enum mcc_ast_data_type type, bool is_array) {
switch(type) {
case MCC_AST_DATA_TYPE_INT:
return is_array ? MCC_TAC_PARAM_INT : MCC_TAC_PARAM_INT_ARR;
case MCC_AST_DATA_TYPE_BOOL:
return is_array ? MCC_TAC_PARAM_BOOL : MCC_TAC_PARAM_BOOL_ARR;
case MCC_AST_DATA_TYPE_FLOAT:
return is_array ? MCC_TAC_PARAM_FLOAT : MCC_TAC_PARAM_FLOAT_ARR;
case MCC_AST_DATA_TYPE_STRING:
return is_array ? MCC_TAC_PARAM_STRING : MCC_TAC_PARAM_STRING_ARR;
default:
return MCC_TAC_UNKNOWN;
}
}
enum mcc_tac_operation mcc_convert_ast_type_to_tac_param_pop(enum mcc_ast_data_type type, bool is_array) {
switch(type) {
case MCC_AST_DATA_TYPE_INT:
return is_array ? MCC_TAC_PARAM_POP_INT : MCC_TAC_PARAM_POP_INT_ARR;
case MCC_AST_DATA_TYPE_BOOL:
return is_array ? MCC_TAC_PARAM_POP_BOOL : MCC_TAC_PARAM_POP_BOOL_ARR;
case MCC_AST_DATA_TYPE_FLOAT:
return is_array ? MCC_TAC_PARAM_POP_FLOAT : MCC_TAC_PARAM_POP_FLOAT_ARR;
case MCC_AST_DATA_TYPE_STRING:
return is_array ? MCC_TAC_PARAM_POP_STRING : MCC_TAC_PARAM_POP_STRING_ARR;
default:
return MCC_TAC_UNKNOWN;
}
}
enum mcc_tac_operation mcc_convert_ast_type_to_tac_unary(enum mcc_ast_data_type type) {
switch(type) {
case MCC_AST_DATA_TYPE_INT:
return MCC_TAC_MINUS_INT_UN;
case MCC_AST_DATA_TYPE_BOOL:
return MCC_TAC_NOT;
case MCC_AST_DATA_TYPE_FLOAT:
return MCC_TAC_MINUS_FLOAT_UN;
default:
return MCC_TAC_UNKNOWN;
}
}
enum mcc_tac_operation
mcc_convert_ast_type_to_tac_binary(enum mcc_ast_binary_op binary_op, enum mcc_ast_data_type type) {
switch(binary_op) {
case MCC_AST_BINARY_OP_ADD:
return (type == MCC_AST_DATA_TYPE_INT)
? MCC_TAC_PLUS_INT
: MCC_TAC_PLUS_FLOAT;
case MCC_AST_BINARY_OP_SUB:
return (type == MCC_AST_DATA_TYPE_INT)
? MCC_TAC_MINUS_INT_BIN
: MCC_TAC_MINUS_FLOAT_BIN;
case MCC_AST_BINARY_OP_MUL:
return (type == MCC_AST_DATA_TYPE_INT)
? MCC_TAC_MUL_INT
: MCC_TAC_MUL_FLOAT;
case MCC_AST_BINARY_OP_DIV:
return (type == MCC_AST_DATA_TYPE_INT)
? MCC_TAC_DIV_INT
: MCC_TAC_DIV_FLOAT;
case MCC_AST_BINARY_OP_LESS:
return (type == MCC_AST_DATA_TYPE_INT)
? MCC_TAC_LT
: MCC_TAC_LT_FLOAT;
case MCC_AST_BINARY_OP_GREATER:
return (type == MCC_AST_DATA_TYPE_INT)
? MCC_TAC_GT
: MCC_TAC_GT_FLOAT;
case MCC_AST_BINARY_OP_LESS_EQUALS:
return (type == MCC_AST_DATA_TYPE_INT)
? MCC_TAC_LTEQ
: MCC_TAC_LTEQ_FLOAT;
case MCC_AST_BINARY_OP_GREATER_EQUALS:
return (type == MCC_AST_DATA_TYPE_INT)
? MCC_TAC_GTEQ
: MCC_TAC_GTEQ_FLOAT;
case MCC_AST_BINARY_OP_EQUALS:
if(type == MCC_AST_DATA_TYPE_BOOL) {
return MCC_TAC_EQ_BOOL;
} else if(type == MCC_AST_DATA_TYPE_INT) {
return MCC_TAC_EQ;
} else {
return MCC_TAC_EQ_FLOAT;
}
case MCC_AST_BINARY_OP_NOT_EQUALS:
if(type == MCC_AST_DATA_TYPE_BOOL) {
return MCC_TAC_NEQ_BOOL;
} else if(type == MCC_AST_DATA_TYPE_INT) {
return MCC_TAC_NEQ;
} else {
return MCC_TAC_NEQ_FLOAT;
}
case MCC_AST_BINARY_OP_AND:
return MCC_TAC_AND;
case MCC_AST_BINARY_OP_OR:
return MCC_TAC_OR;
default:
break;
}
return MCC_TAC_UNKNOWN;
}
enum mcc_tac_operation mcc_convert_ast_type_to_tac_load(enum mcc_ast_data_type type) {
switch(type) {
case MCC_AST_DATA_TYPE_BOOL:
return MCC_TAC_LOAD_BOOL;
case MCC_AST_DATA_TYPE_INT:
return MCC_TAC_LOAD_INT;
case MCC_AST_DATA_TYPE_FLOAT:
return MCC_TAC_LOAD_FLOAT;
case MCC_AST_DATA_TYPE_STRING:
return MCC_TAC_LOAD_STRING;
default:
break;
}
return MCC_TAC_UNKNOWN;
}
enum mcc_tac_operation mcc_convert_ast_type_to_tac_store(enum mcc_ast_data_type type) {
switch(type) {
case MCC_AST_DATA_TYPE_BOOL:
return MCC_TAC_STORE_BOOL;
case MCC_AST_DATA_TYPE_INT:
return MCC_TAC_STORE_INT;
case MCC_AST_DATA_TYPE_FLOAT:
return MCC_TAC_STORE_FLOAT;
case MCC_AST_DATA_TYPE_STRING:
return MCC_TAC_STORE_STRING;
default:
return MCC_TAC_UNKNOWN;
}
}
// --------------------------------------------------------------------- Tac Scope Jump Helper Functions
void mcc_tac_enter_next_deeper_scope(struct mcc_tac *tac) {
struct mcc_symbol_table *next_curr = tac->current_symbol_table->inner_tables->arr[tac->current_symbol_index];
tac->current_symbol_table = next_curr;
tac->current_symbol_index = 0;
}
void mcc_tac_exit_to_outer_scope(struct mcc_tac *tac, int tac_st_index) {
struct mcc_symbol_table *root = tac->current_symbol_table->parent;
tac->current_symbol_table = root;
tac->current_symbol_index = tac_st_index;
}