summaryrefslogtreecommitdiff
path: root/codegen.c
diff options
context:
space:
mode:
authorCarson Fleming <[email protected]>2026-03-26 16:01:27 -0700
committerCarson Fleming <[email protected]>2026-03-26 16:01:27 -0700
commit2e4f713ede25fb6147571858779fde542144c76f (patch)
treeff7989e0f5a985d7368feeb1d0f0a26142c5d7da /codegen.c
parent7d9fb2c733c8c64f6f74eefa0eea35b36be102cd (diff)
downloadccc-2e4f713ede25fb6147571858779fde542144c76f.tar.gz
start codegen work
Diffstat (limited to 'codegen.c')
-rw-r--r--codegen.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/codegen.c b/codegen.c
new file mode 100644
index 0000000..37c7a91
--- /dev/null
+++ b/codegen.c
@@ -0,0 +1,108 @@
+#include "ccc.h"
+#include "ast.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+static void emit_stmt(FILE* outfile, const struct stmt_node* node);
+static void emit_expr(
+ FILE* outfile,
+ const struct expr_node* node,
+ const char* reg);
+
+static void emit_int_lit(
+ FILE* outfile,
+ const struct int_lit_node* node,
+ const char* reg
+) {
+ fprintf(outfile, "\tmov %s, %lld\n", reg, node->val);
+}
+
+static void emit_expr(
+ FILE* outfile,
+ const struct expr_node* node,
+ const char* reg
+) {
+ switch (node->type) {
+ case EXPR_EMPTY:
+ break;
+ case EXPR_INT_LIT:
+ emit_int_lit(outfile, &node->as._int_lit, reg);
+ break;
+ }
+}
+
+static void emit_var_decl(FILE* outfile, const struct var_decl_node* node) {
+ /* TODO: make do smth */
+}
+
+static void emit_return(FILE* outfile, const struct return_node* node) {
+ if (node->ret_val != NULL) emit_expr(outfile, node->ret_val, "rax");
+ fprintf(outfile, "\tret\n");
+}
+
+static void emit_group(FILE* outfile, const struct group_node* node) {
+ const struct stmt_node* body_node = node->body_head;
+ while (body_node != NULL) {
+ emit_stmt(outfile, body_node);
+ body_node = body_node->next;
+ }
+}
+
+static void emit_stmt(FILE* outfile, const struct stmt_node* node) {
+ switch (node->type) {
+ case STMT_VAR_DECL:
+ emit_var_decl(outfile, &node->as._var_decl);
+ break;
+ case STMT_RETURN:
+ emit_return(outfile, &node->as._return);
+ break;
+ case STMT_EXPR:
+ emit_expr(outfile, &node->as._expr, NULL);
+ break;
+ case STMT_GROUP:
+ emit_group(outfile, &node->as._group);
+ break;
+ }
+}
+
+static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) {
+ fprintf(outfile, "%s:\n", node->name);
+ /* TODO: probably something to map the args to temporaries lol */
+ emit_group(outfile, &node->body);
+}
+
+static void emit_root_node(FILE* outfile, const struct root_node* node) {
+ switch (node->type) {
+ case ROOT_FN_DECL:
+ emit_fn_decl(outfile, &node->as._fn_decl);
+ break;
+ }
+}
+
+void emit_code(const struct root_node* ast, const char* path) {
+ FILE* outfile = fopen(path, "w");
+ if (outfile == NULL) CCC_PANIC;
+
+ fprintf(outfile, "section .text\n");
+
+ /* output all non-static function declarations as globals */
+ const struct root_node* node = ast;
+ while (node != NULL) {
+ if (node->type == ROOT_FN_DECL)
+ fprintf(outfile, "global %s\n", node->as._fn_decl.name);
+
+ node = node->next;
+ }
+
+ fprintf(outfile, "\n");
+
+ /* actual code body */
+ node = ast;
+ while (node != NULL) {
+ emit_root_node(outfile, node);
+ fprintf(outfile, "\n");
+ node = node->next;
+ }
+
+ fclose(outfile);
+}