diff options
-rw-r--r-- | src/gas_assembly_generator.c | 83 | ||||
-rw-r--r-- | src/gas_assembly_generator.h | 6 | ||||
-rw-r--r-- | src/main.c | 2 |
3 files changed, 69 insertions, 22 deletions
diff --git a/src/gas_assembly_generator.c b/src/gas_assembly_generator.c index 97ba9ce..413fbb0 100644 --- a/src/gas_assembly_generator.c +++ b/src/gas_assembly_generator.c @@ -137,7 +137,8 @@ gas_assembly_generator_init(gas_assembly_generator_t *gen, FILE *stream) gen->stream = stream; gen->refs = vector_new(); gen->stack_offset = 0; - gen->cur_label_index = 0; + gen->counter_label_index = 1; + gen->return_label_index = 0; } void @@ -183,28 +184,40 @@ gas_assembly_generator_compile_function(gas_assembly_generator_t *gen, ast_funct { assert(func); - if (!string_view_eq(func->identifier.name, string_view_from_str("main"))) { - fprintf(stderr, "[ERROR]: no main function has been defined!\n"); - exit(EXIT_FAILURE); - } + uint64_t previous_index = gen->return_label_index; + uint64_t return_label_index = gen->return_label_index = gen->counter_label_index++; - fprintf(gen->stream, ".global _start\n"); - fprintf(gen->stream, ".text\n"); - fprintf(gen->stream, "_start:\n"); + fprintf(gen->stream, SVFMT ":\n", SVARG(&func->identifier.name)); fprintf(gen->stream, " push %%rbp\n"); fprintf(gen->stream, " mov %%rsp, %%rbp\n"); gas_assembly_generator_compile(gen, func->body); + fprintf(gen->stream, ".L%ld:\n", return_label_index); fprintf(gen->stream, " pop %%rbp\n"); + fprintf(gen->stream, " ret\n"); + + gen->return_label_index = previous_index; } -static void -gas_assembly_generator_compile_return_stmt(gas_assembly_generator_t *gen, ast_return_stmt_t *return_stmt) +void +gas_assembly_generator_compile_linux_main(gas_assembly_generator_t *gen, ast_node_t *func) { - assert(gen && return_stmt); + assert(func); + assert(func->kind == AST_FUNCTION_DECLARATION); - gas_assembly_generator_compile(gen, return_stmt->argument); + if (!string_view_eq(func->data.function.identifier.name, string_view_from_str("main"))) { + fprintf(stderr, "[ERROR]: no main function has been defined!\n"); + exit(EXIT_FAILURE); + } + + fprintf(gen->stream, ".global _start\n"); + fprintf(gen->stream, ".text\n"); + + gas_assembly_generator_compile(gen, func); + + fprintf(gen->stream, "_start:\n"); + fprintf(gen->stream, " call main\n"); switch (gen->latest_evaluation.kind) { case EVALUATION_RESULT_AS_LITERAL_INTEGER: @@ -229,6 +242,36 @@ gas_assembly_generator_compile_return_stmt(gas_assembly_generator_t *gen, ast_re } static void +gas_assembly_generator_compile_return_stmt(gas_assembly_generator_t *gen, ast_return_stmt_t *return_stmt) +{ + assert(gen && return_stmt); + assert(gen->return_label_index != 0 && "There are no return label index set"); + + gas_assembly_generator_compile(gen, return_stmt->argument); + + switch (gen->latest_evaluation.kind) { + case EVALUATION_RESULT_AS_LITERAL_INTEGER: + fprintf(gen->stream, " mov $%ld, %%rax\n", gen->latest_evaluation.data.literal_int); + gas_assembly_generator_set_latest_evaluation_to_rax(gen); + break; + case EVALUATION_RESULT_ON_RAX: + gas_assembly_generator_set_latest_evaluation_to_rax(gen); + break; + case EVALUATION_RESULT_ON_STACK: + fprintf(gen->stream, " mov %d(%%rbp), %%rax\n", gen->latest_evaluation.data.stack_offset); + gas_assembly_generator_set_latest_evaluation_to_rax(gen); + break; + case EVALUATION_RESULT_VOID: + break; + case EVALUATION_RESULT_AS_LITERAL_BOOL: + assert(false && "Unexpected"); + break; + } + + fprintf(gen->stream, " jmp .L%ld\n", gen->return_label_index); +} + +static void gas_assembly_generator_compile_variable_assign_value(gas_assembly_generator_t *gen, ast_node_t *expression, int stack_offset) @@ -241,9 +284,9 @@ gas_assembly_generator_compile_variable_assign_value(gas_assembly_generator_t *g return; } - uint64_t true_label_index = gen->cur_label_index++; - uint64_t false_label_index = gen->cur_label_index++; - uint64_t after_assign_label_index = gen->cur_label_index++; + uint64_t true_label_index = gen->counter_label_index++; + uint64_t false_label_index = gen->counter_label_index++; + uint64_t after_assign_label_index = gen->counter_label_index++; gas_assembly_generator_compile_condition(gen, expression, true_label_index, false, false_label_index, true); @@ -446,7 +489,7 @@ gas_assembly_generator_compile_condition(gas_assembly_generator_t *gen, } if (condition->data.binary_operation.kind == AST_BINOP_OR) { - uint64_t or_false_branch_label_index = gen->cur_label_index++; + uint64_t or_false_branch_label_index = gen->counter_label_index++; gas_assembly_generator_compile_condition( gen, condition->data.binary_operation.left, true_label_index, true, or_false_branch_label_index, false); @@ -459,7 +502,7 @@ gas_assembly_generator_compile_condition(gas_assembly_generator_t *gen, } if (condition->data.binary_operation.kind == AST_BINOP_AND) { - uint64_t and_true_branch_label_index = gen->cur_label_index++; + uint64_t and_true_branch_label_index = gen->counter_label_index++; gas_assembly_generator_compile_condition( gen, condition->data.binary_operation.left, and_true_branch_label_index, false, false_label_index, true); @@ -497,8 +540,8 @@ gas_assembly_generator_compile_if_stmt(gas_assembly_generator_t *gen, ast_if_stm switch (if_stmt->condition->kind) { case AST_BINARY_OPERATION: case AST_LITERAL: { - uint64_t true_label_index = gen->cur_label_index++; - uint64_t false_label_index = gen->cur_label_index++; + uint64_t true_label_index = gen->counter_label_index++; + uint64_t false_label_index = gen->counter_label_index++; gas_assembly_generator_compile_condition( gen, if_stmt->condition, true_label_index, false, false_label_index, true); @@ -510,7 +553,7 @@ gas_assembly_generator_compile_if_stmt(gas_assembly_generator_t *gen, ast_if_stm break; } case AST_VARIABLE: { - uint64_t false_label_index = gen->cur_label_index++; + uint64_t false_label_index = gen->counter_label_index++; int stack_offset = ref_find_variable_reference_stack_offset(gen->refs, if_stmt->condition->data.variable.identifier); diff --git a/src/gas_assembly_generator.h b/src/gas_assembly_generator.h index e400d2c..18ffb7f 100644 --- a/src/gas_assembly_generator.h +++ b/src/gas_assembly_generator.h @@ -48,7 +48,8 @@ typedef struct gas_assembly_generator_t FILE *stream; vector_t *refs; int stack_offset; - uint64_t cur_label_index; + uint64_t counter_label_index; + uint64_t return_label_index; evaluation_result_t latest_evaluation; } gas_assembly_generator_t; @@ -58,4 +59,7 @@ 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); +void +gas_assembly_generator_compile_linux_main(gas_assembly_generator_t *gen, ast_node_t *func); + #endif /* GAS_ASSEMBLY_GENERATOR_H */ @@ -31,7 +31,7 @@ generate_gas_x86_64_linux(ast_node_t *func) { gas_assembly_generator_t gen; gas_assembly_generator_init(&gen, stdout); - gas_assembly_generator_compile(&gen, func); + gas_assembly_generator_compile_linux_main(&gen, func); } static void |