summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarson Fleming <cflems@cflems.net>2026-03-28 17:22:53 -1000
committerCarson Fleming <cflems@cflems.net>2026-03-28 17:22:53 -1000
commit50495e8f815d3d5f92b3d36369acc52a6d2ea9c4 (patch)
tree1b2a512a8c175885dea201d1d764c6b1ddf8704a
parentb4d7305730606126d74862ca472a3efed964c2d8 (diff)
downloadccc-50495e8f815d3d5f92b3d36369acc52a6d2ea9c4.tar.gz
lval-centric storage model
-rw-r--r--codegen.c126
-rw-r--r--scope.h2
2 files changed, 70 insertions, 58 deletions
diff --git a/codegen.c b/codegen.c
index 37dea28..d0c4b27 100644
--- a/codegen.c
+++ b/codegen.c
@@ -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;
}
diff --git a/scope.h b/scope.h
index 2066a51..52ae6b1 100644
--- a/scope.h
+++ b/scope.h
@@ -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 {