summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTing-Wei Lan <lantw44@gmail.com>2016-01-02 18:16:20 +0800
committerTing-Wei Lan <lantw44@gmail.com>2016-01-02 18:16:20 +0800
commit069e14a6ada9a51d12bb0f3222ea83af65e5a289 (patch)
tree951e08a79a8592bb2ee221f4e5868396d0f40286
parent4c7f749733a5aba38dc61b73025f4f27fc7821fb (diff)
downloadcompiler2015-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.c79
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, &current_offset);
+ CcmmcTmp *tmp2 = ccmmc_register_alloc(state->reg_pool, &current_offset);
+ CcmmcTmp *tmp3 = ccmmc_register_alloc(state->reg_pool, &current_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, &current_offset);
+ ccmmc_register_free(state->reg_pool, tmp2, &current_offset);
+ ccmmc_register_free(state->reg_pool, tmp3, &current_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, &current_offset);
- CcmmcTmp *tmp2 = ccmmc_register_alloc(state->reg_pool, &current_offset);
- CcmmcTmp *tmp3 = ccmmc_register_alloc(state->reg_pool, &current_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, &current_offset);
- ccmmc_register_free(state->reg_pool, tmp2, &current_offset);
- ccmmc_register_free(state->reg_pool, tmp3, &current_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);