summaryrefslogtreecommitdiff
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
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>
-rw-r--r--examples/arithmetics.pipa3
-rw-r--r--src/gas_assembly_generator.c50
-rw-r--r--test/integration_test.c1
3 files changed, 49 insertions, 5 deletions
diff --git a/examples/arithmetics.pipa b/examples/arithmetics.pipa
new file mode 100644
index 0000000..e2b7645
--- /dev/null
+++ b/examples/arithmetics.pipa
@@ -0,0 +1,3 @@
+main(): i32 {
+ return ((2 + 1) * (5 - 3) + 7) * 2 / 2;
+}
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);
+}
diff --git a/test/integration_test.c b/test/integration_test.c
index a624f8c..0ef3f5d 100644
--- a/test/integration_test.c
+++ b/test/integration_test.c
@@ -46,6 +46,7 @@ test_examples(const MunitParameter params[],
void *user_data_or_fixture)
{
assert_exit_status("../examples/main.pipa", 69);
+ assert_exit_status("../examples/arithmetics.pipa", 13);
return MUNIT_OK;
}