101 lines
3.0 KiB
C++
101 lines
3.0 KiB
C++
#include "CodeGenVisitor.h"
|
|
|
|
#include "generated/ifccParser.h"
|
|
|
|
antlrcpp::Any CodeGenVisitor::visitStmt(ifccParser::StmtContext *ctx) {
|
|
std::cout << " ;" << ctx->getText() << "\n";
|
|
return this->visitChildren(ctx);
|
|
}
|
|
|
|
// Declare a new variable: reserve a slot on the stack, mark as uninitialized.
|
|
antlrcpp::Any CodeGenVisitor::visitDecl_stmt(ifccParser::Decl_stmtContext *ctx) {
|
|
std::string name = ctx->VAR_NAME()->getText();
|
|
if (symbolTable.find(name) != symbolTable.end()) {
|
|
std::cerr << "error: variable '" << name << "' already declared\n";
|
|
return 1;
|
|
}
|
|
symbolTable[name] = {nextOffset, false};
|
|
nextOffset += 4;
|
|
return 0;
|
|
}
|
|
|
|
// Assign a value to a variable: evaluate val, store on stack, mark as initialized.
|
|
antlrcpp::Any CodeGenVisitor::visitSet_stmt(ifccParser::Set_stmtContext *ctx) {
|
|
std::string name = ctx->VAR_NAME()->getText();
|
|
if (symbolTable.find(name) == symbolTable.end()) {
|
|
std::cerr << "error: variable '" << name << "' undeclared\n";
|
|
return 1;
|
|
}
|
|
int offset = symbolTable[name].offset;
|
|
|
|
this->visit(ctx->val());
|
|
|
|
#ifdef __APPLE__
|
|
std::cout << " str w0, [sp, #" << offset << "]\n";
|
|
#else
|
|
std::cout << " movl %eax, " << offset << "(%rsp)\n";
|
|
#endif
|
|
|
|
symbolTable[name].initialized = true;
|
|
return 0;
|
|
}
|
|
|
|
// Load a constant or variable into the accumulator register
|
|
antlrcpp::Any CodeGenVisitor::visitVal(ifccParser::ValContext *ctx) {
|
|
if (ctx->CONST()) {
|
|
int val = stoi(ctx->CONST()->getText());
|
|
#ifdef __APPLE__
|
|
std::cout << " mov w0, #" << val << "\n";
|
|
#else
|
|
std::cout << " movl $" << val << ", %eax\n";
|
|
#endif
|
|
return val;
|
|
}
|
|
std::string name = ctx->VAR_NAME()->getText();
|
|
if (symbolTable.find(name) == symbolTable.end()) {
|
|
std::cerr << "error: variable '" << name << "' undeclared\n";
|
|
return 1;
|
|
}
|
|
if (!symbolTable[name].initialized) {
|
|
std::cerr << "warning: variable '" << name << "' used before initialization\n";
|
|
}
|
|
int offset = symbolTable[name].offset;
|
|
#ifdef __APPLE__
|
|
std::cout << " ldr w0, [sp, #" << offset << "]\n";
|
|
#else
|
|
std::cout << " movl " << offset << "(%rsp), %eax\n";
|
|
#endif
|
|
return offset;
|
|
}
|
|
|
|
antlrcpp::Any CodeGenVisitor::visitProg(ifccParser::ProgContext *ctx) {
|
|
#ifdef __APPLE__
|
|
std::cout << ".globl _main\n";
|
|
std::cout << "_main:\n";
|
|
// Prologue: reserve space for local variables
|
|
std::cout << " sub sp, sp, #16\n";
|
|
#else
|
|
std::cout << ".globl main\n";
|
|
std::cout << "main:\n";
|
|
// Prologue: reserve space for local variables
|
|
std::cout << " subq $16, %rsp\n";
|
|
#endif
|
|
|
|
this->visitChildren(ctx);
|
|
|
|
// Epilogue
|
|
#ifdef __APPLE__
|
|
std::cout << " add sp, sp, #16\n";
|
|
#else
|
|
std::cout << " addq $16, %rsp\n";
|
|
#endif
|
|
std::cout << " ret\n";
|
|
return 0;
|
|
}
|
|
|
|
antlrcpp::Any CodeGenVisitor::visitReturn_stmt(ifccParser::Return_stmtContext *ctx) {
|
|
// Evaluate the return value into the accumulator register
|
|
this->visit(ctx->val());
|
|
return 0;
|
|
}
|