Adding var declaration and set statement handling
This commit is contained in:
parent
13cb53a437
commit
11ccd45663
@ -3,45 +3,98 @@
|
|||||||
#include "generated/ifccParser.h"
|
#include "generated/ifccParser.h"
|
||||||
|
|
||||||
antlrcpp::Any CodeGenVisitor::visitStmt(ifccParser::StmtContext *ctx) {
|
antlrcpp::Any CodeGenVisitor::visitStmt(ifccParser::StmtContext *ctx) {
|
||||||
|
std::cout << " ;" << ctx->getText() << "\n";
|
||||||
return this->visitChildren(ctx);
|
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) {
|
antlrcpp::Any CodeGenVisitor::visitDecl_stmt(ifccParser::Decl_stmtContext *ctx) {
|
||||||
return 0;
|
std::string name = ctx->VAR_NAME()->getText();
|
||||||
}
|
if (symbolTable.find(name) != symbolTable.end()) {
|
||||||
antlrcpp::Any CodeGenVisitor::visitSet_stmt(ifccParser::Set_stmtContext *ctx) {
|
std::cerr << "error: variable '" << name << "' already declared\n";
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
antlrcpp::Any CodeGenVisitor::visitVal(ifccParser::ValContext *ctx) {
|
symbolTable[name] = {nextOffset, false};
|
||||||
// TODO: return either the const or the variable value from the symbol table
|
nextOffset += 4;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
antlrcpp::Any CodeGenVisitor::visitProg(ifccParser::ProgContext *ctx)
|
// Assign a value to a variable: evaluate val, store on stack, mark as initialized.
|
||||||
{
|
antlrcpp::Any CodeGenVisitor::visitSet_stmt(ifccParser::Set_stmtContext *ctx) {
|
||||||
#ifdef __APPLE__
|
std::string name = ctx->VAR_NAME()->getText();
|
||||||
std::cout << ".globl _main\n" ;
|
if (symbolTable.find(name) == symbolTable.end()) {
|
||||||
std::cout << " _main: \n" ;
|
std::cerr << "error: variable '" << name << "' undeclared\n";
|
||||||
#else
|
return 1;
|
||||||
std::cout << ".globl main\n" ;
|
}
|
||||||
std::cout << " main: \n" ;
|
int offset = symbolTable[name].offset;
|
||||||
#endif
|
|
||||||
|
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);
|
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";
|
std::cout << " ret\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
antlrcpp::Any CodeGenVisitor::visitReturn_stmt(ifccParser::Return_stmtContext *ctx) {
|
||||||
antlrcpp::Any CodeGenVisitor::visitReturn_stmt(ifccParser::Return_stmtContext *ctx)
|
// Evaluate the return value into the accumulator register
|
||||||
{
|
this->visit(ctx->val());
|
||||||
int retval = stoi(ctx->val()->getText());
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
std::cout << " mov w0, #" << retval << "\n" ;
|
|
||||||
#else
|
|
||||||
std::cout << " movl $" << retval << ", %eax\n" ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +1,31 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
#include "antlr4-runtime.h"
|
#include "antlr4-runtime.h"
|
||||||
#include "generated/ifccBaseVisitor.h"
|
#include "generated/ifccBaseVisitor.h"
|
||||||
|
|
||||||
|
|
||||||
class CodeGenVisitor : public ifccBaseVisitor {
|
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:
|
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 ;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,10 @@
|
|||||||
int main() {
|
int main() {
|
||||||
|
int z;
|
||||||
int x;
|
int x;
|
||||||
x=42;
|
x = 56;
|
||||||
return x;
|
int y;
|
||||||
|
x = y;
|
||||||
|
y = 10;
|
||||||
|
z = x;
|
||||||
|
return z;
|
||||||
}
|
}
|
||||||
|
|||||||
10
testfiles/4_multiple_var.c
Normal file
10
testfiles/4_multiple_var.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
int main() {
|
||||||
|
int z;
|
||||||
|
int x;
|
||||||
|
x = 56;
|
||||||
|
int y;
|
||||||
|
y = 10;
|
||||||
|
x = y;
|
||||||
|
z = x;
|
||||||
|
return z;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user