ps5: generate_assignment_statement and indexing shenanigans

This commit is contained in:
2026-03-31 17:27:32 +02:00
parent 8201269c73
commit d811bda7fb
2 changed files with 44 additions and 0 deletions

View File

@@ -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))

View File

@@ -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)