diff options
| author | Carson Fleming <cflems@cflems.net> | 2026-03-28 17:22:53 -1000 |
|---|---|---|
| committer | Carson Fleming <cflems@cflems.net> | 2026-03-28 17:22:53 -1000 |
| commit | 50495e8f815d3d5f92b3d36369acc52a6d2ea9c4 (patch) | |
| tree | 1b2a512a8c175885dea201d1d764c6b1ddf8704a | |
| parent | b4d7305730606126d74862ca472a3efed964c2d8 (diff) | |
| download | ccc-50495e8f815d3d5f92b3d36369acc52a6d2ea9c4.tar.gz | |
lval-centric storage model
| -rw-r--r-- | codegen.c | 126 | ||||
| -rw-r--r-- | scope.h | 2 |
2 files changed, 70 insertions, 58 deletions
@@ -13,6 +13,11 @@ exit(1);\ } +struct lval_def { + struct storage_location loc; + unsigned long long sz; +}; + static const struct storage_location RV_LOC = { .type = REGISTER, .reg = &RAX, @@ -52,32 +57,32 @@ static void emit_storage_loc( static void emit_mov( FILE* outfile, - const struct storage_location* dst, + const struct lval_def* dst, 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) { + switch (dst->loc.type) { case REGISTER: - if (src->type == REGISTER && sz < 4) { + if (src->type == REGISTER && dst->sz < 4) { fprintf(outfile, "\tmovzx "); - emit_storage_loc(outfile, dst, FULL_REG_SZ); + emit_storage_loc(outfile, &dst->loc, FULL_REG_SZ); } else { fprintf(outfile, "\tmov "); - emit_storage_loc(outfile, dst, sz); + emit_storage_loc(outfile, &dst->loc, dst->sz); } fprintf(outfile, ", "); - emit_storage_loc(outfile, src, sz); + emit_storage_loc(outfile, src, dst->sz); break; case BP_OFFSET: if (src->type == BP_OFFSET) { /* `mov mem, mem` is illegal in x86_64 */ - emit_mov(outfile, &RV_LOC, src); + emit_mov( + outfile, + &(struct lval_def) { + .loc = RV_LOC, + .sz = dst->sz, + }, + src); emit_mov(outfile, dst, &RV_LOC); return; } @@ -85,21 +90,21 @@ static void emit_mov( 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 "); + if (dst->sz > 4) fprintf(outfile, "qword "); + else if (dst->sz > 2) fprintf(outfile, "dword "); + else if (dst->sz > 1) fprintf(outfile, "word "); else fprintf(outfile, "byte "); } - emit_storage_loc(outfile, dst, sz); + emit_storage_loc(outfile, &dst->loc, dst->sz); fprintf(outfile, ", "); - emit_storage_loc(outfile, src, sz); + emit_storage_loc(outfile, src, dst->sz); break; case JMP_LABEL: - CGEN_PANIC("can't move value into label %s", dst->label); + CGEN_PANIC("can't move value into label %s", dst->loc.label); case IMMEDIATE: CGEN_PANIC( - "can't move value into immediate value %lld", dst->value); + "can't move value into immediate value %lld", dst->loc.value); } fprintf(outfile, "\n"); } @@ -107,18 +112,17 @@ static void emit_mov( static void emit_expr( FILE* outfile, const struct expr_node* node, - const struct storage_location* storage -); + const struct lval_def* dst); static void emit_int_lit( FILE* outfile, const struct int_lit_node* node, - const struct storage_location* storage + const struct lval_def* dst ) { - if (storage != NULL) + if (dst != NULL) emit_mov( outfile, - storage, + dst, &(struct storage_location) { .type = IMMEDIATE, .value = node->val, @@ -128,9 +132,9 @@ static void emit_int_lit( static void emit_float_lit( FILE* outfile, const struct float_lit_node* node, - const struct storage_location* storage + const struct lval_def* dst ) { - if (storage != NULL) { + if (dst != NULL) { CGEN_PANIC("float literals are not implemented"); } } @@ -138,12 +142,12 @@ static void emit_float_lit( static void emit_char_lit( FILE* outfile, const struct char_lit_node* node, - const struct storage_location* storage + const struct lval_def* dst ) { - if (storage != NULL) { + if (dst != NULL) { emit_mov( outfile, - storage, + dst, &(struct storage_location) { .type = IMMEDIATE, .value = (unsigned long long) node->val @@ -154,9 +158,9 @@ static void emit_char_lit( static void emit_str_lit( FILE* outfile, const struct str_lit_node* node, - const struct storage_location* storage + const struct lval_def* dst ) { - if (storage != NULL) { + if (dst != NULL) { CGEN_PANIC("string literals are not implemented"); } } @@ -171,11 +175,11 @@ static struct var_def get_var(const char* name) { static void emit_var_ref( FILE* outfile, const struct var_ref_node* node, - const struct storage_location* storage + const struct lval_def* dst ) { - if (storage != NULL) { + if (dst != NULL) { struct var_def var_def = get_var(node->ident); - emit_mov(outfile, storage, &var_def.loc); + emit_mov(outfile, dst, &var_def.loc); } } @@ -205,18 +209,13 @@ 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; } -struct lval_def { - struct storage_location loc; - unsigned long long sz; -}; - static struct lval_def emit_lval( FILE* outfile, const struct lval_node* node @@ -225,10 +224,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.loc.sz}; + 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.loc.sz}; + return (struct lval_def) {.loc = var_def.loc, .sz = var_def.sz}; } CGEN_PANIC("unknown lval type: %d", node->type); } @@ -236,41 +235,49 @@ static struct lval_def emit_lval( static void emit_assignment( FILE* outfile, const struct assign_node* node, - const struct storage_location* storage + const struct lval_def* dst ) { 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); + emit_expr(outfile, node->rval, &lval_def); + if (dst != NULL) emit_mov(outfile, dst, &lval_def.loc); } static void emit_expr( FILE* outfile, const struct expr_node* node, - const struct storage_location* storage + const struct lval_def* dst ) { switch (node->type) { case EXPR_INT_LIT: - emit_int_lit(outfile, &node->as._int_lit, storage); + emit_int_lit(outfile, &node->as._int_lit, dst); break; case EXPR_FLOAT_LIT: - emit_float_lit(outfile, &node->as._float_lit, storage); + emit_float_lit(outfile, &node->as._float_lit, dst); break; case EXPR_CHAR_LIT: - emit_char_lit(outfile, &node->as._char_lit, storage); + emit_char_lit(outfile, &node->as._char_lit, dst); break; case EXPR_STR_LIT: - emit_str_lit(outfile, &node->as._str_lit, storage); + emit_str_lit(outfile, &node->as._str_lit, dst); break; case EXPR_VAR_REF: - emit_var_ref(outfile, &node->as._var_ref, storage); + emit_var_ref(outfile, &node->as._var_ref, dst); break; case EXPR_ASSIGN: - emit_assignment(outfile, &node->as._assign, storage); + emit_assignment(outfile, &node->as._assign, dst); } } static void emit_return(FILE* outfile, const struct return_node* node) { - if (node->ret_val != NULL) emit_expr(outfile, node->ret_val, &RV_LOC); + if (node->ret_val != NULL) + emit_expr( + outfile, + node->ret_val, + &(struct lval_def) { + .loc = RV_LOC, + .sz = FULL_REG_SZ /* TODO: need to pull this from return type */ + }); + fprintf(outfile, "\tmov rsp, rbp\n"); fprintf(outfile, "\tpop rbp\n"); fprintf(outfile, "\tret\n"); @@ -334,8 +341,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); @@ -349,11 +356,16 @@ 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); + emit_mov( + outfile, + &(struct lval_def) { + .loc = var_def.loc, + .sz = type_sz, + }, + &arg_src); args_node = args_node->next; } @@ -14,7 +14,6 @@ struct storage_location { long long offset; unsigned long long value; }; - unsigned long long sz; }; struct type_def { @@ -25,6 +24,7 @@ struct type_def { struct var_def { const char* name; struct storage_location loc; + unsigned long long sz; }; struct scope { |
