#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); }