summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkugwa <kugwa2000@gmail.com>2016-01-19 11:14:46 +0800
committerkugwa <kugwa2000@gmail.com>2016-01-19 11:14:46 +0800
commitb0af78b88c674cbc552e348bc3703e792650d1d7 (patch)
tree5b7c1152565dd7454acaa446c7280ef120ba5b18
parente9435761fc4aafe290fe128ac8198afcce796b7e (diff)
downloadcompiler2015-b0af78b88c674cbc552e348bc3703e792650d1d7.tar
compiler2015-b0af78b88c674cbc552e348bc3703e792650d1d7.tar.gz
compiler2015-b0af78b88c674cbc552e348bc3703e792650d1d7.tar.bz2
compiler2015-b0af78b88c674cbc552e348bc3703e792650d1d7.tar.lz
compiler2015-b0af78b88c674cbc552e348bc3703e792650d1d7.tar.xz
compiler2015-b0af78b88c674cbc552e348bc3703e792650d1d7.tar.zst
compiler2015-b0af78b88c674cbc552e348bc3703e792650d1d7.zip
Fix the problem of initializing local variables
-rw-r--r--src/code-generation.c27
1 files changed, 16 insertions, 11 deletions
diff --git a/src/code-generation.c b/src/code-generation.c
index 7bc3416..a2d93da 100644
--- a/src/code-generation.c
+++ b/src/code-generation.c
@@ -991,10 +991,6 @@ static uint64_t generate_local_variable(
CcmmcSymbol *var_sym = ccmmc_symbol_table_retrieve(state->table,
var_decl->value_id.name);
switch (var_decl->value_id.kind) {
- case CCMMC_KIND_ID_NORMAL:
- current_offset += 4;
- var_sym->attr.addr = current_offset;
- break;
case CCMMC_KIND_ID_ARRAY: {
size_t total_elements = 1;
assert(var_sym->type.array_dimension > 0);
@@ -1003,15 +999,11 @@ static uint64_t generate_local_variable(
current_offset += total_elements * 4;
var_sym->attr.addr = current_offset;
} break;
- case CCMMC_KIND_ID_WITH_INIT: {
+ case CCMMC_KIND_ID_NORMAL:
+ case CCMMC_KIND_ID_WITH_INIT:
current_offset += 4;
var_sym->attr.addr = current_offset;
- // 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;
+ break;
default:
assert(false);
}
@@ -1019,6 +1011,17 @@ static uint64_t generate_local_variable(
return current_offset;
}
+static void init_local_variable(
+ CcmmcAst *local_decl, CcmmcState *state, uint64_t current_offset)
+{
+ for (CcmmcAst *var_decl = local_decl->child->right_sibling;
+ var_decl != NULL; var_decl = var_decl->right_sibling) {
+ if (var_decl->value_id.kind == CCMMC_KIND_ID_WITH_INIT)
+ calc_and_save_expression_result(var_decl, var_decl->child,
+ state, &current_offset);
+ }
+}
+
static void generate_block(
CcmmcAst *block, CcmmcState *state, uint64_t current_offset)
{
@@ -1043,6 +1046,8 @@ static void generate_block(
#undef REG_TMP
}
}
+ for (CcmmcAst *local = child->child; local != NULL; local = local->right_sibling)
+ init_local_variable(local, state, current_offset);
child = child->right_sibling;
}
if (child != NULL && child->type_node == CCMMC_AST_NODE_STMT_LIST) {