summaryrefslogtreecommitdiff
path: root/src/gas_assembly_generator.c
diff options
context:
space:
mode:
authorCarlos Maniero <carlosmaniero@gmail.com>2023-04-21 14:36:28 -0300
committerJohnny Richard <johnny@johnnyrichard.com>2023-04-21 19:32:59 +0200
commit39315de738e86e1f1beb52ae14101b5caf7486a2 (patch)
tree8fe675255761e0a5cf8eab283e11d943d20d1f8f /src/gas_assembly_generator.c
parent2b870752f767b8fecaf5ceb1dfe4d3366284a690 (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/gas_assembly_generator.c')
-rw-r--r--src/gas_assembly_generator.c50
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);
+}