summaryrefslogtreecommitdiff
path: root/codegen.c
diff options
context:
space:
mode:
Diffstat (limited to 'codegen.c')
-rw-r--r--codegen.c47
1 files changed, 36 insertions, 11 deletions
diff --git a/codegen.c b/codegen.c
index d6f212a..ab3660b 100644
--- a/codegen.c
+++ b/codegen.c
@@ -50,6 +50,24 @@ static void emit_int_lit(
}
}
+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);
+
+ fprintf(outfile, "\tmov ");
+ emit_storage_loc(outfile, &var_def.loc);
+ fprintf(outfile, ", ");
+ emit_storage_loc(outfile, storage);
+ fprintf(outfile, "\n");
+ }
+}
+
static void emit_expr(
FILE* outfile,
const struct expr_node* node,
@@ -61,22 +79,28 @@ static void emit_expr(
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);
}
}
static void emit_stmt(FILE* outfile, const struct stmt_node* node);
-static struct type_def get_type_def(const char* type_name) {
+static unsigned long long get_type_size(const struct type_node* type) {
+ if (type->ptr_level > 0) return 8;
+
struct type_def type_def;
- if (!scope_get_type(scope, &type_def, type_name))
- CGEN_PANIC("size of type %s is not known", type_name);
- return type_def;
+ if (!scope_get_type(scope, &type_def, type->name))
+ CGEN_PANIC("size of type %s is not known", type->name);
+
+ return type_def.size;
}
static void emit_var_decl(FILE* outfile, const struct var_decl_node* node) {
- struct type_def type_def = get_type_def(node->type.type);
- fprintf(outfile, "\tsub rsp, %llu\n", type_def.size);
- scope->bp_offset += type_def.size;
+ 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) {
.name = node->ident,
.loc = {
@@ -148,7 +172,8 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) {
struct var_decl_node* args_node = node->args_head;
long long arg_bp_offset = -8;
while (args_node != NULL) {
- struct type_def type_def = get_type_def(args_node->type.type);
+ unsigned long long type_sz = get_type_size(&args_node->type);
+
scope_define_var(scope, (struct var_def) {
.name = args_node->ident,
.loc = {
@@ -156,7 +181,8 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) {
.offset = arg_bp_offset,
},
});
- arg_bp_offset -= type_def.size;
+
+ arg_bp_offset -= type_sz;
args_node = args_node->next;
}
@@ -183,8 +209,7 @@ void emit_code(const struct root_node* ast, const char* path) {
fprintf(outfile, "section .text\n");
scope_push(&scope);
-
- /* TODO: register all basic types */
+ scope_install_default_types(scope);
/* output all non-static function declarations as globals */
const struct root_node* node = ast;