aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codegen.c
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-01-23 22:00:27 +0900
committernsfisis <nsfisis@gmail.com>2026-01-23 22:02:59 +0900
commit52df9f8ce8abf17bf6ca70c174a48f41e5ad31d5 (patch)
tree410ba8352f1e3af62c86c537328dcd9504613d61 /src/codegen.c
parent7838acf484f7cb64b7723f2a1dd2fe00f53b77fc (diff)
downloadducc-52df9f8ce8abf17bf6ca70c174a48f41e5ad31d5.tar.gz
ducc-52df9f8ce8abf17bf6ca70c174a48f41e5ad31d5.tar.zst
ducc-52df9f8ce8abf17bf6ca70c174a48f41e5ad31d5.zip
refactor: AST overhaul
Diffstat (limited to 'src/codegen.c')
-rw-r--r--src/codegen.c386
1 files changed, 196 insertions, 190 deletions
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);
}
}