diff options
author | kugwa <kugwa2000@gmail.com> | 2016-01-03 03:37:12 +0800 |
---|---|---|
committer | kugwa <kugwa2000@gmail.com> | 2016-01-03 03:37:12 +0800 |
commit | ad147f510185dc8d8a1af52ac5b983a9536b0287 (patch) | |
tree | 46c7ec559126ff8dd8ee1e619600ea8c8c85af7d | |
parent | 5ae27f1f64d92bde51ca6e084093c2eda222d0eb (diff) | |
download | compiler2015-ad147f510185dc8d8a1af52ac5b983a9536b0287.tar.gz compiler2015-ad147f510185dc8d8a1af52ac5b983a9536b0287.tar.zst compiler2015-ad147f510185dc8d8a1af52ac5b983a9536b0287.zip |
Complete code-gen of if-else statement
-rw-r--r-- | src/code-generation.c | 59 |
1 files changed, 56 insertions, 3 deletions
diff --git a/src/code-generation.c b/src/code-generation.c index e735e57..7a2b6da 100644 --- a/src/code-generation.c +++ b/src/code-generation.c @@ -515,6 +515,7 @@ static void generate_statement( const char *op1 = ccmmc_register_lock(state->reg_pool, tmp2); const char *op2 = ccmmc_register_lock(state->reg_pool, tmp3); + // while condition fprintf(state->asm_output, ".LC%zu\n", label_cmp); generate_expression(stmt->child, state, result, op1, op2); if (stmt->child->type_value == CCMMC_AST_VALUE_FLOAT) @@ -537,6 +538,8 @@ static void generate_statement( 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); + + // while body generate_statement(stmt->child->right_sibling, state, current_offset); fprintf(state->asm_output, @@ -552,14 +555,64 @@ static void generate_statement( calc_and_save_expression_result(stmt->child, stmt->child->right_sibling, state, current_offset); break; - case CCMMC_KIND_STMT_IF: + case CCMMC_KIND_STMT_IF: { +#define FPREG_TMP "s16" + size_t label_cross_if = state->label_number++; + 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); + + // if condition + generate_expression(stmt->child, state, result, op1, op2); + if (stmt->child->type_value == CCMMC_AST_VALUE_FLOAT) + fprintf(state->asm_output, + "\tfmov\t%s, %s\n" + "\tfcmp\t%s, #0.0\n" + "\tb.e\t.LC%zu\n", + FPREG_TMP, + result, + FPREG_TMP, + label_cross_if); + else + fprintf(state->asm_output, + "\tcbz\t%s, .LC%zu\n", + result, + label_cross_if); + 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); + + // if body generate_statement(stmt->child->right_sibling, state, current_offset); + if (stmt->child->right_sibling->right_sibling->type_node - != CCMMC_AST_NODE_NUL) + == CCMMC_AST_NODE_NUL) { + // no else + fprintf(state->asm_output, ".LC%zu\n", label_cross_if); + } + else { + // jump across else + size_t label_exit = state->label_number++; + fprintf(state->asm_output, + "\tb\t.LC%zu\n" + ".LC%zu\n", + label_exit, + label_cross_if); + + // else body generate_statement(stmt->child->right_sibling->right_sibling, state, current_offset); - break; + fprintf(state->asm_output, ".LC%zu\n", label_exit); +#undef FPREG_TMP + } + } break; case CCMMC_KIND_STMT_FUNCTION_CALL: ccmmc_register_caller_save(state->reg_pool); fprintf(state->asm_output, "\tbl\t%s\n", stmt->child->value_id.name); |