diff options
| author | Carson Fleming <cflems@cflems.net> | 2026-03-26 16:01:27 -0700 |
|---|---|---|
| committer | Carson Fleming <cflems@cflems.net> | 2026-03-26 16:01:27 -0700 |
| commit | 2e4f713ede25fb6147571858779fde542144c76f (patch) | |
| tree | ff7989e0f5a985d7368feeb1d0f0a26142c5d7da /codegen.c | |
| parent | 7d9fb2c733c8c64f6f74eefa0eea35b36be102cd (diff) | |
| download | ccc-2e4f713ede25fb6147571858779fde542144c76f.tar.gz | |
start codegen work
Diffstat (limited to 'codegen.c')
| -rw-r--r-- | codegen.c | 108 |
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); +} |
