From 8e85068ff1b04a091d3c0d82d836e98bbe65fbd5 Mon Sep 17 00:00:00 2001
From: Ting-Wei Lan <lantw44@gmail.com>
Date: Thu, 31 Dec 2015 03:53:03 +0800
Subject: Generate code for global variable declarations

---
 src/code-generation.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 45 insertions(+), 6 deletions(-)

(limited to 'src/code-generation.c')

diff --git a/src/code-generation.c b/src/code-generation.c
index aa75f79..bba70c9 100644
--- a/src/code-generation.c
+++ b/src/code-generation.c
@@ -10,19 +10,58 @@
 
 static void generate_global_variable(CcmmcAst *global_decl, CcmmcState *state)
 {
-    fputs("\t.data\n", state->asm_output);
+    fputs("\t.data\n\t.align\t2\n", state->asm_output);
     for (CcmmcAst *var_decl = global_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:
-                fprintf(state->asm_output, "\t.comm %s, 4\n", var_sym->name);
-                break;
-            case CCMMC_KIND_ID_ARRAY:
-                break;
-            case CCMMC_KIND_ID_WITH_INIT:
+                fprintf(state->asm_output, "\t.comm\t%s, 4\n", var_sym->name);
                 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];
+                fprintf(state->asm_output, "\t.comm\t%s, %zu\n",
+                    var_sym->name, total_elements * 4);
+                } break;
+            case CCMMC_KIND_ID_WITH_INIT: {
+                CcmmcAst *init_value = var_decl->child;
+                fprintf(state->asm_output, "\t.size\t%s, 4\n", var_sym->name);
+                if (var_sym->type.type_base == CCMMC_AST_VALUE_INT) {
+                    int int_value;
+                    if (init_value->type_node == CCMMC_AST_NODE_CONST_VALUE) {
+                        assert(init_value->value_const.kind == CCMMC_KIND_CONST_INT);
+                        int_value = init_value->value_const.const_int;
+                    } else if (init_value->type_node == CCMMC_AST_NODE_EXPR) {
+                        assert(ccmmc_ast_expr_get_is_constant(init_value));
+                        assert(ccmmc_ast_expr_get_is_int(init_value));
+                        int_value = ccmmc_ast_expr_get_int(init_value);
+                    } else {
+                        assert(false);
+                    }
+                    fprintf(state->asm_output, "%s:\n\t.word\t%d\n",
+                        var_sym->name, int_value);
+                } else if (var_sym->type.type_base == CCMMC_AST_VALUE_FLOAT) {
+                    float float_value;
+                    if (init_value->type_node == CCMMC_AST_NODE_CONST_VALUE) {
+                        assert(init_value->value_const.kind == CCMMC_KIND_CONST_FLOAT);
+                        float_value = init_value->value_const.const_float;
+                    } else if (init_value->type_node == CCMMC_AST_NODE_EXPR) {
+                        assert(ccmmc_ast_expr_get_is_constant(init_value));
+                        assert(ccmmc_ast_expr_get_is_float(init_value));
+                        float_value = ccmmc_ast_expr_get_float(init_value);
+                    } else {
+                        assert(false);
+                    }
+                    fprintf(state->asm_output, "%s:\n\t.float\t%.9g\n",
+                        var_sym->name, float_value);
+                } else {
+                    assert(false);
+                }
+                } break;
             default:
                 assert(false);
         }
-- 
cgit