summaryrefslogtreecommitdiff
path: root/codegen.c
diff options
context:
space:
mode:
authorCarson Fleming <cflems@cflems.net>2026-08-06 00:24:49 -0400
committerCarson Fleming <cflems@cflems.net>2026-08-06 00:24:49 -0400
commitb48e27f5cc31af65d8bb92d4b81cd03a60c5bcdb (patch)
tree0901fba9ff451968d758ed47b57ff99d1330fb8a /codegen.c
parenta207a7f39514f03ddfafbe39e52a3fae57a414b4 (diff)
downloadccc-b48e27f5cc31af65d8bb92d4b81cd03a60c5bcdb.tar.gz
clean up yesterday's hacks + functions in type system
Diffstat (limited to 'codegen.c')
-rw-r--r--codegen.c87
1 files changed, 42 insertions, 45 deletions
diff --git a/codegen.c b/codegen.c
index 71350e4..3950912 100644
--- a/codegen.c
+++ b/codegen.c
@@ -7,6 +7,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <stddef.h>
#define CGEN_PANIC(format, ...) {\
fprintf(\
@@ -32,7 +33,7 @@ static struct reg* MULDIV_OVERFLOW_REG = &RDX;
static struct hash_map dseg;
static struct scope* scope;
-static const struct fn_decl_node* active_fn;
+struct var_def* active_fn;
static integral_t branch_counter = 0;
static integral_t loop_counter = 0;
@@ -90,8 +91,11 @@ static const struct data_type* get_effective_data_type(
return type->data.data_type;
case TP_PTR:
return &long_long_type;
+ case TP_FN:
+ /* functions have size 1 I guess */
+ return &char_type;
}
- CGEN_PANIC("unhandled type of type case");
+ unreachable();
}
static struct lval_def allocate_stack(
@@ -132,11 +136,8 @@ static void release_temporary(FILE* outfile, const struct lval_def* tmp) {
break;
case STO_STACK:
case STO_IMM:
- case STO_FN:
case STO_LABEL:
break;
- case STO_UNRESOLVED:
- CGEN_PANIC("can't release unresolved storage");
}
}
@@ -149,9 +150,6 @@ static void emit_storage_loc(
case STO_LABEL:
fprintf(outfile, "%s", loc->label);
break;
- case STO_FN:
- fprintf(outfile, "%s", loc->decl->name);
- break;
case STO_REG:
if (sz > 4) fprintf(outfile, "%s", loc->reg->qword);
else if (sz > 2) fprintf(outfile, "%s", loc->reg->dword);
@@ -169,8 +167,6 @@ static void emit_storage_loc(
case STO_IMM:
fprintf(outfile, "0x%llx", loc->value);
break;
- case STO_UNRESOLVED:
- CGEN_PANIC("can't emit unresolved storage location");
}
}
@@ -189,12 +185,8 @@ static bool locs_equal(
return a->bp_offset == b->bp_offset;
case STO_LABEL:
return strcmp(a->label, b->label) == 0;
- case STO_FN:
- return a->decl == b->decl;
- case STO_UNRESOLVED:
- return false;
}
- CGEN_PANIC("unhandled storage type case");
+ unreachable();
}
static void emit_size_const(FILE* outfile, integral_t sz) {
@@ -253,10 +245,8 @@ static void emit_label_lea(
if (spill_reg) unspill_register(outfile, tmp_reg);
else release_register(tmp_reg);
return;
- case STO_FN:
case STO_IMM:
case STO_LABEL:
- case STO_UNRESOLVED:
CGEN_PANIC("can't load label address into non-value storage");
}
}
@@ -331,9 +321,7 @@ static void emit_mov(
break;
case STO_LABEL:
case STO_IMM:
- case STO_FN:
- case STO_UNRESOLVED:
- CGEN_PANIC("can't move value into storage type");
+ CGEN_PANIC("can't move value into non-storage type");
}
fprintf(outfile, "\n");
}
@@ -351,9 +339,7 @@ static void emit_cmp_zero(FILE* outfile, const struct lval_def* lval) {
break;
case STO_LABEL:
case STO_IMM:
- case STO_FN:
- case STO_UNRESOLVED:
- CGEN_PANIC("can't compare this storage type")
+ CGEN_PANIC("can't compare this non-storage type")
}
fprintf(outfile, ", 0\n");
}
@@ -427,7 +413,7 @@ static void emit_var_ref(
const struct lval_def* dst
) {
if (dst != NULL) {
- emit_mov(outfile, dst, &node->def_ref->loc);
+ emit_mov(outfile, dst, &node->def_ref->storage);
}
}
@@ -439,7 +425,7 @@ static void emit_decl(
) {
struct lval_def var_dst =
allocate_stack(outfile, node->def_ref->type);
- node->def_ref->loc = var_dst.loc;
+ node->def_ref->storage = var_dst.loc;
fprintf(outfile, "\t; %s\n", node->def_ref->name);
@@ -468,7 +454,7 @@ static void emit_assignment(
struct var_ref_node* var_ref = &node->lval->inner.var_ref;
lval_def = (struct lval_def) {
.type = var_ref->def_ref->type,
- .loc = var_ref->def_ref->loc,
+ .loc = var_ref->def_ref->storage,
};
break;
default:
@@ -532,10 +518,14 @@ static void emit_call(
}
/* 3. `call <label>` */
- fprintf(outfile, "\tcall %s", node->fn_ref->name);
- // TODO: this is kinda fukt we should probably keep an
- // internal/external flag in the storage loc instead
- if (node->fn_ref->body == NULL) fprintf(outfile, " WRT ..plt");
+ /* TODO: support function pointers */
+ if (node->expr->type != EXPR_VAR_REF)
+ CGEN_PANIC("function pointers are not supported");
+ const struct var_def* fn_def = node->expr->inner.var_ref.def_ref;
+ fprintf(outfile, "\tcall ");
+ emit_storage_loc(outfile, &fn_def->storage, 0);
+ /* TODO: this could be a part of emit_storage_loc for labels */
+ if (!fn_def->fn.resolved) fprintf(outfile, " WRT ..plt");
fprintf(outfile, "\n");
/* 4. `mov dst, rax` */
@@ -732,7 +722,7 @@ static void emit_return(FILE* outfile, const struct return_node* node) {
outfile,
node->ret_val,
&(struct lval_def) {
- .type = &active_fn->return_type,
+ .type = active_fn->type->fn.return_type,
.loc = {
.type = STO_REG,
.reg = RV_REG,
@@ -849,21 +839,24 @@ static void emit_stmt(FILE* outfile, const struct stmt_node* node) {
}
static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) {
- if (node->body == NULL) return;
+ if (!scope_get_var(scope, &active_fn, node->name))
+ CGEN_PANIC("scopes are borked, missing symbol: '%s'", node->name);
- if (active_fn != NULL)
- CGEN_PANIC(
- "can't define function %s inside function %s",
- node->name,
- active_fn->name);
- active_fn = node;
+ const char* label = node->name;
+ active_fn->storage = (struct storage_location) {
+ .type = STO_LABEL,
+ .label = label,
+ };
- /* TODO: we need to account for the base pointer moving in var locs */
- fprintf(outfile, "%s:\n", node->name);
- fprintf(outfile, "\tpush rbp\n");
- fprintf(outfile, "\tmov rbp, rsp\n");
+ if (node->body == NULL) {
+ active_fn = NULL;
+ return;
+ }
enter_scope(node->scope, 0);
+ fprintf(outfile, "%s:\n", label);
+ fprintf(outfile, "\tpush rbp\n");
+ fprintf(outfile, "\tmov rbp, rsp\n");
sintegral_t spilled_bp_ofs = -16; // return address + spilled rbp
struct arg_decl_node* arg_decl = node->args;
@@ -872,7 +865,7 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) {
fprintf(outfile, "\t; %s\n", arg_def->name);
struct lval_def arg_dst =
allocate_stack(outfile, arg_def->type);
- arg_def->loc = arg_dst.loc;
+ arg_def->storage = arg_dst.loc;
struct storage_location arg_src;
if (CALLING_CONV[i] != NULL) {
@@ -900,8 +893,8 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) {
fprintf(outfile, "\tpop rbp\n");
fprintf(outfile, "\tret\n");
- active_fn = NULL;
exit_scope(node->scope, false);
+ active_fn = NULL;
}
static void emit_root_node(FILE* outfile, const struct root_node* node) {
@@ -924,7 +917,11 @@ void emit_code(struct ast* ast, const char* path) {
for (; node != NULL; node = node->next) {
if (node->type != ROOT_FN_DECL) continue;
const struct fn_decl_node* fn = &node->inner.fn_decl;
- if (fn->body != NULL)
+ struct var_def* fn_def;
+ if (!scope_get_var(scope, &fn_def, fn->name))
+ CGEN_PANIC("use of undeclared function '%s'", fn->name);
+
+ if (fn_def->fn.resolved)
fprintf(outfile, "global %s\n", fn->name);
else
fprintf(outfile, "extern %s\n", fn->name);