summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarson Fleming <cflems@cflems.net>2026-03-28 08:04:48 -1000
committerCarson Fleming <cflems@cflems.net>2026-03-28 08:04:48 -1000
commit55929c155f929a886a0fe72c1c16a7913830350a (patch)
tree13482c2822661d8a0ff33369c6856aabe163e2a2
parentee85f90edd17d9c3fadc0d118021c18a5bb8463c (diff)
downloadccc-55929c155f929a886a0fe72c1c16a7913830350a.tar.gz
robust mov situation
-rw-r--r--codegen.c87
-rw-r--r--scope.h6
2 files changed, 62 insertions, 31 deletions
diff --git a/codegen.c b/codegen.c
index 4e9f63a..6dfaf4a 100644
--- a/codegen.c
+++ b/codegen.c
@@ -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;
}
diff --git a/scope.h b/scope.h
index e09e14e..a67c66b 100644
--- a/scope.h
+++ b/scope.h
@@ -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;
};