From 52df9f8ce8abf17bf6ca70c174a48f41e5ad31d5 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Fri, 23 Jan 2026 22:00:27 +0900 Subject: refactor: AST overhaul --- src/codegen.c | 386 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 196 insertions(+), 190 deletions(-) (limited to 'src/codegen.c') diff --git a/src/codegen.c b/src/codegen.c index d35772f..6aac6c6 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -53,49 +53,49 @@ static const char* param_reg(int n) { } } -static void codegen_func_prologue(CodeGen* g, AstNode* ast) { +static void codegen_func_prologue(CodeGen* g, FuncDefNode* func_def) { fprintf(g->out, " push rbp\n"); fprintf(g->out, " mov rbp, rsp\n"); - for (int i = 0, j = 0; i < ast->node_params->node_len; ++i) { - AstNode* param = &ast->node_params->node_items[i]; - if (param->node_stack_offset >= 0) { + for (int i = 0, j = 0; i < func_def->params->as.list->len; ++i) { + AstNode* param = &func_def->params->as.list->items[i]; + if (param->as.param->stack_offset >= 0) { fprintf(g->out, " push %s\n", param_reg(j++)); } } // Note: rsp must be aligned to 8. - fprintf(g->out, " sub rsp, %d\n", to_aligned(ast->node_stack_size, 8)); + fprintf(g->out, " sub rsp, %d\n", to_aligned(func_def->stack_size, 8)); } -static void codegen_func_epilogue(CodeGen* g, AstNode*) { +static void codegen_func_epilogue(CodeGen* g) { fprintf(g->out, " mov rsp, rbp\n"); fprintf(g->out, " pop rbp\n"); fprintf(g->out, " ret\n"); } -static void codegen_int_expr(CodeGen* g, AstNode* ast) { - fprintf(g->out, " mov rax, %d\n", ast->node_int_value); +static void codegen_int_expr(CodeGen* g, IntExprNode* expr) { + fprintf(g->out, " mov rax, %d\n", expr->value); } -static void codegen_str_expr(CodeGen* g, AstNode* ast) { - fprintf(g->out, " lea rax, .Lstr__%d[rip]\n", ast->node_idx); +static void codegen_str_expr(CodeGen* g, StrExprNode* expr) { + fprintf(g->out, " lea rax, .Lstr__%d[rip]\n", expr->idx); } -static void codegen_unary_expr(CodeGen* g, AstNode* ast) { - codegen_expr(g, ast->node_operand, GenMode_rval); - if (ast->node_op == TokenKind_not) { +static void codegen_unary_expr(CodeGen* g, UnaryExprNode* expr) { + codegen_expr(g, expr->operand, GenMode_rval); + if (expr->op == TokenKind_not) { fprintf(g->out, " mov rdi, 0\n"); fprintf(g->out, " cmp rax, rdi\n"); fprintf(g->out, " sete al\n"); fprintf(g->out, " movzb rax, al\n"); - } else if (ast->node_op == TokenKind_tilde) { + } else if (expr->op == TokenKind_tilde) { fprintf(g->out, " not rax\n"); } else { unreachable(); } } -static void codegen_ref_expr(CodeGen* g, AstNode* ast) { - codegen_expr(g, ast->node_operand, GenMode_lval); +static void codegen_ref_expr(CodeGen* g, RefExprNode* expr) { + codegen_expr(g, expr->operand, GenMode_lval); } static void codegen_lval2rval(CodeGen* g, Type* ty) { @@ -117,22 +117,22 @@ static void codegen_lval2rval(CodeGen* g, Type* ty) { } } -static void codegen_deref_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { - codegen_expr(g, ast->node_operand, GenMode_rval); +static void codegen_deref_expr(CodeGen* g, DerefExprNode* expr, GenMode gen_mode) { + codegen_expr(g, expr->operand, GenMode_rval); if (gen_mode == GenMode_rval) { - codegen_lval2rval(g, ast->node_operand->ty->base); + codegen_lval2rval(g, expr->operand->ty->base); } } -static void codegen_cast_expr(CodeGen* g, AstNode* ast) { - codegen_expr(g, ast->node_operand, GenMode_rval); +static void codegen_cast_expr(CodeGen* g, CastExprNode* expr, Type* ty) { + codegen_expr(g, expr->operand, GenMode_rval); // (void) cast does nothing. - if (ast->ty->kind == TypeKind_void) + if (ty->kind == TypeKind_void) return; - int src_size = type_sizeof(ast->node_operand->ty); - int dst_size = type_sizeof(ast->ty); + int src_size = type_sizeof(expr->operand->ty); + int dst_size = type_sizeof(ty); if (src_size == dst_size) return; @@ -164,76 +164,76 @@ static void codegen_cast_expr(CodeGen* g, AstNode* ast) { } } -static void codegen_logical_expr(CodeGen* g, AstNode* ast) { +static void codegen_logical_expr(CodeGen* g, LogicalExprNode* expr) { int label = codegen_new_label(g); - if (ast->node_op == TokenKind_andand) { - codegen_expr(g, ast->node_lhs, GenMode_rval); + if (expr->op == TokenKind_andand) { + codegen_expr(g, expr->lhs, GenMode_rval); fprintf(g->out, " cmp rax, 0\n"); fprintf(g->out, " je .Lelse%d\n", label); - codegen_expr(g, ast->node_rhs, GenMode_rval); + codegen_expr(g, expr->rhs, GenMode_rval); fprintf(g->out, " jmp .Lend%d\n", label); fprintf(g->out, ".Lelse%d:\n", label); fprintf(g->out, " mov rax, 0\n"); fprintf(g->out, ".Lend%d:\n", label); } else { - codegen_expr(g, ast->node_lhs, GenMode_rval); + codegen_expr(g, expr->lhs, GenMode_rval); fprintf(g->out, " cmp rax, 0\n"); fprintf(g->out, " je .Lelse%d\n", label); fprintf(g->out, " mov rax, 1\n"); fprintf(g->out, " jmp .Lend%d\n", label); fprintf(g->out, ".Lelse%d:\n", label); - codegen_expr(g, ast->node_rhs, GenMode_rval); + codegen_expr(g, expr->rhs, GenMode_rval); fprintf(g->out, ".Lend%d:\n", label); } } -static void codegen_binary_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { - codegen_expr(g, ast->node_lhs, gen_mode); +static void codegen_binary_expr(CodeGen* g, BinaryExprNode* expr, GenMode gen_mode) { + codegen_expr(g, expr->lhs, gen_mode); fprintf(g->out, " push rax\n"); - codegen_expr(g, ast->node_rhs, gen_mode); + codegen_expr(g, expr->rhs, gen_mode); fprintf(g->out, " mov rdi, rax\n"); fprintf(g->out, " pop rax\n"); // rax=lhs, rdi=rhs - if (ast->node_op == TokenKind_plus) { + if (expr->op == TokenKind_plus) { fprintf(g->out, " add rax, rdi\n"); - } else if (ast->node_op == TokenKind_minus) { + } else if (expr->op == TokenKind_minus) { fprintf(g->out, " sub rax, rdi\n"); - } else if (ast->node_op == TokenKind_star) { + } else if (expr->op == TokenKind_star) { fprintf(g->out, " imul rax, rdi\n"); - } else if (ast->node_op == TokenKind_slash) { + } else if (expr->op == TokenKind_slash) { fprintf(g->out, " cqo\n"); fprintf(g->out, " idiv rdi\n"); - } else if (ast->node_op == TokenKind_percent) { + } else if (expr->op == TokenKind_percent) { fprintf(g->out, " cqo\n"); fprintf(g->out, " idiv rdi\n"); fprintf(g->out, " mov rax, rdx\n"); - } else if (ast->node_op == TokenKind_and) { + } else if (expr->op == TokenKind_and) { fprintf(g->out, " and rax, rdi\n"); - } else if (ast->node_op == TokenKind_or) { + } else if (expr->op == TokenKind_or) { fprintf(g->out, " or rax, rdi\n"); - } else if (ast->node_op == TokenKind_xor) { + } else if (expr->op == TokenKind_xor) { fprintf(g->out, " xor rax, rdi\n"); - } else if (ast->node_op == TokenKind_lshift) { + } else if (expr->op == TokenKind_lshift) { fprintf(g->out, " mov rcx, rdi\n"); fprintf(g->out, " shl rax, cl\n"); - } else if (ast->node_op == TokenKind_rshift) { + } else if (expr->op == TokenKind_rshift) { // TODO: check if the operand is signed or unsigned fprintf(g->out, " mov rcx, rdi\n"); fprintf(g->out, " sar rax, cl\n"); - } else if (ast->node_op == TokenKind_eq) { + } else if (expr->op == TokenKind_eq) { fprintf(g->out, " cmp rax, rdi\n"); fprintf(g->out, " sete al\n"); fprintf(g->out, " movzb rax, al\n"); - } else if (ast->node_op == TokenKind_ne) { + } else if (expr->op == TokenKind_ne) { fprintf(g->out, " cmp rax, rdi\n"); fprintf(g->out, " setne al\n"); fprintf(g->out, " movzb rax, al\n"); - } else if (ast->node_op == TokenKind_lt) { + } else if (expr->op == TokenKind_lt) { fprintf(g->out, " cmp rax, rdi\n"); fprintf(g->out, " setl al\n"); fprintf(g->out, " movzb rax, al\n"); - } else if (ast->node_op == TokenKind_le) { + } else if (expr->op == TokenKind_le) { fprintf(g->out, " cmp rax, rdi\n"); fprintf(g->out, " setle al\n"); fprintf(g->out, " movzb rax, al\n"); @@ -242,51 +242,51 @@ static void codegen_binary_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { } } -static void codegen_cond_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { +static void codegen_cond_expr(CodeGen* g, CondExprNode* expr, GenMode gen_mode) { int label = codegen_new_label(g); - codegen_expr(g, ast->node_cond, GenMode_rval); + codegen_expr(g, expr->cond, GenMode_rval); fprintf(g->out, " cmp rax, 0\n"); fprintf(g->out, " je .Lelse%d\n", label); - codegen_expr(g, ast->node_then, gen_mode); + codegen_expr(g, expr->then, gen_mode); fprintf(g->out, " jmp .Lend%d\n", label); fprintf(g->out, ".Lelse%d:\n", label); - codegen_expr(g, ast->node_else, gen_mode); + codegen_expr(g, expr->else_, gen_mode); fprintf(g->out, ".Lend%d:\n", label); } -static void codegen_assign_expr_helper(CodeGen* g, AstNode* ast) { - if (ast->node_op == TokenKind_assign) { +static void codegen_assign_expr_helper(CodeGen* g, AssignExprNode* expr) { + if (expr->op == TokenKind_assign) { return; } fprintf(g->out, " mov rdi, rax\n"); fprintf(g->out, " mov rax, [rsp]\n"); - codegen_lval2rval(g, ast->node_lhs->ty); + codegen_lval2rval(g, expr->lhs->ty); - if (ast->node_op == TokenKind_assign_add) { + if (expr->op == TokenKind_assign_add) { fprintf(g->out, " add rax, rdi\n"); - } else if (ast->node_op == TokenKind_assign_sub) { + } else if (expr->op == TokenKind_assign_sub) { fprintf(g->out, " sub rax, rdi\n"); - } else if (ast->node_op == TokenKind_assign_mul) { + } else if (expr->op == TokenKind_assign_mul) { fprintf(g->out, " imul rax, rdi\n"); - } else if (ast->node_op == TokenKind_assign_div) { + } else if (expr->op == TokenKind_assign_div) { fprintf(g->out, " cqo\n"); fprintf(g->out, " idiv rdi\n"); - } else if (ast->node_op == TokenKind_assign_mod) { + } else if (expr->op == TokenKind_assign_mod) { fprintf(g->out, " cqo\n"); fprintf(g->out, " idiv rdi\n"); fprintf(g->out, " mov rax, rdx\n"); - } else if (ast->node_op == TokenKind_assign_or) { + } else if (expr->op == TokenKind_assign_or) { fprintf(g->out, " or rax, rdi\n"); - } else if (ast->node_op == TokenKind_assign_and) { + } else if (expr->op == TokenKind_assign_and) { fprintf(g->out, " and rax, rdi\n"); - } else if (ast->node_op == TokenKind_assign_xor) { + } else if (expr->op == TokenKind_assign_xor) { fprintf(g->out, " xor rax, rdi\n"); - } else if (ast->node_op == TokenKind_assign_lshift) { + } else if (expr->op == TokenKind_assign_lshift) { fprintf(g->out, " mov rcx, rdi\n"); fprintf(g->out, " shl rax, cl\n"); - } else if (ast->node_op == TokenKind_assign_rshift) { + } else if (expr->op == TokenKind_assign_rshift) { fprintf(g->out, " mov rcx, rdi\n"); fprintf(g->out, " sar rax, cl\n"); } else { @@ -294,13 +294,13 @@ static void codegen_assign_expr_helper(CodeGen* g, AstNode* ast) { } } -static void codegen_assign_expr(CodeGen* g, AstNode* ast) { - int sizeof_lhs = type_sizeof(ast->node_lhs->ty); +static void codegen_assign_expr(CodeGen* g, AssignExprNode* expr) { + int sizeof_lhs = type_sizeof(expr->lhs->ty); - codegen_expr(g, ast->node_lhs, GenMode_lval); + codegen_expr(g, expr->lhs, GenMode_lval); fprintf(g->out, " push rax\n"); - codegen_expr(g, ast->node_rhs, GenMode_rval); - codegen_assign_expr_helper(g, ast); + codegen_expr(g, expr->rhs, GenMode_rval); + codegen_assign_expr_helper(g, expr); fprintf(g->out, " pop rdi\n"); if (sizeof_lhs == 1) { fprintf(g->out, " mov BYTE PTR [rdi], al\n"); @@ -311,7 +311,7 @@ static void codegen_assign_expr(CodeGen* g, AstNode* ast) { } else if (sizeof_lhs == 8) { fprintf(g->out, " mov [rdi], rax\n"); } else { - if (ast->node_op != TokenKind_assign) { + if (expr->op != TokenKind_assign) { unimplemented(); } // rax: address of rhs @@ -325,11 +325,11 @@ static void codegen_assign_expr(CodeGen* g, AstNode* ast) { } static void codegen_args(CodeGen* g, AstNode* args) { - int* required_gp_regs_for_each_arg = calloc(args->node_len, sizeof(int)); + int* required_gp_regs_for_each_arg = calloc(args->as.list->len, sizeof(int)); int gp_regs = 6; - for (int i = 0; i < args->node_len; ++i) { - AstNode* arg = &args->node_items[i]; + for (int i = 0; i < args->as.list->len; ++i) { + AstNode* arg = &args->as.list->items[i]; int ty_size = type_sizeof(arg->ty); // TODO if (arg->ty->kind == TypeKind_array) { @@ -353,8 +353,8 @@ static void codegen_args(CodeGen* g, AstNode* args) { // Evaluate arguments in the reverse order (right to left). // Arguments passed by stack. - for (int i = args->node_len - 1; i >= 0; --i) { - AstNode* arg = &args->node_items[i]; + for (int i = args->as.list->len - 1; i >= 0; --i) { + AstNode* arg = &args->as.list->items[i]; if (required_gp_regs_for_each_arg[i] == 0) { codegen_expr(g, arg, GenMode_rval); int ty_size = type_sizeof(arg->ty); @@ -373,8 +373,8 @@ static void codegen_args(CodeGen* g, AstNode* args) { } } // Arguments passed by registers. - for (int i = args->node_len - 1; i >= 0; --i) { - AstNode* arg = &args->node_items[i]; + for (int i = args->as.list->len - 1; i >= 0; --i) { + AstNode* arg = &args->as.list->items[i]; if (required_gp_regs_for_each_arg[i] != 0) { codegen_expr(g, arg, GenMode_rval); if (required_gp_regs_for_each_arg[i] == 1) { @@ -387,19 +387,19 @@ static void codegen_args(CodeGen* g, AstNode* args) { } } // Pop pushed arguments onto registers. - for (int i = 0, j = 0; i < args->node_len; ++i) { + for (int i = 0, j = 0; i < args->as.list->len; ++i) { for (int k = 0; k < required_gp_regs_for_each_arg[i]; ++k) { fprintf(g->out, " pop %s\n", param_reg(j++)); } } } -static void codegen_func_call(CodeGen* g, AstNode* ast) { - const char* func_name = ast->name; +static void codegen_func_call(CodeGen* g, FuncCallNode* call) { + const char* func_name = call->name; if (strcmp(func_name, "__ducc_va_start") == 0) { fprintf(g->out, " # __ducc_va_start BEGIN\n"); - AstNode* va_list_args = &ast->node_args->node_items[0]; + AstNode* va_list_args = &call->args->as.list->items[0]; codegen_expr(g, va_list_args, GenMode_rval); fprintf(g->out, " mov rdi, rax\n"); @@ -429,12 +429,12 @@ static void codegen_func_call(CodeGen* g, AstNode* ast) { fprintf(g->out, " # __ducc_va_arg BEGIN\n"); // Evaluate va_list argument (first argument) - AstNode* va_list_arg = &ast->node_args->node_items[0]; + AstNode* va_list_arg = &call->args->as.list->items[0]; codegen_expr(g, va_list_arg, GenMode_rval); fprintf(g->out, " mov rdi, rax\n"); // rdi = pointer to va_list // Evaluate size argument (second argument) - AstNode* size_arg = &ast->node_args->node_items[1]; + AstNode* size_arg = &call->args->as.list->items[1]; codegen_expr(g, size_arg, GenMode_rval); fprintf(g->out, " mov rsi, rax\n"); // rsi = size @@ -466,12 +466,12 @@ static void codegen_func_call(CodeGen* g, AstNode* ast) { return; } - AstNode* args = ast->node_args; + AstNode* args = call->args; int gp_regs = 6; int pass_by_stack_offset = -16; - for (int i = 0; i < args->node_len; ++i) { - AstNode* arg = &args->node_items[i]; + for (int i = 0; i < args->as.list->len; ++i) { + AstNode* arg = &args->as.list->items[i]; int ty_size = type_sizeof(arg->ty); // TODO if (arg->ty->kind == TypeKind_array) { @@ -523,61 +523,61 @@ static void codegen_func_call(CodeGen* g, AstNode* ast) { fprintf(g->out, " add rsp, %d\n", -pass_by_stack_offset - 16); } -static void codegen_lvar(CodeGen* g, AstNode* ast, GenMode gen_mode) { - fprintf(g->out, " lea rax, %d[rbp]\n", -ast->node_stack_offset); +static void codegen_lvar(CodeGen* g, LvarNode* lvar, Type* ty, GenMode gen_mode) { + fprintf(g->out, " lea rax, %d[rbp]\n", -lvar->stack_offset); if (gen_mode == GenMode_rval) { - codegen_lval2rval(g, ast->ty); + codegen_lval2rval(g, ty); } } -static void codegen_gvar(CodeGen* g, AstNode* ast, GenMode gen_mode) { - fprintf(g->out, " lea rax, %s[rip]\n", ast->name); +static void codegen_gvar(CodeGen* g, GvarNode* gvar, Type* ty, GenMode gen_mode) { + fprintf(g->out, " lea rax, %s[rip]\n", gvar->name); if (gen_mode == GenMode_rval) { - codegen_lval2rval(g, ast->ty); + codegen_lval2rval(g, ty); } } -static void codegen_func_ref(CodeGen* g, AstNode* ast) { - fprintf(g->out, " lea rax, %s[rip]\n", ast->name); +static void codegen_func_ref(CodeGen* g, FuncNode* func) { + fprintf(g->out, " lea rax, %s[rip]\n", func->name); } static void codegen_composite_expr(CodeGen* g, AstNode* ast) { // Standard C does not have composite expression, but ducc internally has. - for (int i = 0; i < ast->node_len; ++i) { - AstNode* expr = ast->node_items + i; + for (int i = 0; i < ast->as.list->len; ++i) { + AstNode* expr = ast->as.list->items + i; codegen_expr(g, expr, GenMode_rval); } } static void codegen_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { if (ast->kind == AstNodeKind_int_expr) { - codegen_int_expr(g, ast); + codegen_int_expr(g, ast->as.int_expr); } else if (ast->kind == AstNodeKind_str_expr) { - codegen_str_expr(g, ast); + codegen_str_expr(g, ast->as.str_expr); } else if (ast->kind == AstNodeKind_unary_expr) { - codegen_unary_expr(g, ast); + codegen_unary_expr(g, ast->as.unary_expr); } else if (ast->kind == AstNodeKind_ref_expr) { - codegen_ref_expr(g, ast); + codegen_ref_expr(g, ast->as.ref_expr); } else if (ast->kind == AstNodeKind_deref_expr) { - codegen_deref_expr(g, ast, gen_mode); + codegen_deref_expr(g, ast->as.deref_expr, gen_mode); } else if (ast->kind == AstNodeKind_cast_expr) { - codegen_cast_expr(g, ast); + codegen_cast_expr(g, ast->as.cast_expr, ast->ty); } else if (ast->kind == AstNodeKind_binary_expr) { - codegen_binary_expr(g, ast, gen_mode); + codegen_binary_expr(g, ast->as.binary_expr, gen_mode); } else if (ast->kind == AstNodeKind_cond_expr) { - codegen_cond_expr(g, ast, gen_mode); + codegen_cond_expr(g, ast->as.cond_expr, gen_mode); } else if (ast->kind == AstNodeKind_logical_expr) { - codegen_logical_expr(g, ast); + codegen_logical_expr(g, ast->as.logical_expr); } else if (ast->kind == AstNodeKind_assign_expr) { - codegen_assign_expr(g, ast); + codegen_assign_expr(g, ast->as.assign_expr); } else if (ast->kind == AstNodeKind_func_call) { - codegen_func_call(g, ast); + codegen_func_call(g, ast->as.func_call); } else if (ast->kind == AstNodeKind_lvar) { - codegen_lvar(g, ast, gen_mode); + codegen_lvar(g, ast->as.lvar, ast->ty, gen_mode); } else if (ast->kind == AstNodeKind_gvar) { - codegen_gvar(g, ast, gen_mode); + codegen_gvar(g, ast->as.gvar, ast->ty, gen_mode); } else if (ast->kind == AstNodeKind_func) { - codegen_func_ref(g, ast); + codegen_func_ref(g, ast->as.func); } else if (ast->kind == AstNodeKind_list) { codegen_composite_expr(g, ast); } else { @@ -585,44 +585,44 @@ static void codegen_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { } } -static void codegen_return_stmt(CodeGen* g, AstNode* ast) { - if (ast->node_expr) { - codegen_expr(g, ast->node_expr, GenMode_rval); +static void codegen_return_stmt(CodeGen* g, ReturnStmtNode* stmt) { + if (stmt->expr) { + codegen_expr(g, stmt->expr, GenMode_rval); } - codegen_func_epilogue(g, ast); + codegen_func_epilogue(g); } -static void codegen_if_stmt(CodeGen* g, AstNode* ast) { +static void codegen_if_stmt(CodeGen* g, IfStmtNode* stmt) { int label = codegen_new_label(g); - codegen_expr(g, ast->node_cond, GenMode_rval); + codegen_expr(g, stmt->cond, GenMode_rval); fprintf(g->out, " cmp rax, 0\n"); fprintf(g->out, " je .Lelse%d\n", label); - codegen_stmt(g, ast->node_then); + codegen_stmt(g, stmt->then); fprintf(g->out, " jmp .Lend%d\n", label); fprintf(g->out, ".Lelse%d:\n", label); - if (ast->node_else) { - codegen_stmt(g, ast->node_else); + if (stmt->else_) { + codegen_stmt(g, stmt->else_); } fprintf(g->out, ".Lend%d:\n", label); } -static void codegen_for_stmt(CodeGen* g, AstNode* ast) { +static void codegen_for_stmt(CodeGen* g, ForStmtNode* stmt) { int label = codegen_new_label(g); ++g->loop_labels; *g->loop_labels = label; - if (ast->node_init) { - codegen_expr(g, ast->node_init, GenMode_rval); + if (stmt->init) { + codegen_expr(g, stmt->init, GenMode_rval); } fprintf(g->out, ".Lbegin%d:\n", label); - codegen_expr(g, ast->node_cond, GenMode_rval); + codegen_expr(g, stmt->cond, GenMode_rval); fprintf(g->out, " cmp rax, 0\n"); fprintf(g->out, " je .Lend%d\n", label); - codegen_stmt(g, ast->node_body); + codegen_stmt(g, stmt->body); fprintf(g->out, ".Lcontinue%d:\n", label); - if (ast->node_update) { - codegen_expr(g, ast->node_update, GenMode_rval); + if (stmt->update) { + codegen_expr(g, stmt->update, GenMode_rval); } fprintf(g->out, " jmp .Lbegin%d\n", label); fprintf(g->out, ".Lend%d:\n", label); @@ -630,15 +630,15 @@ static void codegen_for_stmt(CodeGen* g, AstNode* ast) { --g->loop_labels; } -static void codegen_do_while_stmt(CodeGen* g, AstNode* ast) { +static void codegen_do_while_stmt(CodeGen* g, DoWhileStmtNode* stmt) { int label = codegen_new_label(g); ++g->loop_labels; *g->loop_labels = label; fprintf(g->out, ".Lbegin%d:\n", label); - codegen_stmt(g, ast->node_body); + codegen_stmt(g, stmt->body); fprintf(g->out, ".Lcontinue%d:\n", label); - codegen_expr(g, ast->node_cond, GenMode_rval); + codegen_expr(g, stmt->cond, GenMode_rval); fprintf(g->out, " cmp rax, 0\n"); fprintf(g->out, " je .Lend%d\n", label); fprintf(g->out, " jmp .Lbegin%d\n", label); @@ -647,7 +647,7 @@ static void codegen_do_while_stmt(CodeGen* g, AstNode* ast) { --g->loop_labels; } -static void codegen_break_stmt(CodeGen* g, AstNode*) { +static void codegen_break_stmt(CodeGen* g) { if (g->switch_label != -1) { fprintf(g->out, " jmp .Lend%d\n", g->switch_label); } else { @@ -656,18 +656,18 @@ static void codegen_break_stmt(CodeGen* g, AstNode*) { } } -static void codegen_continue_stmt(CodeGen* g, AstNode*) { +static void codegen_continue_stmt(CodeGen* g) { int label = *g->loop_labels; fprintf(g->out, " jmp .Lcontinue%d\n", label); } -static void codegen_goto_stmt(CodeGen* g, AstNode* ast) { - fprintf(g->out, " jmp .L%s__%s\n", g->current_func->name, ast->name); +static void codegen_goto_stmt(CodeGen* g, GotoStmtNode* stmt) { + fprintf(g->out, " jmp .L%s__%s\n", g->current_func->as.func_def->name, stmt->label); } -static void codegen_label_stmt(CodeGen* g, AstNode* ast) { - fprintf(g->out, ".L%s__%s:\n", g->current_func->name, ast->name); - codegen_stmt(g, ast->node_body); +static void codegen_label_stmt(CodeGen* g, LabelStmtNode* stmt) { + fprintf(g->out, ".L%s__%s:\n", g->current_func->as.func_def->name, stmt->name); + codegen_stmt(g, stmt->body); } // Helper to collect case values from the switch body @@ -676,15 +676,15 @@ static void collect_cases(AstNode* stmt, int* case_values, int* case_labels, int return; if (stmt->kind == AstNodeKind_case_label) { - case_values[*n_cases] = stmt->node_int_value; + case_values[*n_cases] = stmt->as.case_label->value; case_labels[*n_cases] = *n_cases + 1; (*n_cases)++; - collect_cases(stmt->node_body, case_values, case_labels, n_cases); + collect_cases(stmt->as.case_label->body, case_values, case_labels, n_cases); } else if (stmt->kind == AstNodeKind_default_label) { - collect_cases(stmt->node_body, case_values, case_labels, n_cases); + collect_cases(stmt->as.default_label->body, case_values, case_labels, n_cases); } else if (stmt->kind == AstNodeKind_list) { - for (int i = 0; i < stmt->node_len; i++) { - collect_cases(stmt->node_items + i, case_values, case_labels, n_cases); + for (int i = 0; i < stmt->as.list->len; i++) { + collect_cases(stmt->as.list->items + i, case_values, case_labels, n_cases); } } } @@ -694,23 +694,24 @@ static bool codegen_switch_body(CodeGen* g, AstNode* stmt, int* case_values, int return false; if (stmt->kind == AstNodeKind_case_label) { - int value = stmt->node_int_value; + int value = stmt->as.case_label->value; for (int i = 0; i < n_cases; i++) { if (case_values[i] == value) { fprintf(g->out, ".Lcase%d_%d:\n", g->switch_label, case_labels[i]); break; } } - codegen_stmt(g, stmt->node_body); + codegen_stmt(g, stmt->as.case_label->body); return false; } else if (stmt->kind == AstNodeKind_default_label) { fprintf(g->out, ".Ldefault%d:\n", g->switch_label); - codegen_stmt(g, stmt->node_body); + codegen_stmt(g, stmt->as.default_label->body); return true; } else if (stmt->kind == AstNodeKind_list) { bool default_label_emitted = false; - for (int i = 0; i < stmt->node_len; i++) { - default_label_emitted |= codegen_switch_body(g, stmt->node_items + i, case_values, case_labels, n_cases); + for (int i = 0; i < stmt->as.list->len; i++) { + default_label_emitted |= + codegen_switch_body(g, stmt->as.list->items + i, case_values, case_labels, n_cases); } return default_label_emitted; } else { @@ -719,7 +720,7 @@ static bool codegen_switch_body(CodeGen* g, AstNode* stmt, int* case_values, int } } -static void codegen_switch_stmt(CodeGen* g, AstNode* ast) { +static void codegen_switch_stmt(CodeGen* g, SwitchStmtNode* stmt) { int switch_label = codegen_new_label(g); int prev_switch_label = g->switch_label; g->switch_label = switch_label; @@ -728,10 +729,10 @@ static void codegen_switch_stmt(CodeGen* g, AstNode* ast) { int case_values[256]; int case_labels[256]; int n_cases = 0; - collect_cases(ast->node_body, case_values, case_labels, &n_cases); + collect_cases(stmt->body, case_values, case_labels, &n_cases); // Generate jump instructions. - codegen_expr(g, ast->node_expr, GenMode_rval); + codegen_expr(g, stmt->expr, GenMode_rval); for (int i = 0; i < n_cases; i++) { fprintf(g->out, " cmp rax, %d\n", case_values[i]); fprintf(g->out, " je .Lcase%d_%d\n", switch_label, case_labels[i]); @@ -739,7 +740,7 @@ static void codegen_switch_stmt(CodeGen* g, AstNode* ast) { fprintf(g->out, " jmp .Ldefault%d\n", switch_label); // Generate the switch body with labels. - bool default_label_emitted = codegen_switch_body(g, ast->node_body, case_values, case_labels, n_cases); + bool default_label_emitted = codegen_switch_body(g, stmt->body, case_values, case_labels, n_cases); if (!default_label_emitted) { fprintf(g->out, ".Ldefault%d:\n", switch_label); @@ -749,13 +750,13 @@ static void codegen_switch_stmt(CodeGen* g, AstNode* ast) { g->switch_label = prev_switch_label; } -static void codegen_expr_stmt(CodeGen* g, AstNode* ast) { - codegen_expr(g, ast->node_expr, GenMode_rval); +static void codegen_expr_stmt(CodeGen* g, ExprStmtNode* stmt) { + codegen_expr(g, stmt->expr, GenMode_rval); } static void codegen_block_stmt(CodeGen* g, AstNode* ast) { - for (int i = 0; i < ast->node_len; ++i) { - AstNode* stmt = ast->node_items + i; + for (int i = 0; i < ast->as.list->len; ++i) { + AstNode* stmt = ast->as.list->items + i; codegen_stmt(g, stmt); } } @@ -764,25 +765,25 @@ static void codegen_stmt(CodeGen* g, AstNode* ast) { if (ast->kind == AstNodeKind_list) { codegen_block_stmt(g, ast); } else if (ast->kind == AstNodeKind_return_stmt) { - codegen_return_stmt(g, ast); + codegen_return_stmt(g, ast->as.return_stmt); } else if (ast->kind == AstNodeKind_if_stmt) { - codegen_if_stmt(g, ast); + codegen_if_stmt(g, ast->as.if_stmt); } else if (ast->kind == AstNodeKind_switch_stmt) { - codegen_switch_stmt(g, ast); + codegen_switch_stmt(g, ast->as.switch_stmt); } else if (ast->kind == AstNodeKind_for_stmt) { - codegen_for_stmt(g, ast); + codegen_for_stmt(g, ast->as.for_stmt); } else if (ast->kind == AstNodeKind_do_while_stmt) { - codegen_do_while_stmt(g, ast); + codegen_do_while_stmt(g, ast->as.do_while_stmt); } else if (ast->kind == AstNodeKind_break_stmt) { - codegen_break_stmt(g, ast); + codegen_break_stmt(g); } else if (ast->kind == AstNodeKind_continue_stmt) { - codegen_continue_stmt(g, ast); + codegen_continue_stmt(g); } else if (ast->kind == AstNodeKind_goto_stmt) { - codegen_goto_stmt(g, ast); + codegen_goto_stmt(g, ast->as.goto_stmt); } else if (ast->kind == AstNodeKind_label_stmt) { - codegen_label_stmt(g, ast); + codegen_label_stmt(g, ast->as.label_stmt); } else if (ast->kind == AstNodeKind_expr_stmt) { - codegen_expr_stmt(g, ast); + codegen_expr_stmt(g, ast->as.expr_stmt); } else if (ast->kind == AstNodeKind_lvar_decl) { // Do nothing. } else if (ast->kind == AstNodeKind_nop) { @@ -799,17 +800,17 @@ static void codegen_func(CodeGen* g, AstNode* ast) { g->current_func = ast; if (ast->ty->storage_class != StorageClass_static) { - fprintf(g->out, ".globl %s\n", ast->name); + fprintf(g->out, ".globl %s\n", ast->as.func_def->name); } - fprintf(g->out, "%s:\n", ast->name); + fprintf(g->out, "%s:\n", ast->as.func_def->name); - codegen_func_prologue(g, ast); - codegen_stmt(g, ast->node_body); - if (strcmp(ast->name, "main") == 0) { + codegen_func_prologue(g, ast->as.func_def); + codegen_stmt(g, ast->as.func_def->body); + if (strcmp(ast->as.func_def->name, "main") == 0) { // C99: 5.1.2.2.3 fprintf(g->out, " mov rax, 0\n"); } - codegen_func_epilogue(g, ast); + codegen_func_epilogue(g); fprintf(g->out, "\n"); g->current_func = NULL; @@ -831,48 +832,53 @@ void codegen(Program* prog, FILE* out) { } fprintf(g->out, ".data\n\n"); - for (int i = 0; i < prog->vars->node_len; ++i) { - AstNode* var = prog->vars->node_items + i; - if (var->node_expr) { + for (int i = 0; i < prog->vars->as.list->len; ++i) { + AstNode* var = prog->vars->as.list->items + i; + if (var->as.gvar_decl->expr) { if (type_sizeof(var->ty) == 1) { - if (var->node_expr->kind != AstNodeKind_int_expr) + if (var->as.gvar_decl->expr->kind != AstNodeKind_int_expr) unimplemented(); - fprintf(g->out, " %s: .byte %d\n", var->name, var->node_expr->node_int_value); + fprintf(g->out, " %s: .byte %d\n", var->as.gvar_decl->name, + var->as.gvar_decl->expr->as.int_expr->value); } else if (type_sizeof(var->ty) == 2) { - if (var->node_expr->kind != AstNodeKind_int_expr) + if (var->as.gvar_decl->expr->kind != AstNodeKind_int_expr) unimplemented(); - fprintf(g->out, " %s: .word %d\n", var->name, var->node_expr->node_int_value); + fprintf(g->out, " %s: .word %d\n", var->as.gvar_decl->name, + var->as.gvar_decl->expr->as.int_expr->value); } else if (type_sizeof(var->ty) == 4) { - if (var->node_expr->kind != AstNodeKind_int_expr) + if (var->as.gvar_decl->expr->kind != AstNodeKind_int_expr) unimplemented(); - fprintf(g->out, " %s: .int %d\n", var->name, var->node_expr->node_int_value); + fprintf(g->out, " %s: .int %d\n", var->as.gvar_decl->name, + var->as.gvar_decl->expr->as.int_expr->value); } else if (var->ty->kind == TypeKind_ptr) { - if (var->node_expr->kind == AstNodeKind_ref_expr) { - if (var->node_expr->node_operand->kind != AstNodeKind_gvar) { + 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->name, var->node_expr->node_operand->name); - } else if (var->node_expr->kind == AstNodeKind_gvar) { - fprintf(g->out, " %s: .quad %s\n", var->name, var->node_expr->name); + fprintf(g->out, " %s: .quad %s\n", var->as.gvar_decl->name, + 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); } else { unimplemented(); } } else if (var->ty->kind == TypeKind_array && var->ty->base->kind == TypeKind_char) { - if (var->node_expr->kind != AstNodeKind_str_expr) + if (var->as.gvar_decl->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); + 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->name, type_sizeof(var->ty)); + fprintf(g->out, " %s: .zero %d\n", var->as.gvar_decl->name, type_sizeof(var->ty)); } } fprintf(g->out, ".text\n\n"); - for (int i = 0; i < prog->funcs->node_len; ++i) { - AstNode* func = &prog->funcs->node_items[i]; + for (int i = 0; i < prog->funcs->as.list->len; ++i) { + AstNode* func = &prog->funcs->as.list->items[i]; codegen_func(g, func); } } -- cgit v1.3-1-g0d28