summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gas_assembly_generator.c83
-rw-r--r--src/gas_assembly_generator.h6
-rw-r--r--src/main.c2
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 */
diff --git a/src/main.c b/src/main.c
index 4f68256..780499c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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