From a207a7f39514f03ddfafbe39e52a3fae57a414b4 Mon Sep 17 00:00:00 2001 From: Carson Fleming Date: Wed, 5 Aug 2026 01:05:22 -0400 Subject: got hello world working with some hacks --- codegen.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 14 deletions(-) (limited to 'codegen.c') diff --git a/codegen.c b/codegen.c index bca0411..71350e4 100644 --- a/codegen.c +++ b/codegen.c @@ -28,6 +28,7 @@ static struct reg* MULDIV_OVERFLOW_REG = &RDX; #define RETURN_LABEL_FMT "%s@ret" #define FULL_REG_SZ 8 #define WORD_SZ 2 +#define STACK_ALIGNMENT 16 static struct hash_map dseg; static struct scope* scope; @@ -203,6 +204,63 @@ static void emit_size_const(FILE* outfile, integral_t sz) { else fprintf(outfile, "byte "); } +static void emit_mov( + FILE* outfile, + const struct lval_def* dst, + const struct storage_location* src); + +static void emit_label_lea( + FILE* outfile, + const struct lval_def* dst, + const char* label +) { + integral_t dst_sz = get_effective_data_type(dst->type)->sz; + if (dst_sz < FULL_REG_SZ) + CGEN_PANIC("can't load label address into an undersized type"); + + switch (dst->loc.type) { + case STO_REG: + fprintf(outfile, "\tlea "); + emit_storage_loc(outfile, &dst->loc, FULL_REG_SZ); + fprintf(outfile, ", [rel %s]\n", label); + return; + case STO_STACK: + struct reg* tmp_reg = allocate_register(); + bool spill_reg = tmp_reg == NULL; + if (spill_reg) { + tmp_reg = &RBX; + spill_register(outfile, tmp_reg); + } + + emit_label_lea( + outfile, + &(struct lval_def) { + .type = dst->type, + .loc = { + .type = STO_REG, + .reg = tmp_reg, + } + }, + label); + emit_mov( + outfile, + dst, + &(struct storage_location) { + .type = STO_REG, + .reg = tmp_reg, + }); + + 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"); + } +} + static void emit_mov( FILE* outfile, const struct lval_def* dst, @@ -210,6 +268,9 @@ static void emit_mov( ) { /* first optimization: if dst == src, emit nothing */ if (locs_equal(&dst->loc, src)) return; + /* use lea's on label sources to support relative addressing */ + if (src->type == STO_LABEL) + return emit_label_lea(outfile, dst, src->label); integral_t dst_sz = get_effective_data_type(dst->type)->sz; switch (dst->loc.type) { @@ -242,8 +303,8 @@ static void emit_mov( struct reg* tmp_reg = allocate_register(); bool spill_reg = tmp_reg == NULL; if (spill_reg) { - spill_register(outfile, &RCX); tmp_reg = &RCX; + spill_register(outfile, tmp_reg); } struct lval_def tmp = { @@ -256,7 +317,7 @@ static void emit_mov( emit_mov(outfile, &tmp, src); emit_mov(outfile, dst, &tmp.loc); - if (spill_reg) unspill_register(outfile, &RCX); + if (spill_reg) unspill_register(outfile, tmp_reg); else release_register(tmp_reg); return; } @@ -417,6 +478,7 @@ static void emit_assignment( if (dst != NULL) emit_mov(outfile, dst, &lval_def.loc); } +/* TODO: could eventually allocate all space ahead of time instead of repeated sub's */ static integral_t push_stack_args(FILE* outfile, struct expr_list_node* arg) { if (arg == NULL) return 0; @@ -435,8 +497,9 @@ static void emit_call( const struct call_node* node, const struct lval_def* dst ) { - /* 1. spill all existing data registers besides dst */ - const struct reg* dst_reg = dst->loc.type == STO_REG ? dst->loc.reg : NULL; + /* 1. spill all existing data registers besides dst if applicable */ + const struct reg* dst_reg = (dst != NULL && dst->loc.type == STO_REG) + ? dst->loc.reg : NULL; integral_t reg_occupied = 0, n_data_regs = 0; for (; DATA_REGS[n_data_regs] != NULL; n_data_regs++) { if (!DATA_REGS[n_data_regs]->is_occupied) continue; @@ -461,19 +524,30 @@ static void emit_call( }); } integral_t arg_stack_space = push_stack_args(outfile, arg); + integral_t stack_misalignment = + STACK_ALIGNMENT - (scope->bp_offset % STACK_ALIGNMENT); + if (stack_misalignment > 0) { + fprintf(outfile, "\tsub rsp, 0x%llx\n", stack_misalignment); + arg_stack_space += stack_misalignment; + } /* 3. `call