aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-01-10 11:03:51 +0900
committernsfisis <nsfisis@gmail.com>2026-01-10 11:32:14 +0900
commit175b00181b627bec69f645d6d8fc880a2bdd3f81 (patch)
treee6a3d6505c02c6137ddffb4899b41b6dc9cd6867 /src
parent8f0fa8d70ce08ee0347a5880d44faab8307b72f6 (diff)
downloadducc-175b00181b627bec69f645d6d8fc880a2bdd3f81.tar.gz
ducc-175b00181b627bec69f645d6d8fc880a2bdd3f81.tar.zst
ducc-175b00181b627bec69f645d6d8fc880a2bdd3f81.zip
feat: support global variables of char[]
Diffstat (limited to 'src')
-rw-r--r--src/ast.c95
-rw-r--r--src/ast.h2
-rw-r--r--src/codegen.c21
3 files changed, 110 insertions, 8 deletions
diff --git a/src/ast.c b/src/ast.c
index 59a2087..75aa7ee 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -182,6 +182,101 @@ int to_aligned(int n, int a) {
return (n + a - 1) / a * a;
}
+const char* astnode_kind_stringify(AstNodeKind k) {
+ switch (k) {
+ case AstNodeKind_unknown:
+ return "unknown";
+ case AstNodeKind_nop:
+ return "nop";
+ case AstNodeKind_assign_expr:
+ return "assign_expr";
+ case AstNodeKind_binary_expr:
+ return "binary_expr";
+ case AstNodeKind_break_stmt:
+ return "break_stmt";
+ case AstNodeKind_case_label:
+ return "case_label";
+ case AstNodeKind_cast_expr:
+ return "cast_expr";
+ case AstNodeKind_cond_expr:
+ return "cond_expr";
+ case AstNodeKind_continue_stmt:
+ return "continue_stmt";
+ case AstNodeKind_default_label:
+ return "default_label";
+ case AstNodeKind_deref_expr:
+ return "deref_expr";
+ case AstNodeKind_do_while_stmt:
+ return "do_while_stmt";
+ case AstNodeKind_enum_def:
+ return "enum_def";
+ case AstNodeKind_enum_member:
+ return "enum_member";
+ case AstNodeKind_expr_stmt:
+ return "expr_stmt";
+ case AstNodeKind_for_stmt:
+ return "for_stmt";
+ case AstNodeKind_func:
+ return "func";
+ case AstNodeKind_func_call:
+ return "func_call";
+ case AstNodeKind_func_decl:
+ return "func_decl";
+ case AstNodeKind_func_def:
+ return "func_def";
+ case AstNodeKind_goto_stmt:
+ return "goto_stmt";
+ case AstNodeKind_gvar:
+ return "gvar";
+ case AstNodeKind_gvar_decl:
+ return "gvar_decl";
+ case AstNodeKind_if_stmt:
+ return "if_stmt";
+ case AstNodeKind_int_expr:
+ return "int_expr";
+ case AstNodeKind_label_stmt:
+ return "label_stmt";
+ case AstNodeKind_list:
+ return "list";
+ case AstNodeKind_logical_expr:
+ return "logical_expr";
+ case AstNodeKind_lvar:
+ return "lvar";
+ case AstNodeKind_lvar_decl:
+ return "lvar_decl";
+ case AstNodeKind_param:
+ return "param";
+ case AstNodeKind_ref_expr:
+ return "ref_expr";
+ case AstNodeKind_return_stmt:
+ return "return_stmt";
+ case AstNodeKind_str_expr:
+ return "str_expr";
+ case AstNodeKind_struct_decl:
+ return "struct_decl";
+ case AstNodeKind_struct_def:
+ return "struct_def";
+ case AstNodeKind_struct_member:
+ return "struct_member";
+ case AstNodeKind_switch_stmt:
+ return "switch_stmt";
+ case AstNodeKind_type:
+ return "type";
+ case AstNodeKind_typedef_decl:
+ return "typedef_decl";
+ case AstNodeKind_unary_expr:
+ return "unary_expr";
+ case AstNodeKind_union_decl:
+ return "union_decl";
+ case AstNodeKind_union_def:
+ return "union_def";
+ case AstNodeKind_declarator:
+ return "declarator";
+ default:
+ unreachable();
+ }
+}
+
AstNode* ast_new(AstNodeKind kind) {
AstNode* ast = calloc(1, sizeof(AstNode));
ast->kind = kind;
diff --git a/src/ast.h b/src/ast.h
index 4ca2e1b..0339457 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -134,6 +134,8 @@ typedef enum {
AstNodeKind_declarator,
} AstNodeKind;
+const char* astnode_kind_stringify(AstNodeKind k);
+
#define node_items __n1
#define node_len __i1
#define node_cap __i2
diff --git a/src/codegen.c b/src/codegen.c
index 1c7abf7..be8acd7 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -469,18 +469,18 @@ static void codegen_func_call(CodeGen* g, AstNode* ast) {
// Fetch from register save area
fprintf(g->out, " mov rcx, QWORD PTR [rdi+16]\n"); // rcx = reg_save_area
- fprintf(g->out, " movsx rdx, eax\n"); // rdx = gp_offset (sign-extended)
- fprintf(g->out, " add rcx, rdx\n"); // rcx = reg_save_area + gp_offset
- fprintf(g->out, " add eax, 8\n"); // gp_offset += 8
- fprintf(g->out, " mov DWORD PTR [rdi], eax\n"); // store updated gp_offset
- fprintf(g->out, " mov rax, rcx\n"); // return pointer to argument
+ fprintf(g->out, " movsx rdx, eax\n"); // rdx = gp_offset (sign-extended)
+ fprintf(g->out, " add rcx, rdx\n"); // rcx = reg_save_area + gp_offset
+ fprintf(g->out, " add eax, 8\n"); // gp_offset += 8
+ fprintf(g->out, " mov DWORD PTR [rdi], eax\n"); // store updated gp_offset
+ fprintf(g->out, " mov rax, rcx\n"); // return pointer to argument
fprintf(g->out, " jmp .Lva_arg_end%d\n", label);
// Fetch from overflow area (stack)
fprintf(g->out, ".Lva_arg_overflow%d:\n", label);
fprintf(g->out, " mov rcx, QWORD PTR [rdi+8]\n"); // rcx = overflow_arg_area
- fprintf(g->out, " mov rax, rcx\n"); // return pointer to argument
- fprintf(g->out, " add rcx, 8\n"); // overflow_arg_area += 8
+ fprintf(g->out, " mov rax, rcx\n"); // return pointer to argument
+ fprintf(g->out, " add rcx, 8\n"); // overflow_arg_area += 8
fprintf(g->out, " mov QWORD PTR [rdi+8], rcx\n"); // store updated overflow_arg_area
fprintf(g->out, ".Lva_arg_end%d:\n", label);
@@ -903,6 +903,11 @@ void codegen(Program* prog, FILE* out) {
} else {
unimplemented();
}
+ } else if (var->ty->kind == TypeKind_array && var->ty->base->kind == TypeKind_char) {
+ if (var->node_expr->kind != AstNodeKind_str_expr)
+ unimplemented();
+ const char* str = prog->str_literals[var->node_expr->node_idx - 1];
+ fprintf(g->out, " %s: .string \"%s\"\n", var->name, str);
} else {
unimplemented();
}
@@ -913,7 +918,7 @@ void codegen(Program* prog, FILE* out) {
fprintf(g->out, ".text\n\n");
for (int i = 0; i < prog->funcs->node_len; ++i) {
- AstNode* func = prog->funcs->node_items + i;
+ AstNode* func = &prog->funcs->node_items[i];
codegen_func(g, func);
}
}