diff options
Diffstat (limited to 'codegen.c')
| -rw-r--r-- | codegen.c | 86 |
1 files changed, 72 insertions, 14 deletions
@@ -53,9 +53,14 @@ static void emit_storage_loc( static void emit_mov( FILE* outfile, const struct storage_location* dst, - const struct storage_location* src, - unsigned long long sz + const struct storage_location* src ) { + /* size is only defined for memory locations */ + unsigned long long sz; + if (dst->type == BP_OFFSET) sz = dst->sz; + else if (src->type == BP_OFFSET) sz = src->sz; + else sz = FULL_REG_SZ; + switch (dst->type) { case REGISTER: if (src->type == REGISTER && sz < 4) { @@ -72,12 +77,20 @@ static void emit_mov( case BP_OFFSET: if (src->type == BP_OFFSET) { /* `mov mem, mem` is illegal in x86_64 */ - emit_mov(outfile, &RV_LOC, src, sz); - emit_mov(outfile, dst, &RV_LOC, sz); + emit_mov(outfile, &RV_LOC, src); + emit_mov(outfile, dst, &RV_LOC); return; } fprintf(outfile, "\tmov "); + if (src->type == IMMEDIATE) { + /* must specify size to move immediates into memory*/ + 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); @@ -109,8 +122,43 @@ static void emit_int_lit( &(struct storage_location) { .type = IMMEDIATE, .value = node->val, - }, - FULL_REG_SZ); + }); +} + +static void emit_float_lit( + FILE* outfile, + const struct float_lit_node* node, + const struct storage_location* storage +) { + if (storage != NULL) { + CGEN_PANIC("float literals are not implemented"); + } +} + +static void emit_char_lit( + FILE* outfile, + const struct char_lit_node* node, + const struct storage_location* storage +) { + if (storage != NULL) { + emit_mov( + outfile, + storage, + &(struct storage_location) { + .type = IMMEDIATE, + .value = (unsigned long long) node->val + }); + } +} + +static void emit_str_lit( + FILE* outfile, + const struct str_lit_node* node, + const struct storage_location* storage +) { + if (storage != NULL) { + CGEN_PANIC("string literals are not implemented"); + } } static struct var_def get_var(const char* name) { @@ -127,7 +175,7 @@ static void emit_var_ref( ) { if (storage != NULL) { struct var_def var_def = get_var(node->ident); - emit_mov(outfile, storage, &var_def.loc, var_def.sz); + emit_mov(outfile, storage, &var_def.loc); } } @@ -140,7 +188,7 @@ static unsigned long long get_type_size(const struct type_node* type) { if (!scope_get_type(scope, &type_def, type->name)) CGEN_PANIC("size of type %s is not known", type->name); - return type_def.size; + return type_def.sz; } static struct var_def emit_var_decl( @@ -157,8 +205,8 @@ static struct var_def emit_var_decl( .loc = { .type = BP_OFFSET, .offset = scope->bp_offset, + .sz = type_sz, }, - .sz = type_sz, }; scope_define_var(scope, var_def); return var_def; @@ -177,10 +225,10 @@ static struct lval_def emit_lval( switch (node->type) { case LVAL_VAR_DECL: var_def = emit_var_decl(outfile, &node->as._var_decl); - return (struct lval_def) {.loc = var_def.loc, .sz = var_def.sz}; + return (struct lval_def) {.loc = var_def.loc, .sz = var_def.loc.sz}; case LVAL_VAR_REF: var_def = get_var(node->as._var_ref.ident); - return (struct lval_def) {.loc = var_def.loc, .sz = var_def.sz}; + return (struct lval_def) {.loc = var_def.loc, .sz = var_def.loc.sz}; } CGEN_PANIC("unknown lval type: %d", node->type); } @@ -192,7 +240,7 @@ static void emit_assignment( ) { const struct lval_def lval_def = emit_lval(outfile, &node->lval); emit_expr(outfile, node->rval, &lval_def.loc); - if (storage != NULL) emit_mov(outfile, storage, &lval_def.loc, lval_def.sz); + if (storage != NULL) emit_mov(outfile, storage, &lval_def.loc); } static void emit_expr( @@ -204,6 +252,15 @@ static void emit_expr( case EXPR_INT_LIT: emit_int_lit(outfile, &node->as._int_lit, storage); break; + case EXPR_FLOAT_LIT: + emit_float_lit(outfile, &node->as._float_lit, storage); + break; + case EXPR_CHAR_LIT: + emit_char_lit(outfile, &node->as._char_lit, storage); + break; + case EXPR_STR_LIT: + emit_str_lit(outfile, &node->as._str_lit, storage); + break; case EXPR_VAR_REF: emit_var_ref(outfile, &node->as._var_ref, storage); break; @@ -277,8 +334,8 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) { .loc = { .type = BP_OFFSET, .offset = scope->bp_offset, + .sz = type_sz, }, - .sz = type_sz, }; scope_define_var(scope, var_def); @@ -292,10 +349,11 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) { arg_src = (struct storage_location) { .type = BP_OFFSET, .offset = spilled_bp_ofs, + .sz = type_sz, }; spilled_bp_ofs -= type_sz; } - emit_mov(outfile, &var_def.loc, &arg_src, type_sz); + emit_mov(outfile, &var_def.loc, &arg_src); args_node = args_node->next; } |
