aboutsummaryrefslogtreecommitdiffhomepage
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
parent7838acf484f7cb64b7723f2a1dd2fe00f53b77fc (diff)
downloadducc-52df9f8ce8abf17bf6ca70c174a48f41e5ad31d5.tar.gz
ducc-52df9f8ce8abf17bf6ca70c174a48f41e5ad31d5.tar.zst
ducc-52df9f8ce8abf17bf6ca70c174a48f41e5ad31d5.zip
refactor: AST overhaul
-rw-r--r--src/ast.c298
-rw-r--r--src/ast.h273
-rw-r--r--src/codegen.c386
-rw-r--r--src/codegen_wasm.c82
-rw-r--r--src/parse.c484
5 files changed, 943 insertions, 580 deletions
diff --git a/src/ast.c b/src/ast.c
index 75aa7ee..7c7df72 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -75,7 +75,11 @@ const char* type_kind_stringify(TypeKind k) {
}
static AstNode* members_of(Type* ty) {
- return ty->ref.defs->node_items[ty->ref.index].node_members;
+ AstNode* def = &ty->ref.defs->as.list->items[ty->ref.index];
+ if (def->kind == AstNodeKind_struct_def)
+ return def->as.struct_def->members;
+ else
+ return def->as.union_def->members;
}
Type* type_new(TypeKind kind) {
@@ -287,9 +291,10 @@ AstNode* ast_new_list(int capacity) {
if (capacity == 0)
unreachable();
AstNode* list = ast_new(AstNodeKind_list);
- list->node_cap = capacity;
- list->node_len = 0;
- list->node_items = calloc(list->node_cap, sizeof(AstNode));
+ list->as.list = calloc(1, sizeof(ListNode));
+ list->as.list->cap = capacity;
+ list->as.list->len = 0;
+ list->as.list->items = calloc(list->as.list->cap, sizeof(AstNode));
return list;
}
@@ -300,35 +305,39 @@ void ast_append(AstNode* list, AstNode* item) {
if (!item) {
return;
}
- if (list->node_cap <= list->node_len) {
- list->node_cap *= 2;
- list->node_items = realloc(list->node_items, sizeof(AstNode) * list->node_cap);
- memset(list->node_items + list->node_len, 0, sizeof(AstNode) * (list->node_cap - list->node_len));
+ if (list->as.list->cap <= list->as.list->len) {
+ list->as.list->cap *= 2;
+ list->as.list->items = realloc(list->as.list->items, sizeof(AstNode) * list->as.list->cap);
+ memset(list->as.list->items + list->as.list->len, 0,
+ sizeof(AstNode) * (list->as.list->cap - list->as.list->len));
}
- memcpy(list->node_items + list->node_len, item, sizeof(AstNode));
- ++list->node_len;
+ memcpy(list->as.list->items + list->as.list->len, item, sizeof(AstNode));
+ ++list->as.list->len;
}
AstNode* ast_new_int(int v) {
AstNode* e = ast_new(AstNodeKind_int_expr);
- e->node_int_value = v;
+ e->as.int_expr = calloc(1, sizeof(IntExprNode));
+ e->as.int_expr->value = v;
e->ty = type_new(TypeKind_int);
return e;
}
AstNode* ast_new_unary_expr(int op, AstNode* operand) {
AstNode* e = ast_new(AstNodeKind_unary_expr);
- e->node_op = op;
- e->node_operand = operand;
+ e->as.unary_expr = calloc(1, sizeof(UnaryExprNode));
+ e->as.unary_expr->op = op;
+ e->as.unary_expr->operand = operand;
e->ty = type_new(TypeKind_int);
return e;
}
AstNode* ast_new_binary_expr(int op, AstNode* lhs, AstNode* rhs) {
AstNode* e = ast_new(AstNodeKind_binary_expr);
- e->node_op = op;
- e->node_lhs = lhs;
- e->node_rhs = rhs;
+ e->as.binary_expr = calloc(1, sizeof(BinaryExprNode));
+ e->as.binary_expr->op = op;
+ e->as.binary_expr->lhs = lhs;
+ e->as.binary_expr->rhs = rhs;
if (op == TokenKind_plus) {
if (lhs->ty->kind == TypeKind_ptr) {
e->ty = lhs->ty;
@@ -357,9 +366,10 @@ AstNode* ast_new_binary_expr(int op, AstNode* lhs, AstNode* rhs) {
AstNode* ast_new_assign_expr(int op, AstNode* lhs, AstNode* rhs) {
AstNode* e = ast_new(AstNodeKind_assign_expr);
- e->node_op = op;
- e->node_lhs = lhs;
- e->node_rhs = rhs;
+ e->as.assign_expr = calloc(1, sizeof(AssignExprNode));
+ e->as.assign_expr->op = op;
+ e->as.assign_expr->lhs = lhs;
+ e->as.assign_expr->rhs = rhs;
e->ty = lhs->ty;
return e;
}
@@ -382,39 +392,251 @@ AstNode* ast_new_assign_sub_expr(AstNode* lhs, AstNode* rhs) {
AstNode* ast_new_ref_expr(AstNode* operand) {
AstNode* e = ast_new(AstNodeKind_ref_expr);
- e->node_operand = operand;
+ e->as.ref_expr = calloc(1, sizeof(RefExprNode));
+ e->as.ref_expr->operand = operand;
e->ty = type_new_ptr(operand->ty);
return e;
}
AstNode* ast_new_deref_expr(AstNode* operand) {
AstNode* e = ast_new(AstNodeKind_deref_expr);
- e->node_operand = operand;
+ e->as.deref_expr = calloc(1, sizeof(DerefExprNode));
+ e->as.deref_expr->operand = operand;
e->ty = operand->ty->base;
return e;
}
AstNode* ast_new_member_access_expr(AstNode* obj, const char* name) {
AstNode* e = ast_new(AstNodeKind_deref_expr);
- e->node_operand = ast_new_binary_expr(TokenKind_plus, obj, ast_new_int(type_offsetof(obj->ty->base, name)));
+ e->as.deref_expr = calloc(1, sizeof(DerefExprNode));
+ e->as.deref_expr->operand =
+ ast_new_binary_expr(TokenKind_plus, obj, ast_new_int(type_offsetof(obj->ty->base, name)));
e->ty = type_member_typeof(obj->ty->base, name);
- e->node_operand->ty = type_new_ptr(e->ty);
+ e->as.deref_expr->operand->ty = type_new_ptr(e->ty);
return e;
}
AstNode* ast_new_cast_expr(AstNode* operand, Type* result_ty) {
AstNode* e = ast_new(AstNodeKind_cast_expr);
- e->node_operand = operand;
+ e->as.cast_expr = calloc(1, sizeof(CastExprNode));
+ e->as.cast_expr->operand = operand;
e->ty = result_ty;
return e;
}
+AstNode* ast_new_logical_expr(int op, AstNode* lhs, AstNode* rhs) {
+ AstNode* e = ast_new(AstNodeKind_logical_expr);
+ e->as.logical_expr = calloc(1, sizeof(LogicalExprNode));
+ e->as.logical_expr->op = op;
+ e->as.logical_expr->lhs = lhs;
+ e->as.logical_expr->rhs = rhs;
+ e->ty = type_new(TypeKind_int);
+ return e;
+}
+
+AstNode* ast_new_cond_expr(AstNode* cond, AstNode* then, AstNode* else_) {
+ AstNode* e = ast_new(AstNodeKind_cond_expr);
+ e->as.cond_expr = calloc(1, sizeof(CondExprNode));
+ e->as.cond_expr->cond = cond;
+ e->as.cond_expr->then = then;
+ e->as.cond_expr->else_ = else_;
+ e->ty = then->ty;
+ return e;
+}
+
+AstNode* ast_new_str_expr(int idx, Type* ty) {
+ AstNode* e = ast_new(AstNodeKind_str_expr);
+ e->as.str_expr = calloc(1, sizeof(StrExprNode));
+ e->as.str_expr->idx = idx;
+ e->ty = ty;
+ return e;
+}
+
+AstNode* ast_new_func_call(const char* name, Type* ty) {
+ AstNode* e = ast_new(AstNodeKind_func_call);
+ e->as.func_call = calloc(1, sizeof(FuncCallNode));
+ e->as.func_call->name = name;
+ e->ty = ty;
+ return e;
+}
+
+AstNode* ast_new_func(const char* name, Type* ty) {
+ AstNode* e = ast_new(AstNodeKind_func);
+ e->as.func = calloc(1, sizeof(FuncNode));
+ e->as.func->name = name;
+ e->ty = ty;
+ return e;
+}
+
+AstNode* ast_new_gvar(const char* name, Type* ty) {
+ AstNode* e = ast_new(AstNodeKind_gvar);
+ e->as.gvar = calloc(1, sizeof(GvarNode));
+ e->as.gvar->name = name;
+ e->ty = ty;
+ return e;
+}
+
+AstNode* ast_new_lvar(const char* name, int stack_offset, Type* ty) {
+ AstNode* e = ast_new(AstNodeKind_lvar);
+ e->as.lvar = calloc(1, sizeof(LvarNode));
+ e->as.lvar->name = name;
+ e->as.lvar->stack_offset = stack_offset;
+ e->ty = ty;
+ return e;
+}
+
+AstNode* ast_new_nop(void) {
+ return ast_new(AstNodeKind_nop);
+}
+
+AstNode* ast_new_break_stmt(void) {
+ return ast_new(AstNodeKind_break_stmt);
+}
+
+AstNode* ast_new_continue_stmt(void) {
+ return ast_new(AstNodeKind_continue_stmt);
+}
+
+AstNode* ast_new_return_stmt(AstNode* expr) {
+ AstNode* e = ast_new(AstNodeKind_return_stmt);
+ e->as.return_stmt = calloc(1, sizeof(ReturnStmtNode));
+ e->as.return_stmt->expr = expr;
+ return e;
+}
+
+AstNode* ast_new_expr_stmt(AstNode* expr) {
+ AstNode* e = ast_new(AstNodeKind_expr_stmt);
+ e->as.expr_stmt = calloc(1, sizeof(ExprStmtNode));
+ e->as.expr_stmt->expr = expr;
+ return e;
+}
+
+AstNode* ast_new_if_stmt(AstNode* cond, AstNode* then, AstNode* else_) {
+ AstNode* e = ast_new(AstNodeKind_if_stmt);
+ e->as.if_stmt = calloc(1, sizeof(IfStmtNode));
+ e->as.if_stmt->cond = cond;
+ e->as.if_stmt->then = then;
+ e->as.if_stmt->else_ = else_;
+ return e;
+}
+
+AstNode* ast_new_for_stmt(AstNode* init, AstNode* cond, AstNode* update, AstNode* body) {
+ AstNode* e = ast_new(AstNodeKind_for_stmt);
+ e->as.for_stmt = calloc(1, sizeof(ForStmtNode));
+ e->as.for_stmt->init = init;
+ e->as.for_stmt->cond = cond;
+ e->as.for_stmt->update = update;
+ e->as.for_stmt->body = body;
+ return e;
+}
+
+AstNode* ast_new_do_while_stmt(AstNode* cond, AstNode* body) {
+ AstNode* e = ast_new(AstNodeKind_do_while_stmt);
+ e->as.do_while_stmt = calloc(1, sizeof(DoWhileStmtNode));
+ e->as.do_while_stmt->cond = cond;
+ e->as.do_while_stmt->body = body;
+ return e;
+}
+
+AstNode* ast_new_switch_stmt(AstNode* expr) {
+ AstNode* e = ast_new(AstNodeKind_switch_stmt);
+ e->as.switch_stmt = calloc(1, sizeof(SwitchStmtNode));
+ e->as.switch_stmt->expr = expr;
+ return e;
+}
+
+AstNode* ast_new_case_label(int value, AstNode* body) {
+ AstNode* e = ast_new(AstNodeKind_case_label);
+ e->as.case_label = calloc(1, sizeof(CaseLabelNode));
+ e->as.case_label->value = value;
+ e->as.case_label->body = body;
+ return e;
+}
+
+AstNode* ast_new_default_label(AstNode* body) {
+ AstNode* e = ast_new(AstNodeKind_default_label);
+ e->as.default_label = calloc(1, sizeof(DefaultLabelNode));
+ e->as.default_label->body = body;
+ return e;
+}
+
+AstNode* ast_new_goto_stmt(const char* label) {
+ AstNode* e = ast_new(AstNodeKind_goto_stmt);
+ e->as.goto_stmt = calloc(1, sizeof(GotoStmtNode));
+ e->as.goto_stmt->label = label;
+ return e;
+}
+
+AstNode* ast_new_label_stmt(const char* name, AstNode* body) {
+ AstNode* e = ast_new(AstNodeKind_label_stmt);
+ e->as.label_stmt = calloc(1, sizeof(LabelStmtNode));
+ e->as.label_stmt->name = name;
+ e->as.label_stmt->body = body;
+ return e;
+}
+
+AstNode* ast_new_declarator(const char* name, Type* ty) {
+ AstNode* e = ast_new(AstNodeKind_declarator);
+ e->as.declarator = calloc(1, sizeof(DeclaratorNode));
+ e->as.declarator->name = name;
+ e->ty = ty;
+ return e;
+}
+
+AstNode* ast_new_func_def(const char* name, Type* ty, AstNode* params, AstNode* body, int stack_size) {
+ AstNode* e = ast_new(AstNodeKind_func_def);
+ e->as.func_def = calloc(1, sizeof(FuncDefNode));
+ e->as.func_def->name = name;
+ e->as.func_def->params = params;
+ e->as.func_def->body = body;
+ e->as.func_def->stack_size = stack_size;
+ e->ty = ty;
+ return e;
+}
+
+AstNode* ast_new_enum_member(const char* name, int value) {
+ AstNode* e = ast_new(AstNodeKind_enum_member);
+ e->as.enum_member = calloc(1, sizeof(EnumMemberNode));
+ e->as.enum_member->name = name;
+ e->as.enum_member->value = value;
+ return e;
+}
+
+AstNode* ast_new_typedef_decl(const char* name, Type* ty) {
+ AstNode* e = ast_new(AstNodeKind_typedef_decl);
+ e->as.typedef_decl = calloc(1, sizeof(TypedefDeclNode));
+ e->as.typedef_decl->name = name;
+ e->ty = ty;
+ return e;
+}
+
+AstNode* ast_new_struct_def(const char* name) {
+ AstNode* e = ast_new(AstNodeKind_struct_def);
+ e->as.struct_def = calloc(1, sizeof(StructDefNode));
+ e->as.struct_def->name = name;
+ return e;
+}
+
+AstNode* ast_new_union_def(const char* name) {
+ AstNode* e = ast_new(AstNodeKind_union_def);
+ e->as.union_def = calloc(1, sizeof(UnionDefNode));
+ e->as.union_def->name = name;
+ return e;
+}
+
+AstNode* ast_new_enum_def(const char* name) {
+ AstNode* e = ast_new(AstNodeKind_enum_def);
+ e->as.enum_def = calloc(1, sizeof(EnumDefNode));
+ e->as.enum_def->name = name;
+ return e;
+}
+
int type_sizeof_struct(Type* ty) {
int next_offset = 0;
int struct_align = 0;
- for (int i = 0; i < members_of(ty)->node_len; ++i) {
- AstNode* member = &members_of(ty)->node_items[i];
+ for (int i = 0; i < members_of(ty)->as.list->len; ++i) {
+ AstNode* member = &members_of(ty)->as.list->items[i];
int size = type_sizeof(member->ty);
int align = type_alignof(member->ty);
@@ -431,8 +653,8 @@ int type_sizeof_union(Type* ty) {
int union_size = 0;
int union_align = 0;
- for (int i = 0; i < members_of(ty)->node_len; ++i) {
- AstNode* member = &members_of(ty)->node_items[i];
+ for (int i = 0; i < members_of(ty)->as.list->len; ++i) {
+ AstNode* member = &members_of(ty)->as.list->items[i];
int size = type_sizeof(member->ty);
int align = type_alignof(member->ty);
@@ -450,8 +672,8 @@ int type_sizeof_union(Type* ty) {
int type_alignof_struct(Type* ty) {
int struct_align = 0;
- for (int i = 0; i < members_of(ty)->node_len; ++i) {
- AstNode* member = &members_of(ty)->node_items[i];
+ for (int i = 0; i < members_of(ty)->as.list->len; ++i) {
+ AstNode* member = &members_of(ty)->as.list->items[i];
int align = type_alignof(member->ty);
if (struct_align < align) {
@@ -464,8 +686,8 @@ int type_alignof_struct(Type* ty) {
int type_alignof_union(Type* ty) {
int union_align = 0;
- for (int i = 0; i < members_of(ty)->node_len; ++i) {
- AstNode* member = &members_of(ty)->node_items[i];
+ for (int i = 0; i < members_of(ty)->as.list->len; ++i) {
+ AstNode* member = &members_of(ty)->as.list->items[i];
int align = type_alignof(member->ty);
if (union_align < align) {
@@ -485,13 +707,13 @@ int type_offsetof(Type* ty, const char* name) {
int next_offset = 0;
- for (int i = 0; i < members_of(ty)->node_len; ++i) {
- AstNode* member = &members_of(ty)->node_items[i];
+ for (int i = 0; i < members_of(ty)->as.list->len; ++i) {
+ AstNode* member = &members_of(ty)->as.list->items[i];
int size = type_sizeof(member->ty);
int align = type_alignof(member->ty);
next_offset = to_aligned(next_offset, align);
- if (strcmp(member->name, name) == 0) {
+ if (strcmp(member->as.struct_member->name, name) == 0) {
return next_offset;
}
next_offset += size;
@@ -505,9 +727,9 @@ Type* type_member_typeof(Type* ty, const char* name) {
fatal_error("type_member_typeof: type is neither a struct nor a union");
}
- for (int i = 0; i < members_of(ty)->node_len; ++i) {
- AstNode* member = &members_of(ty)->node_items[i];
- if (strcmp(member->name, name) == 0) {
+ for (int i = 0; i < members_of(ty)->as.list->len; ++i) {
+ AstNode* member = &members_of(ty)->as.list->items[i];
+ if (strcmp(member->as.struct_member->name, name) == 0) {
return member->ty;
}
}
diff --git a/src/ast.h b/src/ast.h
index 0339457..498e6c3 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -136,38 +136,226 @@ typedef enum {
const char* astnode_kind_stringify(AstNodeKind k);
-#define node_items __n1
-#define node_len __i1
-#define node_cap __i2
-#define node_expr __n1
-#define node_lhs __n1
-#define node_rhs __n2
-#define node_operand __n1
-#define node_cond __n1
-#define node_init __n2
-#define node_update __n3
-#define node_then __n2
-#define node_else __n3
-#define node_body __n4
-#define node_members __n1
-#define node_params __n1
-#define node_args __n1
-#define node_int_value __i1
-#define node_idx __i1
-#define node_op __i1
-#define node_stack_offset __i1
-#define node_stack_size __i1
+// Expression nodes
+typedef struct {
+ int value;
+} IntExprNode;
+
+typedef struct {
+ int idx;
+} StrExprNode;
+
+typedef struct {
+ int op;
+ AstNode* operand;
+} UnaryExprNode;
+
+typedef struct {
+ int op;
+ AstNode* lhs;
+ AstNode* rhs;
+} BinaryExprNode;
+
+typedef struct {
+ int op;
+ AstNode* lhs;
+ AstNode* rhs;
+} LogicalExprNode;
+
+typedef struct {
+ int op;
+ AstNode* lhs;
+ AstNode* rhs;
+} AssignExprNode;
+
+typedef struct {
+ AstNode* operand;
+} CastExprNode;
+
+typedef struct {
+ AstNode* cond;
+ AstNode* then;
+ AstNode* else_;
+} CondExprNode;
+
+typedef struct {
+ AstNode* operand;
+} DerefExprNode;
+
+typedef struct {
+ AstNode* operand;
+} RefExprNode;
+
+typedef struct {
+ const char* name;
+ AstNode* args;
+} FuncCallNode;
+
+// Statement nodes
+typedef struct {
+ AstNode* cond;
+ AstNode* then;
+ AstNode* else_;
+} IfStmtNode;
+
+typedef struct {
+ AstNode* init;
+ AstNode* cond;
+ AstNode* update;
+ AstNode* body;
+} ForStmtNode;
+
+typedef struct {
+ AstNode* cond;
+ AstNode* body;
+} DoWhileStmtNode;
+
+typedef struct {
+ AstNode* expr;
+ AstNode* body;
+} SwitchStmtNode;
+
+typedef struct {
+ int value;
+ AstNode* body;
+} CaseLabelNode;
+
+typedef struct {
+ AstNode* body;
+} DefaultLabelNode;
+
+typedef struct {
+ const char* name;
+ AstNode* body;
+} LabelStmtNode;
+
+typedef struct {
+ AstNode* expr;
+} ReturnStmtNode;
+
+typedef struct {
+ const char* label;
+} GotoStmtNode;
+
+typedef struct {
+ AstNode* expr;
+} ExprStmtNode;
+
+// Declaration nodes
+typedef struct {
+ const char* name;
+ AstNode* params;
+ AstNode* body;
+ int stack_size;
+} FuncDefNode;
+
+typedef struct {
+ const char* name;
+ int stack_offset;
+} LvarNode;
+
+typedef struct {
+ AstNode* expr;
+} LvarDeclNode;
+
+typedef struct {
+ const char* name;
+ int stack_offset;
+} ParamNode;
+
+typedef struct {
+ const char* name;
+ AstNode* expr;
+} GvarDeclNode;
+
+typedef struct {
+ const char* name;
+ AstNode* members;
+} StructDefNode;
+
+typedef struct {
+ const char* name;
+ AstNode* members;
+} UnionDefNode;
+
+typedef struct {
+ const char* name;
+ AstNode* members;
+} EnumDefNode;
+
+typedef struct {
+ const char* name;
+ int value;
+} EnumMemberNode;
+
+typedef struct {
+ const char* name;
+ AstNode* init;
+} DeclaratorNode;
+
+typedef struct {
+ const char* name;
+} FuncNode;
+
+typedef struct {
+ const char* name;
+} GvarNode;
+
+typedef struct {
+ const char* name;
+} StructMemberNode;
+
+typedef struct {
+ const char* name;
+} TypedefDeclNode;
+
+typedef struct {
+ AstNode* items;
+ int len;
+ int cap;
+} ListNode;
struct AstNode {
AstNodeKind kind;
- const char* name;
Type* ty;
- struct AstNode* __n1;
- struct AstNode* __n2;
- struct AstNode* __n3;
- struct AstNode* __n4;
- int __i1;
- int __i2;
+ union {
+ IntExprNode* int_expr;
+ StrExprNode* str_expr;
+ UnaryExprNode* unary_expr;
+ BinaryExprNode* binary_expr;
+ LogicalExprNode* logical_expr;
+ AssignExprNode* assign_expr;
+ CastExprNode* cast_expr;
+ CondExprNode* cond_expr;
+ DerefExprNode* deref_expr;
+ RefExprNode* ref_expr;
+ FuncCallNode* func_call;
+ IfStmtNode* if_stmt;
+ ForStmtNode* for_stmt;
+ DoWhileStmtNode* do_while_stmt;
+ SwitchStmtNode* switch_stmt;
+ CaseLabelNode* case_label;
+ DefaultLabelNode* default_label;
+ LabelStmtNode* label_stmt;
+ ReturnStmtNode* return_stmt;
+ GotoStmtNode* goto_stmt;
+ ExprStmtNode* expr_stmt;
+ FuncDefNode* func_def;
+ LvarNode* lvar;
+ LvarDeclNode* lvar_decl;
+ ParamNode* param;
+ GvarDeclNode* gvar_decl;
+ StructDefNode* struct_def;
+ UnionDefNode* union_def;
+ EnumDefNode* enum_def;
+ EnumMemberNode* enum_member;
+ DeclaratorNode* declarator;
+ FuncNode* func;
+ GvarNode* gvar;
+ StructMemberNode* struct_member;
+ TypedefDeclNode* typedef_decl;
+ ListNode* list;
+ } as;
};
typedef struct {
@@ -190,5 +378,34 @@ AstNode* ast_new_ref_expr(AstNode* operand);
AstNode* ast_new_deref_expr(AstNode* operand);
AstNode* ast_new_member_access_expr(AstNode* obj, const char* name);
AstNode* ast_new_cast_expr(AstNode* operand, Type* result_ty);
+AstNode* ast_new_logical_expr(int op, AstNode* lhs, AstNode* rhs);
+AstNode* ast_new_cond_expr(AstNode* cond, AstNode* then, AstNode* else_);
+AstNode* ast_new_str_expr(int idx, Type* ty);
+AstNode* ast_new_func_call(const char* name, Type* ty);
+AstNode* ast_new_func(const char* name, Type* ty);
+AstNode* ast_new_gvar(const char* name, Type* ty);
+AstNode* ast_new_lvar(const char* name, int stack_offset, Type* ty);
+
+AstNode* ast_new_nop(void);
+AstNode* ast_new_break_stmt(void);
+AstNode* ast_new_continue_stmt(void);
+AstNode* ast_new_return_stmt(AstNode* expr);
+AstNode* ast_new_expr_stmt(AstNode* expr);
+AstNode* ast_new_if_stmt(AstNode* cond, AstNode* then, AstNode* else_);
+AstNode* ast_new_for_stmt(AstNode* init, AstNode* cond, AstNode* update, AstNode* body);
+AstNode* ast_new_do_while_stmt(AstNode* cond, AstNode* body);
+AstNode* ast_new_switch_stmt(AstNode* expr);
+AstNode* ast_new_case_label(int value, AstNode* body);
+AstNode* ast_new_default_label(AstNode* body);
+AstNode* ast_new_goto_stmt(const char* label);
+AstNode* ast_new_label_stmt(const char* name, AstNode* body);
+
+AstNode* ast_new_declarator(const char* name, Type* ty);
+AstNode* ast_new_func_def(const char* name, Type* ty, AstNode* params, AstNode* body, int stack_size);
+AstNode* ast_new_enum_member(const char* name, int value);
+AstNode* ast_new_typedef_decl(const char* name, Type* ty);
+AstNode* ast_new_struct_def(const char* name);
+AstNode* ast_new_union_def(const char* name);
+AstNode* ast_new_enum_def(const char* name);
#endif
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);
}
}
diff --git a/src/codegen_wasm.c b/src/codegen_wasm.c
index e0be383..cb48f38 100644
--- a/src/codegen_wasm.c
+++ b/src/codegen_wasm.c
@@ -29,77 +29,77 @@ static CodeGen* codegen_new(FILE* out) {
static void codegen_expr(CodeGen* g, AstNode* ast, GenMode gen_mode);
static void codegen_stmt(CodeGen* g, AstNode* ast);
-static void codegen_func_prologue(CodeGen* g, AstNode* ast) {
- for (int i = 0; i < ast->node_params->node_len; ++i) {
- fprintf(g->out, " (param $l_%s i32)", ast->node_params->node_items[i].name);
+static void codegen_func_prologue(CodeGen* g, FuncDefNode* func_def) {
+ for (int i = 0; i < func_def->params->as.list->len; ++i) {
+ fprintf(g->out, " (param $l_%s i32)", func_def->params->as.list->items[i].as.param->name);
}
fprintf(g->out, " (result i32)\n");
}
-static void codegen_func_epilogue(CodeGen*, AstNode*) {
+static void codegen_func_epilogue(CodeGen*) {
}
-static void codegen_int_expr(CodeGen* g, AstNode* ast) {
- fprintf(g->out, " i32.const %d\n", ast->node_int_value);
+static void codegen_int_expr(CodeGen* g, IntExprNode* expr) {
+ fprintf(g->out, " i32.const %d\n", expr->value);
}
-static void codegen_binary_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) {
- codegen_expr(g, ast->node_lhs, gen_mode);
- codegen_expr(g, ast->node_rhs, gen_mode);
- if (ast->node_op == TokenKind_plus) {
+static void codegen_binary_expr(CodeGen* g, BinaryExprNode* expr, GenMode gen_mode) {
+ codegen_expr(g, expr->lhs, gen_mode);
+ codegen_expr(g, expr->rhs, gen_mode);
+ if (expr->op == TokenKind_plus) {
fprintf(g->out, " i32.add\n");
- } else if (ast->node_op == TokenKind_minus) {
+ } else if (expr->op == TokenKind_minus) {
fprintf(g->out, " i32.sub\n");
- } else if (ast->node_op == TokenKind_le) {
+ } else if (expr->op == TokenKind_le) {
fprintf(g->out, " i32.le_s\n");
} else {
unreachable();
}
}
-static void codegen_lvar(CodeGen* g, AstNode* ast, GenMode) {
- fprintf(g->out, " local.get $l_%s\n", ast->name);
+static void codegen_lvar(CodeGen* g, LvarNode* lvar, GenMode) {
+ fprintf(g->out, " local.get $l_%s\n", lvar->name);
}
-static void codegen_func_call(CodeGen* g, AstNode* ast) {
- AstNode* args = ast->node_args;
- for (int i = 0; i < args->node_len; ++i) {
- AstNode* arg = args->node_items + i;
+static void codegen_func_call(CodeGen* g, FuncCallNode* call) {
+ AstNode* args = call->args;
+ for (int i = 0; i < args->as.list->len; ++i) {
+ AstNode* arg = args->as.list->items + i;
codegen_expr(g, arg, GenMode_rval);
}
- fprintf(g->out, " call $%s\n", ast->name);
+ fprintf(g->out, " call $%s\n", call->name);
}
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_binary_expr) {
- codegen_binary_expr(g, ast, gen_mode);
+ codegen_binary_expr(g, ast->as.binary_expr, gen_mode);
} else if (ast->kind == AstNodeKind_lvar) {
- codegen_lvar(g, ast, gen_mode);
+ codegen_lvar(g, ast->as.lvar, gen_mode);
} else if (ast->kind == AstNodeKind_func_call) {
- codegen_func_call(g, ast);
+ codegen_func_call(g, ast->as.func_call);
} else {
unreachable();
}
}
-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);
}
fprintf(g->out, " return\n");
}
-static void codegen_if_stmt(CodeGen* g, AstNode* ast) {
- codegen_expr(g, ast->node_cond, GenMode_rval);
+static void codegen_if_stmt(CodeGen* g, IfStmtNode* stmt) {
+ codegen_expr(g, stmt->cond, GenMode_rval);
fprintf(g->out, " (if (result i32)\n");
fprintf(g->out, " (then\n");
- codegen_stmt(g, ast->node_then);
+ codegen_stmt(g, stmt->then);
fprintf(g->out, " )\n");
- if (ast->node_else) {
+ if (stmt->else_) {
fprintf(g->out, " (else\n");
- codegen_stmt(g, ast->node_else);
+ codegen_stmt(g, stmt->else_);
fprintf(g->out, " )\n");
} else {
fprintf(g->out, " (else\n");
@@ -110,8 +110,8 @@ static void codegen_if_stmt(CodeGen* g, AstNode* ast) {
}
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);
}
}
@@ -120,9 +120,9 @@ 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_nop) {
// Do nothing.
} else {
@@ -133,11 +133,11 @@ static void codegen_stmt(CodeGen* g, AstNode* ast) {
static void codegen_func(CodeGen* g, AstNode* ast) {
g->current_func = ast;
- fprintf(g->out, "(func $%s (export \"%s\")", ast->name, ast->name);
+ fprintf(g->out, "(func $%s (export \"%s\")", ast->as.func_def->name, ast->as.func_def->name);
- codegen_func_prologue(g, ast);
- codegen_stmt(g, ast->node_body);
- codegen_func_epilogue(g, ast);
+ codegen_func_prologue(g, ast->as.func_def);
+ codegen_stmt(g, ast->as.func_def->body);
+ codegen_func_epilogue(g);
fprintf(g->out, ")\n");
g->current_func = NULL;
@@ -148,8 +148,8 @@ void codegen_wasm(Program* prog, FILE* out) {
fprintf(g->out, "(module\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);
}
diff --git a/src/parse.c b/src/parse.c
index 2818082..59ca219 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -257,11 +257,7 @@ static int add_lvar(Parser* p, const char* name, Type* ty, int stack_offset) {
static AstNode* generate_temporary_lvar(Parser* p, Type* ty) {
int stack_offset = add_lvar(p, NULL, ty, calc_lvar_stack_offset(p, ty));
- AstNode* lvar = ast_new(AstNodeKind_lvar);
- lvar->name = NULL;
- lvar->node_stack_offset = stack_offset;
- lvar->ty = ty;
- return lvar;
+ return ast_new_lvar(NULL, stack_offset, ty);
}
static int find_gvar(Parser* p, const char* name) {
@@ -283,8 +279,8 @@ static int find_func(Parser* p, const char* name) {
}
static int find_struct(Parser* p, const char* name) {
- for (int i = 0; i < p->structs->node_len; ++i) {
- if (strcmp(p->structs->node_items[i].name, name) == 0) {
+ for (int i = 0; i < p->structs->as.list->len; ++i) {
+ if (strcmp(p->structs->as.list->items[i].as.struct_def->name, name) == 0) {
return i;
}
}
@@ -292,8 +288,8 @@ static int find_struct(Parser* p, const char* name) {
}
static int find_union(Parser* p, const char* name) {
- for (int i = 0; i < p->unions->node_len; ++i) {
- if (strcmp(p->unions->node_items[i].name, name) == 0) {
+ for (int i = 0; i < p->unions->as.list->len; ++i) {
+ if (strcmp(p->unions->as.list->items[i].as.union_def->name, name) == 0) {
return i;
}
}
@@ -301,8 +297,8 @@ static int find_union(Parser* p, const char* name) {
}
static int find_enum(Parser* p, const char* name) {
- for (int i = 0; i < p->enums->node_len; ++i) {
- if (strcmp(p->enums->node_items[i].name, name) == 0) {
+ for (int i = 0; i < p->enums->as.list->len; ++i) {
+ if (strcmp(p->enums->as.list->items[i].as.enum_def->name, name) == 0) {
return i;
}
}
@@ -310,9 +306,12 @@ static int find_enum(Parser* p, const char* name) {
}
static int find_enum_member(Parser* p, const char* name) {
- for (int i = 0; i < p->enums->node_len; ++i) {
- for (int j = 0; j < p->enums->node_items[i].node_members->node_len; ++j) {
- if (strcmp(p->enums->node_items[i].node_members->node_items[j].name, name) == 0) {
+ for (int i = 0; i < p->enums->as.list->len; ++i) {
+ AstNode* members = p->enums->as.list->items[i].as.enum_def->members;
+ if (!members)
+ continue;
+ for (int j = 0; j < members->as.list->len; ++j) {
+ if (strcmp(members->as.list->items[j].as.enum_member->name, name) == 0) {
return i * 1000 + j;
}
}
@@ -321,8 +320,8 @@ static int find_enum_member(Parser* p, const char* name) {
}
static int find_typedef(Parser* p, const char* name) {
- for (int i = 0; i < p->typedefs->node_len; ++i) {
- if (strcmp(p->typedefs->node_items[i].name, name) == 0) {
+ for (int i = 0; i < p->typedefs->as.list->len; ++i) {
+ if (strcmp(p->typedefs->as.list->items[i].as.typedef_decl->name, name) == 0) {
return i;
}
}
@@ -370,10 +369,8 @@ static AstNode* parse_primary_expr(Parser* p) {
} else if (t->kind == TokenKind_keyword_false) {
return ast_new_int(0);
} else if (t->kind == TokenKind_literal_str) {
- AstNode* e = ast_new(AstNodeKind_str_expr);
- e->node_idx = register_str_literal(p, t->value.string);
- e->ty = type_new_static_string(strlen(t->value.string));
- return e;
+ return ast_new_str_expr(register_str_literal(p, t->value.string),
+ type_new_static_string(strlen(t->value.string)));
} else if (t->kind == TokenKind_paren_l) {
AstNode* e = parse_expr(p);
expect(p, TokenKind_paren_r);
@@ -382,14 +379,11 @@ static AstNode* parse_primary_expr(Parser* p) {
const char* name = t->value.string;
if (peek_token(p)->kind == TokenKind_paren_l) {
- AstNode* e = ast_new(AstNodeKind_func_call);
int func_idx = find_func(p, name);
if (func_idx == -1) {
fatal_error("%s:%d: undefined function: %s", t->loc.filename, t->loc.line, name);
}
- e->name = name;
- e->ty = p->funcs.data[func_idx].ty->result;
- return e;
+ return ast_new_func_call(name, p->funcs.data[func_idx].ty->result);
}
int lvar_idx = find_lvar(p, name);
@@ -402,30 +396,21 @@ static AstNode* parse_primary_expr(Parser* p) {
if (func_idx == -1) {
fatal_error("%s:%d: undefined variable: %s", t->loc.filename, t->loc.line, name);
}
- AstNode* e = ast_new(AstNodeKind_func);
- e->name = name;
- e->ty = p->funcs.data[func_idx].ty;
- return e;
+ return ast_new_func(name, p->funcs.data[func_idx].ty);
}
int enum_idx = enum_member_idx / 1000;
int n = enum_member_idx % 1000;
- AstNode* e = ast_new_int(p->enums->node_items[enum_idx].node_members->node_items[n].node_int_value);
+ AstNode* e = ast_new_int(
+ p->enums->as.list->items[enum_idx].as.enum_def->members->as.list->items[n].as.enum_member->value);
e->ty = type_new(TypeKind_enum);
e->ty->ref.defs = p->enums;
e->ty->ref.index = enum_idx;
return e;
}
- AstNode* e = ast_new(AstNodeKind_gvar);
- e->name = name;
- e->ty = p->gvars.data[gvar_idx].ty;
- return e;
+ return ast_new_gvar(name, p->gvars.data[gvar_idx].ty);
}
- AstNode* e = ast_new(AstNodeKind_lvar);
- e->name = name;
- e->node_stack_offset = p->lvars.data[lvar_idx].stack_offset;
- e->ty = p->lvars.data[lvar_idx].ty;
- return e;
+ return ast_new_lvar(name, p->lvars.data[lvar_idx].stack_offset, p->lvars.data[lvar_idx].ty);
} else {
fatal_error("%s:%d: expected an expression, but got '%s'", t->loc.filename, t->loc.line, token_stringify(t));
}
@@ -476,7 +461,7 @@ static AstNode* parse_postfix_expr(Parser* p) {
if (consume_token_if(p, TokenKind_paren_l)) {
AstNode* args = parse_arg_list(p);
expect(p, TokenKind_paren_r);
- ret->node_args = args;
+ ret->as.func_call->args = args;
} else if (consume_token_if(p, TokenKind_bracket_l)) {
AstNode* idx = parse_expr(p);
expect(p, TokenKind_bracket_r);
@@ -742,12 +727,7 @@ static AstNode* parse_logical_and_expr(Parser* p) {
while (1) {
if (consume_token_if(p, TokenKind_andand)) {
AstNode* rhs = parse_bitwise_or_expr(p);
- AstNode* e = ast_new(AstNodeKind_logical_expr);
- e->node_op = TokenKind_andand;
- e->node_lhs = lhs;
- e->node_rhs = rhs;
- e->ty = type_new(TypeKind_int);
- lhs = e;
+ lhs = ast_new_logical_expr(TokenKind_andand, lhs, rhs);
} else {
break;
}
@@ -760,12 +740,7 @@ static AstNode* parse_logical_or_expr(Parser* p) {
while (1) {
if (consume_token_if(p, TokenKind_oror)) {
AstNode* rhs = parse_logical_and_expr(p);
- AstNode* e = ast_new(AstNodeKind_logical_expr);
- e->node_op = TokenKind_oror;
- e->node_lhs = lhs;
- e->node_rhs = rhs;
- e->ty = type_new(TypeKind_int);
- lhs = e;
+ lhs = ast_new_logical_expr(TokenKind_oror, lhs, rhs);
} else {
break;
}
@@ -779,12 +754,7 @@ static AstNode* parse_conditional_expr(Parser* p) {
AstNode* then_expr = parse_expr(p);
expect(p, TokenKind_colon);
AstNode* else_expr = parse_assignment_expr(p);
- AstNode* ret = ast_new(AstNodeKind_cond_expr);
- ret->node_cond = e;
- ret->node_then = then_expr;
- ret->node_else = else_expr;
- ret->ty = then_expr->ty;
- return ret;
+ return ast_new_cond_expr(e, then_expr, else_expr);
} else {
return e;
}
@@ -844,15 +814,12 @@ static AstNode* parse_expr(Parser* p) {
static AstNode* parse_return_stmt(Parser* p) {
expect(p, TokenKind_keyword_return);
if (consume_token_if(p, TokenKind_semicolon)) {
- return ast_new(AstNodeKind_return_stmt);
+ return ast_new_return_stmt(NULL);
}
AstNode* expr = parse_expr(p);
expect(p, TokenKind_semicolon);
-
- AstNode* ret = ast_new(AstNodeKind_return_stmt);
- ret->node_expr = expr;
- return ret;
+ return ast_new_return_stmt(expr);
}
static AstNode* parse_if_stmt(Parser* p) {
@@ -866,11 +833,7 @@ static AstNode* parse_if_stmt(Parser* p) {
else_body = parse_stmt(p);
}
- AstNode* stmt = ast_new(AstNodeKind_if_stmt);
- stmt->node_cond = cond;
- stmt->node_then = then_body;
- stmt->node_else = else_body;
- return stmt;
+ return ast_new_if_stmt(cond, then_body, else_body);
}
// type-qualifier-list:
@@ -916,9 +879,7 @@ static AstNode* parse_declarator_or_abstract_declarator_opt(Parser* p, Type* ty)
AstNode* decl;
if (peek_token(p)->kind == TokenKind_ident) {
- decl = ast_new(AstNodeKind_declarator);
- decl->name = parse_ident(p)->value.string;
- decl->ty = ty;
+ decl = ast_new_declarator(parse_ident(p)->value.string, ty);
} else if (peek_token(p)->kind == TokenKind_paren_l && !is_type_token(p, peek_token2(p))) {
next_token(p);
if (peek_token(p)->kind == TokenKind_paren_r) {
@@ -929,8 +890,7 @@ static AstNode* parse_declarator_or_abstract_declarator_opt(Parser* p, Type* ty)
decl = parse_declarator_or_abstract_declarator_opt(p, ty);
expect(p, TokenKind_paren_r);
} else {
- decl = ast_new(AstNodeKind_declarator);
- decl->ty = ty;
+ decl = ast_new_declarator(NULL, ty);
}
while (1) {
@@ -953,9 +913,7 @@ static Type* parse_declaration_specifiers(Parser* p);
// TODO attribute-specifier-sequence? declaration-specifiers abstract-declarator?
static AstNode* parse_parameter_declaration(Parser* p) {
if (consume_token_if(p, TokenKind_ellipsis)) {
- AstNode* decl = ast_new(AstNodeKind_declarator);
- decl->name = "...";
- return decl;
+ return ast_new_declarator("...", NULL);
}
Type* base_ty = parse_declaration_specifiers(p);
@@ -987,22 +945,23 @@ static AstNode* parse_parameter_type_list(Parser* p) {
AstNode* params = parse_parameter_list(p);
bool has_void = false;
- for (int i = 0; i < params->node_len; ++i) {
- if (params->node_items[i].name && strcmp(params->node_items[i].name, "...") == 0) {
- if (i != params->node_len - 1) {
+ for (int i = 0; i < params->as.list->len; ++i) {
+ if (params->as.list->items[i].as.declarator->name &&
+ strcmp(params->as.list->items[i].as.declarator->name, "...") == 0) {
+ if (i != params->as.list->len - 1) {
fatal_error("...");
}
- --params->node_len;
+ --params->as.list->len;
break;
}
- has_void |= params->node_items[i].ty->kind == TypeKind_void;
+ has_void |= params->as.list->items[i].ty->kind == TypeKind_void;
}
if (has_void) {
- if (params->node_len != 1) {
+ if (params->as.list->len != 1) {
fatal_error("invalid use of void param");
}
- params->node_len = 0;
+ params->as.list->len = 0;
}
return params;
@@ -1057,16 +1016,13 @@ static AstNode* parse_declarator(Parser* p, Type* ty);
static AstNode* parse_direct_declarator(Parser* p, Type* ty) {
AstNode* decl;
if (peek_token(p)->kind == TokenKind_ident) {
- decl = ast_new(AstNodeKind_declarator);
- decl->name = parse_ident(p)->value.string;
- decl->ty = ty;
+ decl = ast_new_declarator(parse_ident(p)->value.string, ty);
} else if (peek_token(p)->kind == TokenKind_paren_l && !is_type_token(p, peek_token2(p))) {
next_token(p);
decl = parse_declarator(p, ty);
expect(p, TokenKind_paren_r);
} else {
- decl = ast_new(AstNodeKind_declarator);
- decl->ty = ty;
+ decl = ast_new_declarator(NULL, ty);
}
while (1) {
@@ -1079,10 +1035,7 @@ static AstNode* parse_direct_declarator(Parser* p, Type* ty) {
}
}
- AstNode* ret = ast_new(AstNodeKind_declarator);
- ret->name = decl->name;
- ret->ty = decl->ty;
- return ret;
+ return ast_new_declarator(decl->as.declarator->name, decl->ty);
}
// declarator:
@@ -1104,11 +1057,9 @@ static AstNode* parse_initializer(Parser* p) {
// declarator '=' initializer
static AstNode* parse_init_declarator(Parser* p, Type* ty) {
AstNode* decl = parse_declarator(p, ty);
- AstNode* init = NULL;
if (consume_token_if(p, TokenKind_assign)) {
- init = parse_initializer(p);
+ decl->as.declarator->init = parse_initializer(p);
}
- decl->node_init = init;
return decl;
}
@@ -1131,7 +1082,7 @@ static AstNode* parse_init_declarator_list(Parser* p, Type* ty) {
}
// Immediately declare to allow following initializer to access previous variables. For example,
// int a = 1, b = a;
- declare_func_or_var(p, &list->node_items[list->node_len - 1]);
+ declare_func_or_var(p, &list->as.list->items[list->as.list->len - 1]);
}
return list;
}
@@ -1140,7 +1091,7 @@ static AstNode* parse_var_decl(Parser* p) {
Type* base_ty = parse_type_name(p);
AstNode* decls = parse_init_declarator_list(p, base_ty);
expect(p, TokenKind_semicolon);
- declare_func_or_var(p, &decls->node_items[decls->node_len - 1]);
+ declare_func_or_var(p, &decls->as.list->items[decls->as.list->len - 1]);
return decls;
}
@@ -1155,10 +1106,10 @@ static AstNode* parse_for_stmt(Parser* p) {
if (is_type_token(p, peek_token(p))) {
AstNode* decls = parse_var_decl(p);
AstNode* initializers = ast_new_list(1);
- for (int i = 0; i < decls->node_len; i++) {
- AstNode* initializer = decls->node_items[i].node_expr;
- if (initializer) {
- ast_append(initializers, initializer);
+ for (int i = 0; i < decls->as.list->len; i++) {
+ AstNode* item = &decls->as.list->items[i];
+ if (item->kind == AstNodeKind_expr_stmt) {
+ ast_append(initializers, item->as.expr_stmt->expr);
}
}
init = initializers;
@@ -1181,13 +1132,7 @@ static AstNode* parse_for_stmt(Parser* p) {
expect(p, TokenKind_paren_r);
AstNode* body = parse_stmt(p);
leave_scope(p);
-
- AstNode* stmt = ast_new(AstNodeKind_for_stmt);
- stmt->node_cond = cond;
- stmt->node_init = init;
- stmt->node_update = update;
- stmt->node_body = body;
- return stmt;
+ return ast_new_for_stmt(init, cond, update, body);
}
static AstNode* parse_while_stmt(Parser* p) {
@@ -1196,11 +1141,7 @@ static AstNode* parse_while_stmt(Parser* p) {
AstNode* cond = parse_expr(p);
expect(p, TokenKind_paren_r);
AstNode* body = parse_stmt(p);
-
- AstNode* stmt = ast_new(AstNodeKind_for_stmt);
- stmt->node_cond = cond;
- stmt->node_body = body;
- return stmt;
+ return ast_new_for_stmt(NULL, cond, NULL, body);
}
static AstNode* parse_do_while_stmt(Parser* p) {
@@ -1212,10 +1153,7 @@ static AstNode* parse_do_while_stmt(Parser* p) {
expect(p, TokenKind_paren_r);
expect(p, TokenKind_semicolon);
- AstNode* stmt = ast_new(AstNodeKind_do_while_stmt);
- stmt->node_cond = cond;
- stmt->node_body = body;
- return stmt;
+ return ast_new_do_while_stmt(cond, body);
}
static AstNode* parse_switch_stmt(Parser* p) {
@@ -1226,15 +1164,13 @@ static AstNode* parse_switch_stmt(Parser* p) {
AstNode* tmp_var = generate_temporary_lvar(p, expr->ty);
AstNode* assignment = ast_new_assign_expr(TokenKind_assign, tmp_var, expr);
- AstNode* assign_stmt = ast_new(AstNodeKind_expr_stmt);
- assign_stmt->node_expr = assignment;
+ AstNode* assign_stmt = ast_new_expr_stmt(assignment);
- AstNode* switch_stmt = ast_new(AstNodeKind_switch_stmt);
- switch_stmt->node_expr = tmp_var;
+ AstNode* switch_stmt = ast_new_switch_stmt(tmp_var);
AstNode* prev_switch = p->current_switch;
p->current_switch = switch_stmt;
- switch_stmt->node_body = parse_stmt(p);
+ switch_stmt->as.switch_stmt->body = parse_stmt(p);
p->current_switch = prev_switch;
AstNode* list = ast_new_list(2);
@@ -1246,21 +1182,19 @@ static AstNode* parse_switch_stmt(Parser* p) {
static AstNode* parse_break_stmt(Parser* p) {
expect(p, TokenKind_keyword_break);
expect(p, TokenKind_semicolon);
- return ast_new(AstNodeKind_break_stmt);
+ return ast_new_break_stmt();
}
static AstNode* parse_continue_stmt(Parser* p) {
expect(p, TokenKind_keyword_continue);
expect(p, TokenKind_semicolon);
- return ast_new(AstNodeKind_continue_stmt);
+ return ast_new_continue_stmt();
}
static AstNode* parse_expr_stmt(Parser* p) {
AstNode* e = parse_expr(p);
expect(p, TokenKind_semicolon);
- AstNode* stmt = ast_new(AstNodeKind_expr_stmt);
- stmt->node_expr = e;
- return stmt;
+ return ast_new_expr_stmt(e);
}
static AstNode* parse_block_stmt(Parser* p) {
@@ -1278,7 +1212,7 @@ static AstNode* parse_block_stmt(Parser* p) {
static AstNode* parse_empty_stmt(Parser* p) {
consume_token_if(p, TokenKind_semicolon);
- return ast_new(AstNodeKind_nop);
+ return ast_new_nop();
}
static AstNode* parse_stmt(Parser* p) {
@@ -1293,10 +1227,7 @@ static AstNode* parse_stmt(Parser* p) {
expect(p, TokenKind_colon);
AstNode* stmt = parse_stmt(p);
- AstNode* case_label = ast_new(AstNodeKind_case_label);
- case_label->node_int_value = eval(value);
- case_label->node_body = stmt;
- return case_label;
+ return ast_new_case_label(eval(value), stmt);
} else if (t->kind == TokenKind_keyword_default) {
if (!p->current_switch) {
fatal_error("%s:%d: 'default' label not within a switch statement", t->loc.filename, t->loc.line);
@@ -1305,9 +1236,7 @@ static AstNode* parse_stmt(Parser* p) {
expect(p, TokenKind_colon);
AstNode* stmt = parse_stmt(p);
- AstNode* default_label = ast_new(AstNodeKind_default_label);
- default_label->node_body = stmt;
- return default_label;
+ return ast_new_default_label(stmt);
} else if (t->kind == TokenKind_keyword_return) {
return parse_return_stmt(p);
} else if (t->kind == TokenKind_keyword_if) {
@@ -1329,9 +1258,7 @@ static AstNode* parse_stmt(Parser* p) {
Token* label_token = expect(p, TokenKind_ident);
expect(p, TokenKind_semicolon);
- AstNode* goto_stmt = ast_new(AstNodeKind_goto_stmt);
- goto_stmt->name = label_token->value.string;
- return goto_stmt;
+ return ast_new_goto_stmt(label_token->value.string);
} else if (t->kind == TokenKind_brace_l) {
return parse_block_stmt(p);
} else if (t->kind == TokenKind_semicolon) {
@@ -1344,10 +1271,7 @@ static AstNode* parse_stmt(Parser* p) {
expect(p, TokenKind_colon);
AstNode* stmt = parse_stmt(p);
- AstNode* label_stmt = ast_new(AstNodeKind_label_stmt);
- label_stmt->name = label_token->value.string;
- label_stmt->node_body = stmt;
- return label_stmt;
+ return ast_new_label_stmt(label_token->value.string, stmt);
} else {
return parse_expr_stmt(p);
}
@@ -1357,8 +1281,8 @@ static void register_params(Parser* p, AstNode* params) {
int gp_regs = 6;
int pass_by_reg_offset = 8;
int pass_by_stack_offset = -16;
- for (int i = 0; i < params->node_len; ++i) {
- AstNode* param = &params->node_items[i];
+ for (int i = 0; i < params->as.list->len; ++i) {
+ AstNode* param = &params->as.list->items[i];
int ty_size = type_sizeof(param->ty);
int required_gp_regs;
if (ty_size <= 8) {
@@ -1381,8 +1305,12 @@ static void register_params(Parser* p, AstNode* params) {
stack_offset = pass_by_reg_offset;
pass_by_reg_offset += to_aligned(ty_size, 8);
}
- param->node_stack_offset = stack_offset;
- add_lvar(p, param->name, param->ty, stack_offset);
+ const char* name = param->as.declarator->name;
+ param->kind = AstNodeKind_param;
+ param->as.param = calloc(1, sizeof(ParamNode));
+ param->as.param->name = name;
+ param->as.param->stack_offset = stack_offset;
+ add_lvar(p, name, param->ty, stack_offset);
}
}
@@ -1393,11 +1321,12 @@ static void register_func(Parser* p, const char* name, Type* ty) {
}
static void declare_func_or_var(Parser* p, AstNode* decl) {
+ const char* name = decl->as.declarator->name;
if (decl->ty->kind == TypeKind_func) {
// TODO: refactor
decl->ty->storage_class = decl->ty->result->storage_class;
decl->ty->result->storage_class = StorageClass_unspecified;
- register_func(p, decl->name, decl->ty);
+ register_func(p, name, decl->ty);
decl->kind = AstNodeKind_func_decl;
} else {
if (type_is_unsized(decl->ty)) {
@@ -1405,26 +1334,24 @@ static void declare_func_or_var(Parser* p, AstNode* decl) {
}
if (p->scope) {
- if (find_lvar_in_current_scope(p, decl->name) != -1) {
+ if (find_lvar_in_current_scope(p, name) != -1) {
// TODO: use name's location.
- fatal_error("%s:%d: '%s' redeclared", peek_token(p)->loc.filename, peek_token(p)->loc.line, decl->name);
+ fatal_error("%s:%d: '%s' redeclared", peek_token(p)->loc.filename, peek_token(p)->loc.line, name);
}
- int stack_offset = add_lvar(p, decl->name, decl->ty, calc_lvar_stack_offset(p, decl->ty));
+ int stack_offset = add_lvar(p, name, decl->ty, calc_lvar_stack_offset(p, decl->ty));
- if (decl->node_init) {
- AstNode* lhs = ast_new(AstNodeKind_lvar);
- lhs->name = decl->name;
- lhs->node_stack_offset = stack_offset;
- lhs->ty = decl->ty;
- AstNode* assign = ast_new_assign_expr(TokenKind_assign, lhs, decl->node_init);
+ if (decl->as.declarator->init) {
+ AstNode* lhs = ast_new_lvar(name, stack_offset, decl->ty);
+ AstNode* assign = ast_new_assign_expr(TokenKind_assign, lhs, decl->as.declarator->init);
decl->kind = AstNodeKind_expr_stmt;
- decl->node_expr = assign;
+ decl->as.expr_stmt = calloc(1, sizeof(ExprStmtNode));
+ decl->as.expr_stmt->expr = assign;
} else {
decl->kind = AstNodeKind_nop;
}
} else {
- if (find_gvar(p, decl->name) != -1) {
- fatal_error("declare_func_or_var: %s redeclared", decl->name);
+ if (find_gvar(p, name) != -1) {
+ fatal_error("declare_func_or_var: %s redeclared", name);
}
// TODO: refactor
Type* base_ty = decl->ty;
@@ -1435,32 +1362,35 @@ static void declare_func_or_var(Parser* p, AstNode* decl) {
base_ty->storage_class = StorageClass_unspecified;
GlobalVar* gvar = gvars_push_new(&p->gvars);
- gvar->name = decl->name;
+ gvar->name = name;
gvar->ty = decl->ty;
if (decl->ty->storage_class == StorageClass_extern) {
decl->kind = AstNodeKind_nop;
} else {
+ AstNode* init_expr = decl->as.declarator ? decl->as.declarator->init : NULL;
decl->kind = AstNodeKind_gvar_decl;
- decl->node_expr = decl->node_init;
+ decl->as.gvar_decl = calloc(1, sizeof(GvarDeclNode));
+ decl->as.gvar_decl->name = name;
+ decl->as.gvar_decl->expr = init_expr;
}
}
}
}
static AstNode* parse_func_def(Parser* p, AstNode* decls) {
- if (decls->node_len != 1) {
+ if (decls->as.list->len != 1) {
fatal_error("parse_func_def: invalid syntax");
}
- Type* ty = decls->node_items[0].ty;
+ Type* ty = decls->as.list->items[0].ty;
Type* base_ty = ty->result;
while (base_ty->base) {
base_ty = base_ty->base;
}
ty->storage_class = base_ty->storage_class;
base_ty->storage_class = StorageClass_unspecified;
- const char* name = decls->node_items[0].name;
+ const char* name = decls->as.list->items[0].as.declarator->name;
AstNode* params = ty->params;
register_func(p, name, ty);
@@ -1469,21 +1399,14 @@ static AstNode* parse_func_def(Parser* p, AstNode* decls) {
AstNode* body = parse_block_stmt(p);
leave_func(p);
- AstNode* func = ast_new(AstNodeKind_func_def);
- func->ty = ty;
- func->name = name;
- func->node_params = params;
- func->node_body = body;
- if (p->lvars.len == 0) {
- func->node_stack_size = 0;
- } else {
- int stack_size = p->lvars.data[p->lvars.len - 1].stack_offset + type_sizeof(p->lvars.data[p->lvars.len - 1].ty);
+ int stack_size = 0;
+ if (p->lvars.len != 0) {
+ stack_size = p->lvars.data[p->lvars.len - 1].stack_offset + type_sizeof(p->lvars.data[p->lvars.len - 1].ty);
if (stack_size < 0) {
stack_size = 0;
}
- func->node_stack_size = stack_size;
}
- return func;
+ return ast_new_func_def(name, ty, params, body, stack_size);
}
// member-declarator:
@@ -1523,8 +1446,11 @@ static AstNode* parse_member_declaration(Parser* p) {
expect(p, TokenKind_semicolon);
- for (int i = 0; i < decls->node_len; i++) {
- decls->node_items[i].kind = AstNodeKind_struct_member;
+ for (int i = 0; i < decls->as.list->len; i++) {
+ const char* member_name = decls->as.list->items[i].as.declarator->name;
+ decls->as.list->items[i].kind = AstNodeKind_struct_member;
+ decls->as.list->items[i].as.struct_member = calloc(1, sizeof(StructMemberNode));
+ decls->as.list->items[i].as.struct_member->name = member_name;
}
return decls;
}
@@ -1535,44 +1461,36 @@ static AstNode* parse_member_declaration_list(Parser* p) {
AstNode* members = ast_new_list(4);
while (peek_token(p)->kind != TokenKind_brace_r) {
AstNode* decls = parse_member_declaration(p);
- for (int i = 0; i < decls->node_len; i++) {
- ast_append(members, &decls->node_items[i]);
+ for (int i = 0; i < decls->as.list->len; i++) {
+ ast_append(members, &decls->as.list->items[i]);
}
}
return members;
}
-static AstNode* parse_enum_member(Parser* p) {
+static AstNode* parse_enum_member(Parser* p, int next_value) {
const Token* name = parse_ident(p);
- AstNode* member = ast_new(AstNodeKind_enum_member);
- member->name = name->value.string;
-
+ int value;
if (consume_token_if(p, TokenKind_assign)) {
- member->node_expr = parse_constant_expression(p);
+ AstNode* expr = parse_constant_expression(p);
+ value = eval(expr);
+ } else {
+ value = next_value;
}
-
- return member;
+ return ast_new_enum_member(name->value.string, value);
}
static void parse_enum_members(Parser* p, int enum_idx) {
int next_value = 0;
AstNode* list = ast_new_list(16);
- if (!p->enums->node_items[enum_idx].node_members) {
- p->enums->node_items[enum_idx].node_members = list;
+ if (!p->enums->as.list->items[enum_idx].as.enum_def->members) {
+ p->enums->as.list->items[enum_idx].as.enum_def->members = list;
}
while (peek_token(p)->kind != TokenKind_brace_r) {
- AstNode* member = parse_enum_member(p);
-
- if (member->node_expr) {
- member->node_int_value = eval(member->node_expr);
- member->node_expr = NULL;
- next_value = member->node_int_value;
- } else {
- member->node_int_value = next_value;
- }
- ++next_value;
+ AstNode* member = parse_enum_member(p, next_value);
+ next_value = member->as.enum_member->value + 1;
ast_append(list, member);
@@ -1584,12 +1502,10 @@ static void parse_enum_members(Parser* p, int enum_idx) {
void parse_typedef_decl(Parser* p, AstNode* decls) {
expect(p, TokenKind_semicolon);
- for (int i = 0; i < decls->node_len; ++i) {
- AstNode* decl = &decls->node_items[i];
+ for (int i = 0; i < decls->as.list->len; ++i) {
+ AstNode* decl = &decls->as.list->items[i];
- AstNode* typedef_ = ast_new(AstNodeKind_typedef_decl);
- typedef_->name = decl->name;
- typedef_->ty = decl->ty;
+ AstNode* typedef_ = ast_new_typedef_decl(decl->as.declarator->name, decl->ty);
ast_append(p->typedefs, typedef_);
}
}
@@ -1629,10 +1545,9 @@ static Type* parse_struct_specifier(Parser* p) {
return ty;
} else {
// TODO
- AstNode* new_struct = ast_new(AstNodeKind_struct_def);
- new_struct->name = name->value.string;
+ AstNode* new_struct = ast_new_struct_def(name->value.string);
ast_append(p->structs, new_struct);
- struct_idx = p->structs->node_len - 1;
+ struct_idx = p->structs->as.list->len - 1;
Type* ty = type_new(TypeKind_struct);
ty->ref.defs = p->structs;
@@ -1642,20 +1557,19 @@ static Type* parse_struct_specifier(Parser* p) {
}
int struct_idx = find_struct(p, name->value.string);
- if (struct_idx != -1 && p->structs->node_items[struct_idx].node_members) {
+ if (struct_idx != -1 && p->structs->as.list->items[struct_idx].as.struct_def->members) {
fatal_error("%s:%d: struct %s redefined", name->loc.filename, name->loc.line, name->value.string);
}
if (struct_idx == -1) {
- AstNode* new_struct = ast_new(AstNodeKind_struct_def);
- new_struct->name = name->value.string;
+ AstNode* new_struct = ast_new_struct_def(name->value.string);
ast_append(p->structs, new_struct);
- struct_idx = p->structs->node_len - 1;
+ struct_idx = p->structs->as.list->len - 1;
}
AstNode* members = parse_member_declaration_list(p);
expect(p, TokenKind_brace_r);
- p->structs->node_items[struct_idx].node_members = members;
+ p->structs->as.list->items[struct_idx].as.struct_def->members = members;
Type* ty = type_new(TypeKind_struct);
ty->ref.defs = p->structs;
@@ -1692,10 +1606,9 @@ static Type* parse_union_specifier(Parser* p) {
return ty;
} else {
// TODO
- AstNode* new_union = ast_new(AstNodeKind_union_def);
- new_union->name = name->value.string;
+ AstNode* new_union = ast_new_union_def(name->value.string);
ast_append(p->unions, new_union);
- union_idx = p->unions->node_len - 1;
+ union_idx = p->unions->as.list->len - 1;
Type* ty = type_new(TypeKind_union);
ty->ref.defs = p->unions;
@@ -1705,20 +1618,19 @@ static Type* parse_union_specifier(Parser* p) {
}
int union_idx = find_union(p, name->value.string);
- if (union_idx != -1 && p->unions->node_items[union_idx].node_members) {
+ if (union_idx != -1 && p->unions->as.list->items[union_idx].as.union_def->members) {
fatal_error("%s:%d: union %s redefined", name->loc.filename, name->loc.line, name->value.string);
}
if (union_idx == -1) {
- AstNode* new_union = ast_new(AstNodeKind_union_def);
- new_union->name = name->value.string;
+ AstNode* new_union = ast_new_union_def(name->value.string);
ast_append(p->unions, new_union);
- union_idx = p->unions->node_len - 1;
+ union_idx = p->unions->as.list->len - 1;
}
AstNode* members = parse_member_declaration_list(p);
expect(p, TokenKind_brace_r);
- p->unions->node_items[union_idx].node_members = members;
+ p->unions->as.list->items[union_idx].as.union_def->members = members;
Type* ty = type_new(TypeKind_union);
ty->ref.defs = p->unions;
@@ -1755,10 +1667,9 @@ static Type* parse_enum_specifier(Parser* p) {
return ty;
} else {
// TODO
- AstNode* new_enum = ast_new(AstNodeKind_enum_def);
- new_enum->name = name->value.string;
+ AstNode* new_enum = ast_new_enum_def(name->value.string);
ast_append(p->enums, new_enum);
- enum_idx = p->enums->node_len - 1;
+ enum_idx = p->enums->as.list->len - 1;
Type* ty = type_new(TypeKind_enum);
ty->ref.defs = p->enums;
@@ -1768,15 +1679,14 @@ static Type* parse_enum_specifier(Parser* p) {
}
int enum_idx = find_enum(p, name->value.string);
- if (enum_idx != -1 && p->enums->node_items[enum_idx].node_members) {
+ if (enum_idx != -1 && p->enums->as.list->items[enum_idx].as.enum_def->members) {
fatal_error("%s:%d: enum %s redefined", name->loc.filename, name->loc.line, name->value.string);
}
if (enum_idx == -1) {
- AstNode* new_enum = ast_new(AstNodeKind_enum_def);
- new_enum->name = name->value.string;
+ AstNode* new_enum = ast_new_enum_def(name->value.string);
ast_append(p->enums, new_enum);
- enum_idx = p->enums->node_len - 1;
+ enum_idx = p->enums->as.list->len - 1;
}
parse_enum_members(p, enum_idx);
@@ -2104,7 +2014,7 @@ static Type* parse_declaration_specifiers(Parser* p) {
}
next_token(p);
int typedef_idx = find_typedef(p, tok->value.string);
- ty = p->typedefs->node_items[typedef_idx].ty;
+ ty = p->typedefs->as.list->items[typedef_idx].ty;
type_specifiers += TypeSpecifierMask_typedef_name;
}
// type-specifier-qualifier > type-qualifier
@@ -2281,7 +2191,7 @@ static Type* parse_specifier_qualifier_list(Parser* p) {
}
next_token(p);
int typedef_idx = find_typedef(p, tok->value.string);
- ty = p->typedefs->node_items[typedef_idx].ty;
+ ty = p->typedefs->as.list->items[typedef_idx].ty;
type_specifiers += TypeSpecifierMask_typedef_name;
}
// type-specifier-qualifier > type-qualifier
@@ -2348,7 +2258,7 @@ static AstNode* parse_toplevel(Parser* p) {
return NULL;
} else {
expect(p, TokenKind_semicolon);
- declare_func_or_var(p, &decls->node_items[decls->node_len - 1]);
+ declare_func_or_var(p, &decls->as.list->items[decls->as.list->len - 1]);
return decls;
}
}
@@ -2366,9 +2276,9 @@ Program* parse(TokenArray* tokens) {
} else if (n->kind == AstNodeKind_gvar_decl) {
ast_append(vars, n);
} else if (n->kind == AstNodeKind_list) {
- for (int i = 0; i < n->node_len; ++i) {
- if (n->node_items[i].kind == AstNodeKind_gvar_decl)
- ast_append(vars, &n->node_items[i]);
+ for (int i = 0; i < n->as.list->len; ++i) {
+ if (n->as.list->items[i].kind == AstNodeKind_gvar_decl)
+ ast_append(vars, &n->as.list->items[i]);
}
}
}
@@ -2379,71 +2289,79 @@ Program* parse(TokenArray* tokens) {
return prog;
}
+static int eval_binary_expr(int op, int v1, int v2) {
+ if (op == TokenKind_andand) {
+ return v1 && v2;
+ } else if (op == TokenKind_oror) {
+ return v1 || v2;
+ } else if (op == TokenKind_plus) {
+ return v1 + v2;
+ } else if (op == TokenKind_minus) {
+ return v1 - v2;
+ } else if (op == TokenKind_star) {
+ return v1 * v2;
+ } else if (op == TokenKind_slash) {
+ if (v2 == 0) {
+ fatal_error("eval: division by zero");
+ }
+ return v1 / v2;
+ } else if (op == TokenKind_percent) {
+ if (v2 == 0) {
+ fatal_error("eval: division by zero");
+ }
+ return v1 % v2;
+ } else if (op == TokenKind_eq) {
+ return v1 == v2;
+ } else if (op == TokenKind_ne) {
+ return v1 != v2;
+ } else if (op == TokenKind_lt) {
+ return v1 < v2;
+ } else if (op == TokenKind_le) {
+ return v1 <= v2;
+ } else if (op == TokenKind_lshift) {
+ return v1 << v2;
+ } else if (op == TokenKind_rshift) {
+ return v1 >> v2;
+ } else if (op == TokenKind_and) {
+ return v1 & v2;
+ } else if (op == TokenKind_or) {
+ return v1 | v2;
+ } else if (op == TokenKind_xor) {
+ return v1 ^ v2;
+ } else {
+ unimplemented();
+ }
+}
+
static int eval(AstNode* e) {
if (e->kind == AstNodeKind_int_expr) {
- return e->node_int_value;
+ return e->as.int_expr->value;
} else if (e->kind == AstNodeKind_unary_expr) {
- int v = eval(e->node_operand);
- if (e->node_op == TokenKind_not) {
+ int v = eval(e->as.unary_expr->operand);
+ if (e->as.unary_expr->op == TokenKind_not) {
return !v;
- } else if (e->node_op == TokenKind_minus) {
+ } else if (e->as.unary_expr->op == TokenKind_minus) {
return -v;
} else {
unimplemented();
}
- } else if (e->kind == AstNodeKind_binary_expr || e->kind == AstNodeKind_logical_expr) {
- int v1 = eval(e->node_lhs);
- int v2 = eval(e->node_rhs);
- if (e->node_op == TokenKind_andand) {
- return v1 && v2;
- } else if (e->node_op == TokenKind_oror) {
- return v1 || v2;
- } else if (e->node_op == TokenKind_plus) {
- return v1 + v2;
- } else if (e->node_op == TokenKind_minus) {
- return v1 - v2;
- } else if (e->node_op == TokenKind_star) {
- return v1 * v2;
- } else if (e->node_op == TokenKind_slash) {
- if (v2 == 0) {
- fatal_error("eval: division by zero");
- }
- return v1 / v2;
- } else if (e->node_op == TokenKind_percent) {
- if (v2 == 0) {
- fatal_error("eval: division by zero");
- }
- return v1 % v2;
- } else if (e->node_op == TokenKind_eq) {
- return v1 == v2;
- } else if (e->node_op == TokenKind_ne) {
- return v1 != v2;
- } else if (e->node_op == TokenKind_lt) {
- return v1 < v2;
- } else if (e->node_op == TokenKind_le) {
- return v1 <= v2;
- } else if (e->node_op == TokenKind_lshift) {
- return v1 << v2;
- } else if (e->node_op == TokenKind_rshift) {
- return v1 >> v2;
- } else if (e->node_op == TokenKind_and) {
- return v1 & v2;
- } else if (e->node_op == TokenKind_or) {
- return v1 | v2;
- } else if (e->node_op == TokenKind_xor) {
- return v1 ^ v2;
- } else {
- unimplemented();
- }
+ } else if (e->kind == AstNodeKind_binary_expr) {
+ int v1 = eval(e->as.binary_expr->lhs);
+ int v2 = eval(e->as.binary_expr->rhs);
+ return eval_binary_expr(e->as.binary_expr->op, v1, v2);
+ } else if (e->kind == AstNodeKind_logical_expr) {
+ int v1 = eval(e->as.logical_expr->lhs);
+ int v2 = eval(e->as.logical_expr->rhs);
+ return eval_binary_expr(e->as.logical_expr->op, v1, v2);
} else if (e->kind == AstNodeKind_cond_expr) {
- int cond = eval(e->node_cond);
+ int cond = eval(e->as.cond_expr->cond);
if (cond) {
- return eval(e->node_then);
+ return eval(e->as.cond_expr->then);
} else {
- return eval(e->node_else);
+ return eval(e->as.cond_expr->else_);
}
} else if (e->kind == AstNodeKind_cast_expr) {
- return eval(e->node_operand);
+ return eval(e->as.cast_expr->operand);
} else {
unimplemented();
}