diff --git a/ps5/src/generator.c b/ps5/src/generator.c index 1b70e14..ec93f17 100644 --- a/ps5/src/generator.c +++ b/ps5/src/generator.c @@ -135,8 +135,8 @@ static void generate_function(symbol_t* function) symbol_t *sym = symtable->symbols[i]; switch (sym->type) { case SYMBOL_PARAMETER: - if (i < NUM_REGISTER_PARAMS) { - PUSHQ(REGISTER_PARAMS[i]); + if (sym->sequence_number < NUM_REGISTER_PARAMS) { + PUSHQ(REGISTER_PARAMS[sym->sequence_number]); } else { /* these params are already on the stack */; } @@ -177,6 +177,10 @@ static void generate_function_call(node_t* call) POPQ(REGISTER_PARAMS[i]); } CALL(call->children[0]->symbol->name); + if (args->n_children > NUM_REGISTER_PARAMS) { + int stack_args = args->n_children - NUM_REGISTER_PARAMS; + EMIT("addq $%d, %s", stack_args * 8, RSP); + } } #define UNARY_OP(OP, INST) \ @@ -189,7 +193,8 @@ static void generate_function_call(node_t* call) generate_expression(left); \ PUSHQ(RAX); \ generate_expression(right); \ - POPQ(RCX); \ + MOVQ(RAX, RCX); \ + POPQ(RAX); \ INST(RCX, RAX); \ } #define DIVISION_OP \ @@ -238,7 +243,12 @@ static void generate_expression(node_t* expression) switch (expression->n_children) { case 1: UNARY_OP("-", NEGQ); - /* logical not "!" is omitted */ + if (strcmp(op, "!") == 0) { + generate_expression(expression->children[0]); + CMPQ("$0", RAX); + SETE(AL); + MOVZBQ(AL, RAX); + } break; case 2: node_t *left = expression->children[0]; @@ -269,19 +279,24 @@ static void generate_expression(node_t* expression) static void generate_base_address(node_t *identifier) { assert(identifier->type == IDENTIFIER); symbol_t *sym = identifier->symbol; + int offset; switch (sym->type) { case SYMBOL_GLOBAL_VAR: + case SYMBOL_GLOBAL_ARRAY: LEAQ_GLOBAL(sym->name, RAX); break; case SYMBOL_LOCAL_VAR: - int offset = -8 * (sym->sequence_number - FUNC_PARAM_COUNT(current_function) + 6 + 1); + int spill = FUNC_PARAM_COUNT(current_function) > NUM_REGISTER_PARAMS + ? NUM_REGISTER_PARAMS : FUNC_PARAM_COUNT(current_function); + int local_index = sym->sequence_number - FUNC_PARAM_COUNT(current_function); + offset = -8 * (spill + local_index + 1); LEAQ_OFFSET(offset, RBP, RAX); break; case SYMBOL_PARAMETER: - if (FUNC_PARAM_COUNT(current_function) < NUM_REGISTER_PARAMS) { - int offset = -8 * (sym->sequence_number + 1); + if (sym->sequence_number < NUM_REGISTER_PARAMS) { + offset = -8 * (sym->sequence_number + 1); } else { - int offset = 8 * (sym->sequence_number - 6 + 2); + offset = 8 * (sym->sequence_number - 6 + 2); } LEAQ_OFFSET(offset, RBP, RAX); break; @@ -299,7 +314,7 @@ static void generate_assignment_statement(node_t* statement) if (child->type == IDENTIFIER) { generate_expression(statement->children[1]); STASH(); - generate_base_address(child->children[0]); + generate_base_address(child); EMIT("movq %s, (%s)", RCX, RAX); } else if (child->type == ARRAY_INDEXING) { generate_base_address(child->children[0]); @@ -307,7 +322,9 @@ static void generate_assignment_statement(node_t* statement) generate_expression(child->children[1]); POPQ(RCX); EMIT("leaq (%s, %s, 8), %s", RCX, RAX, RCX); + PUSHQ(RCX); generate_expression(statement->children[1]); + POPQ(RCX); EMIT("movq %s, (%s)", RAX, RCX); // save the value in rax to the address of identifier[index] } }