aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/ast.c95
-rw-r--r--src/ast.h2
-rw-r--r--src/codegen.c21
-rw-r--r--tests/global_variables.c (renamed from tests/global_variables.sh)33
4 files changed, 125 insertions, 26 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);
}
}
diff --git a/tests/global_variables.sh b/tests/global_variables.c
index fac386d..20e0a64 100644
--- a/tests/global_variables.sh
+++ b/tests/global_variables.c
@@ -1,28 +1,20 @@
-cat <<'EOF' > expected
-42 123 999
-EOF
-
-test_diff <<'EOF'
-int printf();
-
-char a = 42;
-short b = 123;
-int c = 999;
-
-int main() {
- printf("%d %d %d\n", a, b, c);
-}
-EOF
-
-test_exit_code 0 <<'EOF'
#include <helpers.h>
+int printf(const char*, ...);
+int strcmp(const char*, const char*);
+
int a;
int* b = &a;
int c[10];
int* d = c;
int e, *f = e, g[10], *h = g;
+char i = 42;
+short j = 123;
+int k = 999;
+
+char l[6] = "hello";
+
int main() {
*b = 123;
ASSERT_EQ(123, a);
@@ -35,5 +27,10 @@ int main() {
h[5] = 789;
ASSERT_EQ(789, g[5]);
+
+ ASSERT_EQ(42, i);
+ ASSERT_EQ(123, j);
+ ASSERT_EQ(999, k);
+
+ ASSERT_EQ(0, strcmp("hello", l));
}
-EOF