diff options
author | Carlos Maniero <carlosmaniero@gmail.com> | 2023-04-21 14:36:28 -0300 |
---|---|---|
committer | Johnny Richard <johnny@johnnyrichard.com> | 2023-04-21 19:32:59 +0200 |
commit | 39315de738e86e1f1beb52ae14101b5caf7486a2 (patch) | |
tree | 8fe675255761e0a5cf8eab283e11d943d20d1f8f /src | |
parent | 2b870752f767b8fecaf5ceb1dfe4d3366284a690 (diff) |
gas: Generate arithmetics expressions
We decided for using push and pop to simplify the implementation, we
want to revisit the approach latter.
Signed-off-by: Carlos Maniero <carlosmaniero@gmail.com>
Co-authored-by: Johnny Richard <johnny@johnnyrichard.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/gas_assembly_generator.c | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/src/gas_assembly_generator.c b/src/gas_assembly_generator.c index ae4d762..10a67f3 100644 --- a/src/gas_assembly_generator.c +++ b/src/gas_assembly_generator.c @@ -22,7 +22,8 @@ static void gas_assembly_generator_visit_function(ast_visitor_t *visitor, ast_function_declaration_t *func); static void gas_assembly_generator_visit_return_stmt(ast_visitor_t *visitor, ast_return_stmt_t *return_stmt); -static void gas_assembly_generator_visit_literal(ast_visitor_t *visitor, ast_literal_t *return_stmt); +static void gas_assembly_generator_visit_literal(ast_visitor_t *visitor, ast_literal_t *literal); +static void gas_assembly_generator_binary_operation(ast_visitor_t *visitor, ast_binary_operation_t *binary_operation); void gas_assembly_generator_init(gas_assembly_generator_t *gen, FILE *out) @@ -31,7 +32,8 @@ gas_assembly_generator_init(gas_assembly_generator_t *gen, FILE *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_return_stmt = &gas_assembly_generator_visit_return_stmt, + .visit_binary_operation = &gas_assembly_generator_binary_operation }; gen->out = out; } @@ -63,7 +65,7 @@ gas_assembly_generator_visit_return_stmt(ast_visitor_t *visitor, ast_return_stmt ast_visitor_visit(visitor, return_stmt->argument); - fprintf(gen->out, " mov %%eax, %%ebx\n"); + fprintf(gen->out, " mov %%rax, %%rbx\n"); fprintf(gen->out, " mov $1, %%al\n"); fprintf(gen->out, " int $0x80\n"); } @@ -74,9 +76,47 @@ gas_assembly_generator_visit_literal(ast_visitor_t *visitor, ast_literal_t *lite gas_assembly_generator_t *gen = (gas_assembly_generator_t *) visitor; switch (literal->kind) { case AST_LITERAL_INTEGER: - fprintf(gen->out, " mov $%d, %%eax\n", literal->value.integer); + fprintf(gen->out, " mov $%d, %%rax\n", literal->value.integer); return; default: - assert(false && "No code generation strategy."); + assert(false && "no code generation strategy."); } } + +static void +gas_assembly_generator_binary_operation(ast_visitor_t *visitor, ast_binary_operation_t *binary_operation) +{ + gas_assembly_generator_t *gen = (gas_assembly_generator_t *) visitor; + + ast_visitor_visit(visitor, binary_operation->right); + + fprintf(gen->out, " push %%rax\n"); + + ast_visitor_visit(visitor, binary_operation->left); + + fprintf(gen->out, " pop %%rcx\n"); + + if (string_view_eq(binary_operation->op, string_view_from_str("+"))) { + fprintf(gen->out, " add %%rcx, %%rax\n"); + return; + } + + if (string_view_eq(binary_operation->op, string_view_from_str("-"))) { + fprintf(gen->out, " sub %%rcx, %%rax\n"); + return; + } + + if (string_view_eq(binary_operation->op, string_view_from_str("*"))) { + fprintf(gen->out, " mul %%rcx\n"); + return; + } + + if (string_view_eq(binary_operation->op, string_view_from_str("/"))) { + fprintf(gen->out, " xor %%rdx, %%rdx\n"); + fprintf(gen->out, " div %%rcx\n"); + return; + } + + fprintf(stderr, "no strategy defined for: "SVFMT"\n", SVARG(&binary_operation->op)); + assert(false); +} |