diff options
Diffstat (limited to 'codegen.c')
| -rw-r--r-- | codegen.c | 58 |
1 files changed, 47 insertions, 11 deletions
@@ -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; } |
