ps5: generate_assignment_statement and indexing shenanigans
This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user