diff options
Diffstat (limited to 'src/gas_assembly_generator.c')
-rw-r--r-- | src/gas_assembly_generator.c | 65 |
1 files changed, 57 insertions, 8 deletions
diff --git a/src/gas_assembly_generator.c b/src/gas_assembly_generator.c index 5091120..fab4cd2 100644 --- a/src/gas_assembly_generator.c +++ b/src/gas_assembly_generator.c @@ -41,6 +41,19 @@ gas_assembly_generator_compile_variable_declaration(gas_assembly_generator_t *ge static void gas_assembly_generator_compile_variable(gas_assembly_generator_t *gen, ast_variable_t *variable); +static void +gas_assembly_generator_set_latest_evaluation_as_literal(gas_assembly_generator_t *gen, int64_t value) +{ + gen->latest_evaluation = + (evaluation_result_t){ .kind = EVALUATION_RESULT_LITERAL_INTEGER, .data = { .literal_int = value } }; +} + +static void +gas_assembly_generator_set_latest_evaluation_as_register(gas_assembly_generator_t *gen) +{ + gen->latest_evaluation = (evaluation_result_t){ .kind = EVALUATION_RESULT_REGISTER }; +} + typedef struct ref_entry_t { ast_identifier_t *id; @@ -61,7 +74,6 @@ ref_entry_new(void) return entry; } - void gas_assembly_generator_init(gas_assembly_generator_t *gen, FILE *stream) { @@ -74,6 +86,8 @@ gas_assembly_generator_init(gas_assembly_generator_t *gen, FILE *stream) void gas_assembly_generator_compile(gas_assembly_generator_t *gen, ast_node_t *ast) { + gen->latest_evaluation.kind = EVALUATION_RESULT_VOID; + switch (ast->kind) { case AST_BINARY_OPERATION: gas_assembly_generator_binary_operation(gen, &ast->data.binary_operation); @@ -131,7 +145,11 @@ gas_assembly_generator_compile_return_stmt(gas_assembly_generator_t *gen, ast_re gas_assembly_generator_compile(gen, return_stmt->argument); - fprintf(gen->stream, " mov %%rax, %%rdi\n"); + if (gen->latest_evaluation.kind == EVALUATION_RESULT_LITERAL_INTEGER) { + fprintf(gen->stream, " mov $%ld, %%rdi\n", gen->latest_evaluation.data.literal_int); + } else { + fprintf(gen->stream, " mov %%rax, %%rdi\n"); + } fprintf(gen->stream, " mov $60, %%rax\n"); fprintf(gen->stream, " syscall\n"); } @@ -147,7 +165,17 @@ gas_assembly_generator_compile_variable_declaration(gas_assembly_generator_t *ge *entry = (ref_entry_t){ .id = &variable_declaration->identifier, .stack_offset = gen->stack_offset }; vector_push_back(gen->refs, entry); - fprintf(gen->stream, " mov %%rax, %d(%%rbp)\n", entry->stack_offset); + switch (gen->latest_evaluation.kind) { + case EVALUATION_RESULT_LITERAL_INTEGER: + fprintf(gen->stream, " mov $%ld, %d(%%rbp)\n", gen->latest_evaluation.data.literal_int, entry->stack_offset); + break; + case EVALUATION_RESULT_REGISTER: + fprintf(gen->stream, " mov %%rax, %d(%%rbp)\n", entry->stack_offset); + break; + case EVALUATION_RESULT_VOID: + assert(false && "Unexpected void result for variable declaration"); + // FIXME: store the latest node at latest evaluation and print_ast + } } static void @@ -163,6 +191,7 @@ gas_assembly_generator_compile_variable(gas_assembly_generator_t *gen, ast_varia } assert(entry && "reference not found"); fprintf(gen->stream, " mov %d(%%rbp), %%rax\n", entry->stack_offset); + gas_assembly_generator_set_latest_evaluation_as_register(gen); } static void @@ -170,7 +199,7 @@ gas_assembly_generator_compile_literal(gas_assembly_generator_t *gen, ast_litera { switch (literal->kind) { case AST_LITERAL_INTEGER: - fprintf(gen->stream, " mov $%d, %%rax\n", literal->value.integer); + gas_assembly_generator_set_latest_evaluation_as_literal(gen, literal->value.integer); return; default: assert(false && "no code generation strategy."); @@ -181,14 +210,34 @@ static void gas_assembly_generator_binary_operation(gas_assembly_generator_t *gen, ast_binary_operation_t *binary_operation) { gas_assembly_generator_compile(gen, binary_operation->right); + evaluation_result_t right_evaluation = gen->latest_evaluation; - gen->stack_offset -= 8; - fprintf(gen->stream, " mov %%rax, %d(%%rbp)\n", gen->stack_offset); + if (right_evaluation.kind == EVALUATION_RESULT_REGISTER) { + gen->stack_offset -= 8; + fprintf(gen->stream, " mov %%rax, %d(%%rbp)\n", gen->stack_offset); + } gas_assembly_generator_compile(gen, binary_operation->left); + evaluation_result_t left_evaluation = gen->latest_evaluation; - fprintf(gen->stream, " mov %d(%%rbp), %%rcx\n", gen->stack_offset); - gen->stack_offset += 8; + switch (right_evaluation.kind) { + case EVALUATION_RESULT_LITERAL_INTEGER: + fprintf(gen->stream, " mov $%ld, %%rcx\n", right_evaluation.data.literal_int); + break; + case EVALUATION_RESULT_REGISTER: + fprintf(gen->stream, " mov %d(%%rbp), %%rcx\n", gen->stack_offset); + gen->stack_offset += 8; + break; + case EVALUATION_RESULT_VOID: + assert(false && "Unexpected void result for variable declaration"); + // FIXME: store the latest node at latest evaluation and print_ast + } + + gas_assembly_generator_set_latest_evaluation_as_register(gen); + + if (left_evaluation.kind == EVALUATION_RESULT_LITERAL_INTEGER) { + fprintf(gen->stream, " mov $%ld, %%rax\n", left_evaluation.data.literal_int); + } if (binary_operation->kind == AST_BINOP_ADITION) { fprintf(gen->stream, " add %%rcx, %%rax\n"); |