From 11ccd45663593235dab42d8b1246e4f4dfd79d79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Grennerat?= Date: Mon, 2 Mar 2026 21:01:45 +0100 Subject: [PATCH] Adding var declaration and set statement handling --- compiler/CodeGenVisitor.cpp | 107 +++++++++++++++++++++++++++--------- compiler/CodeGenVisitor.h | 32 +++++++---- prog/main.c | 9 ++- testfiles/4_multiple_var.c | 10 ++++ 4 files changed, 117 insertions(+), 41 deletions(-) create mode 100644 testfiles/4_multiple_var.c diff --git a/compiler/CodeGenVisitor.cpp b/compiler/CodeGenVisitor.cpp index b6f4bf7..0398d07 100644 --- a/compiler/CodeGenVisitor.cpp +++ b/compiler/CodeGenVisitor.cpp @@ -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; } diff --git a/compiler/CodeGenVisitor.h b/compiler/CodeGenVisitor.h index 37c2818..47ff99d 100644 --- a/compiler/CodeGenVisitor.h +++ b/compiler/CodeGenVisitor.h @@ -1,23 +1,31 @@ #pragma once - +#include +#include #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 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 ; }; + + diff --git a/prog/main.c b/prog/main.c index c0e169b..12be2b8 100644 --- a/prog/main.c +++ b/prog/main.c @@ -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; } diff --git a/testfiles/4_multiple_var.c b/testfiles/4_multiple_var.c new file mode 100644 index 0000000..21a4434 --- /dev/null +++ b/testfiles/4_multiple_var.c @@ -0,0 +1,10 @@ +int main() { + int z; + int x; + x = 56; + int y; + y = 10; + x = y; + z = x; + return z; +}