summaryrefslogtreecommitdiffstats
path: root/src/code-generation.c
diff options
context:
space:
mode:
authorTing-Wei Lan <lantw44@gmail.com>2015-12-31 14:14:31 +0800
committerTing-Wei Lan <lantw44@gmail.com>2015-12-31 14:14:31 +0800
commit5b68086fd32ceb374e5b0efbaaa802ec512c3e1b (patch)
tree5e6c06255109d769ea10ca7a95946cdc7f645140 /src/code-generation.c
parent8e85068ff1b04a091d3c0d82d836e98bbe65fbd5 (diff)
downloadcompiler2015-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.c100
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)