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.c58
1 files changed, 51 insertions, 7 deletions
diff --git a/src/gas_assembly_generator.c b/src/gas_assembly_generator.c
index dd5d240..fca02ed 100644
--- a/src/gas_assembly_generator.c
+++ b/src/gas_assembly_generator.c
@@ -37,6 +37,9 @@ gas_assembly_generator_compile_return_stmt(gas_assembly_generator_t *gen, ast_re
static void
gas_assembly_generator_compile_variable_declaration(gas_assembly_generator_t *gen,
ast_variable_declaration_t *variable_declaration);
+static void
+gas_assembly_generator_compile_variable_assignment(gas_assembly_generator_t *gen,
+ ast_variable_assignment_t *variable_assignment);
static void
gas_assembly_generator_compile_variable(gas_assembly_generator_t *gen, ast_variable_t *variable);
@@ -81,6 +84,18 @@ ref_entry_new(void)
return entry;
}
+static ref_entry_t *
+find_ref_entry(vector_t *refs, ast_identifier_t *identifier)
+{
+ for (int i = refs->size - 1; i >= 0; --i) {
+ ref_entry_t *entry = (ref_entry_t *)vector_at(refs, i);
+ if (entry->id == identifier) {
+ return entry;
+ }
+ }
+ return NULL;
+}
+
void
gas_assembly_generator_init(gas_assembly_generator_t *gen, FILE *stream)
{
@@ -114,6 +129,9 @@ gas_assembly_generator_compile(gas_assembly_generator_t *gen, ast_node_t *ast)
case AST_VARIABLE_DECLARATION:
gas_assembly_generator_compile_variable_declaration(gen, &ast->data.variable_declaration);
break;
+ case AST_VARIABLE_ASSIGNMENT:
+ gas_assembly_generator_compile_variable_assignment(gen, &ast->data.variable_assignment);
+ break;
case AST_VARIABLE:
gas_assembly_generator_compile_variable(gen, &ast->data.variable);
break;
@@ -190,16 +208,42 @@ 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)
+gas_assembly_generator_compile_variable_assignment(gas_assembly_generator_t *gen,
+ ast_variable_assignment_t *variable_assignment)
{
- ref_entry_t *entry = NULL;
- for (int i = gen->refs->size - 1; i >= 0; --i) {
- ref_entry_t *entry_tmp = (ref_entry_t *)vector_at(gen->refs, i);
- if (entry_tmp->id == variable->identifier) {
- entry = entry_tmp;
+ ref_entry_t *entry = find_ref_entry(gen->refs, variable_assignment->identifier);
+ assert(entry && "reference not found");
+
+ gas_assembly_generator_compile(gen, variable_assignment->expression);
+
+ switch (gen->latest_evaluation.kind) {
+ case EVALUATION_RESULT_AS_LITERAL_INTEGER:
+ fprintf(gen->stream, " movq $%ld, %d(%%rbp)\n", gen->latest_evaluation.data.literal_int, entry->stack_offset);
break;
- }
+ case EVALUATION_RESULT_ON_RAX:
+ fprintf(gen->stream, " mov %%rax, %d(%%rbp)\n", entry->stack_offset);
+ break;
+ case EVALUATION_RESULT_ON_STACK:
+ fprintf(gen->stream, " movq %d(%%rbp), %%rax\n", gen->latest_evaluation.data.stack_offset);
+ fprintf(gen->stream, " movq %%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
}
+ // Today we dont't support chain-assignment like this:
+ //
+ // a = b = 1;
+ //
+ // If we start supporting it, we need to change the latest evaluation kind to
+ // stack.
+ gen->latest_evaluation.kind = EVALUATION_RESULT_VOID;
+}
+
+static void
+gas_assembly_generator_compile_variable(gas_assembly_generator_t *gen, ast_variable_t *variable)
+{
+ ref_entry_t *entry = find_ref_entry(gen->refs, variable->identifier);
assert(entry && "reference not found");
gas_assembly_generator_set_latest_evaluation_on_stack(gen, entry->stack_offset);
}