diff options
author | Ting-Wei Lan <lantw44@gmail.com> | 2015-12-31 14:14:31 +0800 |
---|---|---|
committer | Ting-Wei Lan <lantw44@gmail.com> | 2015-12-31 14:14:31 +0800 |
commit | 5b68086fd32ceb374e5b0efbaaa802ec512c3e1b (patch) | |
tree | 5e6c06255109d769ea10ca7a95946cdc7f645140 /src/code-generation.c | |
parent | 8e85068ff1b04a091d3c0d82d836e98bbe65fbd5 (diff) | |
download | compiler2015-5b68086fd32ceb374e5b0efbaaa802ec512c3e1b.tar.gz compiler2015-5b68086fd32ceb374e5b0efbaaa802ec512c3e1b.tar.zst compiler2015-5b68086fd32ceb374e5b0efbaaa802ec512c3e1b.zip |
Generate fp offsets for local variables
Diffstat (limited to 'src/code-generation.c')
-rw-r--r-- | src/code-generation.c | 100 |
1 files changed, 99 insertions, 1 deletions
diff --git a/src/code-generation.c b/src/code-generation.c index bba70c9..8d3a44d 100644 --- a/src/code-generation.c +++ b/src/code-generation.c @@ -5,6 +5,7 @@ #include "code-generation.h" #include <assert.h> +#include <inttypes.h> #include <stdio.h> #include <stdlib.h> @@ -68,8 +69,105 @@ static void generate_global_variable(CcmmcAst *global_decl, CcmmcState *state) } } -static void generate_function(CcmmcAst *funcion, CcmmcState *state) +static void generate_block( + CcmmcAst *block, CcmmcState *state, uint64_t current_offset); +static uint64_t generate_statement( + CcmmcAst *stmt, CcmmcState *state, uint64_t current_offset) { + if (stmt->type_node == CCMMC_AST_NODE_NUL) + return current_offset; + if (stmt->type_node == CCMMC_AST_NODE_BLOCK) { + generate_block(stmt, state, current_offset); + return current_offset; + } + + assert(stmt->type_node == CCMMC_AST_NODE_STMT); + switch(stmt->value_stmt.kind) { + case CCMMC_KIND_STMT_WHILE: + current_offset = generate_statement(stmt->child->right_sibling, + state, current_offset); + break; + case CCMMC_KIND_STMT_FOR: + break; + case CCMMC_KIND_STMT_ASSIGN: + break; + case CCMMC_KIND_STMT_IF: + current_offset = generate_statement(stmt->child->right_sibling, + state, current_offset); + break; + case CCMMC_KIND_STMT_FUNCTION_CALL: + break; + case CCMMC_KIND_STMT_RETURN: + break; + default: + assert(false); + } + + return current_offset; +} + +static uint64_t generate_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) { + 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); + for (size_t i = 0; i < var_sym->type.array_dimension; i++) + total_elements *= var_sym->type.array_size[i]; + current_offset += total_elements * 4; + var_sym->attr.addr = current_offset; + } break; + case CCMMC_KIND_ID_WITH_INIT: { + current_offset += 4; + var_sym->attr.addr = current_offset; + } break; + default: + assert(false); + } + } + return current_offset; +} + +static void generate_block( + CcmmcAst *block, CcmmcState *state, uint64_t current_offset) +{ + ccmmc_symbol_table_reopen_scope(state->table); + + CcmmcAst *child = block->child; + uint64_t orig_offset = current_offset; + if (child != NULL && child->type_node == CCMMC_AST_NODE_VARIABLE_DECL_LIST) { + for (CcmmcAst *local = child->child; local != NULL; local = local->right_sibling) + current_offset = generate_local_variable(local, state, current_offset); + fprintf(state->asm_output, + "\tsub\tsp, sp, #%" PRIu64 "\n", current_offset - orig_offset); + child = child->right_sibling; + } + if (child != NULL && child->type_node == CCMMC_AST_NODE_STMT_LIST) { + for (CcmmcAst *stmt = child->child; stmt != NULL; stmt = stmt->right_sibling) + current_offset = generate_statement(stmt, state, current_offset); + } + if (current_offset != orig_offset) + fprintf(state->asm_output, + "\tadd\tsp, sp, #%" PRIu64 "\n", current_offset - orig_offset); + + ccmmc_symbol_table_close_scope(state->table); +} + +static void generate_function(CcmmcAst *function, CcmmcState *state) +{ + fputs("\t.text\n\t.align\t2\n", state->asm_output); + CcmmcAst *param_node = function->child->right_sibling->right_sibling; + CcmmcAst *block_node = param_node->right_sibling; + generate_block(block_node, state, 0); } static void generate_program(CcmmcState *state) |