diff options
author | Ting-Wei Lan <lantw44@gmail.com> | 2016-01-02 18:16:20 +0800 |
---|---|---|
committer | Ting-Wei Lan <lantw44@gmail.com> | 2016-01-02 18:16:20 +0800 |
commit | 069e14a6ada9a51d12bb0f3222ea83af65e5a289 (patch) | |
tree | 951e08a79a8592bb2ee221f4e5868396d0f40286 | |
parent | 4c7f749733a5aba38dc61b73025f4f27fc7821fb (diff) | |
download | compiler2015-069e14a6ada9a51d12bb0f3222ea83af65e5a289.tar compiler2015-069e14a6ada9a51d12bb0f3222ea83af65e5a289.tar.gz compiler2015-069e14a6ada9a51d12bb0f3222ea83af65e5a289.tar.bz2 compiler2015-069e14a6ada9a51d12bb0f3222ea83af65e5a289.tar.lz compiler2015-069e14a6ada9a51d12bb0f3222ea83af65e5a289.tar.xz compiler2015-069e14a6ada9a51d12bb0f3222ea83af65e5a289.tar.zst compiler2015-069e14a6ada9a51d12bb0f3222ea83af65e5a289.zip |
Generate code to initialize variables with constants
This implementation only works with single constant. Using expressions
as initializers can corrupt values stored on the stack.
-rw-r--r-- | src/code-generation.c | 79 |
1 files changed, 44 insertions, 35 deletions
diff --git a/src/code-generation.c b/src/code-generation.c index 755f5af..1853001 100644 --- a/src/code-generation.c +++ b/src/code-generation.c @@ -430,6 +430,43 @@ static void generate_expression(CcmmcAst *expr, CcmmcState *state, assert(false); } +static void calc_and_save_expression_result(CcmmcAst *lvar, CcmmcAst *expr, + CcmmcState *state, uint64_t current_offset) +{ +#define FPREG_TMP "s16" + CcmmcTmp *tmp1 = ccmmc_register_alloc(state->reg_pool, ¤t_offset); + CcmmcTmp *tmp2 = ccmmc_register_alloc(state->reg_pool, ¤t_offset); + CcmmcTmp *tmp3 = ccmmc_register_alloc(state->reg_pool, ¤t_offset); + const char *result = ccmmc_register_lock(state->reg_pool, tmp1); + const char *op1 = ccmmc_register_lock(state->reg_pool, tmp2); + const char *op2 = ccmmc_register_lock(state->reg_pool, tmp3); + generate_expression(expr, state, result, op1, op2); + if (lvar->type_value == CCMMC_AST_VALUE_INT && + expr->type_value == CCMMC_AST_VALUE_FLOAT) { + fprintf(state->asm_output, + "\tfmov\t%s, %s\n" + "\tfcvtas\t%s, %s\n", + FPREG_TMP, result, + result, FPREG_TMP); + } else if ( + lvar->type_value == CCMMC_AST_VALUE_FLOAT && + expr->type_value == CCMMC_AST_VALUE_INT) { + fprintf(state->asm_output, + "\tscvtf\t%s, %s\n" + "\tfmov\t%s, %s\n", + FPREG_TMP, result, + result, FPREG_TMP); + } + store_variable(lvar, state, result); + ccmmc_register_unlock(state->reg_pool, tmp1); + ccmmc_register_unlock(state->reg_pool, tmp2); + ccmmc_register_unlock(state->reg_pool, tmp3); + ccmmc_register_free(state->reg_pool, tmp1, ¤t_offset); + ccmmc_register_free(state->reg_pool, tmp2, ¤t_offset); + ccmmc_register_free(state->reg_pool, tmp3, ¤t_offset); +#undef FPREG_TMP +} + static void generate_block( CcmmcAst *block, CcmmcState *state, uint64_t current_offset); static void generate_statement( @@ -451,40 +488,8 @@ static void generate_statement( case CCMMC_KIND_STMT_FOR: break; case CCMMC_KIND_STMT_ASSIGN: { -#define FPREG_TMP "s16" - CcmmcTmp *tmp1 = ccmmc_register_alloc(state->reg_pool, ¤t_offset); - CcmmcTmp *tmp2 = ccmmc_register_alloc(state->reg_pool, ¤t_offset); - CcmmcTmp *tmp3 = ccmmc_register_alloc(state->reg_pool, ¤t_offset); - const char *result = ccmmc_register_lock(state->reg_pool, tmp1); - const char *op1 = ccmmc_register_lock(state->reg_pool, tmp2); - const char *op2 = ccmmc_register_lock(state->reg_pool, tmp3); - CcmmcAst *lvar = stmt->child; - CcmmcAst *expr = stmt->child->right_sibling; - generate_expression(expr, state, result, op1, op2); - if (lvar->type_value == CCMMC_AST_VALUE_INT && - expr->type_value == CCMMC_AST_VALUE_FLOAT) { - fprintf(state->asm_output, - "\tfmov\t%s, %s\n" - "\tfcvtas\t%s, %s\n", - FPREG_TMP, result, - result, FPREG_TMP); - } else if ( - lvar->type_value == CCMMC_AST_VALUE_FLOAT && - expr->type_value == CCMMC_AST_VALUE_INT) { - fprintf(state->asm_output, - "\tscvtf\t%s, %s\n" - "\tfmov\t%s, %s\n", - FPREG_TMP, result, - result, FPREG_TMP); - } - store_variable(lvar, state, result); - ccmmc_register_unlock(state->reg_pool, tmp1); - ccmmc_register_unlock(state->reg_pool, tmp2); - ccmmc_register_unlock(state->reg_pool, tmp3); - ccmmc_register_free(state->reg_pool, tmp1, ¤t_offset); - ccmmc_register_free(state->reg_pool, tmp2, ¤t_offset); - ccmmc_register_free(state->reg_pool, tmp3, ¤t_offset); -#undef FPREG_TMP + calc_and_save_expression_result(stmt->child, + stmt->child->right_sibling, state, current_offset); } break; case CCMMC_KIND_STMT_IF: generate_statement(stmt->child->right_sibling, @@ -526,7 +531,11 @@ static uint64_t generate_local_variable( case CCMMC_KIND_ID_WITH_INIT: { current_offset += 4; var_sym->attr.addr = current_offset; - // TODO: initializer + // FIXME: This only works for single constant initializer. + // The value of sp is wrong, so evaluating expressions + // can overwrite other variables! + calc_and_save_expression_result(var_decl, var_decl->child, + state, current_offset); } break; default: assert(false); |