From e3d8e031c6f20c68f2227028ee8b3e73cd9b8161 Mon Sep 17 00:00:00 2001 From: Johnny Richard Date: Mon, 1 May 2023 01:57:22 +0200 Subject: 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 Co-authored-by: Carlos Maniero --- src/gas_assembly_generator.c | 58 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 7 deletions(-) (limited to 'src/gas_assembly_generator.c') 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); } -- cgit v1.2.3