Adding var declaration and set statement handling

This commit is contained in:
Clément Grennerat 2026-03-02 21:01:45 +01:00
parent 13cb53a437
commit 11ccd45663
4 changed files with 117 additions and 41 deletions

View File

@ -3,45 +3,98 @@
#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) {
return 0;
}
antlrcpp::Any CodeGenVisitor::visitSet_stmt(ifccParser::Set_stmtContext *ctx) {
return 0;
}
antlrcpp::Any CodeGenVisitor::visitVal(ifccParser::ValContext *ctx) {
// TODO: return either the const or the variable value from the symbol table
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;
}
antlrcpp::Any CodeGenVisitor::visitProg(ifccParser::ProgContext *ctx)
{
#ifdef __APPLE__
std::cout << ".globl _main\n" ;
std::cout << " _main: \n" ;
#else
std::cout << ".globl main\n" ;
std::cout << " main: \n" ;
#endif
// 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)
{
int retval = stoi(ctx->val()->getText());
#ifdef __APPLE__
std::cout << " mov w0, #" << retval << "\n" ;
#else
std::cout << " movl $" << retval << ", %eax\n" ;
#endif
antlrcpp::Any CodeGenVisitor::visitReturn_stmt(ifccParser::Return_stmtContext *ctx) {
// Evaluate the return value into the accumulator register
this->visit(ctx->val());
return 0;
}

View File

@ -1,23 +1,31 @@
#pragma once
#include <map>
#include <string>
#include "antlr4-runtime.h"
#include "generated/ifccBaseVisitor.h"
class CodeGenVisitor : public ifccBaseVisitor {
struct VarInfo {
int offset; // stack offset relative to sp
bool initialized; // true after a set_stmt assigns a value
};
// Symbol table: variable name -> VarInfo
std::map<std::string, VarInfo> symbolTable;
int nextOffset = 0; // first variable at [sp, #0], next at [sp, #4], etc.
public:
std::any visitProg(ifccParser::ProgContext *ctx) override ;
std::any visitStmt(ifccParser::StmtContext *ctx) override ;
std::any visitReturn_stmt(ifccParser::Return_stmtContext *ctx) override ;
std::any visitDecl_stmt(ifccParser::Decl_stmtContext *ctx) override ;
std::any visitSet_stmt(ifccParser::Set_stmtContext *ctx) override ;
std::any visitVal(ifccParser::ValContext *ctx) override ;
std::any visitProg(ifccParser::ProgContext *ctx) override ;
std::any visitStmt(ifccParser::StmtContext *ctx) override ;
std::any visitReturn_stmt(ifccParser::Return_stmtContext *ctx) override ;
std::any visitDecl_stmt(ifccParser::Decl_stmtContext *ctx) override ;
std::any visitSet_stmt(ifccParser::Set_stmtContext *ctx) override ;
std::any visitVal(ifccParser::ValContext *ctx) override ;
};

View File

@ -1,5 +1,10 @@
int main() {
int z;
int x;
x=42;
return x;
x = 56;
int y;
x = y;
y = 10;
z = x;
return z;
}

View File

@ -0,0 +1,10 @@
int main() {
int z;
int x;
x = 56;
int y;
y = 10;
x = y;
z = x;
return z;
}