summaryrefslogtreecommitdiff
path: root/codegen.c
diff options
context:
space:
mode:
Diffstat (limited to 'codegen.c')
-rw-r--r--codegen.c58
1 files changed, 47 insertions, 11 deletions
diff --git a/codegen.c b/codegen.c
index 9d7f183..4e9f63a 100644
--- a/codegen.c
+++ b/codegen.c
@@ -1,6 +1,7 @@
#include "ccc.h"
#include "codegen.h"
#include "scope.h"
+#include "register.h"
#include <stdlib.h>
#include <stdio.h>
@@ -14,17 +15,25 @@
static const struct storage_location RV_LOC = {
.type = REGISTER,
- .label = "rax",
+ .reg = &RAX,
};
+#define FULL_REG_SZ 8
static struct scope* scope;
static void emit_storage_loc(
FILE* outfile,
- const struct storage_location* loc
+ const struct storage_location* loc,
+ unsigned long long sz
) {
switch (loc->type) {
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;
case JMP_LABEL:
fprintf(outfile, "%s", loc->label);
break;
@@ -45,7 +54,7 @@ static void emit_int_lit(
) {
if (storage != NULL) {
fprintf(outfile, "\tmov ");
- emit_storage_loc(outfile, storage);
+ emit_storage_loc(outfile, storage, FULL_REG_SZ);
fprintf(outfile, ", %lld\n", node->val);
}
}
@@ -61,9 +70,9 @@ static void emit_var_ref(
CGEN_PANIC("reference to undefined variable %s", node->ident);
fprintf(outfile, "\tmov ");
- emit_storage_loc(outfile, storage);
+ emit_storage_loc(outfile, storage, var_def.sz);
fprintf(outfile, ", ");
- emit_storage_loc(outfile, &var_def.loc);
+ emit_storage_loc(outfile, &var_def.loc, var_def.sz);
fprintf(outfile, "\n");
}
}
@@ -108,6 +117,7 @@ static void emit_var_decl(FILE* outfile, const struct var_decl_node* node) {
.type = BP_OFFSET,
.offset = scope->bp_offset,
},
+ .sz = type_sz,
});
}
@@ -137,10 +147,13 @@ static void emit_stmt_group(FILE* outfile, const struct group_node* node) {
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,
- });
+ emit_storage_loc(
+ outfile,
+ &(struct storage_location) {
+ .type = BP_OFFSET,
+ .offset = scope->bp_offset,
+ },
+ FULL_REG_SZ);
fprintf(outfile, "\n");
}
}
@@ -170,18 +183,41 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) {
scope_push(&scope);
scope->bp_offset = 0;
+ long long spilled_bp_ofs = -16; // return address + old bp
+ unsigned long long arg_regnum = 0;
struct var_decl_node* args_node = node->args_head;
while (args_node != NULL) {
unsigned long long type_sz = get_type_size(&args_node->type);
scope->bp_offset += type_sz;
- scope_define_var(scope, (struct var_def) {
+ struct var_def var_def = {
.name = args_node->ident,
.loc = {
.type = BP_OFFSET,
.offset = scope->bp_offset,
},
- });
+ .sz = type_sz,
+ };
+ scope_define_var(scope, var_def);
+
+ struct storage_location arg_src;
+ if (arg_regnum < CC_N_REGS) {
+ arg_src = (struct storage_location) {
+ .type = REGISTER,
+ .reg = CALLING_CONV[arg_regnum++]
+ };
+ } else {
+ arg_src = (struct storage_location) {
+ .type = BP_OFFSET,
+ .offset = spilled_bp_ofs,
+ };
+ 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");
args_node = args_node->next;
}