diff options
| author | Carson Fleming <cflems@cflems.net> | 2026-07-29 23:35:15 -0400 |
|---|---|---|
| committer | Carson Fleming <cflems@cflems.net> | 2026-07-29 23:35:15 -0400 |
| commit | 29510d33cab6e86b28b12c6246bca58acdab26e2 (patch) | |
| tree | 8513245e730aa68fb119e88932ab658fea1dc169 /codegen.c | |
| parent | 4f9d0247549b06ddb25b76bb425541190105cb48 (diff) | |
| download | ccc-29510d33cab6e86b28b12c6246bca58acdab26e2.tar.gz | |
support for comma-separated expression lists where valid
Diffstat (limited to 'codegen.c')
| -rw-r--r-- | codegen.c | 100 |
1 files changed, 52 insertions, 48 deletions
@@ -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; |
