From 39315de738e86e1f1beb52ae14101b5caf7486a2 Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Fri, 21 Apr 2023 14:36:28 -0300 Subject: 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 Co-authored-by: Johnny Richard --- examples/arithmetics.pipa | 3 +++ src/gas_assembly_generator.c | 50 +++++++++++++++++++++++++++++++++++++++----- test/integration_test.c | 1 + 3 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 examples/arithmetics.pipa 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; } -- cgit v1.2.3