summaryrefslogtreecommitdiff
path: root/src/gas_assembly_generator.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gas_assembly_generator.c')
-rw-r--r--src/gas_assembly_generator.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/src/gas_assembly_generator.c b/src/gas_assembly_generator.c
index 2d6b993..26bf3f9 100644
--- a/src/gas_assembly_generator.c
+++ b/src/gas_assembly_generator.c
@@ -22,6 +22,9 @@
#include <stdlib.h>
#include <string.h>
+size_t available_calling_registers = 6;
+char *calling_registers[] = { "rdi", "rsi", "rdx", "rcx", "r8", "r9" };
+
static void
gas_assembly_generator_binary_operation(gas_assembly_generator_t *gen, ast_binary_operation_t *binary_operation);
@@ -183,6 +186,7 @@ gas_assembly_generator_compile(gas_assembly_generator_t *gen, ast_node_t *ast)
case AST_IF_STMT:
gas_assembly_generator_compile_if_stmt(gen, &ast->data.if_stmt);
break;
+ case AST_FUNCTION_PARAMETER:
case AST_UNKOWN_NODE:
assert(false && "unreachable");
}
@@ -204,10 +208,27 @@ gas_assembly_generator_compile_function(gas_assembly_generator_t *gen, ast_funct
uint64_t previous_index = gen->return_label_index;
uint64_t return_label_index = gen->return_label_index = gen->counter_label_index++;
- fprintf(gen->stream, SVFMT ":\n", SVARG(&func->identifier.name));
+ assert((func->prototype.parameters->size <= available_calling_registers) &&
+ "Not enough registers to process this function. Stack parameters will come soon.");
+
+ fprintf(gen->stream, SVFMT ":\n", SVARG(&func->prototype.identifier.name));
fprintf(gen->stream, " push %%rbp\n");
fprintf(gen->stream, " mov %%rsp, %%rbp\n");
+ for (size_t i = 0; i < func->prototype.parameters->size; i++) {
+ char *reg = calling_registers[i];
+ ast_node_t *parameter = vector_at(func->prototype.parameters, i);
+
+ assert(parameter->kind == AST_FUNCTION_PARAMETER);
+
+ gen->stack_offset -= 8;
+
+ fprintf(gen->stream, " mov %%%s, %d(%%rbp)\n", reg, gen->stack_offset);
+
+ ref_set_variable_reference_stack_offset(
+ gen->refs, &parameter->data.function_parameter.identifier, gen->stack_offset);
+ }
+
gas_assembly_generator_compile(gen, func->body);
fprintf(gen->stream, ".L%ld:\n", return_label_index);
@@ -215,11 +236,38 @@ gas_assembly_generator_compile_function(gas_assembly_generator_t *gen, ast_funct
fprintf(gen->stream, " ret\n");
gen->return_label_index = previous_index;
+ gen->stack_offset = 0;
}
static void
gas_assembly_generator_compile_function_call(gas_assembly_generator_t *gen, ast_function_call_t *func_call)
{
+ assert((func_call->arguments->size <= available_calling_registers) &&
+ "Not enough registers to process this function. Stack parameters will come soon.");
+
+ for (size_t i = 0; i < func_call->arguments->size; i++) {
+ char *reg = calling_registers[i];
+ ast_node_t *argument = vector_at(func_call->arguments, i);
+
+ gas_assembly_generator_compile(gen, argument);
+
+ switch (gen->latest_evaluation.kind) {
+ case EVALUATION_RESULT_AS_LITERAL_INTEGER:
+ fprintf(gen->stream, " mov $%ld, %%%s\n", gen->latest_evaluation.data.literal_int, reg);
+ break;
+ case EVALUATION_RESULT_ON_RAX:
+ fprintf(gen->stream, " mov %%rax, %%%s\n", reg);
+ break;
+ case EVALUATION_RESULT_ON_STACK:
+ fprintf(gen->stream, " mov %d(%%rbp), %%%s\n", gen->latest_evaluation.data.stack_offset, reg);
+ break;
+ case EVALUATION_RESULT_AS_LITERAL_BOOL:
+ fprintf(gen->stream, " mov %d(%%rbp), %%%s\n", gen->latest_evaluation.data.literal_bool, reg);
+ break;
+ case EVALUATION_RESULT_VOID:
+ assert(false && "Unexpected");
+ }
+ }
fprintf(gen->stream, " call " SVFMT "\n", SVARG(&func_call->identifier->name));
gas_assembly_generator_set_latest_evaluation_to_rax(gen);
}