summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTing-Wei Lan <lantw44@gmail.com>2015-12-31 03:53:03 +0800
committerTing-Wei Lan <lantw44@gmail.com>2015-12-31 03:53:03 +0800
commit8e85068ff1b04a091d3c0d82d836e98bbe65fbd5 (patch)
treeb9e94375c3332345563dd7ca9fd50cde0524f1bd
parenta95fb07e9e74d8c8a4d1295211cb3d996c68a89c (diff)
downloadcompiler2015-8e85068ff1b04a091d3c0d82d836e98bbe65fbd5.tar
compiler2015-8e85068ff1b04a091d3c0d82d836e98bbe65fbd5.tar.gz
compiler2015-8e85068ff1b04a091d3c0d82d836e98bbe65fbd5.tar.bz2
compiler2015-8e85068ff1b04a091d3c0d82d836e98bbe65fbd5.tar.lz
compiler2015-8e85068ff1b04a091d3c0d82d836e98bbe65fbd5.tar.xz
compiler2015-8e85068ff1b04a091d3c0d82d836e98bbe65fbd5.tar.zst
compiler2015-8e85068ff1b04a091d3c0d82d836e98bbe65fbd5.zip
Generate code for global variable declarations
-rw-r--r--src/code-generation.c51
1 files changed, 45 insertions, 6 deletions
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);
}