aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-02-01 12:56:38 +0900
committernsfisis <nsfisis@gmail.com>2026-02-01 12:56:38 +0900
commit0dcaa7de7208bbcd56624011a43bac66f5dee44b (patch)
treef93385ab8e7e7f562bada428543a5e8066563899
parent385d2e3722c22e788230c1cfba679356fbdd2d0a (diff)
downloadducc-0dcaa7de7208bbcd56624011a43bac66f5dee44b.tar.gz
ducc-0dcaa7de7208bbcd56624011a43bac66f5dee44b.tar.zst
ducc-0dcaa7de7208bbcd56624011a43bac66f5dee44b.zip
feat: implement array global variables
-rw-r--r--src/codegen.c47
-rw-r--r--tests/variables.c16
2 files changed, 48 insertions, 15 deletions
diff --git a/src/codegen.c b/src/codegen.c
index 6aac6c6..2247c6c 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -834,45 +834,62 @@ void codegen(Program* prog, FILE* out) {
fprintf(g->out, ".data\n\n");
for (int i = 0; i < prog->vars->as.list->len; ++i) {
AstNode* var = prog->vars->as.list->items + i;
+ fprintf(g->out, " %s:\n", var->as.gvar_decl->name);
if (var->as.gvar_decl->expr) {
if (type_sizeof(var->ty) == 1) {
if (var->as.gvar_decl->expr->kind != AstNodeKind_int_expr)
unimplemented();
- fprintf(g->out, " %s: .byte %d\n", var->as.gvar_decl->name,
- var->as.gvar_decl->expr->as.int_expr->value);
+ fprintf(g->out, " .byte %d\n", var->as.gvar_decl->expr->as.int_expr->value);
} else if (type_sizeof(var->ty) == 2) {
if (var->as.gvar_decl->expr->kind != AstNodeKind_int_expr)
unimplemented();
- fprintf(g->out, " %s: .word %d\n", var->as.gvar_decl->name,
- var->as.gvar_decl->expr->as.int_expr->value);
+ fprintf(g->out, " .word %d\n", var->as.gvar_decl->expr->as.int_expr->value);
} else if (type_sizeof(var->ty) == 4) {
if (var->as.gvar_decl->expr->kind != AstNodeKind_int_expr)
unimplemented();
- fprintf(g->out, " %s: .int %d\n", var->as.gvar_decl->name,
- var->as.gvar_decl->expr->as.int_expr->value);
+ fprintf(g->out, " .long %d\n", var->as.gvar_decl->expr->as.int_expr->value);
} else if (var->ty->kind == TypeKind_ptr) {
if (var->as.gvar_decl->expr->kind == AstNodeKind_ref_expr) {
if (var->as.gvar_decl->expr->as.ref_expr->operand->kind != AstNodeKind_gvar) {
unimplemented();
}
- fprintf(g->out, " %s: .quad %s\n", var->as.gvar_decl->name,
- var->as.gvar_decl->expr->as.ref_expr->operand->as.gvar->name);
+ fprintf(g->out, " .quad %s\n", var->as.gvar_decl->expr->as.ref_expr->operand->as.gvar->name);
} else if (var->as.gvar_decl->expr->kind == AstNodeKind_gvar) {
- fprintf(g->out, " %s: .quad %s\n", var->as.gvar_decl->name,
- var->as.gvar_decl->expr->as.gvar->name);
+ fprintf(g->out, " .quad %s\n", var->as.gvar_decl->expr->as.gvar->name);
} else {
unimplemented();
}
- } else if (var->ty->kind == TypeKind_array && var->ty->base->kind == TypeKind_char) {
- if (var->as.gvar_decl->expr->kind != AstNodeKind_str_expr)
+ } else if (var->ty->kind == TypeKind_array) {
+ if (var->as.gvar_decl->expr->kind == AstNodeKind_str_expr) {
+ const char* str = prog->str_literals[var->as.gvar_decl->expr->as.str_expr->idx - 1];
+ fprintf(g->out, " .string \"%s\"\n", str);
+ } else if (var->as.gvar_decl->expr->kind == AstNodeKind_array_initializer) {
+ AstNode* init = var->as.gvar_decl->expr->as.array_initializer->list;
+ int elem_size = type_sizeof(var->ty->base);
+ const char* directive;
+ if (elem_size == 1) {
+ directive = ".byte";
+ } else if (elem_size == 2) {
+ directive = ".word";
+ } else if (elem_size == 4) {
+ directive = ".long";
+ } else {
+ unimplemented();
+ }
+ for (int j = 0; j < init->as.list->len; ++j) {
+ AstNode* elem = &init->as.list->items[j];
+ if (elem->kind != AstNodeKind_int_expr)
+ unimplemented();
+ fprintf(g->out, " %s %d\n", directive, elem->as.int_expr->value);
+ }
+ } else {
unimplemented();
- const char* str = prog->str_literals[var->as.gvar_decl->expr->as.str_expr->idx - 1];
- fprintf(g->out, " %s: .string \"%s\"\n", var->as.gvar_decl->name, str);
+ }
} else {
unimplemented();
}
} else {
- fprintf(g->out, " %s: .zero %d\n", var->as.gvar_decl->name, type_sizeof(var->ty));
+ fprintf(g->out, " .zero %d\n", type_sizeof(var->ty));
}
}
diff --git a/tests/variables.c b/tests/variables.c
index 228a625..0be59a3 100644
--- a/tests/variables.c
+++ b/tests/variables.c
@@ -16,6 +16,10 @@ int g_k = 999;
char g_l[6] = "hello";
+char arr1[3] = {65, 66, 67};
+short arr2[3] = {10, 20, 30};
+int arr3[3] = {1, 2, 3};
+
int main() {
// global variables
*g_b = 123;
@@ -36,6 +40,18 @@ int main() {
ASSERT_EQ(0, strcmp("hello", g_l));
+ ASSERT_EQ(65, arr1[0]);
+ ASSERT_EQ(66, arr1[1]);
+ ASSERT_EQ(67, arr1[2]);
+
+ ASSERT_EQ(10, arr2[0]);
+ ASSERT_EQ(20, arr2[1]);
+ ASSERT_EQ(30, arr2[2]);
+
+ ASSERT_EQ(1, arr3[0]);
+ ASSERT_EQ(2, arr3[1]);
+ ASSERT_EQ(3, arr3[2]);
+
// local variables
int foo;
foo = 42;