summaryrefslogtreecommitdiff
path: root/codegen.c
diff options
context:
space:
mode:
authorCarson Fleming <cflems@cflems.net>2026-07-29 23:35:15 -0400
committerCarson Fleming <cflems@cflems.net>2026-07-29 23:35:15 -0400
commit29510d33cab6e86b28b12c6246bca58acdab26e2 (patch)
tree8513245e730aa68fb119e88932ab658fea1dc169 /codegen.c
parent4f9d0247549b06ddb25b76bb425541190105cb48 (diff)
downloadccc-29510d33cab6e86b28b12c6246bca58acdab26e2.tar.gz
support for comma-separated expression lists where valid
Diffstat (limited to 'codegen.c')
-rw-r--r--codegen.c100
1 files changed, 52 insertions, 48 deletions
diff --git a/codegen.c b/codegen.c
index d274fb7..6d55d2c 100644
--- a/codegen.c
+++ b/codegen.c
@@ -311,9 +311,9 @@ static void emit_var_ref(
static void emit_stmt(FILE* outfile, const struct stmt_node* node);
-static void emit_var_decl(
+static void emit_decl(
FILE* outfile,
- const struct var_decl_node* node
+ const struct decl_node* node
) {
struct lval_def var_dst =
allocate_stack(outfile, node->def_ref->type);
@@ -328,6 +328,16 @@ static void emit_var_decl(
emit_expr(outfile, node->initial_value, &var_dst);
}
+static void emit_decl_list(
+ FILE* outfile,
+ const struct decl_list_node* node
+) {
+ for (const struct decl_node* cur = node->head;
+ cur != NULL;
+ cur = cur->next)
+ emit_decl(outfile, cur);
+}
+
static void emit_assignment(
FILE* outfile,
const struct assign_node* node,
@@ -357,31 +367,21 @@ static void emit_call(
integral_t orig_bp_offset = scope->bp_offset;
integral_t arg_bp_offset = orig_bp_offset;
- struct decl_list_node* arg_decl = node->called_fn_ref->args;
+ struct arg_decl_node* arg_decl = node->fn_ref->args;
struct expr_list_node* arg_eval = node->args;
while (arg_decl != NULL && arg_eval != NULL) {
struct lval_def arg_dst =
- allocate_stack(outfile, arg_decl->decl->def_ref->type);
+ allocate_stack(outfile, arg_decl->def_ref->type);
emit_expr(outfile, arg_eval->expr, &arg_dst);
arg_decl = arg_decl->next;
arg_eval = arg_eval->next;
}
- if (arg_decl != NULL)
- CGEN_PANIC(
- "too many arguments to function %s",
- node->called_fn_ref->name);
- if (arg_eval != NULL)
- CGEN_PANIC(
- "missing arguments to function %s",
- node->called_fn_ref->name);
-
unsigned char arg_regnum = 0;
- arg_decl = node->called_fn_ref->args;
+ arg_decl = node->fn_ref->args;
while (arg_decl != NULL) {
- const struct type* arg_type =
- arg_decl->decl->def_ref->type;
+ const struct type* arg_type = arg_decl->def_ref->type;
arg_bp_offset += get_effective_data_type(arg_type)->sz;
struct lval_def arg_dst;
@@ -405,10 +405,10 @@ static void emit_call(
arg_decl = arg_decl->next;
}
- fprintf(outfile, "\tcall %s\n", node->called_fn_ref->name);
+ fprintf(outfile, "\tcall %s\n", node->fn_ref->name);
if (dst != NULL) {
if (get_effective_data_type(
- &node->called_fn_ref->return_type) == &void_type)
+ &node->fn_ref->return_type) == &void_type)
CGEN_PANIC("can't assign the result of a void function");
emit_mov(outfile, dst, &RV_LOC);
@@ -506,6 +506,23 @@ static void emit_binary(
deallocate_temporary(outfile, &rhs_dst);
}
+static void emit_expr_list(
+ FILE* outfile,
+ const struct expr_list_node* node,
+ const struct lval_def* dst
+) {
+ for (; node != NULL; node = node->next)
+ emit_expr(outfile, node->expr, node->next == NULL ? dst : NULL);
+}
+
+static void emit_paren(
+ FILE* outfile,
+ const struct paren_node* node,
+ const struct lval_def* dst
+) {
+ emit_expr_list(outfile, node->expr_list, dst);
+}
+
static void emit_expr(
FILE* outfile,
const struct expr_node* node,
@@ -539,30 +556,22 @@ static void emit_expr(
case EXPR_BINARY:
emit_binary(outfile, &node->inner.binary, dst);
break;
+ case EXPR_PAREN:
+ emit_paren(outfile, &node->inner.paren, dst);
+ break;
}
}
static void emit_return(FILE* outfile, const struct return_node* node) {
if (active_fn == NULL) CGEN_PANIC("must be inside a function to return");
- bool is_void_fn =
- get_effective_data_type(&active_fn->return_type) == &void_type;
-
- if (node->ret_val != NULL) {
- if (is_void_fn)
- CGEN_PANIC(
- "returning a value from void function %s", active_fn->name);
-
- emit_expr(
+ if (node->ret_val != NULL)
+ emit_expr_list(
outfile,
node->ret_val,
&(struct lval_def) {
.loc = RV_LOC,
.type = &active_fn->return_type,
});
- } else if (!is_void_fn) {
- CGEN_PANIC(
- "non-void function %s should return a value", active_fn->name);
- }
fprintf(outfile, "\tjmp " RETURN_LABEL_FMT "\n", active_fn->name);
}
@@ -590,7 +599,7 @@ static void emit_if(FILE* outfile, const struct if_node* node) {
struct lval_def cond_result =
allocate_temporary(outfile, node->cond->resolved_type);
- emit_expr(outfile, node->cond, &cond_result);
+ emit_expr_list(outfile, node->cond, &cond_result);
emit_cmp_zero(outfile, &cond_result);
integral_t branch_num = ++branch_counter;
@@ -609,18 +618,13 @@ static void emit_if(FILE* outfile, const struct if_node* node) {
exit_scope(node->scope, true);
}
-static void emit_expr_list(FILE* outfile, const struct expr_list_node* node) {
- for (; node != NULL; node = node->next)
- emit_expr(outfile, node->expr, NULL);
-}
-
static void emit_loop_init(FILE* outfile, const struct loop_init_node* node) {
switch (node->type) {
case INIT_EXPR_LIST:
- emit_expr_list(outfile, node->expr_list);
+ emit_expr_list(outfile, node->expr_list, NULL);
break;
- case INIT_DECL:
- emit_var_decl(outfile, node->decl);
+ case INIT_DECL_LIST:
+ emit_decl_list(outfile, node->decl_list);
break;
}
}
@@ -635,7 +639,7 @@ static void emit_loop(FILE* outfile, const struct loop_node* node) {
struct lval_def cond_dst =
allocate_temporary(outfile, node->cond->resolved_type);
fprintf(outfile, "loop_head@%lld:\n", loop_num);
- emit_expr(outfile, node->cond, &cond_dst);
+ emit_expr_list(outfile, node->cond, &cond_dst);
emit_cmp_zero(outfile, &cond_dst);
fprintf(outfile, "\tjz loop_done@%lld\n", loop_num);
} else {
@@ -643,7 +647,7 @@ static void emit_loop(FILE* outfile, const struct loop_node* node) {
}
emit_stmt(outfile, node->body);
- if (node->incr != NULL) emit_expr(outfile, node->incr, NULL);
+ if (node->incr != NULL) emit_expr_list(outfile, node->incr, NULL);
fprintf(outfile, "\tjmp loop_head@%lld\n", loop_num);
fprintf(outfile, "loop_done@%lld:\n", loop_num);
@@ -655,14 +659,14 @@ static void emit_stmt(FILE* outfile, const struct stmt_node* node) {
switch (node->type) {
case STMT_EMPTY:
break;
- case STMT_VAR_DECL:
- emit_var_decl(outfile, &node->inner.var_decl);
+ case STMT_DECL_LIST:
+ emit_decl_list(outfile, &node->inner.decl_list);
break;
case STMT_RETURN:
emit_return(outfile, &node->inner.return_);
break;
- case STMT_EXPR:
- emit_expr(outfile, &node->inner.expr, NULL);
+ case STMT_EXPR_LIST:
+ emit_expr_list(outfile, &node->inner.expr_list, NULL);
break;
case STMT_GROUP:
emit_group(outfile, &node->inner.group);
@@ -695,9 +699,9 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) {
long long spilled_bp_ofs = -16; // return address + old bp
unsigned char arg_regnum = 0;
- struct decl_list_node* arg_decl = node->args;
+ struct arg_decl_node* arg_decl = node->args;
for (; arg_decl != NULL; arg_decl = arg_decl->next) {
- struct var_def* arg_def = arg_decl->decl->def_ref;
+ struct var_def* arg_def = arg_decl->def_ref;
struct lval_def arg_dst =
allocate_stack(outfile, arg_def->type);
arg_def->loc = arg_dst.loc;