diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/code-generation.c | 246 | ||||
-rw-r--r-- | src/register.c | 24 | ||||
-rw-r--r-- | src/register.h | 7 | ||||
-rw-r--r-- | src/semantic-analysis.c | 3 | ||||
-rw-r--r-- | src/symbol-table.h | 10 |
5 files changed, 257 insertions, 33 deletions
diff --git a/src/code-generation.c b/src/code-generation.c index a2d93da..8636322 100644 --- a/src/code-generation.c +++ b/src/code-generation.c @@ -96,21 +96,27 @@ static void calc_array_offset(CcmmcAst *ref, CcmmcSymbolType *type, generate_expression(ref->child, state, result, current_offset); index = ccmmc_register_alloc(state->reg_pool, current_offset); mul = ccmmc_register_alloc(state->reg_pool, current_offset); - for (i = 1, index_node = ref->child->right_sibling; index_node != NULL; - i++, index_node = index_node->right_sibling) { - generate_expression(index_node, state, index, current_offset); + for (i = 1, index_node = ref->child->right_sibling; + index_node != NULL || i < type->array_dimension; + i++, index_node = index_node == NULL ? NULL : index_node->right_sibling) { + if (index_node != NULL) { + generate_expression(index_node, state, index, current_offset); + index_reg = ccmmc_register_lock(state->reg_pool, index); + } result_reg = ccmmc_register_lock(state->reg_pool, result); - index_reg = ccmmc_register_lock(state->reg_pool, index); mul_reg = ccmmc_register_lock(state->reg_pool, mul); fprintf(state->asm_output, "\tldr\t%s, =%zu\n" - "\tmul\t%s, %s, %s\n" - "\tadd\t%s, %s, %s\n", + "\tmul\t%s, %s, %s\n", mul_reg, type->array_size[i], - result_reg, result_reg, mul_reg, - result_reg, result_reg, index_reg); + result_reg, result_reg, mul_reg); + if (index_node != NULL) { + fprintf(state->asm_output, + "\tadd\t%s, %s, %s\n", + result_reg, result_reg, index_reg); + ccmmc_register_unlock(state->reg_pool, index); + } ccmmc_register_unlock(state->reg_pool, result); - ccmmc_register_unlock(state->reg_pool, index); ccmmc_register_unlock(state->reg_pool, mul); } ccmmc_register_free(state->reg_pool, index, current_offset); @@ -123,6 +129,10 @@ static void calc_array_offset(CcmmcAst *ref, CcmmcSymbolType *type, ccmmc_register_unlock(state->reg_pool, result); } +static inline int calc_arg_offset(int arg_num) { + return 16 + (arg_num - 8) * 8; +} + #define REG_TMP "x9" static void load_variable(CcmmcAst *id, CcmmcState *state, CcmmcTmp *dist, uint64_t *current_offset) @@ -171,7 +181,16 @@ static void load_variable(CcmmcAst *id, CcmmcState *state, CcmmcTmp *dist, } else { if (id->value_id.kind != CCMMC_KIND_ID_ARRAY) { dist_reg = ccmmc_register_lock(state->reg_pool, dist); - if (safe_immediate(var_sym->attr.addr)) { + if (var_sym->attr.is_arg) { + if (var_sym->attr.arg_num < 8) + fprintf(state->asm_output, + "\tmov\t%s, w%d\n", + dist_reg, var_sym->attr.arg_num); + else + fprintf(state->asm_output, + "\tldr\t%s, [fp, #%d]\n", + dist_reg, calc_arg_offset(var_sym->attr.arg_num)); + } else if (safe_immediate(var_sym->attr.addr)) { fprintf(state->asm_output, "\tldr\t%s, [fp, #-%" PRIu64 "]\n", dist_reg, var_sym->attr.addr); @@ -196,14 +215,27 @@ static void load_variable(CcmmcAst *id, CcmmcState *state, CcmmcTmp *dist, offset_reg = ccmmc_register_lock(state->reg_pool, offset); ccmmc_register_extend_name(offset, extend); + + if (var_sym->attr.is_arg) { + if (var_sym->attr.arg_num < 8) + fprintf(state->asm_output, + "\tmov\t" REG_TMP ", x%d\n", + var_sym->attr.arg_num); + else + fprintf(state->asm_output, + "\tldr\t" REG_TMP ", [fp, #%d]\n", + calc_arg_offset(var_sym->attr.arg_num)); + } else { + fprintf(state->asm_output, + "\tldr\t" REG_TMP ", =%" PRIu64 "\n" + "\tsub\t" REG_TMP ", fp, " REG_TMP "\n" + "\tsxtw\t%s, %s\n", + var_sym->attr.addr, + extend, offset_reg); + } fprintf(state->asm_output, - "\tldr\t" REG_TMP ", =%" PRIu64 "\n" - "\tsub\t" REG_TMP ", fp, " REG_TMP "\n" - "\tsxtw\t%s, %s\n" "\tadd\t" REG_TMP ", " REG_TMP ", %s\n" "\tldr\t%s, [" REG_TMP "]\n", - var_sym->attr.addr, - extend, offset_reg, extend, dist_reg); @@ -261,7 +293,16 @@ static void store_variable(CcmmcAst *id, CcmmcState *state, CcmmcTmp *src, } else { if (id->value_id.kind != CCMMC_KIND_ID_ARRAY) { src_reg = ccmmc_register_lock(state->reg_pool, src); - if (safe_immediate(var_sym->attr.addr)) { + if (var_sym->attr.is_arg) { + if (var_sym->attr.arg_num < 8) + fprintf(state->asm_output, + "\tmov\tw%d, %s\n", + var_sym->attr.arg_num, src_reg); + else + fprintf(state->asm_output, + "\tstr\t%s, [fp, #%d]\n", + src_reg, calc_arg_offset(var_sym->attr.arg_num)); + } else if (safe_immediate(var_sym->attr.addr)) { fprintf(state->asm_output, "\tstr\t%s, [fp, #-%" PRIu64 "]\n", src_reg, var_sym->attr.addr); } else { @@ -285,14 +326,27 @@ static void store_variable(CcmmcAst *id, CcmmcState *state, CcmmcTmp *src, offset_reg = ccmmc_register_lock(state->reg_pool, offset); ccmmc_register_extend_name(offset, extend); + + if (var_sym->attr.is_arg) { + if (var_sym->attr.arg_num < 8) + fprintf(state->asm_output, + "\tmov\t" REG_TMP ", x%d\n", + var_sym->attr.arg_num); + else + fprintf(state->asm_output, + "\tldr\t" REG_TMP ", [fp, #%d]\n", + calc_arg_offset(var_sym->attr.arg_num)); + } else { + fprintf(state->asm_output, + "\tldr\t" REG_TMP ", =%" PRIu64 "\n" + "\tsub\t" REG_TMP ", fp, " REG_TMP "\n" + "\tsxtw\t%s, %s\n", + var_sym->attr.addr, + extend, offset_reg); + } fprintf(state->asm_output, - "\tldr\t" REG_TMP ", =%" PRIu64 "\n" - "\tsub\t" REG_TMP ", fp, " REG_TMP "\n" - "\tsxtw\t%s, %s\n" "\tadd\t" REG_TMP ", " REG_TMP ", %s\n" "\tstr\t%s, [" REG_TMP "]\n", - var_sym->attr.addr, - extend, offset_reg, extend, src_reg); @@ -352,15 +406,140 @@ static void call_function(CcmmcAst *id, CcmmcState *state, uint64_t *current_offset) { const char *func_name = id->value_id.name; - ccmmc_register_caller_save(state->reg_pool); + size_t stored_param_count = 0; if (strcmp(func_name, "write") == 0) func_name = call_write(id, state, current_offset); else if (strcmp(func_name, "read") == 0) func_name = "_read_int"; else if (strcmp(func_name, "fread") == 0) func_name = "_read_float"; + else if (id->right_sibling->child != NULL) { + CcmmcSymbol *func_sym = ccmmc_symbol_table_retrieve( + state->table, func_name); + size_t call_param_count = func_sym->type.param_count; + + // XXX: We should have a better way to find the function in which we are + CcmmcAst *in_func = id->parent; + for (; in_func->type_node != CCMMC_AST_NODE_DECL || + in_func->value_decl.kind != CCMMC_KIND_DECL_FUNCTION; + in_func = in_func->parent); + // XXX: We should not search scopes other than the global scope + CcmmcSymbol *in_func_sym = ccmmc_symbol_table_retrieve( + state->table, in_func->child->right_sibling->value_id.name); + stored_param_count = in_func_sym->type.param_count; + + CcmmcAst *arg; + CcmmcTmp *dists[call_param_count]; + size_t i; + for (i = 0; i < call_param_count; i++) + dists[i] = ccmmc_register_alloc(state->reg_pool, current_offset); + for (i = 0, arg = id->right_sibling->child; i < call_param_count; + i++, arg = arg->right_sibling) + if (!ccmmc_symbol_type_is_array(func_sym->type.param_list[i])) + generate_expression(arg, state, dists[i], current_offset); + ccmmc_register_save_arguments(state->reg_pool, stored_param_count); + ccmmc_register_caller_save(state->reg_pool); + for (i = 0, arg = id->right_sibling->child; i < call_param_count; + i++, arg = arg->right_sibling) { + if (ccmmc_symbol_type_is_array(func_sym->type.param_list[i])) { + assert(arg->type_node == CCMMC_AST_NODE_ID); + + CcmmcTmp *offset = ccmmc_register_alloc( + state->reg_pool, current_offset); + CcmmcSymbol *var_sym = ccmmc_symbol_table_retrieve( + state->table, arg->value_id.name); + if (arg->child != NULL) + calc_array_offset(arg, &var_sym->type, state, + offset, current_offset); + + const char *offset_reg = ccmmc_register_lock( + state->reg_pool, offset); + char offset_extend[8]; + ccmmc_register_extend_name(offset, offset_extend); + +#define REG_TMP "x9" + if (var_sym->attr.is_arg) { + if (var_sym->attr.arg_num < 8) + fprintf(state->asm_output, + "\tmov\t" REG_TMP ", x%d\n", + var_sym->attr.arg_num); + else + fprintf(state->asm_output, + "\tldr\t" REG_TMP ", [fp, #%d]\n", + calc_arg_offset(var_sym->attr.arg_num)); + } else { + fprintf(state->asm_output, + "\tldr\t" REG_TMP ", =%" PRIu64 "\n" + "\tsub\t" REG_TMP ", fp, " REG_TMP "\n" + "\tsxtw\t%s, %s\n", + var_sym->attr.addr, + offset_extend, offset_reg); + } + if (arg->child != NULL) + fprintf(state->asm_output, + "\tadd\t" REG_TMP ", " REG_TMP ", %s\n", + offset_extend); + if (i < 8) + fprintf(state->asm_output, + "\tmov\tx%zu, " REG_TMP "\n", i); + else + fprintf(state->asm_output, + "\tstr\t" REG_TMP ", [sp, -8]!\n"); +#undef REG_TMP + ccmmc_register_unlock(state->reg_pool, offset); + ccmmc_register_free(state->reg_pool, offset, current_offset); + } else { + CcmmcAstValueType arg_type = arg->type_value; + CcmmcAstValueType expected_type = + func_sym->type.param_list[i].type_base; + const char *dist_reg = ccmmc_register_lock( + state->reg_pool, dists[i]); + char dist_extend[8]; + ccmmc_register_extend_name(dists[i], dist_extend); +#define FPREG_TMP "s16" + if (arg_type == CCMMC_AST_VALUE_FLOAT && + expected_type == CCMMC_AST_VALUE_INT) + fprintf(state->asm_output, + "\tfmov\t%s, %s\n" + "\tfcvtas\t%s, %s\n", + FPREG_TMP, dist_reg, + dist_reg, FPREG_TMP); + else if (arg_type == CCMMC_AST_VALUE_INT && + expected_type == CCMMC_AST_VALUE_FLOAT) + fprintf(state->asm_output, + "\tscvtf\t%s, %s\n" + "\tfmov\t%s, %s\n", + FPREG_TMP, dist_reg, + dist_reg, FPREG_TMP); +#undef FPREG_TMP + if (i < 8) + fprintf(state->asm_output, + "\tsxtw\tx%zu, %s\n", + i, dist_reg); + else + fprintf(state->asm_output, + "\tsxtw\t%s, %s\n" + "\tstr\t%s, [sp, -8]!\n", + dist_reg, dist_reg, + dist_reg); + ccmmc_register_unlock(state->reg_pool, dists[i]); + } + } + fprintf(state->asm_output, "\tbl\t%s\n", func_name); + if (call_param_count > 8) + fprintf(state->asm_output, + "\tadd\tsp, sp, %zu\n", + call_param_count * 8); + ccmmc_register_caller_load(state->reg_pool); + ccmmc_register_load_arguments(state->reg_pool, stored_param_count); + for (i = 0; i < call_param_count; i++) + ccmmc_register_free(state->reg_pool, dists[i], current_offset); + return; + } + ccmmc_register_caller_save(state->reg_pool); fprintf(state->asm_output, "\tbl\t%s\n", func_name); ccmmc_register_caller_load(state->reg_pool); + ccmmc_register_load_arguments(state->reg_pool, stored_param_count); } static void generate_expression(CcmmcAst *expr, CcmmcState *state, @@ -778,15 +957,15 @@ static void calc_and_save_expression_result(CcmmcAst *lvar, CcmmcAst *expr, ccmmc_register_free(state->reg_pool, result, current_offset); } -static void generate_block( - CcmmcAst *block, CcmmcState *state, uint64_t current_offset); +static void generate_block(CcmmcAst *block, CcmmcState *state, + uint64_t current_offset, bool scope_already_open); static void generate_statement( CcmmcAst *stmt, CcmmcState *state, uint64_t current_offset) { if (stmt->type_node == CCMMC_AST_NODE_NUL) return; if (stmt->type_node == CCMMC_AST_NODE_BLOCK) { - generate_block(stmt, state, current_offset); + generate_block(stmt, state, current_offset, false); return; } @@ -1022,10 +1201,11 @@ static void init_local_variable( } } -static void generate_block( - CcmmcAst *block, CcmmcState *state, uint64_t current_offset) +static void generate_block(CcmmcAst *block, CcmmcState *state, + uint64_t current_offset, bool scope_already_open) { - ccmmc_symbol_table_reopen_scope(state->table); + if (!scope_already_open) + ccmmc_symbol_table_reopen_scope(state->table); CcmmcAst *child = block->child; uint64_t orig_offset = current_offset; @@ -1088,8 +1268,16 @@ static void generate_function(CcmmcAst *function, CcmmcState *state) symbol_name, symbol_name); CcmmcAst *param_node = function->child->right_sibling->right_sibling; + ccmmc_symbol_table_reopen_scope(state->table); + CcmmcAst *arg_node = param_node->child; + for (int i = 0; arg_node != NULL; arg_node = arg_node->right_sibling, i++) { + CcmmcSymbol *arg_sym = ccmmc_symbol_table_retrieve(state->table, + arg_node->child->right_sibling->value_id.name); + arg_sym->attr.is_arg = true; + arg_sym->attr.arg_num = i; + } CcmmcAst *block_node = param_node->right_sibling; - generate_block(block_node, state, 0); + generate_block(block_node, state, 0, true); fprintf(state->asm_output, ".LR_%s:\n" "\tldp\tlr, fp, [sp], 16\n" diff --git a/src/register.c b/src/register.c index 8ca8b6c..e7759fd 100644 --- a/src/register.c +++ b/src/register.c @@ -218,6 +218,30 @@ void ccmmc_register_caller_load(CcmmcRegPool *pool) (i + 1) * REG_SIZE); } +void ccmmc_register_save_arguments(CcmmcRegPool *pool, int arg_count) +{ + if (arg_count <= 0) + return; + if (arg_count >= 8) + arg_count = 8; + for (int i = 0; i < arg_count; i++) + fprintf(pool->asm_output, "\tstr\tx%d, [sp, #-%d]\n", + i, (i + 1) * 8); + fprintf(pool->asm_output, "\tsub\tsp, sp, %d\n", arg_count * 8); +} + +void ccmmc_register_load_arguments(CcmmcRegPool *pool, int arg_count) +{ + if (arg_count <= 0) + return; + if (arg_count >= 8) + arg_count = 8; + fprintf(pool->asm_output, "\tadd\tsp, sp, %d\n", arg_count * 8); + for (int i = 0; i < arg_count; i++) + fprintf(pool->asm_output, "\tldr\tx%d, [sp, #-%d]\n", + i, (i + 1) * 8); +} + void ccmmc_register_fini(CcmmcRegPool *pool) { // TODO: free register pool diff --git a/src/register.h b/src/register.h index 1172714..04e4d8a 100644 --- a/src/register.h +++ b/src/register.h @@ -37,9 +37,14 @@ void ccmmc_register_unlock (CcmmcRegPool *pool, void ccmmc_register_free (CcmmcRegPool *pool, CcmmcTmp *tmp, uint64_t *offset); -void ccmmc_register_extend_name (CcmmcTmp *tmp, char *extend_name); +void ccmmc_register_extend_name (CcmmcTmp *tmp, + char *extend_name); void ccmmc_register_caller_save (CcmmcRegPool *pool); void ccmmc_register_caller_load (CcmmcRegPool *pool); +void ccmmc_register_save_arguments (CcmmcRegPool *pool, + int arg_count); +void ccmmc_register_load_arguments (CcmmcRegPool *pool, + int arg_count); void ccmmc_register_fini (CcmmcRegPool *pool); #endif diff --git a/src/semantic-analysis.c b/src/semantic-analysis.c index 15b3f8c..155ab57 100644 --- a/src/semantic-analysis.c +++ b/src/semantic-analysis.c @@ -451,6 +451,9 @@ static bool check_call(CcmmcAst *call, CcmmcSymbolTable *table) any_error = true; continue; } + // Get the type of the scalar variable for later use + if (func->type.param_list[i].array_dimension == 0) + any_error = check_relop_expr(param, table) || any_error; } else { any_error = check_relop_expr(param, table) || any_error; diff --git a/src/symbol-table.h b/src/symbol-table.h index dbd9e33..589b9f9 100644 --- a/src/symbol-table.h +++ b/src/symbol-table.h @@ -25,7 +25,11 @@ typedef struct CcmmcSymbolType_struct { } CcmmcSymbolType; typedef struct CcmmcSymbolAttr_struct { - uint64_t addr; + bool is_arg; + union { + uint64_t addr; + unsigned int arg_num; + }; } CcmmcSymbolAttr; typedef struct CcmmcSymbol_struct CcmmcSymbol; @@ -72,10 +76,10 @@ static inline bool ccmmc_symbol_is_function(CcmmcSymbol *symbol) { return ccmmc_symbol_type_is_function(symbol->type); } static inline bool ccmmc_symbol_attr_is_global(CcmmcSymbolAttr *attr) { - return attr->addr == 0; + return !attr->is_arg && attr->addr == 0; } static inline bool ccmmc_symbol_attr_is_local(CcmmcSymbolAttr *attr) { - return attr->addr != 0; + return !ccmmc_symbol_attr_is_global(attr); } void ccmmc_symbol_table_open_scope (CcmmcSymbolTable *table); |