From 75c8e5dc68339f50b5260400274ee43d5fb10e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind?= Date: Fri, 22 Apr 2022 18:41:50 +0200 Subject: [PATCH] working while, not sure of the continue --- exercises/06/vslc/src/generator.c | 105 ++++++++++++++++++++++-------- 1 file changed, 79 insertions(+), 26 deletions(-) diff --git a/exercises/06/vslc/src/generator.c b/exercises/06/vslc/src/generator.c index 40933cf..dadeb37 100644 --- a/exercises/06/vslc/src/generator.c +++ b/exercises/06/vslc/src/generator.c @@ -16,7 +16,8 @@ static uint64_t stack_depth, if_seq, - while_seq; + while_seq, + closest_while; /**Generate table of strings in a rodata section. */ void generate_stringtable ( void ); @@ -251,9 +252,9 @@ generate_node ( node_t *node) switch (node->type) { case ASSIGNMENT_STATEMENT: + // First solve the rhs solve_expressions(node->children[1]); - //ASM(popq, %rax); - //POP(%rax); + // Then store in lhs writeback_variable(node->children[0], "%rax"); break; @@ -309,10 +310,10 @@ generate_node ( node_t *node) break; case WHILE_STATEMENT: - /* DO NOTHING YET */ + generate_while_statement(node); break; case NULL_STATEMENT: - /* USED IN WHILE */ + solve_continue_statement(); break; @@ -511,13 +512,25 @@ generate_function_call(node_t *node) for (int arg = 0; arg < MIN(NO_REG_RECORD, arg_list->n_children); arg++) { - if (arg_list->children[arg]->type == NUMBER_DATA) + switch (arg_list->children[arg]->type) + { + case NUMBER_DATA: printf("\tmovq\t$%ld, %s\n", *(int64_t*)arg_list->children[arg]->data, record[arg] ); - else + break; + + case EXPRESSION: + solve_expressions(arg_list->children[arg]); + printf("\tmovq\t%%rax, %s\n",record[arg]); + break; + + default: fetch_variable(arg_list->children[arg], record[arg]); + break; + } + } if (arg_list->n_children > NO_REG_RECORD) @@ -528,19 +541,30 @@ generate_function_call(node_t *node) for (int arg = arg_list->n_children - 1; arg >= NO_REG_RECORD; arg--) { - if (arg_list->children[arg]->type == NUMBER_DATA) + switch (arg_list->children[arg]->type) + { + case NUMBER_DATA: printf("\tpushq\t$%ld\t\t\t\t# PUSH: %ld\n", *(int64_t*)arg_list->children[arg]->data, ++stack_depth ); - else - { + break; + + // Arg can be an expression + case EXPRESSION: + solve_expressions(arg_list->children[arg]); + PUSH(%rax); + break; + + default: printf("\tpushq\t"); generate_var_ident(arg_list->children[arg]); printf("\t\t\t\t# PUSH: %ld", ++stack_depth); putchar('\n'); + break; } } + } printf("\tcall\t_%s\n", (char*)node->children[0]->data); @@ -548,6 +572,7 @@ generate_function_call(node_t *node) // Aaaand pop the stack to return back to stack alignment if (isStack16ByteAligned) POP(%rcx); + printf("# End of function call\n"); } @@ -571,15 +596,10 @@ solve_statements(node_t *node, char *operator) writeback_variable(node->children[0], "%rax"); } +// Takes in a relation/number node and sets %rax to true if the statement is true void -generate_if_statement(node_t *node) +solve_relations(node_t *relation_root) { - uint64_t current_if_seq = if_seq++; - - COMMENT("Begin IF %ld", current_if_seq); - - node_t *relation_root = node->children[0]; - switch (relation_root->type) { case NUMBER_DATA: @@ -603,47 +623,80 @@ generate_if_statement(node_t *node) POP(%rax); ASM(cmp, %r10, %rax); + ASM(movq, $0, %rax); switch (*(char*)relation_root->data) { case '=': - ASM(sete, %rax); + ASM(sete, %al); break; case '>': - ASM(setg, %rax); + ASM(setg, %al); break; case '<': - ASM(setl, %rax); + ASM(setl, %al); break; } break; } +} + +void +generate_if_statement(node_t *node) +{ + uint64_t current_if_seq = if_seq++; + + COMMENT("Begin IF %ld", current_if_seq); + + // The realtion is allways in the first part of the IF + solve_relations(node->children[0]); ASM(cmp, $1, %rax); printf("\tjne\t%s%03ld\n", (node->n_children > 2) ? "ELSE" : "ENDIF", current_if_seq); - solve_expressions(node->children[1]); + generate_node(node->children[1]); if (node->n_children > 2) { - printf("\tjmp\tENDIF%03ld\n", current_if_seq); + printf("\tjmp \tENDIF%03ld\n", current_if_seq); printf("ELSE%03ld:\n", current_if_seq); - solve_expressions(node->children[2]); + + generate_node(node->children[2]); } - printf("ENDIF%03ld:\n", current_if_seq); - COMMENT("End IF %ld", current_if_seq); + printf("ENDIF%03ld:\n", current_if_seq); } void generate_while_statement(node_t *node) { + uint64_t current_while_seq = while_seq++; + uint64_t prev_closest_while = closest_while; + closest_while = current_while_seq; + + COMMENT("Begin WHILE %ld", current_while_seq); + printf("WHILE%03ld:\n", current_while_seq); + + // Relation is allways the first entry in a while + solve_relations(node->children[0]); + + ASM(cmp, $1, %rax); + + printf("\tjne\tENDWHILE%03ld\n", current_while_seq); + + generate_node(node->children[1]); + closest_while = prev_closest_while; + + printf("\tjmp \tWHILE%03ld\n", current_while_seq); + printf("ENDWHILE%03ld:\n", current_while_seq); + } void solve_continue_statement() { - + COMMENT("Continue to WHILE%03ld", closest_while); + printf("\tjmp \tWHILE%03ld\n", closest_while); } /**Generates the main function with argument parsing and calling of our