summaryrefslogtreecommitdiff
path: root/codegen.c
diff options
context:
space:
mode:
authorCarson Fleming <cflems@cflems.net>2026-07-26 19:20:30 -0700
committerCarson Fleming <cflems@cflems.net>2026-07-26 19:20:30 -0700
commit4f9d0247549b06ddb25b76bb425541190105cb48 (patch)
tree56f191c3611fc7509e6350138ce03c20956b656f /codegen.c
parent6a169de321b131e73b86967a1a8564365217275a (diff)
downloadccc-4f9d0247549b06ddb25b76bb425541190105cb48.tar.gz
functioning type system perhaps?
Diffstat (limited to 'codegen.c')
-rw-r--r--codegen.c110
1 files changed, 65 insertions, 45 deletions
diff --git a/codegen.c b/codegen.c
index 019baf0..d274fb7 100644
--- a/codegen.c
+++ b/codegen.c
@@ -15,7 +15,7 @@
}
struct lval_def {
- const struct type_def* type;
+ const struct type* type;
struct storage_location loc;
};
@@ -57,7 +57,7 @@ static void exit_scope(struct scope* child_scope, bool save_bp_offset) {
if (save_bp_offset) scope->bp_offset = child_scope->bp_offset;
}
-static struct lval_def allocate_register(const struct type_def* type) {
+static struct lval_def allocate_register(const struct type* type) {
return (struct lval_def) {
.loc = {
.type = STO_REG,
@@ -67,12 +67,25 @@ static struct lval_def allocate_register(const struct type_def* type) {
};
}
+static const struct data_type* get_effective_data_type(
+ const struct type* type
+) {
+ switch (type->type) {
+ case TP_DATA:
+ return type->data.data_type;
+ case TP_PTR:
+ return &long_long_type;
+ }
+ CGEN_PANIC("unhandled type of type case");
+}
+
static struct lval_def allocate_stack(
FILE* outfile,
- const struct type_def* type
+ const struct type* type
) {
- fprintf(outfile, "\tsub rsp, %llu\n", type->sz);
- scope->bp_offset += type->sz;
+ integral_t type_sz = get_effective_data_type(type)->sz;
+ fprintf(outfile, "\tsub rsp, %llu\n", type_sz);
+ scope->bp_offset += type_sz;
return (struct lval_def) {
.loc = {
.type = STO_STACK,
@@ -84,15 +97,18 @@ static struct lval_def allocate_stack(
static struct lval_def allocate_temporary(
FILE* outfile,
- const struct type_def* type
+ const struct type* type
) {
return allocate_stack(outfile, type);
}
static void deallocate_temporary(FILE* outfile, const struct lval_def* tmp) {
if (tmp->loc.type == STO_STACK) {
- fprintf(outfile, "\tadd rsp, %llu\n", tmp->type->sz);
- scope->bp_offset -= tmp->type->sz;
+ integral_t type_sz = get_effective_data_type(tmp->type)->sz;
+ fprintf(outfile, "\tadd rsp, %llu\n", type_sz);
+ scope->bp_offset -= type_sz;
+ } else if (tmp->loc.type == STO_REG) {
+ /* TOOD: release the register back to the algo */
}
}
@@ -168,18 +184,19 @@ static void emit_mov(
/* first optimization: if dst == src, emit nothing */
if (locs_equal(&dst->loc, src)) return;
+ integral_t dst_sz = get_effective_data_type(dst->type)->sz;
switch (dst->loc.type) {
case STO_REG:
- if (src->type == STO_REG && dst->type->sz < 4) {
+ if (src->type == STO_REG && dst_sz < 4) {
fprintf(outfile, "\tmovzx ");
emit_storage_loc(outfile, &dst->loc, FULL_REG_SZ);
} else {
fprintf(outfile, "\tmov ");
- emit_storage_loc(outfile, &dst->loc, dst->type->sz);
+ emit_storage_loc(outfile, &dst->loc, dst_sz);
}
fprintf(outfile, ", ");
- emit_storage_loc(outfile, src, dst->type->sz);
+ emit_storage_loc(outfile, src, dst_sz);
break;
case STO_STACK:
if (src->type == STO_STACK) {
@@ -191,11 +208,11 @@ static void emit_mov(
}
fprintf(outfile, "\tmov ");
- if (src->type == STO_IMM) emit_size_const(outfile, dst->type->sz);
+ if (src->type == STO_IMM) emit_size_const(outfile, dst_sz);
- emit_storage_loc(outfile, &dst->loc, dst->type->sz);
+ emit_storage_loc(outfile, &dst->loc, dst_sz);
fprintf(outfile, ", ");
- emit_storage_loc(outfile, src, dst->type->sz);
+ emit_storage_loc(outfile, src, dst_sz);
break;
case STO_LABEL:
case STO_IMM:
@@ -208,13 +225,14 @@ static void emit_mov(
static void emit_cmp_zero(FILE* outfile, const struct lval_def* lval) {
fprintf(outfile, "\tcmp ");
+ integral_t type_sz = get_effective_data_type(lval->type)->sz;
switch (lval->loc.type) {
case STO_REG:
- emit_storage_loc(outfile, &lval->loc, lval->type->sz);
+ emit_storage_loc(outfile, &lval->loc, type_sz);
break;
case STO_STACK:
- emit_size_const(outfile, lval->type->sz);
- emit_storage_loc(outfile, &lval->loc, lval->type->sz);
+ emit_size_const(outfile, type_sz);
+ emit_storage_loc(outfile, &lval->loc, type_sz);
break;
case STO_LABEL:
case STO_IMM:
@@ -225,13 +243,6 @@ static void emit_cmp_zero(FILE* outfile, const struct lval_def* lval) {
fprintf(outfile, ", 0\n");
}
-static inline struct lval_def make_stack_lval(
- FILE* outfile,
- const struct type_def* type
-) {
- return allocate_stack(outfile, type);
-}
-
static void emit_expr(
FILE* outfile,
const struct expr_node* node,
@@ -305,11 +316,12 @@ static void emit_var_decl(
const struct var_decl_node* node
) {
struct lval_def var_dst =
- make_stack_lval(outfile, node->def_ref->resolved_type);
+ allocate_stack(outfile, node->def_ref->type);
node->def_ref->loc = var_dst.loc;
fprintf(outfile, "\t; '%s' lives in: ", node->def_ref->name);
- emit_storage_loc(outfile, &var_dst.loc, var_dst.type->sz);
+ integral_t dst_sz = get_effective_data_type(var_dst.type)->sz;
+ emit_storage_loc(outfile, &var_dst.loc, dst_sz);
fprintf(outfile, "\n");
if (node->initial_value != NULL)
@@ -326,7 +338,7 @@ static void emit_assignment(
case EXPR_VAR_REF:
struct var_ref_node* var_ref = &node->lval->inner.var_ref;
lval_def = (struct lval_def) {
- .type = var_ref->def_ref->resolved_type,
+ .type = var_ref->def_ref->type,
.loc = var_ref->def_ref->loc,
};
break;
@@ -349,7 +361,7 @@ static void emit_call(
struct expr_list_node* arg_eval = node->args;
while (arg_decl != NULL && arg_eval != NULL) {
struct lval_def arg_dst =
- make_stack_lval(outfile, arg_decl->decl->def_ref->resolved_type);
+ allocate_stack(outfile, arg_decl->decl->def_ref->type);
emit_expr(outfile, arg_eval->expr, &arg_dst);
arg_decl = arg_decl->next;
@@ -368,11 +380,13 @@ static void emit_call(
unsigned char arg_regnum = 0;
arg_decl = node->called_fn_ref->args;
while (arg_decl != NULL) {
- const struct type_def* arg_type =
- arg_decl->decl->def_ref->resolved_type;
- arg_bp_offset += arg_type->sz;
+ const struct type* arg_type =
+ arg_decl->decl->def_ref->type;
+ arg_bp_offset += get_effective_data_type(arg_type)->sz;
struct lval_def arg_dst;
+ /* TODO: if the convention register is used,
+ * will need to spill the current value */
if (arg_regnum < CC_N_REGS)
arg_dst = (struct lval_def) {
.type = arg_type,
@@ -382,7 +396,7 @@ static void emit_call(
},
};
else
- arg_dst = make_stack_lval(outfile, arg_type);
+ arg_dst = allocate_stack(outfile, arg_type);
emit_mov(outfile, &arg_dst, &(struct storage_location) {
.type = STO_STACK,
@@ -393,7 +407,8 @@ static void emit_call(
fprintf(outfile, "\tcall %s\n", node->called_fn_ref->name);
if (dst != NULL) {
- if (node->called_fn_ref->resolved_return_type->sz == 0)
+ if (get_effective_data_type(
+ &node->called_fn_ref->return_type) == &void_type)
CGEN_PANIC("can't assign the result of a void function");
emit_mov(outfile, dst, &RV_LOC);
@@ -415,14 +430,15 @@ static void emit_unary(
emit_expr(outfile, node->expr, dst);
if (dst == NULL) return;
+ integral_t dst_sz = get_effective_data_type(dst->type)->sz;
switch (node->op) {
case UNARY_NEG:
fprintf(outfile, "\tneg ");
if (dst->loc.type == STO_STACK)
- emit_size_const(outfile, dst->type->sz);
+ emit_size_const(outfile, dst_sz);
- emit_storage_loc(outfile, &dst->loc, dst->type->sz);
+ emit_storage_loc(outfile, &dst->loc, dst_sz);
fprintf(outfile, "\n");
break;
}
@@ -449,21 +465,22 @@ static void emit_binary(
};
emit_expr(outfile, node->lhs, &lhs_dst);
+ integral_t dst_sz = get_effective_data_type(dst->type)->sz;
switch (node->op) {
case BINARY_ADD:
fprintf(outfile, "\tadd ");
- emit_storage_loc(outfile, &lhs_dst.loc, dst->type->sz);
+ emit_storage_loc(outfile, &lhs_dst.loc, dst_sz);
fprintf(outfile, ", ");
break;
case BINARY_SUB:
fprintf(outfile, "\tsub ");
- emit_storage_loc(outfile, &lhs_dst.loc, dst->type->sz);
+ emit_storage_loc(outfile, &lhs_dst.loc, dst_sz);
fprintf(outfile, ", ");
break;
case BINARY_MUL:
fprintf(outfile, "\timul ");
if (rhs_dst.loc.type == STO_STACK)
- emit_size_const(outfile, dst->type->sz);
+ emit_size_const(outfile, dst_sz);
break;
case BINARY_DIV:
/* nothing in the top half reg */
@@ -475,11 +492,11 @@ static void emit_binary(
fprintf(outfile, "\tidiv ");
if (rhs_dst.loc.type == STO_STACK)
- emit_size_const(outfile, dst->type->sz);
+ emit_size_const(outfile, dst_sz);
break;
}
- emit_storage_loc(outfile, &rhs_dst.loc, dst->type->sz);
+ emit_storage_loc(outfile, &rhs_dst.loc, dst_sz);
fprintf(outfile, "\n");
/* TODO: deal with RDX overflow shit for imul and idiv */
@@ -527,9 +544,11 @@ static void emit_expr(
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 (active_fn->resolved_return_type->sz == 0)
+ if (is_void_fn)
CGEN_PANIC(
"returning a value from void function %s", active_fn->name);
@@ -538,9 +557,9 @@ static void emit_return(FILE* outfile, const struct return_node* node) {
node->ret_val,
&(struct lval_def) {
.loc = RV_LOC,
- .type = active_fn->resolved_return_type,
+ .type = &active_fn->return_type,
});
- } else if (active_fn->resolved_return_type > 0) {
+ } else if (!is_void_fn) {
CGEN_PANIC(
"non-void function %s should return a value", active_fn->name);
}
@@ -680,7 +699,7 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) {
for (; arg_decl != NULL; arg_decl = arg_decl->next) {
struct var_def* arg_def = arg_decl->decl->def_ref;
struct lval_def arg_dst =
- make_stack_lval(outfile, arg_def->resolved_type);
+ allocate_stack(outfile, arg_def->type);
arg_def->loc = arg_dst.loc;
struct storage_location arg_src;
@@ -694,7 +713,8 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) {
.type = STO_STACK,
.bp_offset = spilled_bp_ofs,
};
- spilled_bp_ofs -= arg_def->resolved_type->sz;
+ integral_t arg_sz = get_effective_data_type(arg_def->type)->sz;
+ spilled_bp_ofs -= arg_sz;
}
emit_mov(outfile, &arg_dst, &arg_src);
}