From 2e4f713ede25fb6147571858779fde542144c76f Mon Sep 17 00:00:00 2001 From: Carson Fleming Date: Thu, 26 Mar 2026 16:01:27 -0700 Subject: start codegen work --- codegen.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 codegen.c (limited to 'codegen.c') 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 +#include + +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); +} -- cgit v1.2.3