diff options
author | Johnny Richard <johnny@johnnyrichard.com> | 2023-05-01 01:57:22 +0200 |
---|---|---|
committer | Carlos Maniero <carlos@maniero.me> | 2023-05-01 18:24:42 -0300 |
commit | e3d8e031c6f20c68f2227028ee8b3e73cd9b8161 (patch) | |
tree | 52068df5df3fea73eea9e5af311b03771a0f614a /src/gas_assembly_generator.c | |
parent | 8c56ddf0b640b8880eb5b97e5ca1b787585c29c0 (diff) |
parser: Implement variable assignment
This commit introduces variable assignment making it possible to
change a variable value. Example:
myvar: i32 = 1;
myvar = 2;
Signed-off-by: Johnny Richard <johnny@johnnyrichard.com>
Co-authored-by: Carlos Maniero <carlos@maniero.me>
Diffstat (limited to 'src/gas_assembly_generator.c')
-rw-r--r-- | src/gas_assembly_generator.c | 58 |
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); } |