diff options
Diffstat (limited to 'src/gas_assembly_generator.c')
-rw-r--r-- | src/gas_assembly_generator.c | 102 |
1 files changed, 61 insertions, 41 deletions
diff --git a/src/gas_assembly_generator.c b/src/gas_assembly_generator.c index bf98255..34864dd 100644 --- a/src/gas_assembly_generator.c +++ b/src/gas_assembly_generator.c @@ -21,66 +21,88 @@ #include <stdlib.h> static void -gas_assembly_generator_visit_function(ast_visitor_t *visitor, ast_function_declaration_t *func); +gas_assembly_generator_binary_operation(gas_assembly_generator_t *gen, ast_binary_operation_t *binary_operation); + static void -gas_assembly_generator_visit_return_stmt(ast_visitor_t *visitor, ast_return_stmt_t *return_stmt); +gas_assembly_generator_compile_function(gas_assembly_generator_t *gen, ast_function_declaration_t *func); + static void -gas_assembly_generator_visit_literal(ast_visitor_t *visitor, ast_literal_t *literal); +gas_assembly_generator_compile_literal(gas_assembly_generator_t *gen, ast_literal_t *literal); + static void -gas_assembly_generator_binary_operation(ast_visitor_t *visitor, ast_binary_operation_t *binary_operation); +gas_assembly_generator_compile_return_stmt(gas_assembly_generator_t *gen, ast_return_stmt_t *return_stmt); + +void +gas_assembly_generator_init(gas_assembly_generator_t *gen, FILE *stream) +{ + assert(gen && stream); + gen->stream = stream; +} void -gas_assembly_generator_init(gas_assembly_generator_t *gen, FILE *out) +gas_assembly_generator_compile(gas_assembly_generator_t *gen, ast_node_t *ast) { - assert(gen && out); - gen->super = (ast_visitor_t){ .visit_function = &gas_assembly_generator_visit_function, - .visit_literal = &gas_assembly_generator_visit_literal, - .visit_return_stmt = &gas_assembly_generator_visit_return_stmt, - .visit_binary_operation = &gas_assembly_generator_binary_operation }; - gen->out = out; + switch (ast->kind) { + case AST_BINARY_OPERATION: + gas_assembly_generator_binary_operation(gen, &ast->data.binary_operation); + break; + case AST_FUNCTION_DECLARATION: + gas_assembly_generator_compile_function(gen, &ast->data.function); + break; + case AST_LITERAL: + gas_assembly_generator_compile_literal(gen, &ast->data.literal); + break; + case AST_RETURN_STMT: + gas_assembly_generator_compile_return_stmt(gen, &ast->data.return_stmt); + break; + case AST_IDENTIFIER: + assert(false && "TODO: ast identifier not implemented yet"); + break; + case AST_VARIABLE_DECLARATION: + assert(false && "TODO: ast variable declaration not implemented yet"); + break; + case AST_UNKOWN_NODE: + assert(false && "unreachable"); + } } static void -gas_assembly_generator_visit_function(ast_visitor_t *visitor, ast_function_declaration_t *func) +gas_assembly_generator_compile_function(gas_assembly_generator_t *gen, ast_function_declaration_t *func) { - assert(visitor && func); + assert(func); if (!string_view_eq(func->name, string_view_from_str("main"))) { fprintf(stderr, "[ERROR]: no main function has been defined!\n"); exit(EXIT_FAILURE); } - gas_assembly_generator_t *gen = (gas_assembly_generator_t *)visitor; - - fprintf(gen->out, ".global _start\n"); - fprintf(gen->out, ".text\n"); - fprintf(gen->out, "_start:\n"); + fprintf(gen->stream, ".global _start\n"); + fprintf(gen->stream, ".text\n"); + fprintf(gen->stream, "_start:\n"); for (size_t i = 0; i < func->body->size; i++) { - ast_visitor_visit(visitor, vector_at(func->body, i)); + gas_assembly_generator_compile(gen, vector_at(func->body, i)); } } static void -gas_assembly_generator_visit_return_stmt(ast_visitor_t *visitor, ast_return_stmt_t *return_stmt) +gas_assembly_generator_compile_return_stmt(gas_assembly_generator_t *gen, ast_return_stmt_t *return_stmt) { - assert(visitor && return_stmt); - gas_assembly_generator_t *gen = (gas_assembly_generator_t *)visitor; + assert(gen && return_stmt); - ast_visitor_visit(visitor, return_stmt->argument); + gas_assembly_generator_compile(gen, return_stmt->argument); - fprintf(gen->out, " mov %%rax, %%rbx\n"); - fprintf(gen->out, " mov $1, %%al\n"); - fprintf(gen->out, " int $0x80\n"); + fprintf(gen->stream, " mov %%rax, %%rbx\n"); + fprintf(gen->stream, " mov $1, %%al\n"); + fprintf(gen->stream, " int $0x80\n"); } static void -gas_assembly_generator_visit_literal(ast_visitor_t *visitor, ast_literal_t *literal) +gas_assembly_generator_compile_literal(gas_assembly_generator_t *gen, ast_literal_t *literal) { - gas_assembly_generator_t *gen = (gas_assembly_generator_t *)visitor; switch (literal->kind) { case AST_LITERAL_INTEGER: - fprintf(gen->out, " mov $%d, %%rax\n", literal->value.integer); + fprintf(gen->stream, " mov $%d, %%rax\n", literal->value.integer); return; default: assert(false && "no code generation strategy."); @@ -88,36 +110,34 @@ gas_assembly_generator_visit_literal(ast_visitor_t *visitor, ast_literal_t *lite } static void -gas_assembly_generator_binary_operation(ast_visitor_t *visitor, ast_binary_operation_t *binary_operation) +gas_assembly_generator_binary_operation(gas_assembly_generator_t *gen, ast_binary_operation_t *binary_operation) { - gas_assembly_generator_t *gen = (gas_assembly_generator_t *)visitor; - - ast_visitor_visit(visitor, binary_operation->right); + gas_assembly_generator_compile(gen, binary_operation->right); - fprintf(gen->out, " push %%rax\n"); + fprintf(gen->stream, " push %%rax\n"); - ast_visitor_visit(visitor, binary_operation->left); + gas_assembly_generator_compile(gen, binary_operation->left); - fprintf(gen->out, " pop %%rcx\n"); + fprintf(gen->stream, " pop %%rcx\n"); if (binary_operation->kind == AST_BINOP_ADITION) { - fprintf(gen->out, " add %%rcx, %%rax\n"); + fprintf(gen->stream, " add %%rcx, %%rax\n"); return; } if (binary_operation->kind == AST_BINOP_SUBTRACTION) { - fprintf(gen->out, " sub %%rcx, %%rax\n"); + fprintf(gen->stream, " sub %%rcx, %%rax\n"); return; } if (binary_operation->kind == AST_BINOP_MULTIPLICATION) { - fprintf(gen->out, " mul %%rcx\n"); + fprintf(gen->stream, " mul %%rcx\n"); return; } if (binary_operation->kind == AST_BINOP_DIVISION) { - fprintf(gen->out, " xor %%rdx, %%rdx\n"); - fprintf(gen->out, " div %%rcx\n"); + fprintf(gen->stream, " xor %%rdx, %%rdx\n"); + fprintf(gen->stream, " div %%rcx\n"); return; } |