diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-09-05 01:47:01 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-09-05 01:47:05 +0900 |
| commit | 68251039083d21af43da11d76980e1ea426a3a4a (patch) | |
| tree | 31183efbcb3a914d2fcacf1d3fbf28a2d071cecd | |
| parent | 6e4010b7c14af83b15d28bc020fe601991d209d3 (diff) | |
| download | ducc-68251039083d21af43da11d76980e1ea426a3a4a.tar.gz ducc-68251039083d21af43da11d76980e1ea426a3a4a.tar.zst ducc-68251039083d21af43da11d76980e1ea426a3a4a.zip | |
feat: make va_list definition compatible with GCC's
| -rw-r--r-- | include/stdarg.h | 4 | ||||
| -rw-r--r-- | src/codegen.c | 37 | ||||
| -rw-r--r-- | tests/066.sh | 2 |
3 files changed, 23 insertions, 20 deletions
diff --git a/include/stdarg.h b/include/stdarg.h index 95c068c..609e6af 100644 --- a/include/stdarg.h +++ b/include/stdarg.h @@ -12,9 +12,7 @@ struct __ducc_va_list { void* overflow_arg_area; void* reg_save_area; }; -// ducc currently does not support array type. -// typedef struct __ducc_va_list va_list[1]; -typedef struct __ducc_va_list* va_list; +typedef struct __ducc_va_list va_list[1]; #define va_start(args, start) __ducc_va_start(args, start) #define va_end(args) diff --git a/src/codegen.c b/src/codegen.c index a16ae73..000126b 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -307,24 +307,29 @@ static void codegen_func_call(CodeGen* g, AstNode* ast) { const char* func_name = ast->name; if (strcmp(func_name, "__ducc_va_start") == 0) { - int stack_size = g->current_func->node_stack_size; fprintf(g->out, " # __ducc_va_start BEGIN\n"); - for (int i = 0; i < 6; ++i) { - fprintf(g->out, " mov rax, %s\n", param_reg(i)); - fprintf(g->out, " mov [rbp-%d], rax\n", 8 + (stack_size - 4 - i) * 8); - } - AstNode* va_list_args = ast->node_args->node_items; - codegen_expr(g, va_list_args, GenMode_lval); + AstNode* va_list_args = &ast->node_args->node_items[0]; + codegen_expr(g, va_list_args, GenMode_rval); fprintf(g->out, " pop rdi\n"); - fprintf(g->out, " mov rax, rbp\n"); - fprintf(g->out, " sub rax, %d\n", 8 + (stack_size - 1) * 8); - fprintf(g->out, " mov [rdi], rax\n"); - fprintf(g->out, " mov DWORD PTR [rax], 8\n"); - fprintf(g->out, " mov DWORD PTR [rax+4], 0\n"); - fprintf(g->out, " mov QWORD PTR [rax+8], 0\n"); - fprintf(g->out, " mov rdi, rbp\n"); - fprintf(g->out, " sub rdi, %d\n", 8 + (stack_size - 4) * 8); - fprintf(g->out, " mov QWORD PTR [rax+16], rdi\n"); + + // Allocate save area. + fprintf(g->out, " sub rsp, 48\n"); + + fprintf(g->out, " mov [rsp+ 0], rdi\n"); + fprintf(g->out, " mov [rsp+ 8], rsi\n"); + fprintf(g->out, " mov [rsp+16], rdx\n"); + fprintf(g->out, " mov [rsp+24], rcx\n"); + fprintf(g->out, " mov [rsp+32], r8\n"); + fprintf(g->out, " mov [rsp+40], r9\n"); + + // Initialize va_list. + fprintf(g->out, " mov DWORD PTR [rdi], 8\n"); // gp_offset + fprintf(g->out, " mov DWORD PTR [rdi+4], 0\n"); // fp_offset + fprintf(g->out, " lea rax, [rbp+16]\n"); // overflow_arg_area + fprintf(g->out, " mov QWORD PTR [rdi+8], rax\n"); + fprintf(g->out, " mov QWORD PTR [rdi+16], rsp\n"); // reg_save_area + + fprintf(g->out, " push 0\n"); // dummy return value fprintf(g->out, " # __ducc_va_start END\n"); return; } diff --git a/tests/066.sh b/tests/066.sh index 21ef9c6..0a5e570 100644 --- a/tests/066.sh +++ b/tests/066.sh @@ -1,5 +1,5 @@ cat <<'EOF' > expected -8 +24 EOF test_diff <<'EOF' |
