diff --git a/ps5/src/emit.h b/ps5/src/emit.h index b70f7c0..9a0aef6 100644 --- a/ps5/src/emit.h +++ b/ps5/src/emit.h @@ -30,8 +30,12 @@ #define MOVQ(src, dst) EMIT("movq %s, %s", (src), (dst)) #define MOVQ_IMM(imm, dst) EMIT("movq $%ld, %s", (int64_t)(imm), (dst)) +#define MOVQ_OFFSET(offset, src, dst) EMIT("movq %d(%s), %s", (offset), (src), (dst)) #define PUSHQ(src) EMIT("pushq %s", (src)) #define POPQ(src) EMIT("popq %s", (src)) +#define LEAQ_GLOBAL(name, dst) EMIT("leaq .%s(%%rip), %s", (name), (dst)) +#define LEAQ_OFFSET(offset, src, dst) EMIT("leaq %d(%s), %s", (offset), (src), (dst)) +#define STASH() MOVQ(RAX, RCX) #define ADDQ(src, dst) EMIT("addq %s, %s", (src), (dst)) #define SUBQ(src, dst) EMIT("subq %s, %s", (src), (dst)) diff --git a/ps5/src/generator.c b/ps5/src/generator.c index 86ea78c..d87553a 100644 --- a/ps5/src/generator.c +++ b/ps5/src/generator.c @@ -1,4 +1,6 @@ #include "symbol_table.h" +#include "symbols.h" +#include "tree.h" #include "vslc.h" // This header defines a bunch of macros we can use to emit assembly to stdout @@ -121,6 +123,7 @@ static void generate_function(symbol_t* function) // TODO (Task 3.1): Do the prologue, including call frame building and parameter pushing // Tip: use the definitions REGISTER_PARAMS and NUM_REGISTER_PARAMS at the top of this file + current_function = function; LABEL(".%s", function->name); PUSHQ(RBP); @@ -185,6 +188,29 @@ static void generate_expression(node_t* expression) } } +// helper function to get the base address of any identifier +static void generate_base_address(node_t *identifier) { + assert(identifier->type == IDENTIFIER); + symbol_t *sym = identifier->symbol; + switch (sym->type) { + case SYMBOL_GLOBAL_VAR: + LEAQ_GLOBAL(sym->name, RAX); + break; + case SYMBOL_LOCAL_VAR: + int offset = -8 * (sym->sequence_number - FUNC_PARAM_COUNT(current_function) + 6 + 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); + } else { + int offset = 8 * (sym->sequence_number - 6 + 2); + } + LEAQ_OFFSET(offset, RBP, RAX); + break; + } +} + static void generate_assignment_statement(node_t* statement) { // TODO (Task 4.2): @@ -192,6 +218,20 @@ static void generate_assignment_statement(node_t* statement) // Use the IDENTIFIER's symbol to find out what kind of symbol you are assigning to. // The left hand side of an assignment statement may also be an ARRAY_INDEXING node. // In that case, you must also emit code for evaluating the index being stored to + node_t *child = statement->children[0]; + if (child->type == IDENTIFIER) { + generate_expression(statement->children[1]); + STASH(); + generate_base_address(child->children[0]); + EMIT("movq %s, (%s)", RCX, RAX); + } else if (child->type == ARRAY_INDEXING) { + generate_base_address(child->children[0]); + STASH(); + generate_expression(child->children[1]); + EMIT("leaq (%s, %s, 8), %s", RCX, RAX, RCX); + generate_expression(statement->children[1]); + EMIT("movq %s, (%s)", RAX, RCX); // save the value in rax to the address of identifier[index] + } } static void generate_print_statement(node_t* statement)