diff options
| author | Carson Fleming <cflems@cflems.net> | 2026-03-28 08:04:48 -1000 |
|---|---|---|
| committer | Carson Fleming <cflems@cflems.net> | 2026-03-28 08:04:48 -1000 |
| commit | 55929c155f929a886a0fe72c1c16a7913830350a (patch) | |
| tree | 13482c2822661d8a0ff33369c6856aabe163e2a2 | |
| parent | ee85f90edd17d9c3fadc0d118021c18a5bb8463c (diff) | |
| download | ccc-55929c155f929a886a0fe72c1c16a7913830350a.tar.gz | |
robust mov situation
| -rw-r--r-- | codegen.c | 87 | ||||
| -rw-r--r-- | scope.h | 6 |
2 files changed, 62 insertions, 31 deletions
@@ -30,7 +30,6 @@ static void emit_storage_loc( case REGISTER: if (sz > 4) fprintf(outfile, "%s", loc->reg->qword); else if (sz > 2) fprintf(outfile, "%s", loc->reg->dword); - // TODO: for word and byte make sure moving into these zeroes the high register else if (sz > 1) fprintf(outfile, "%s", loc->reg->word); else fprintf(outfile, "%s", loc->reg->byte); break; @@ -44,19 +43,68 @@ static void emit_storage_loc( fprintf(outfile, "[rbp - %lld]", loc->offset); else fprintf(outfile, "[rbp]"); + break; + case IMMEDIATE: + fprintf(outfile, "%llu", loc->value); + break; } } +static void emit_mov( + FILE* outfile, + const struct storage_location* dst, + const struct storage_location* src, + unsigned long long sz +) { + switch (dst->type) { + case REGISTER: + if (src->type == REGISTER && sz < 4) { + fprintf(outfile, "\tmovzx "); + emit_storage_loc(outfile, dst, FULL_REG_SZ); + fprintf(outfile, ", "); + emit_storage_loc(outfile, src, sz); + } else { + fprintf(outfile, "\tmov "); + emit_storage_loc(outfile, dst, sz); + fprintf(outfile, ", "); + emit_storage_loc(outfile, src, sz); + } + break; + case BP_OFFSET: + fprintf(outfile, "\tmov "); + if (src->type == BP_OFFSET) { + if (sz > 4) fprintf(outfile, "qword "); + else if (sz > 2) fprintf(outfile, "dword "); + else if (sz > 1) fprintf(outfile, "word "); + else fprintf(outfile, "byte "); + } + emit_storage_loc(outfile, dst, sz); + fprintf(outfile, ", "); + emit_storage_loc(outfile, src, sz); + break; + case JMP_LABEL: + CGEN_PANIC("can't move value into label %s", dst->label); + case IMMEDIATE: + CGEN_PANIC( + "can't move value into immediate value %lld", dst->value); + } + fprintf(outfile, "\n"); +} + static void emit_int_lit( FILE* outfile, const struct int_lit_node* node, const struct storage_location* storage ) { - if (storage != NULL) { - fprintf(outfile, "\tmov "); - emit_storage_loc(outfile, storage, FULL_REG_SZ); - fprintf(outfile, ", %lld\n", node->val); - } + if (storage != NULL) + emit_mov( + outfile, + storage, + &(struct storage_location) { + .type = IMMEDIATE, + .value = node->val, + }, + FULL_REG_SZ); } static void emit_var_ref( @@ -69,11 +117,7 @@ static void emit_var_ref( if (!scope_get_var(scope, &var_def, node->ident)) CGEN_PANIC("reference to undefined variable %s", node->ident); - fprintf(outfile, "\tmov "); - emit_storage_loc(outfile, storage, var_def.sz); - fprintf(outfile, ", "); - emit_storage_loc(outfile, &var_def.loc, var_def.sz); - fprintf(outfile, "\n"); + emit_mov(outfile, storage, &var_def.loc, var_def.sz); } } @@ -142,20 +186,9 @@ static void emit_stmt_group(FILE* outfile, const struct group_node* node) { emit_group(outfile, node); + /* don't reset sp because alloca needs to work */ + scope->next_out->bp_offset = scope->bp_offset; scope_pop(&scope); - if (scope->bp_offset == 0) - fprintf(outfile, "\tmov rsp, rbp\n"); - else { - fprintf(outfile, "\tlea rsp, "); - emit_storage_loc( - outfile, - &(struct storage_location) { - .type = BP_OFFSET, - .offset = scope->bp_offset, - }, - FULL_REG_SZ); - fprintf(outfile, "\n"); - } } static void emit_stmt(FILE* outfile, const struct stmt_node* node) { @@ -213,11 +246,7 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) { }; spilled_bp_ofs -= type_sz; } - fprintf(outfile, "\tmov "); - emit_storage_loc(outfile, &var_def.loc, type_sz); - fprintf(outfile, ", "); - emit_storage_loc(outfile, &arg_src,type_sz); - fprintf(outfile, "\n"); + emit_mov(outfile, &var_def.loc, &arg_src, type_sz); args_node = args_node->next; } @@ -6,11 +6,13 @@ struct storage_location { REGISTER, JMP_LABEL, BP_OFFSET, + IMMEDIATE, } type; union { - long long offset; - const char* label; const struct reg* reg; + const char* label; + long long offset; + unsigned long long value; }; unsigned long long sz; }; |
