diff options
| author | Carson Fleming <cflems@cflems.net> | 2026-03-28 09:42:44 -1000 |
|---|---|---|
| committer | Carson Fleming <cflems@cflems.net> | 2026-03-28 09:42:44 -1000 |
| commit | 33d10c0a684eaacb59102e2e2c2494ef54113aa1 (patch) | |
| tree | 230b1f1cfc4a6cde3285e2fac35c7f9a7a414e17 /codegen.c | |
| parent | 55929c155f929a886a0fe72c1c16a7913830350a (diff) | |
| download | ccc-33d10c0a684eaacb59102e2e2c2494ef54113aa1.tar.gz | |
we got assignments bois
Diffstat (limited to 'codegen.c')
| -rw-r--r-- | codegen.c | 115 |
1 files changed, 82 insertions, 33 deletions
@@ -61,23 +61,23 @@ static void emit_mov( 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); } + + 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 "); + /* `mov mem, mem` is illegal in x86_64 */ + emit_mov(outfile, &RV_LOC, src, sz); + emit_mov(outfile, dst, &RV_LOC, sz); + return; } + + fprintf(outfile, "\tmov "); emit_storage_loc(outfile, dst, sz); fprintf(outfile, ", "); emit_storage_loc(outfile, src, sz); @@ -91,6 +91,12 @@ static void emit_mov( fprintf(outfile, "\n"); } +static void emit_expr( + FILE* outfile, + const struct expr_node* node, + const struct storage_location* storage +); + static void emit_int_lit( FILE* outfile, const struct int_lit_node* node, @@ -107,37 +113,24 @@ static void emit_int_lit( FULL_REG_SZ); } +static struct var_def get_var(const char* name) { + struct var_def var_def; + if (!scope_get_var(scope, &var_def, name)) + CGEN_PANIC("reference to undefined variable %s", name); + return var_def; +} + static void emit_var_ref( FILE* outfile, const struct var_ref_node* node, const struct storage_location* storage ) { if (storage != NULL) { - struct var_def var_def; - if (!scope_get_var(scope, &var_def, node->ident)) - CGEN_PANIC("reference to undefined variable %s", node->ident); - + struct var_def var_def = get_var(node->ident); emit_mov(outfile, storage, &var_def.loc, var_def.sz); } } -static void emit_expr( - FILE* outfile, - const struct expr_node* node, - const struct storage_location* storage -) { - switch (node->type) { - case EXPR_EMPTY: - break; - case EXPR_INT_LIT: - emit_int_lit(outfile, &node->as._int_lit, storage); - break; - case EXPR_VAR_REF: - emit_var_ref(outfile, &node->as._var_ref, storage); - break; - } -} - static void emit_stmt(FILE* outfile, const struct stmt_node* node); static unsigned long long get_type_size(const struct type_node* type) { @@ -150,19 +143,73 @@ static unsigned long long get_type_size(const struct type_node* type) { return type_def.size; } -static void emit_var_decl(FILE* outfile, const struct var_decl_node* node) { +static struct var_def emit_var_decl( + FILE* outfile, + const struct var_decl_node* node +) { unsigned long long type_sz = get_type_size(&node->type); fprintf(outfile, "\tsub rsp, %llu\n", type_sz); scope->bp_offset += type_sz; - scope_define_var(scope, (struct var_def) { + + struct var_def var_def = { .name = node->ident, .loc = { .type = BP_OFFSET, .offset = scope->bp_offset, }, .sz = type_sz, - }); + }; + scope_define_var(scope, var_def); + return var_def; +} + +struct lval_def { + struct storage_location loc; + unsigned long long sz; +}; + +static struct lval_def emit_lval( + FILE* outfile, + const struct lval_node* node +) { + struct var_def var_def; + 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}; + 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}; + } + CGEN_PANIC("unknown lval type: %d", node->type); +} + +static void emit_assignment( + FILE* outfile, + const struct assign_node* node, + const struct storage_location* storage +) { + 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); +} + +static void emit_expr( + FILE* outfile, + const struct expr_node* node, + const struct storage_location* storage +) { + switch (node->type) { + case EXPR_INT_LIT: + emit_int_lit(outfile, &node->as._int_lit, storage); + break; + case EXPR_VAR_REF: + emit_var_ref(outfile, &node->as._var_ref, storage); + break; + case EXPR_ASSIGN: + emit_assignment(outfile, &node->as._assign, storage); + } } static void emit_return(FILE* outfile, const struct return_node* node) { @@ -193,6 +240,8 @@ static void emit_stmt_group(FILE* outfile, const struct group_node* node) { static void emit_stmt(FILE* outfile, const struct stmt_node* node) { switch (node->type) { + case STMT_EMPTY: + break; case STMT_VAR_DECL: emit_var_decl(outfile, &node->as._var_decl); break; |
