From ac75f3fdddb0c62f79a885285426fe547d5a6c10 Mon Sep 17 00:00:00 2001 From: Lixuanwang Date: Sun, 9 Mar 2025 15:18:49 +0800 Subject: [PATCH 01/16] up dated gitignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ae0af5b..ae441e3 100644 --- a/.gitignore +++ b/.gitignore @@ -38,4 +38,6 @@ doxygen !/testdata/functional/*.out !/testdata/performance/*.out build -.antlr \ No newline at end of file +.antlr + +tmp \ No newline at end of file From b0b03ff55b18548bd78748aeaf511f6b201c6923 Mon Sep 17 00:00:00 2001 From: Lixuanwang Date: Mon, 10 Mar 2025 16:50:18 +0800 Subject: [PATCH 02/16] [lab2] runnable --- .gitignore | 6 +- src/SysYIRGenerator.cpp | 261 ++++++++++++++++++++++++++++++++++++---- src/SysYIRGenerator.h | 54 +++++---- src/sysyc.cpp | 31 +++-- 4 files changed, 288 insertions(+), 64 deletions(-) diff --git a/.gitignore b/.gitignore index ae441e3..3649ac4 100644 --- a/.gitignore +++ b/.gitignore @@ -40,4 +40,8 @@ doxygen build .antlr -tmp \ No newline at end of file +tmp + +GPATH +GRTAGS +GTAGS \ No newline at end of file diff --git a/src/SysYIRGenerator.cpp b/src/SysYIRGenerator.cpp index 3eccc14..1acead1 100644 --- a/src/SysYIRGenerator.cpp +++ b/src/SysYIRGenerator.cpp @@ -1,30 +1,239 @@ -#include "IR.h" -#include -#include -using namespace std; #include "SysYIRGenerator.h" +#include -namespace sysy { - -any SysYIRGenerator::visitCompUnit(SysYParser::CompUnitContext *ctx) { - // create the IR module - auto pModule = new Module(); - assert(pModule); - module.reset(pModule); - // generates globals and functions - visitChildren(ctx); - // return the IR module - return pModule; -} -std::any -SysYIRGenerator::visitFuncRParams(SysYParser::FuncRParamsContext *ctx) { - return visitChildren(ctx); -} -std::any SysYIRGenerator::visitNumber(SysYParser::NumberContext *ctx) { - return visitChildren(ctx); -} -std::any SysYIRGenerator::visitString(SysYParser::StringContext *ctx) { - return visitChildren(ctx); +std::string SysYIRGenerator::generateIR(SysYParser::CompUnitContext* unit) { + visitCompUnit(unit); + return irStream.str(); } -} // namespace sysy \ No newline at end of file +std::string SysYIRGenerator::getNextTemp() { + return "%" + std::to_string(tempCounter++); +} + +std::string SysYIRGenerator::getLLVMType(const std::string& type) { + if (type == "int") return "i32"; + if (type == "float") return "float"; + if (type.find("[]") != std::string::npos) + return getLLVMType(type.substr(0, type.size() - 2)) + "*"; + return "i32"; +} + +std::any SysYIRGenerator::visitCompUnit(SysYParser::CompUnitContext* ctx) { + for (auto decl : ctx->decl()) { + decl->accept(this); + } + for (auto funcDef : ctx->funcDef()) { + funcDef->accept(this); + } + return nullptr; +} + +std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext* ctx) { + // 常量声明暂不处理(LLVM IR 中常量通常内联) + return nullptr; +} + +std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext* ctx) { + for (auto varDef : ctx->varDef()) { + varDef->accept(this); + } + return nullptr; +} + +std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext* ctx) { + currentFunction = ctx->Ident()->getText(); + symbolTable.clear(); + + // 函数头 + std::string returnType = getLLVMType(ctx->funcType()->getText()); + irStream << "define " << returnType << " @" << currentFunction << "("; + + // 参数 + auto paramsCtx = ctx->funcFParams(); + if (paramsCtx) { + auto params = paramsCtx->funcFParam(); + for (size_t i = 0; i < params.size(); ++i) { + if (i > 0) irStream << ", "; + auto param = params[i]; + std::string paramName = "%" + std::to_string(i); + std::string paramType = getLLVMType(param->bType()->getText()); + irStream << paramType << " " << paramName; + + // 分配参数 + std::string allocaName = getNextTemp(); + symbolTable[param->Ident()->getText()] = allocaName; + irStream << "\n " << allocaName << " = alloca " << paramType; + irStream << "\n store " << paramType << " %" << i << ", " << paramType << "* " << allocaName; + } + } + irStream << ") {\nentry:\n"; + + // 函数体 + ctx->blockStmt()->accept(this); + + // 默认返回值 + if (returnType == "void") { + irStream << " ret void\n"; + } else { + irStream << " ret " << returnType << " 0\n"; + } + irStream << "}\n\n"; + return nullptr; +} + +std::any SysYIRGenerator::visitBlockStmt(SysYParser::BlockStmtContext* ctx) { + for (auto item : ctx->blockItem()) { + item->accept(this); + } + return nullptr; +} + +std::any SysYIRGenerator::visitStmt(SysYParser::StmtContext* ctx) { + if (ctx->lValue() && ctx->exp()) { + // 赋值语句 + std::string lhs = std::any_cast(ctx->lValue()->accept(this)); + std::string rhs = std::any_cast(ctx->exp()->accept(this)); + irStream << " store " << getLLVMType("") << " " << rhs << ", " << getLLVMType("") << "* " << lhs << "\n"; + } else if (ctx->RETURN()) { + // 返回语句 + if (ctx->exp()) { + std::string value = std::any_cast(ctx->exp()->accept(this)); + irStream << " ret " << getLLVMType("") << " " << value << "\n"; + } else { + irStream << " ret void\n"; + } + } + return nullptr; +} + +std::any SysYIRGenerator::visitLValue(SysYParser::LValueContext* ctx) { + std::string varName = ctx->Ident()->getText(); + if (symbolTable.find(varName) == symbolTable.end()) { + std::string allocaName = getNextTemp(); + symbolTable[varName] = allocaName; + irStream << " " << allocaName << " = alloca " << getLLVMType("") << "\n"; + } + return symbolTable[varName]; +} + +std::any SysYIRGenerator::visitNumber(SysYParser::NumberContext* ctx) { + if (ctx->ILITERAL()) { + return "i32 " + ctx->ILITERAL()->getText(); + } else if (ctx->FLITERAL()) { + return "float " + ctx->FLITERAL()->getText(); + } + return ""; +} + +std::any SysYIRGenerator::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { + if (ctx->unaryOp()) { + std::string operand = std::any_cast(ctx->unaryExp()->accept(this)); + std::string op = ctx->unaryOp()->getText(); + std::string temp = getNextTemp(); + if (op == "-") { + irStream << " " << temp << " = sub " << getLLVMType("") << " 0, " << operand << "\n"; + } else if (op == "!") { + irStream << " " << temp << " = xor " << getLLVMType("") << " " << operand << ", 1\n"; + } + return temp; + } + return ctx->primaryExp()->accept(this); +} + +std::any SysYIRGenerator::visitMulExp(SysYParser::MulExpContext* ctx) { + auto unaryExps = ctx->unaryExp(); + std::string left = std::any_cast(unaryExps[0]->accept(this)); + for (size_t i = 1; i < unaryExps.size(); ++i) { + std::string right = std::any_cast(unaryExps[i]->accept(this)); + std::string op = ctx->children[2 * i - 1]->getText(); + std::string temp = getNextTemp(); + if (op == "*") { + irStream << " " << temp << " = mul " << getLLVMType("") << " " << left << ", " << right << "\n"; + } else if (op == "/") { + irStream << " " << temp << " = sdiv " << getLLVMType("") << " " << left << ", " << right << "\n"; + } else if (op == "%") { + irStream << " " << temp << " = srem " << getLLVMType("") << " " << left << ", " << right << "\n"; + } + left = temp; + } + return left; +} + +std::any SysYIRGenerator::visitAddExp(SysYParser::AddExpContext* ctx) { + auto mulExps = ctx->mulExp(); + std::string left = std::any_cast(mulExps[0]->accept(this)); + for (size_t i = 1; i < mulExps.size(); ++i) { + std::string right = std::any_cast(mulExps[i]->accept(this)); + std::string op = ctx->children[2 * i - 1]->getText(); + std::string temp = getNextTemp(); + if (op == "+") { + irStream << " " << temp << " = add " << getLLVMType("") << " " << left << ", " << right << "\n"; + } else if (op == "-") { + irStream << " " << temp << " = sub " << getLLVMType("") << " " << left << ", " << right << "\n"; + } + left = temp; + } + return left; +} + +std::any SysYIRGenerator::visitRelExp(SysYParser::RelExpContext* ctx) { + auto addExps = ctx->addExp(); + std::string left = std::any_cast(addExps[0]->accept(this)); + for (size_t i = 1; i < addExps.size(); ++i) { + std::string right = std::any_cast(addExps[i]->accept(this)); + std::string op = ctx->children[2 * i - 1]->getText(); + std::string temp = getNextTemp(); + if (op == "<") { + irStream << " " << temp << " = icmp slt " << getLLVMType("") << " " << left << ", " << right << "\n"; + } else if (op == ">") { + irStream << " " << temp << " = icmp sgt " << getLLVMType("") << " " << left << ", " << right << "\n"; + } else if (op == "<=") { + irStream << " " << temp << " = icmp sle " << getLLVMType("") << " " << left << ", " << right << "\n"; + } else if (op == ">=") { + irStream << " " << temp << " = icmp sge " << getLLVMType("") << " " << left << ", " << right << "\n"; + } + left = temp; + } + return left; +} + +std::any SysYIRGenerator::visitEqExp(SysYParser::EqExpContext* ctx) { + auto relExps = ctx->relExp(); + std::string left = std::any_cast(relExps[0]->accept(this)); + for (size_t i = 1; i < relExps.size(); ++i) { + std::string right = std::any_cast(relExps[i]->accept(this)); + std::string op = ctx->children[2 * i - 1]->getText(); + std::string temp = getNextTemp(); + if (op == "==") { + irStream << " " << temp << " = icmp eq " << getLLVMType("") << " " << left << ", " << right << "\n"; + } else if (op == "!=") { + irStream << " " << temp << " = icmp ne " << getLLVMType("") << " " << left << ", " << right << "\n"; + } + left = temp; + } + return left; +} + +std::any SysYIRGenerator::visitLAndExp(SysYParser::LAndExpContext* ctx) { + auto eqExps = ctx->eqExp(); + std::string left = std::any_cast(eqExps[0]->accept(this)); + for (size_t i = 1; i < eqExps.size(); ++i) { + std::string right = std::any_cast(eqExps[i]->accept(this)); + std::string temp = getNextTemp(); + irStream << " " << temp << " = and " << getLLVMType("") << " " << left << ", " << right << "\n"; + left = temp; + } + return left; +} + +std::any SysYIRGenerator::visitLOrExp(SysYParser::LOrExpContext* ctx) { + auto lAndExps = ctx->lAndExp(); + std::string left = std::any_cast(lAndExps[0]->accept(this)); + for (size_t i = 1; i < lAndExps.size(); ++i) { + std::string right = std::any_cast(lAndExps[i]->accept(this)); + std::string temp = getNextTemp(); + irStream << " " << temp << " = or " << getLLVMType("") << " " << left << ", " << right << "\n"; + left = temp; + } + return left; +} \ No newline at end of file diff --git a/src/SysYIRGenerator.h b/src/SysYIRGenerator.h index bfc1865..c11d8ab 100644 --- a/src/SysYIRGenerator.h +++ b/src/SysYIRGenerator.h @@ -1,29 +1,41 @@ #pragma once - -#include "IR.h" -#include "IRBuilder.h" #include "SysYBaseVisitor.h" #include "SysYParser.h" -#include - -namespace sysy { +#include +#include +#include class SysYIRGenerator : public SysYBaseVisitor { +public: + std::string generateIR(SysYParser::CompUnitContext* unit); // 公共接口,用于生成 IR + std::string getIR() const { return irStream.str(); } // 获取生成的 IR + private: - std::unique_ptr module; - IRBuilder builder; + std::stringstream irStream; + int tempCounter = 0; + std::map symbolTable; // 符号表 + std::vector globalVars; // 全局变量 + std::string currentFunction; // 当前函数名 + std::vector breakStack; // break 目标标签栈 + std::vector continueStack; // continue 目标标签栈 -public: - SysYIRGenerator() = default; + std::string getNextTemp(); // 获取下一个临时变量名 + std::string getLLVMType(const std::string& type); // 获取 LLVM 类型 -public: - Module *get() const { return module.get(); } - -public: - std::any visitCompUnit(SysYParser::CompUnitContext *ctx) override; - std::any visitFuncRParams(SysYParser::FuncRParamsContext *ctx) override; - std::any visitNumber(SysYParser::NumberContext *ctx) override; - std::any visitString(SysYParser::StringContext *ctx) override; -}; // class SysYIRGenerator - -} // namespace sysy \ No newline at end of file + // 访问方法 + std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override; + std::any visitConstDecl(SysYParser::ConstDeclContext* ctx) override; + std::any visitVarDecl(SysYParser::VarDeclContext* ctx) override; + std::any visitFuncDef(SysYParser::FuncDefContext* ctx) override; + std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override; + std::any visitStmt(SysYParser::StmtContext* ctx) override; + std::any visitLValue(SysYParser::LValueContext* ctx) override; + std::any visitNumber(SysYParser::NumberContext* ctx) override; + std::any visitUnaryExp(SysYParser::UnaryExpContext* ctx) override; + std::any visitMulExp(SysYParser::MulExpContext* ctx) override; + std::any visitAddExp(SysYParser::AddExpContext* ctx) override; + std::any visitRelExp(SysYParser::RelExpContext* ctx) override; + std::any visitEqExp(SysYParser::EqExpContext* ctx) override; + std::any visitLAndExp(SysYParser::LAndExpContext* ctx) override; + std::any visitLOrExp(SysYParser::LOrExpContext* ctx) override; +}; \ No newline at end of file diff --git a/src/sysyc.cpp b/src/sysyc.cpp index d18df3c..b67c12d 100644 --- a/src/sysyc.cpp +++ b/src/sysyc.cpp @@ -18,9 +18,9 @@ static bool argFormat = false; void usage(int code = EXIT_FAILURE) { const char *msg = "Usage: sysyc [options] inputfile\n\n" "Supported options:\n" - " -h \tprint help message and exit\n"; - " -f \tpretty-format the input file\n"; - " -s {ast,ir,asm}\tstop after generating AST/IR/Assembly\n"; + " -h \tprint help message and exit\n" + " -f \tpretty-format the input file\n" + " -s {ast,ir,asm}\tstop after generating AST/IR/Assembly\n"; cerr << msg; exit(code); } @@ -51,14 +51,14 @@ void parseArgs(int argc, char **argv) { int main(int argc, char **argv) { parseArgs(argc, argv); - // open the input file + // 打开输入文件 ifstream fin(argInputFile); if (not fin) { cerr << "Failed to open file " << argv[1]; return EXIT_FAILURE; } - // parse sysy source to AST + // 解析 SysY 源码为 AST ANTLRInputStream input(fin); SysYLexer lexer(&input); CommonTokenStream tokens(&lexer); @@ -69,28 +69,27 @@ int main(int argc, char **argv) { return EXIT_SUCCESS; } - // pretty format the input file + // 格式化输入文件 if (argFormat) { ASTPrinter printer; printer.visitCompUnit(moduleAST); return EXIT_SUCCESS; } - // visit AST to generate IR + // 遍历 AST 生成 IR SysYIRGenerator generator; - generator.visitCompUnit(moduleAST); - auto moduleIR = generator.get(); + generator.generateIR(moduleAST); // 使用公共接口生成 IR if (argStopAfter == "ir") { - moduleIR->print(cout); + cout << generator.getIR(); // 输出生成的 IR return EXIT_SUCCESS; } - // generate assembly - CodeGen codegen(moduleIR); - string asmCode = codegen.code_gen(); - cout << asmCode << endl; - if (argStopAfter == "asm") - return EXIT_SUCCESS; + // // 生成汇编代码 + // CodeGen codegen(generator.getIR()); // 假设 CodeGen 接受字符串作为输入 + // string asmCode = codegen.code_gen(); + // cout << asmCode << endl; + // if (argStopAfter == "asm") + // return EXIT_SUCCESS; return EXIT_SUCCESS; } \ No newline at end of file From 3d60a94894a3541b84e9a49fadd54fd83ba5b0ab Mon Sep 17 00:00:00 2001 From: Lixuanwang Date: Mon, 10 Mar 2025 21:43:20 +0800 Subject: [PATCH 03/16] [lab2] testfile01 finished --- src/SysYIRGenerator.cpp | 129 ++++++++++++++++++++++++---------------- src/SysYIRGenerator.h | 26 ++++---- test/10_test.sy | 2 +- 3 files changed, 93 insertions(+), 64 deletions(-) diff --git a/src/SysYIRGenerator.cpp b/src/SysYIRGenerator.cpp index 1acead1..55e4396 100644 --- a/src/SysYIRGenerator.cpp +++ b/src/SysYIRGenerator.cpp @@ -1,3 +1,4 @@ +// SysYIRGenerator.cpp #include "SysYIRGenerator.h" #include @@ -14,7 +15,7 @@ std::string SysYIRGenerator::getLLVMType(const std::string& type) { if (type == "int") return "i32"; if (type == "float") return "float"; if (type.find("[]") != std::string::npos) - return getLLVMType(type.substr(0, type.size() - 2)) + "*"; + return getLLVMType(type.substr(0, type.size()-2)) + "*"; return "i32"; } @@ -29,26 +30,40 @@ std::any SysYIRGenerator::visitCompUnit(SysYParser::CompUnitContext* ctx) { } std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext* ctx) { - // 常量声明暂不处理(LLVM IR 中常量通常内联) return nullptr; } std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext* ctx) { + std::string type = ctx->bType()->getText(); for (auto varDef : ctx->varDef()) { + symbolTable[varDef->Ident()->getText()].second = type; varDef->accept(this); } return nullptr; } +std::any SysYIRGenerator::visitVarDef(SysYParser::VarDefContext* ctx) { + std::string varName = ctx->Ident()->getText(); + std::string type = symbolTable[varName].second; + std::string llvmType = getLLVMType(type); + std::string allocaName = getNextTemp(); + symbolTable[varName] = {allocaName, llvmType}; + irStream << " " << allocaName << " = alloca " << llvmType << ", align " << (type == "float" ? "4" : "4") << "\n"; + + if (ctx->ASSIGN()) { + std::string value = std::any_cast(ctx->initVal()->accept(this)); + irStream << " store " << llvmType << " " << value << ", " << llvmType << "* " << allocaName << ", align " << (type == "float" ? "4" : "4") << "\n"; + } + return nullptr; +} + std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext* ctx) { currentFunction = ctx->Ident()->getText(); + currentReturnType = getLLVMType(ctx->funcType()->getText()); symbolTable.clear(); + hasReturn = false; - // 函数头 - std::string returnType = getLLVMType(ctx->funcType()->getText()); - irStream << "define " << returnType << " @" << currentFunction << "("; - - // 参数 + irStream << "define " << currentReturnType << " @" << currentFunction << "("; auto paramsCtx = ctx->funcFParams(); if (paramsCtx) { auto params = paramsCtx->funcFParam(); @@ -58,26 +73,22 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext* ctx) { std::string paramName = "%" + std::to_string(i); std::string paramType = getLLVMType(param->bType()->getText()); irStream << paramType << " " << paramName; - - // 分配参数 std::string allocaName = getNextTemp(); - symbolTable[param->Ident()->getText()] = allocaName; - irStream << "\n " << allocaName << " = alloca " << paramType; - irStream << "\n store " << paramType << " %" << i << ", " << paramType << "* " << allocaName; + symbolTable[param->Ident()->getText()] = {allocaName, paramType}; + irStream << "\n " << allocaName << " = alloca " << paramType << ", align " << (paramType == "float" ? "4" : "4"); + irStream << "\n store " << paramType << " %" << i << ", " << paramType << "* " << allocaName << ", align " << (paramType == "float" ? "4" : "4"); } } irStream << ") {\nentry:\n"; - - // 函数体 ctx->blockStmt()->accept(this); - - // 默认返回值 - if (returnType == "void") { - irStream << " ret void\n"; - } else { - irStream << " ret " << returnType << " 0\n"; + if (!hasReturn) { + if (currentReturnType == "void") { + irStream << " ret void\n"; + } else { + irStream << " ret " << currentReturnType << " 0\n"; + } } - irStream << "}\n\n"; + irStream << "}\n"; return nullptr; } @@ -89,16 +100,17 @@ std::any SysYIRGenerator::visitBlockStmt(SysYParser::BlockStmtContext* ctx) { } std::any SysYIRGenerator::visitStmt(SysYParser::StmtContext* ctx) { - if (ctx->lValue() && ctx->exp()) { - // 赋值语句 - std::string lhs = std::any_cast(ctx->lValue()->accept(this)); + if (ctx->lValue() && ctx->ASSIGN()) { + std::string lhsAlloca = std::any_cast(ctx->lValue()->accept(this)); + std::string varName = ctx->lValue()->Ident()->getText(); + std::string lhsType = symbolTable[varName].second; std::string rhs = std::any_cast(ctx->exp()->accept(this)); - irStream << " store " << getLLVMType("") << " " << rhs << ", " << getLLVMType("") << "* " << lhs << "\n"; + irStream << " store " << lhsType << " " << rhs << ", " << lhsType << "* " << lhsAlloca << ", align " << (lhsType == "float" ? "4" : "4") << "\n"; } else if (ctx->RETURN()) { - // 返回语句 + hasReturn = true; if (ctx->exp()) { std::string value = std::any_cast(ctx->exp()->accept(this)); - irStream << " ret " << getLLVMType("") << " " << value << "\n"; + irStream << " ret " << currentReturnType << " " << value << "\n"; } else { irStream << " ret void\n"; } @@ -108,12 +120,22 @@ std::any SysYIRGenerator::visitStmt(SysYParser::StmtContext* ctx) { std::any SysYIRGenerator::visitLValue(SysYParser::LValueContext* ctx) { std::string varName = ctx->Ident()->getText(); - if (symbolTable.find(varName) == symbolTable.end()) { - std::string allocaName = getNextTemp(); - symbolTable[varName] = allocaName; - irStream << " " << allocaName << " = alloca " << getLLVMType("") << "\n"; + return symbolTable[varName].first; +} + +std::any SysYIRGenerator::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) { + if (ctx->lValue()) { + std::string allocaPtr = std::any_cast(ctx->lValue()->accept(this)); + std::string varName = ctx->lValue()->Ident()->getText(); + std::string type = symbolTable[varName].second; + std::string temp = getNextTemp(); + irStream << " " << temp << " = load " << type << ", " << type << "* " << allocaPtr << ", align " << (type == "float" ? "4" : "4") << "\n"; + return temp; + } else if (ctx->exp()) { + return ctx->exp()->accept(this); + } else { + return ctx->number()->accept(this); } - return symbolTable[varName]; } std::any SysYIRGenerator::visitNumber(SysYParser::NumberContext* ctx) { @@ -130,10 +152,11 @@ std::any SysYIRGenerator::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { std::string operand = std::any_cast(ctx->unaryExp()->accept(this)); std::string op = ctx->unaryOp()->getText(); std::string temp = getNextTemp(); + std::string type = operand.substr(0, operand.find(' ')); if (op == "-") { - irStream << " " << temp << " = sub " << getLLVMType("") << " 0, " << operand << "\n"; + irStream << " " << temp << " = sub " << type << " 0, " << operand << "\n"; } else if (op == "!") { - irStream << " " << temp << " = xor " << getLLVMType("") << " " << operand << ", 1\n"; + irStream << " " << temp << " = xor " << type << " " << operand << ", 1\n"; } return temp; } @@ -145,14 +168,15 @@ std::any SysYIRGenerator::visitMulExp(SysYParser::MulExpContext* ctx) { std::string left = std::any_cast(unaryExps[0]->accept(this)); for (size_t i = 1; i < unaryExps.size(); ++i) { std::string right = std::any_cast(unaryExps[i]->accept(this)); - std::string op = ctx->children[2 * i - 1]->getText(); + std::string op = ctx->children[2*i-1]->getText(); std::string temp = getNextTemp(); + std::string type = left.substr(0, left.find(' ')); if (op == "*") { - irStream << " " << temp << " = mul " << getLLVMType("") << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = mul " << type << " " << left << ", " << right << "\n"; } else if (op == "/") { - irStream << " " << temp << " = sdiv " << getLLVMType("") << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = sdiv " << type << " " << left << ", " << right << "\n"; } else if (op == "%") { - irStream << " " << temp << " = srem " << getLLVMType("") << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = srem " << type << " " << left << ", " << right << "\n"; } left = temp; } @@ -164,12 +188,13 @@ std::any SysYIRGenerator::visitAddExp(SysYParser::AddExpContext* ctx) { std::string left = std::any_cast(mulExps[0]->accept(this)); for (size_t i = 1; i < mulExps.size(); ++i) { std::string right = std::any_cast(mulExps[i]->accept(this)); - std::string op = ctx->children[2 * i - 1]->getText(); + std::string op = ctx->children[2*i-1]->getText(); std::string temp = getNextTemp(); + std::string type = left.substr(0, left.find(' ')); if (op == "+") { - irStream << " " << temp << " = add " << getLLVMType("") << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = add " << type << " " << left << ", " << right << "\n"; } else if (op == "-") { - irStream << " " << temp << " = sub " << getLLVMType("") << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = sub " << type << " " << left << ", " << right << "\n"; } left = temp; } @@ -181,16 +206,17 @@ std::any SysYIRGenerator::visitRelExp(SysYParser::RelExpContext* ctx) { std::string left = std::any_cast(addExps[0]->accept(this)); for (size_t i = 1; i < addExps.size(); ++i) { std::string right = std::any_cast(addExps[i]->accept(this)); - std::string op = ctx->children[2 * i - 1]->getText(); + std::string op = ctx->children[2*i-1]->getText(); std::string temp = getNextTemp(); + std::string type = left.substr(0, left.find(' ')); if (op == "<") { - irStream << " " << temp << " = icmp slt " << getLLVMType("") << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = icmp slt " << type << " " << left << ", " << right << "\n"; } else if (op == ">") { - irStream << " " << temp << " = icmp sgt " << getLLVMType("") << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = icmp sgt " << type << " " << left << ", " << right << "\n"; } else if (op == "<=") { - irStream << " " << temp << " = icmp sle " << getLLVMType("") << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = icmp sle " << type << " " << left << ", " << right << "\n"; } else if (op == ">=") { - irStream << " " << temp << " = icmp sge " << getLLVMType("") << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = icmp sge " << type << " " << left << ", " << right << "\n"; } left = temp; } @@ -202,12 +228,13 @@ std::any SysYIRGenerator::visitEqExp(SysYParser::EqExpContext* ctx) { std::string left = std::any_cast(relExps[0]->accept(this)); for (size_t i = 1; i < relExps.size(); ++i) { std::string right = std::any_cast(relExps[i]->accept(this)); - std::string op = ctx->children[2 * i - 1]->getText(); + std::string op = ctx->children[2*i-1]->getText(); std::string temp = getNextTemp(); + std::string type = left.substr(0, left.find(' ')); if (op == "==") { - irStream << " " << temp << " = icmp eq " << getLLVMType("") << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = icmp eq " << type << " " << left << ", " << right << "\n"; } else if (op == "!=") { - irStream << " " << temp << " = icmp ne " << getLLVMType("") << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = icmp ne " << type << " " << left << ", " << right << "\n"; } left = temp; } @@ -220,7 +247,7 @@ std::any SysYIRGenerator::visitLAndExp(SysYParser::LAndExpContext* ctx) { for (size_t i = 1; i < eqExps.size(); ++i) { std::string right = std::any_cast(eqExps[i]->accept(this)); std::string temp = getNextTemp(); - irStream << " " << temp << " = and " << getLLVMType("") << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = and i1 " << left << ", " << right << "\n"; left = temp; } return left; @@ -232,7 +259,7 @@ std::any SysYIRGenerator::visitLOrExp(SysYParser::LOrExpContext* ctx) { for (size_t i = 1; i < lAndExps.size(); ++i) { std::string right = std::any_cast(lAndExps[i]->accept(this)); std::string temp = getNextTemp(); - irStream << " " << temp << " = or " << getLLVMType("") << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = or i1 " << left << ", " << right << "\n"; left = temp; } return left; diff --git a/src/SysYIRGenerator.h b/src/SysYIRGenerator.h index c11d8ab..0f1b362 100644 --- a/src/SysYIRGenerator.h +++ b/src/SysYIRGenerator.h @@ -1,3 +1,4 @@ +// SysYIRGenerator.h #pragma once #include "SysYBaseVisitor.h" #include "SysYParser.h" @@ -7,29 +8,30 @@ class SysYIRGenerator : public SysYBaseVisitor { public: - std::string generateIR(SysYParser::CompUnitContext* unit); // 公共接口,用于生成 IR - std::string getIR() const { return irStream.str(); } // 获取生成的 IR - + std::string generateIR(SysYParser::CompUnitContext* unit); + std::string getIR() const { return irStream.str(); } private: std::stringstream irStream; int tempCounter = 0; - std::map symbolTable; // 符号表 - std::vector globalVars; // 全局变量 - std::string currentFunction; // 当前函数名 - std::vector breakStack; // break 目标标签栈 - std::vector continueStack; // continue 目标标签栈 + std::map> symbolTable; // {varName: {allocaName, type}} + std::vector globalVars; + std::string currentFunction; + std::string currentReturnType; + std::vector breakStack; + std::vector continueStack; + bool hasReturn = false; - std::string getNextTemp(); // 获取下一个临时变量名 - std::string getLLVMType(const std::string& type); // 获取 LLVM 类型 - - // 访问方法 + std::string getNextTemp(); + std::string getLLVMType(const std::string& type); std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override; std::any visitConstDecl(SysYParser::ConstDeclContext* ctx) override; std::any visitVarDecl(SysYParser::VarDeclContext* ctx) override; + std::any visitVarDef(SysYParser::VarDefContext* ctx) override; std::any visitFuncDef(SysYParser::FuncDefContext* ctx) override; std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override; std::any visitStmt(SysYParser::StmtContext* ctx) override; std::any visitLValue(SysYParser::LValueContext* ctx) override; + std::any visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) override; std::any visitNumber(SysYParser::NumberContext* ctx) override; std::any visitUnaryExp(SysYParser::UnaryExpContext* ctx) override; std::any visitMulExp(SysYParser::MulExpContext* ctx) override; diff --git a/test/10_test.sy b/test/10_test.sy index 05dab29..bf84af2 100644 --- a/test/10_test.sy +++ b/test/10_test.sy @@ -1,7 +1,7 @@ //test file for backend lab int main() { - const int a = 1; + int a; const int b = 2; int c; From 57ccf6f0e3d56c8bf43a0bede1279fdea20a014d Mon Sep 17 00:00:00 2001 From: Lixuanwang Date: Wed, 12 Mar 2025 16:11:06 +0800 Subject: [PATCH 04/16] [lab2]bugs fixed,but more bugs rised up --- src/SysYIRGenerator.cpp | 132 ++++++++++++++++++++++++++++++++-------- src/SysYIRGenerator.h | 9 ++- 2 files changed, 112 insertions(+), 29 deletions(-) diff --git a/src/SysYIRGenerator.cpp b/src/SysYIRGenerator.cpp index 55e4396..f38db5c 100644 --- a/src/SysYIRGenerator.cpp +++ b/src/SysYIRGenerator.cpp @@ -1,4 +1,3 @@ -// SysYIRGenerator.cpp #include "SysYIRGenerator.h" #include @@ -30,6 +29,21 @@ std::any SysYIRGenerator::visitCompUnit(SysYParser::CompUnitContext* ctx) { } std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext* ctx) { + std::string type = ctx->bType()->getText(); + for (auto constDef : ctx->constDef()) { + std::string varName = constDef->Ident()->getText(); + symbolTable[varName].second = type; + std::string llvmType = getLLVMType(type); + std::string allocaName = getNextTemp(); + symbolTable[varName] = {allocaName, llvmType}; + irStream << " " << allocaName << " = alloca " << llvmType << ", align 4\n"; + + if (constDef->constInitVal()) { + std::string value = std::any_cast(constDef->constInitVal()->accept(this)); + irStream << " store " << llvmType << " " << value << ", " << llvmType + << "* " << allocaName << ", align 4\n"; + } + } return nullptr; } @@ -48,11 +62,12 @@ std::any SysYIRGenerator::visitVarDef(SysYParser::VarDefContext* ctx) { std::string llvmType = getLLVMType(type); std::string allocaName = getNextTemp(); symbolTable[varName] = {allocaName, llvmType}; - irStream << " " << allocaName << " = alloca " << llvmType << ", align " << (type == "float" ? "4" : "4") << "\n"; + irStream << " " << allocaName << " = alloca " << llvmType << ", align 4\n"; if (ctx->ASSIGN()) { std::string value = std::any_cast(ctx->initVal()->accept(this)); - irStream << " store " << llvmType << " " << value << ", " << llvmType << "* " << allocaName << ", align " << (type == "float" ? "4" : "4") << "\n"; + irStream << " store " << llvmType << " " << value << ", " << llvmType + << "* " << allocaName << ", align 4\n"; } return nullptr; } @@ -62,25 +77,30 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext* ctx) { currentReturnType = getLLVMType(ctx->funcType()->getText()); symbolTable.clear(); hasReturn = false; - - irStream << "define " << currentReturnType << " @" << currentFunction << "("; - auto paramsCtx = ctx->funcFParams(); - if (paramsCtx) { - auto params = paramsCtx->funcFParam(); + tempCounter = 0; + + irStream << "define dso_local " << currentReturnType << " @" << currentFunction << "("; + if (ctx->funcFParams()) { + auto params = ctx->funcFParams()->funcFParam(); for (size_t i = 0; i < params.size(); ++i) { if (i > 0) irStream << ", "; - auto param = params[i]; - std::string paramName = "%" + std::to_string(i); - std::string paramType = getLLVMType(param->bType()->getText()); - irStream << paramType << " " << paramName; - std::string allocaName = getNextTemp(); - symbolTable[param->Ident()->getText()] = {allocaName, paramType}; - irStream << "\n " << allocaName << " = alloca " << paramType << ", align " << (paramType == "float" ? "4" : "4"); - irStream << "\n store " << paramType << " %" << i << ", " << paramType << "* " << allocaName << ", align " << (paramType == "float" ? "4" : "4"); + std::string paramType = getLLVMType(params[i]->bType()->getText()); + irStream << paramType << " noundef %" << i; } } - irStream << ") {\nentry:\n"; + irStream << ") #0 {\nentry:\n"; + + if (ctx->funcFParams()) { + auto params = ctx->funcFParams()->funcFParam(); + for (size_t i = 0; i < params.size(); ++i) { + std::string paramName = params[i]->Ident()->getText(); + std::string paramType = getLLVMType(params[i]->bType()->getText()); + symbolTable[paramName] = {"%" + std::to_string(i), paramType}; + } + } + ctx->blockStmt()->accept(this); + if (!hasReturn) { if (currentReturnType == "void") { irStream << " ret void\n"; @@ -88,7 +108,7 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext* ctx) { irStream << " ret " << currentReturnType << " 0\n"; } } - irStream << "}\n"; + irStream << "}\n\n"; return nullptr; } @@ -105,7 +125,8 @@ std::any SysYIRGenerator::visitStmt(SysYParser::StmtContext* ctx) { std::string varName = ctx->lValue()->Ident()->getText(); std::string lhsType = symbolTable[varName].second; std::string rhs = std::any_cast(ctx->exp()->accept(this)); - irStream << " store " << lhsType << " " << rhs << ", " << lhsType << "* " << lhsAlloca << ", align " << (lhsType == "float" ? "4" : "4") << "\n"; + irStream << " store " << lhsType << " " << rhs << ", " << lhsType + << "* " << lhsAlloca << ", align 4\n"; } else if (ctx->RETURN()) { hasReturn = true; if (ctx->exp()) { @@ -114,6 +135,25 @@ std::any SysYIRGenerator::visitStmt(SysYParser::StmtContext* ctx) { } else { irStream << " ret void\n"; } + } else if (ctx->IF()) { + std::string cond = std::any_cast(ctx->cond()->accept(this)); + std::string trueLabel = "if.then." + std::to_string(tempCounter); + std::string falseLabel = "if.else." + std::to_string(tempCounter); + std::string mergeLabel = "if.end." + std::to_string(tempCounter++); + + irStream << " br i1 " << cond << ", label %" << trueLabel << ", label %" << falseLabel << "\n\n"; + + irStream << trueLabel << ":\n"; + ctx->stmt(0)->accept(this); + irStream << " br label %" << mergeLabel << "\n\n"; + + irStream << falseLabel << ":\n"; + if (ctx->ELSE()) { + ctx->stmt(1)->accept(this); + } + irStream << " br label %" << mergeLabel << "\n\n"; + + irStream << mergeLabel << ":\n"; } return nullptr; } @@ -129,7 +169,7 @@ std::any SysYIRGenerator::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) { std::string varName = ctx->lValue()->Ident()->getText(); std::string type = symbolTable[varName].second; std::string temp = getNextTemp(); - irStream << " " << temp << " = load " << type << ", " << type << "* " << allocaPtr << ", align " << (type == "float" ? "4" : "4") << "\n"; + irStream << " " << temp << " = load " << type << ", " << type << "* " << allocaPtr << ", align 4\n"; return temp; } else if (ctx->exp()) { return ctx->exp()->accept(this); @@ -159,6 +199,24 @@ std::any SysYIRGenerator::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { irStream << " " << temp << " = xor " << type << " " << operand << ", 1\n"; } return temp; + } else if (ctx->Ident()) { + std::string funcName = ctx->Ident()->getText(); + std::vector args; + if (ctx->funcRParams()) { + for (auto argCtx : ctx->funcRParams()->exp()) { + args.push_back(std::any_cast(argCtx->accept(this))); + } + } + + std::string temp = getNextTemp(); + std::string argList = ""; + for (size_t i = 0; i < args.size(); ++i) { + if (i > 0) argList += ", "; + argList += args[i]; + } + + irStream << " " << temp << " = call " << currentReturnType << " @" << funcName << "(" << argList << ")\n"; + return temp; } return ctx->primaryExp()->accept(this); } @@ -172,7 +230,7 @@ std::any SysYIRGenerator::visitMulExp(SysYParser::MulExpContext* ctx) { std::string temp = getNextTemp(); std::string type = left.substr(0, left.find(' ')); if (op == "*") { - irStream << " " << temp << " = mul " << type << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = mul nsw " << type << " " << left << ", " << right << "\n"; } else if (op == "/") { irStream << " " << temp << " = sdiv " << type << " " << left << ", " << right << "\n"; } else if (op == "%") { @@ -192,9 +250,9 @@ std::any SysYIRGenerator::visitAddExp(SysYParser::AddExpContext* ctx) { std::string temp = getNextTemp(); std::string type = left.substr(0, left.find(' ')); if (op == "+") { - irStream << " " << temp << " = add " << type << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = add nsw " << type << " " << left << ", " << right << "\n"; } else if (op == "-") { - irStream << " " << temp << " = sub " << type << " " << left << ", " << right << "\n"; + irStream << " " << temp << " = sub nsw " << type << " " << left << ", " << right << "\n"; } left = temp; } @@ -245,9 +303,19 @@ std::any SysYIRGenerator::visitLAndExp(SysYParser::LAndExpContext* ctx) { auto eqExps = ctx->eqExp(); std::string left = std::any_cast(eqExps[0]->accept(this)); for (size_t i = 1; i < eqExps.size(); ++i) { - std::string right = std::any_cast(eqExps[i]->accept(this)); + std::string falseLabel = "land.false." + std::to_string(tempCounter); + std::string endLabel = "land.end." + std::to_string(tempCounter++); std::string temp = getNextTemp(); - irStream << " " << temp << " = and i1 " << left << ", " << right << "\n"; + + irStream << " " << temp << " = and i1 " << left << ", 1\n"; + irStream << " br i1 " << temp << ", label %" << falseLabel << ", label %" << endLabel << "\n\n"; + + irStream << falseLabel << ":\n"; + std::string right = std::any_cast(eqExps[i]->accept(this)); + irStream << " " << temp << " = and i1 " << temp << ", " << right << "\n"; + irStream << " br label %" << endLabel << "\n\n"; + + irStream << endLabel << ":\n"; left = temp; } return left; @@ -257,9 +325,19 @@ std::any SysYIRGenerator::visitLOrExp(SysYParser::LOrExpContext* ctx) { auto lAndExps = ctx->lAndExp(); std::string left = std::any_cast(lAndExps[0]->accept(this)); for (size_t i = 1; i < lAndExps.size(); ++i) { - std::string right = std::any_cast(lAndExps[i]->accept(this)); + std::string trueLabel = "lor.true." + std::to_string(tempCounter); + std::string endLabel = "lor.end." + std::to_string(tempCounter++); std::string temp = getNextTemp(); - irStream << " " << temp << " = or i1 " << left << ", " << right << "\n"; + + irStream << " " << temp << " = or i1 " << left << ", 0\n"; + irStream << " br i1 " << temp << ", label %" << trueLabel << ", label %" << endLabel << "\n\n"; + + irStream << trueLabel << ":\n"; + std::string right = std::any_cast(lAndExps[i]->accept(this)); + irStream << " " << temp << " = or i1 " << temp << ", " << right << "\n"; + irStream << " br label %" << endLabel << "\n\n"; + + irStream << endLabel << ":\n"; left = temp; } return left; diff --git a/src/SysYIRGenerator.h b/src/SysYIRGenerator.h index 0f1b362..c65e1ff 100644 --- a/src/SysYIRGenerator.h +++ b/src/SysYIRGenerator.h @@ -1,28 +1,33 @@ -// SysYIRGenerator.h #pragma once #include "SysYBaseVisitor.h" #include "SysYParser.h" #include #include #include +#include class SysYIRGenerator : public SysYBaseVisitor { public: std::string generateIR(SysYParser::CompUnitContext* unit); std::string getIR() const { return irStream.str(); } + private: std::stringstream irStream; int tempCounter = 0; - std::map> symbolTable; // {varName: {allocaName, type}} + std::map> symbolTable; std::vector globalVars; std::string currentFunction; std::string currentReturnType; std::vector breakStack; std::vector continueStack; bool hasReturn = false; + std::stack loopEndStack; + std::stack loopCondStack; std::string getNextTemp(); std::string getLLVMType(const std::string& type); + + // 访问方法 std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override; std::any visitConstDecl(SysYParser::ConstDeclContext* ctx) override; std::any visitVarDecl(SysYParser::VarDeclContext* ctx) override; From ed4487716414dcee9d1ff93095499fb241ddd68b Mon Sep 17 00:00:00 2001 From: Lixuanwang Date: Wed, 19 Mar 2025 20:59:50 +0800 Subject: [PATCH 05/16] [lab2]some bugs fixed --- src/SysYIRGenerator.cpp | 52 ++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 34 deletions(-) diff --git a/src/SysYIRGenerator.cpp b/src/SysYIRGenerator.cpp index f38db5c..6fe421f 100644 --- a/src/SysYIRGenerator.cpp +++ b/src/SysYIRGenerator.cpp @@ -1,3 +1,4 @@ +// SysYIRGenerator.cpp #include "SysYIRGenerator.h" #include @@ -32,10 +33,9 @@ std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext* ctx) { std::string type = ctx->bType()->getText(); for (auto constDef : ctx->constDef()) { std::string varName = constDef->Ident()->getText(); - symbolTable[varName].second = type; std::string llvmType = getLLVMType(type); std::string allocaName = getNextTemp(); - symbolTable[varName] = {allocaName, llvmType}; + irStream << " " << allocaName << " = alloca " << llvmType << ", align 4\n"; if (constDef->constInitVal()) { @@ -43,6 +43,7 @@ std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext* ctx) { irStream << " store " << llvmType << " " << value << ", " << llvmType << "* " << allocaName << ", align 4\n"; } + symbolTable[varName] = {allocaName, llvmType}; } return nullptr; } @@ -50,7 +51,6 @@ std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext* ctx) { std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext* ctx) { std::string type = ctx->bType()->getText(); for (auto varDef : ctx->varDef()) { - symbolTable[varDef->Ident()->getText()].second = type; varDef->accept(this); } return nullptr; @@ -61,7 +61,7 @@ std::any SysYIRGenerator::visitVarDef(SysYParser::VarDefContext* ctx) { std::string type = symbolTable[varName].second; std::string llvmType = getLLVMType(type); std::string allocaName = getNextTemp(); - symbolTable[varName] = {allocaName, llvmType}; + irStream << " " << allocaName << " = alloca " << llvmType << ", align 4\n"; if (ctx->ASSIGN()) { @@ -69,6 +69,7 @@ std::any SysYIRGenerator::visitVarDef(SysYParser::VarDefContext* ctx) { irStream << " store " << llvmType << " " << value << ", " << llvmType << "* " << allocaName << ", align 4\n"; } + symbolTable[varName] = {allocaName, llvmType}; return nullptr; } @@ -86,18 +87,10 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext* ctx) { if (i > 0) irStream << ", "; std::string paramType = getLLVMType(params[i]->bType()->getText()); irStream << paramType << " noundef %" << i; + symbolTable[params[i]->Ident()->getText()] = {"%" + std::to_string(i), paramType}; } } - irStream << ") #0 {\nentry:\n"; - - if (ctx->funcFParams()) { - auto params = ctx->funcFParams()->funcFParam(); - for (size_t i = 0; i < params.size(); ++i) { - std::string paramName = params[i]->Ident()->getText(); - std::string paramType = getLLVMType(params[i]->bType()->getText()); - symbolTable[paramName] = {"%" + std::to_string(i), paramType}; - } - } + irStream << ") #0 {\n"; ctx->blockStmt()->accept(this); @@ -108,7 +101,7 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext* ctx) { irStream << " ret " << currentReturnType << " 0\n"; } } - irStream << "}\n\n"; + irStream << "}\n"; return nullptr; } @@ -122,8 +115,7 @@ std::any SysYIRGenerator::visitBlockStmt(SysYParser::BlockStmtContext* ctx) { std::any SysYIRGenerator::visitStmt(SysYParser::StmtContext* ctx) { if (ctx->lValue() && ctx->ASSIGN()) { std::string lhsAlloca = std::any_cast(ctx->lValue()->accept(this)); - std::string varName = ctx->lValue()->Ident()->getText(); - std::string lhsType = symbolTable[varName].second; + std::string lhsType = symbolTable[ctx->lValue()->Ident()->getText()].second; std::string rhs = std::any_cast(ctx->exp()->accept(this)); irStream << " store " << lhsType << " " << rhs << ", " << lhsType << "* " << lhsAlloca << ", align 4\n"; @@ -141,17 +133,17 @@ std::any SysYIRGenerator::visitStmt(SysYParser::StmtContext* ctx) { std::string falseLabel = "if.else." + std::to_string(tempCounter); std::string mergeLabel = "if.end." + std::to_string(tempCounter++); - irStream << " br i1 " << cond << ", label %" << trueLabel << ", label %" << falseLabel << "\n\n"; + irStream << " br i1 " << cond << ", label %" << trueLabel << ", label %" << falseLabel << "\n"; irStream << trueLabel << ":\n"; ctx->stmt(0)->accept(this); - irStream << " br label %" << mergeLabel << "\n\n"; + irStream << " br label %" << mergeLabel << "\n"; irStream << falseLabel << ":\n"; if (ctx->ELSE()) { ctx->stmt(1)->accept(this); } - irStream << " br label %" << mergeLabel << "\n\n"; + irStream << " br label %" << mergeLabel << "\n"; irStream << mergeLabel << ":\n"; } @@ -207,14 +199,12 @@ std::any SysYIRGenerator::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { args.push_back(std::any_cast(argCtx->accept(this))); } } - std::string temp = getNextTemp(); std::string argList = ""; for (size_t i = 0; i < args.size(); ++i) { if (i > 0) argList += ", "; argList += args[i]; } - irStream << " " << temp << " = call " << currentReturnType << " @" << funcName << "(" << argList << ")\n"; return temp; } @@ -307,14 +297,11 @@ std::any SysYIRGenerator::visitLAndExp(SysYParser::LAndExpContext* ctx) { std::string endLabel = "land.end." + std::to_string(tempCounter++); std::string temp = getNextTemp(); - irStream << " " << temp << " = and i1 " << left << ", 1\n"; - irStream << " br i1 " << temp << ", label %" << falseLabel << ", label %" << endLabel << "\n\n"; - + irStream << " br label %" << falseLabel << "\n"; irStream << falseLabel << ":\n"; std::string right = std::any_cast(eqExps[i]->accept(this)); - irStream << " " << temp << " = and i1 " << temp << ", " << right << "\n"; - irStream << " br label %" << endLabel << "\n\n"; - + irStream << " " << temp << " = and i1 " << left << ", " << right << "\n"; + irStream << " br label %" << endLabel << "\n"; irStream << endLabel << ":\n"; left = temp; } @@ -329,14 +316,11 @@ std::any SysYIRGenerator::visitLOrExp(SysYParser::LOrExpContext* ctx) { std::string endLabel = "lor.end." + std::to_string(tempCounter++); std::string temp = getNextTemp(); - irStream << " " << temp << " = or i1 " << left << ", 0\n"; - irStream << " br i1 " << temp << ", label %" << trueLabel << ", label %" << endLabel << "\n\n"; - + irStream << " br label %" << trueLabel << "\n"; irStream << trueLabel << ":\n"; std::string right = std::any_cast(lAndExps[i]->accept(this)); - irStream << " " << temp << " = or i1 " << temp << ", " << right << "\n"; - irStream << " br label %" << endLabel << "\n\n"; - + irStream << " " << temp << " = or i1 " << left << ", " << right << "\n"; + irStream << " br label %" << endLabel << "\n"; irStream << endLabel << ":\n"; left = temp; } From 5567f8278366f1e7324d9f6daa5b2be9abe65fae Mon Sep 17 00:00:00 2001 From: ladev789 Date: Sat, 22 Mar 2025 22:33:00 +0800 Subject: [PATCH 06/16] =?UTF-8?q?[lab2]=E4=BF=AE=E5=A4=8D=E4=BA=86?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E5=86=97=E4=BD=99=E9=94=99=E8=AF=AF=EF=BC=8C?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E4=B8=80=E4=BA=9B=E5=85=B6=E4=BB=96bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SysYIRGenerator.cpp | 47 +++++++++++++++++++++++++++++++++++------ src/SysYIRGenerator.h | 2 ++ test/01_add.sy | 14 +++++++----- 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/SysYIRGenerator.cpp b/src/SysYIRGenerator.cpp index 6fe421f..f221205 100644 --- a/src/SysYIRGenerator.cpp +++ b/src/SysYIRGenerator.cpp @@ -8,7 +8,9 @@ std::string SysYIRGenerator::generateIR(SysYParser::CompUnitContext* unit) { } std::string SysYIRGenerator::getNextTemp() { - return "%" + std::to_string(tempCounter++); + std::string ret = "%" + std::to_string(tempCounter++); + tmpTable[ret] = "void"; + return ret; } std::string SysYIRGenerator::getLLVMType(const std::string& type) { @@ -44,12 +46,14 @@ std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext* ctx) { << "* " << allocaName << ", align 4\n"; } symbolTable[varName] = {allocaName, llvmType}; + tmpTable[allocaName] = llvmType; } return nullptr; } std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext* ctx) { std::string type = ctx->bType()->getText(); + currentVarType = getLLVMType(type); for (auto varDef : ctx->varDef()) { varDef->accept(this); } @@ -58,7 +62,7 @@ std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext* ctx) { std::any SysYIRGenerator::visitVarDef(SysYParser::VarDefContext* ctx) { std::string varName = ctx->Ident()->getText(); - std::string type = symbolTable[varName].second; + std::string type = currentVarType; std::string llvmType = getLLVMType(type); std::string allocaName = getNextTemp(); @@ -66,10 +70,23 @@ std::any SysYIRGenerator::visitVarDef(SysYParser::VarDefContext* ctx) { if (ctx->ASSIGN()) { std::string value = std::any_cast(ctx->initVal()->accept(this)); + + if (llvmType == "float") { + try { + double floatValue = std::stod(value); + uint64_t hexValue = reinterpret_cast(floatValue); + std::stringstream ss; + ss << "0x" << std::hex << std::uppercase << hexValue; + value = ss.str(); + } catch (...) { + throw std::runtime_error("Invalid float literal: " + value); + } + } irStream << " store " << llvmType << " " << value << ", " << llvmType << "* " << allocaName << ", align 4\n"; } symbolTable[varName] = {allocaName, llvmType}; + tmpTable[allocaName] = llvmType; return nullptr; } @@ -78,18 +95,20 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext* ctx) { currentReturnType = getLLVMType(ctx->funcType()->getText()); symbolTable.clear(); hasReturn = false; - tempCounter = 0; irStream << "define dso_local " << currentReturnType << " @" << currentFunction << "("; if (ctx->funcFParams()) { auto params = ctx->funcFParams()->funcFParam(); + tempCounter += params.size(); for (size_t i = 0; i < params.size(); ++i) { if (i > 0) irStream << ", "; std::string paramType = getLLVMType(params[i]->bType()->getText()); irStream << paramType << " noundef %" << i; symbolTable[params[i]->Ident()->getText()] = {"%" + std::to_string(i), paramType}; + tmpTable["%" + std::to_string(i)] = paramType; } } + tempCounter++; irStream << ") #0 {\n"; ctx->blockStmt()->accept(this); @@ -117,6 +136,17 @@ std::any SysYIRGenerator::visitStmt(SysYParser::StmtContext* ctx) { std::string lhsAlloca = std::any_cast(ctx->lValue()->accept(this)); std::string lhsType = symbolTable[ctx->lValue()->Ident()->getText()].second; std::string rhs = std::any_cast(ctx->exp()->accept(this)); + if (lhsType == "float") { + try { + double floatValue = std::stod(rhs); + uint64_t hexValue = reinterpret_cast(floatValue); + std::stringstream ss; + ss << "0x" << std::hex << std::uppercase << hexValue; + rhs = ss.str(); + } catch (...) { + throw std::runtime_error("Invalid float literal: " + rhs); + } + } irStream << " store " << lhsType << " " << rhs << ", " << lhsType << "* " << lhsAlloca << ", align 4\n"; } else if (ctx->RETURN()) { @@ -162,6 +192,7 @@ std::any SysYIRGenerator::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) { std::string type = symbolTable[varName].second; std::string temp = getNextTemp(); irStream << " " << temp << " = load " << type << ", " << type << "* " << allocaPtr << ", align 4\n"; + tmpTable[temp] = type; return temp; } else if (ctx->exp()) { return ctx->exp()->accept(this); @@ -172,9 +203,9 @@ std::any SysYIRGenerator::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) { std::any SysYIRGenerator::visitNumber(SysYParser::NumberContext* ctx) { if (ctx->ILITERAL()) { - return "i32 " + ctx->ILITERAL()->getText(); + return ctx->ILITERAL()->getText(); } else if (ctx->FLITERAL()) { - return "float " + ctx->FLITERAL()->getText(); + return ctx->FLITERAL()->getText(); } return ""; } @@ -185,6 +216,7 @@ std::any SysYIRGenerator::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { std::string op = ctx->unaryOp()->getText(); std::string temp = getNextTemp(); std::string type = operand.substr(0, operand.find(' ')); + tmpTable[temp] = type; if (op == "-") { irStream << " " << temp << " = sub " << type << " 0, " << operand << "\n"; } else if (op == "!") { @@ -206,6 +238,7 @@ std::any SysYIRGenerator::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { argList += args[i]; } irStream << " " << temp << " = call " << currentReturnType << " @" << funcName << "(" << argList << ")\n"; + tmpTable[temp] = currentReturnType; return temp; } return ctx->primaryExp()->accept(this); @@ -218,7 +251,7 @@ std::any SysYIRGenerator::visitMulExp(SysYParser::MulExpContext* ctx) { std::string right = std::any_cast(unaryExps[i]->accept(this)); std::string op = ctx->children[2*i-1]->getText(); std::string temp = getNextTemp(); - std::string type = left.substr(0, left.find(' ')); + std::string type = tmpTable[left]; if (op == "*") { irStream << " " << temp << " = mul nsw " << type << " " << left << ", " << right << "\n"; } else if (op == "/") { @@ -238,7 +271,7 @@ std::any SysYIRGenerator::visitAddExp(SysYParser::AddExpContext* ctx) { std::string right = std::any_cast(mulExps[i]->accept(this)); std::string op = ctx->children[2*i-1]->getText(); std::string temp = getNextTemp(); - std::string type = left.substr(0, left.find(' ')); + std::string type = tmpTable[left]; if (op == "+") { irStream << " " << temp << " = add nsw " << type << " " << left << ", " << right << "\n"; } else if (op == "-") { diff --git a/src/SysYIRGenerator.h b/src/SysYIRGenerator.h index c65e1ff..3e07914 100644 --- a/src/SysYIRGenerator.h +++ b/src/SysYIRGenerator.h @@ -14,7 +14,9 @@ public: private: std::stringstream irStream; int tempCounter = 0; + std::string currentVarType; std::map> symbolTable; + std::map tmpTable; std::vector globalVars; std::string currentFunction; std::string currentReturnType; diff --git a/test/01_add.sy b/test/01_add.sy index fc6c9be..d28d6f8 100644 --- a/test/01_add.sy +++ b/test/01_add.sy @@ -1,12 +1,16 @@ //test add -int main(){ +int main(int e){ int a, b; - float d; + float c; a = 10; b = 2; - int c = a; - d = 1.1 ; - return a + b + c; + a = 11; + c = 1.3 ; + return a+b; } + +int add(int a, int b){ + return a+b; +} \ No newline at end of file From 93607333ad4b0b6014303360b28c45e92a151d70 Mon Sep 17 00:00:00 2001 From: ladev789 Date: Mon, 24 Mar 2025 19:26:42 +0800 Subject: [PATCH 07/16] [lab2]fixed a lot of bugs --- test/01_add.sy | 2 +- test/20_test_licm_sr.sy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/01_add.sy b/test/01_add.sy index d28d6f8..488d209 100644 --- a/test/01_add.sy +++ b/test/01_add.sy @@ -7,7 +7,7 @@ int main(int e){ a = 10; b = 2; a = 11; - c = 1.3 ; + c = 1.6 ; return a+b; } diff --git a/test/20_test_licm_sr.sy b/test/20_test_licm_sr.sy index fe5afc4..aadadd6 100644 --- a/test/20_test_licm_sr.sy +++ b/test/20_test_licm_sr.sy @@ -13,7 +13,7 @@ int main(){ if(i > 50){ f = i * d; } - i++; + i = i + 1; } return f; From 8a743a0036a2088c62a8087727cf322e246cb162 Mon Sep 17 00:00:00 2001 From: ladev789 Date: Mon, 24 Mar 2025 21:18:40 +0800 Subject: [PATCH 08/16] [lab2]add a TODO table --- src/SysYIRGenerator.cpp | 42 ++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/src/SysYIRGenerator.cpp b/src/SysYIRGenerator.cpp index f221205..967ee0d 100644 --- a/src/SysYIRGenerator.cpp +++ b/src/SysYIRGenerator.cpp @@ -1,7 +1,7 @@ // SysYIRGenerator.cpp #include "SysYIRGenerator.h" #include - +// #TODO浮点数精度还是有问题 std::string SysYIRGenerator::generateIR(SysYParser::CompUnitContext* unit) { visitCompUnit(unit); return irStream.str(); @@ -42,6 +42,17 @@ std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext* ctx) { if (constDef->constInitVal()) { std::string value = std::any_cast(constDef->constInitVal()->accept(this)); + if (llvmType == "float") { + try { + double floatValue = std::stod(value); + uint64_t hexValue = reinterpret_cast(floatValue); + std::stringstream ss; + ss << "0x" << std::hex << std::uppercase << hexValue; + value = ss.str(); + } catch (...) { + throw std::runtime_error("Invalid float literal: " + value); + } + } irStream << " store " << llvmType << " " << value << ", " << llvmType << "* " << allocaName << ", align 4\n"; } @@ -76,7 +87,7 @@ std::any SysYIRGenerator::visitVarDef(SysYParser::VarDefContext* ctx) { double floatValue = std::stod(value); uint64_t hexValue = reinterpret_cast(floatValue); std::stringstream ss; - ss << "0x" << std::hex << std::uppercase << hexValue; + ss << "0x" << std::hex << std::uppercase << (hexValue & (0xffffffffUL << 32)); value = ss.str(); } catch (...) { throw std::runtime_error("Invalid float literal: " + value); @@ -94,6 +105,8 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext* ctx) { currentFunction = ctx->Ident()->getText(); currentReturnType = getLLVMType(ctx->funcType()->getText()); symbolTable.clear(); + tmpTable.clear(); + tempCounter = 0; hasReturn = false; irStream << "define dso_local " << currentReturnType << " @" << currentFunction << "("; @@ -110,7 +123,22 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext* ctx) { } tempCounter++; irStream << ") #0 {\n"; - + + if (ctx->funcFParams()) { + auto params = ctx->funcFParams()->funcFParam(); + for (size_t i = 0; i < params.size(); ++i) { + std::string varName = params[i]->Ident()->getText(); + std::string type = params[i]->bType()->getText(); + std::string llvmType = getLLVMType(type); + std::string allocaName = getNextTemp(); + tmpTable[allocaName] = llvmType; + + irStream << " " << allocaName << " = alloca " << llvmType << ", align 4\n"; + irStream << " store " << llvmType << " " << symbolTable[varName].first << ", " << llvmType + << "* " << allocaName << ", align 4\n"; + + } + } ctx->blockStmt()->accept(this); if (!hasReturn) { @@ -141,13 +169,13 @@ std::any SysYIRGenerator::visitStmt(SysYParser::StmtContext* ctx) { double floatValue = std::stod(rhs); uint64_t hexValue = reinterpret_cast(floatValue); std::stringstream ss; - ss << "0x" << std::hex << std::uppercase << hexValue; + ss << "0x" << std::hex << std::uppercase << (hexValue & (0xffffffffUL << 32)); rhs = ss.str(); } catch (...) { throw std::runtime_error("Invalid float literal: " + rhs); } } - irStream << " store " << lhsType << " " << rhs << ", " << lhsType + irStream << " store1 " << lhsType << " " << rhs << ", " << lhsType << "* " << lhsAlloca << ", align 4\n"; } else if (ctx->RETURN()) { hasReturn = true; @@ -289,7 +317,7 @@ std::any SysYIRGenerator::visitRelExp(SysYParser::RelExpContext* ctx) { std::string right = std::any_cast(addExps[i]->accept(this)); std::string op = ctx->children[2*i-1]->getText(); std::string temp = getNextTemp(); - std::string type = left.substr(0, left.find(' ')); + std::string type = tmpTable[left]; if (op == "<") { irStream << " " << temp << " = icmp slt " << type << " " << left << ", " << right << "\n"; } else if (op == ">") { @@ -311,7 +339,7 @@ std::any SysYIRGenerator::visitEqExp(SysYParser::EqExpContext* ctx) { std::string right = std::any_cast(relExps[i]->accept(this)); std::string op = ctx->children[2*i-1]->getText(); std::string temp = getNextTemp(); - std::string type = left.substr(0, left.find(' ')); + std::string type = tmpTable[left]; if (op == "==") { irStream << " " << temp << " = icmp eq " << type << " " << left << ", " << right << "\n"; } else if (op == "!=") { From dfa396b06f866bfc90bd6ae2d5e2e2e20f07ca32 Mon Sep 17 00:00:00 2001 From: ladev789 Date: Mon, 31 Mar 2025 03:54:39 +0800 Subject: [PATCH 09/16] [lab2]now 01_add.ll generated by sysy can be compiled to executable by clang --- src/SysYIRGenerator.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/SysYIRGenerator.cpp b/src/SysYIRGenerator.cpp index 967ee0d..9077eee 100644 --- a/src/SysYIRGenerator.cpp +++ b/src/SysYIRGenerator.cpp @@ -136,7 +136,8 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext* ctx) { irStream << " " << allocaName << " = alloca " << llvmType << ", align 4\n"; irStream << " store " << llvmType << " " << symbolTable[varName].first << ", " << llvmType << "* " << allocaName << ", align 4\n"; - + + symbolTable[varName] = {allocaName, llvmType}; } } ctx->blockStmt()->accept(this); @@ -175,7 +176,7 @@ std::any SysYIRGenerator::visitStmt(SysYParser::StmtContext* ctx) { throw std::runtime_error("Invalid float literal: " + rhs); } } - irStream << " store1 " << lhsType << " " << rhs << ", " << lhsType + irStream << " store " << lhsType << " " << rhs << ", " << lhsType << "* " << lhsAlloca << ", align 4\n"; } else if (ctx->RETURN()) { hasReturn = true; From 9d619b11d7c4aacaebc654d33488d0eb08c36b97 Mon Sep 17 00:00:00 2001 From: ladev789 Date: Mon, 31 Mar 2025 20:46:04 +0800 Subject: [PATCH 10/16] [lab2]checkopint with "while, continue, break" not implemented --- src/SysYIRGenerator.cpp | 2 +- src/SysYIRGenerator.h | 8 +++++--- test/10_test.sy | 2 +- test/11_add2.sy | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/SysYIRGenerator.cpp b/src/SysYIRGenerator.cpp index 9077eee..9974771 100644 --- a/src/SysYIRGenerator.cpp +++ b/src/SysYIRGenerator.cpp @@ -264,7 +264,7 @@ std::any SysYIRGenerator::visitUnaryExp(SysYParser::UnaryExpContext* ctx) { std::string argList = ""; for (size_t i = 0; i < args.size(); ++i) { if (i > 0) argList += ", "; - argList += args[i]; + argList +=tmpTable[args[i]] + " noundef " + args[i]; } irStream << " " << temp << " = call " << currentReturnType << " @" << funcName << "(" << argList << ")\n"; tmpTable[temp] = currentReturnType; diff --git a/src/SysYIRGenerator.h b/src/SysYIRGenerator.h index 3e07914..8608cc2 100644 --- a/src/SysYIRGenerator.h +++ b/src/SysYIRGenerator.h @@ -23,9 +23,11 @@ private: std::vector breakStack; std::vector continueStack; bool hasReturn = false; - std::stack loopEndStack; - std::stack loopCondStack; - + struct LoopLabels { + std::string breakLabel; + std::string continueLabel; + }; + std::stack loopStack; // 用于管理循环的break和continue标签 std::string getNextTemp(); std::string getLLVMType(const std::string& type); diff --git a/test/10_test.sy b/test/10_test.sy index bf84af2..cadb6da 100644 --- a/test/10_test.sy +++ b/test/10_test.sy @@ -1,7 +1,7 @@ //test file for backend lab int main() { - int a; + int a = 1; const int b = 2; int c; diff --git a/test/11_add2.sy b/test/11_add2.sy index c783a32..7d3ff7f 100644 --- a/test/11_add2.sy +++ b/test/11_add2.sy @@ -7,7 +7,7 @@ int mul(int x, int y) { int main(){ int a, b; a = 10; - b = 0; + b = 3; a = mul(a, b); return a + b; } From 9f562aa0be1349618d70202a67f48443ed94821d Mon Sep 17 00:00:00 2001 From: ladev789 Date: Tue, 1 Apr 2025 17:50:17 +0800 Subject: [PATCH 11/16] [lab2]implemented while, break, continue --- src/SysYIRGenerator.cpp | 35 +++++++++++++++++++++++++++++++++++ src/SysYIRGenerator.h | 5 +++-- test/01_add.sy | 34 +++++++++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/SysYIRGenerator.cpp b/src/SysYIRGenerator.cpp index 9974771..63a4bd7 100644 --- a/src/SysYIRGenerator.cpp +++ b/src/SysYIRGenerator.cpp @@ -205,6 +205,38 @@ std::any SysYIRGenerator::visitStmt(SysYParser::StmtContext* ctx) { irStream << " br label %" << mergeLabel << "\n"; irStream << mergeLabel << ":\n"; + } else if (ctx->WHILE()) { + std::string loop_cond = "while.cond." + std::to_string(tempCounter); + std::string loop_body = "while.body." + std::to_string(tempCounter); + std::string loop_end = "while.end." + std::to_string(tempCounter++); + + loopStack.push({loop_end, loop_cond}); + irStream << " br label %" << loop_cond << "\n"; + irStream << loop_cond << ":\n"; + + std::string cond = std::any_cast(ctx->cond()->accept(this)); + irStream << " br i1 " << cond << ", label %" << loop_body << ", label %" << loop_end << "\n"; + irStream << loop_body << ":\n"; + ctx->stmt(0)->accept(this); + irStream << " br label %" << loop_cond << "\n"; + irStream << loop_end << ":\n"; + + loopStack.pop(); + + } else if (ctx->BREAK()) { + if (loopStack.empty()) { + throw std::runtime_error("Break statement outside of a loop."); + } + irStream << " br label %" << loopStack.top().breakLabel << "\n"; + } else if (ctx->CONTINUE()) { + if (loopStack.empty()) { + throw std::runtime_error("Continue statement outside of a loop."); + } + irStream << " br label %" << loopStack.top().continueLabel << "\n"; + } else if (ctx->blockStmt()) { + ctx->blockStmt()->accept(this); + } else if (ctx->exp()) { + ctx->exp()->accept(this); } return nullptr; } @@ -289,6 +321,7 @@ std::any SysYIRGenerator::visitMulExp(SysYParser::MulExpContext* ctx) { irStream << " " << temp << " = srem " << type << " " << left << ", " << right << "\n"; } left = temp; + tmpTable[temp] = type; } return left; } @@ -298,6 +331,7 @@ std::any SysYIRGenerator::visitAddExp(SysYParser::AddExpContext* ctx) { std::string left = std::any_cast(mulExps[0]->accept(this)); for (size_t i = 1; i < mulExps.size(); ++i) { std::string right = std::any_cast(mulExps[i]->accept(this)); + irStream << "right is " << right << "\n"; std::string op = ctx->children[2*i-1]->getText(); std::string temp = getNextTemp(); std::string type = tmpTable[left]; @@ -307,6 +341,7 @@ std::any SysYIRGenerator::visitAddExp(SysYParser::AddExpContext* ctx) { irStream << " " << temp << " = sub nsw " << type << " " << left << ", " << right << "\n"; } left = temp; + tmpTable[temp] = type; } return left; } diff --git a/src/SysYIRGenerator.h b/src/SysYIRGenerator.h index 8608cc2..50c2568 100644 --- a/src/SysYIRGenerator.h +++ b/src/SysYIRGenerator.h @@ -23,9 +23,10 @@ private: std::vector breakStack; std::vector continueStack; bool hasReturn = false; + struct LoopLabels { - std::string breakLabel; - std::string continueLabel; + std::string breakLabel; // break跳转的目标标签 + std::string continueLabel; // continue跳转的目标标签 }; std::stack loopStack; // 用于管理循环的break和continue标签 std::string getNextTemp(); diff --git a/test/01_add.sy b/test/01_add.sy index 488d209..325c3ca 100644 --- a/test/01_add.sy +++ b/test/01_add.sy @@ -1,5 +1,37 @@ //test add +int a1 = 1; +int a2 = 2; +int a3 = 3; +int a4 = 4; +int a5 = 5; +int a6 = 6; +int a7 = 7; +int a8 = 8; +int a9 = 9; +int a10 = 10; +int a11 = 11; +int a12 = 12; +int a13 = 13; +int a14 = 14; +int a15 = 15; +int a16 = 16; +int a17 = 1; +int a18 = 2; +int a19 = 3; +int a20 = 4; +int a21 = 5; +int a22 = 6; +int a23 = 7; +int a24 = 8; +int a25 = 9; +int a26 = 10; +int a27 = 11; +int a28 = 12; +int a29 = 13; +int a30 = 14; +int a31 = 15; +int a32 = 16; int main(int e){ int a, b; @@ -8,7 +40,7 @@ int main(int e){ b = 2; a = 11; c = 1.6 ; - return a+b; + return a+b+1; } int add(int a, int b){ From ec8deeeebfaba9f3461e4c762a934340e61c56dc Mon Sep 17 00:00:00 2001 From: ladev789 Date: Wed, 2 Apr 2025 18:40:01 +0800 Subject: [PATCH 12/16] [lab2][night release]temporary stable version 0.1 --- src/SysYIRGenerator.cpp | 103 +++++++++++++++++++++++++++++++--------- src/SysYIRGenerator.h | 2 + test/01_add.sy | 38 ++------------- 3 files changed, 86 insertions(+), 57 deletions(-) diff --git a/src/SysYIRGenerator.cpp b/src/SysYIRGenerator.cpp index 63a4bd7..27eb9af 100644 --- a/src/SysYIRGenerator.cpp +++ b/src/SysYIRGenerator.cpp @@ -1,7 +1,11 @@ // SysYIRGenerator.cpp +// TODO:类型转换及其检查 +// TODO:sysy库函数处理 +// TODO:数组处理 +// TODO:对while、continue、break的测试 #include "SysYIRGenerator.h" #include -// #TODO浮点数精度还是有问题 + std::string SysYIRGenerator::generateIR(SysYParser::CompUnitContext* unit) { visitCompUnit(unit); return irStream.str(); @@ -26,22 +30,83 @@ std::any SysYIRGenerator::visitCompUnit(SysYParser::CompUnitContext* ctx) { decl->accept(this); } for (auto funcDef : ctx->funcDef()) { + inFunction = true; // 进入函数定义 funcDef->accept(this); + inFunction = false; // 离开函数定义 + } + return nullptr; +} + +std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext* ctx) { + // TODO:数组初始化 + std::string type = ctx->bType()->getText(); + currentVarType = getLLVMType(type); + + for (auto varDef : ctx->varDef()) { + if (!inFunction) { + // 全局变量声明 + std::string varName = varDef->Ident()->getText(); + std::string llvmType = getLLVMType(type); + std::string value = "0"; // 默认值为 0 + + if (varDef->ASSIGN()) { + value = std::any_cast(varDef->initVal()->accept(this)); + } + + irStream << "@" << varName << " = dso_local global " << llvmType << " " << value << ", align 4\n"; + globalVars.push_back(varName); // 记录全局变量 + } else { + // 局部变量声明 + varDef->accept(this); + } } return nullptr; } std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext* ctx) { + // TODO:数组初始化 std::string type = ctx->bType()->getText(); for (auto constDef : ctx->constDef()) { - std::string varName = constDef->Ident()->getText(); - std::string llvmType = getLLVMType(type); - std::string allocaName = getNextTemp(); - - irStream << " " << allocaName << " = alloca " << llvmType << ", align 4\n"; - - if (constDef->constInitVal()) { - std::string value = std::any_cast(constDef->constInitVal()->accept(this)); + if (!inFunction) { + // 全局常量声明 + std::string varName = constDef->Ident()->getText(); + std::string llvmType = getLLVMType(type); + std::string value = "0"; // 默认值为 0 + + try { + value = std::any_cast(constDef->constInitVal()->accept(this)); + } catch (...) { + throw std::runtime_error("Const value must be initialized upon definition."); + } + + if (llvmType == "float") { + try { + double floatValue = std::stod(value); + uint64_t hexValue = reinterpret_cast(floatValue); + std::stringstream ss; + ss << "0x" << std::hex << std::uppercase << hexValue; + value = ss.str(); + } catch (...) { + throw std::runtime_error("Invalid float literal: " + value); + } + } + + irStream << "@" << varName << " = dso_local constant " << llvmType << " " << value << ", align 4\n"; + globalVars.push_back(varName); // 记录全局变量 + } else { + // 局部常量声明 + std::string varName = constDef->Ident()->getText(); + std::string llvmType = getLLVMType(type); + std::string allocaName = getNextTemp(); + std::string value = "0"; // 默认值为 0 + + try { + value = std::any_cast(constDef->constInitVal()->accept(this)); + } catch (...) { + throw std::runtime_error("Const value must be initialized upon definition."); + } + + irStream << " " << allocaName << " = alloca " << llvmType << ", align 4\n"; if (llvmType == "float") { try { double floatValue = std::stod(value); @@ -54,24 +119,17 @@ std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext* ctx) { } } irStream << " store " << llvmType << " " << value << ", " << llvmType - << "* " << allocaName << ", align 4\n"; - } - symbolTable[varName] = {allocaName, llvmType}; - tmpTable[allocaName] = llvmType; - } - return nullptr; -} - -std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext* ctx) { - std::string type = ctx->bType()->getText(); - currentVarType = getLLVMType(type); - for (auto varDef : ctx->varDef()) { - varDef->accept(this); + << "* " << allocaName << ", align 4\n"; + + symbolTable[varName] = {allocaName, llvmType}; + tmpTable[allocaName] = llvmType; + } } return nullptr; } std::any SysYIRGenerator::visitVarDef(SysYParser::VarDefContext* ctx) { + // TODO:数组初始化 std::string varName = ctx->Ident()->getText(); std::string type = currentVarType; std::string llvmType = getLLVMType(type); @@ -331,7 +389,6 @@ std::any SysYIRGenerator::visitAddExp(SysYParser::AddExpContext* ctx) { std::string left = std::any_cast(mulExps[0]->accept(this)); for (size_t i = 1; i < mulExps.size(); ++i) { std::string right = std::any_cast(mulExps[i]->accept(this)); - irStream << "right is " << right << "\n"; std::string op = ctx->children[2*i-1]->getText(); std::string temp = getNextTemp(); std::string type = tmpTable[left]; diff --git a/src/SysYIRGenerator.h b/src/SysYIRGenerator.h index 50c2568..f5000ff 100644 --- a/src/SysYIRGenerator.h +++ b/src/SysYIRGenerator.h @@ -32,6 +32,8 @@ private: std::string getNextTemp(); std::string getLLVMType(const std::string& type); + bool inFunction = false; // 标识当前是否处于函数内部 + // 访问方法 std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override; std::any visitConstDecl(SysYParser::ConstDeclContext* ctx) override; diff --git a/test/01_add.sy b/test/01_add.sy index 325c3ca..51e5659 100644 --- a/test/01_add.sy +++ b/test/01_add.sy @@ -1,40 +1,10 @@ //test add +//const int a33[2] = {66,88}; -int a1 = 1; -int a2 = 2; -int a3 = 3; -int a4 = 4; -int a5 = 5; -int a6 = 6; -int a7 = 7; -int a8 = 8; -int a9 = 9; -int a10 = 10; -int a11 = 11; -int a12 = 12; -int a13 = 13; -int a14 = 14; -int a15 = 15; -int a16 = 16; -int a17 = 1; -int a18 = 2; -int a19 = 3; -int a20 = 4; -int a21 = 5; -int a22 = 6; -int a23 = 7; -int a24 = 8; -int a25 = 9; -int a26 = 10; -int a27 = 11; -int a28 = 12; -int a29 = 13; -int a30 = 14; -int a31 = 15; -int a32 = 16; - -int main(int e){ +int main(){ int a, b; +// int g[2][3][4] = {0,1,2,3,4,5,6,7,8,}; +// const int f[2] = {33,44}; float c; a = 10; b = 2; From 338e5ef9a4c8a032bcae15f276b8fa8574e2bb86 Mon Sep 17 00:00:00 2001 From: Lixuanwang Date: Sat, 24 May 2025 16:27:48 +0800 Subject: [PATCH 13/16] Introduce middle-end --- .gitignore | 6 +++++- src/pysrc/requirements.txt | 1 + src/pysrc/sysy/backend/x86_emitter.py | 27 +++++++++++++++++++++++++++ src/pysrc/sysy/middle_ir.py | 14 ++++++++++++++ src/pysrc/sysy/utils/ir_parser.py | 22 ++++++++++++++++++++++ src/pysrc/sysyc.py | 23 +++++++++++++++++++++++ src/pysrc/tests/test_add.ll | 5 +++++ 7 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/pysrc/requirements.txt create mode 100644 src/pysrc/sysy/backend/x86_emitter.py create mode 100644 src/pysrc/sysy/middle_ir.py create mode 100644 src/pysrc/sysy/utils/ir_parser.py create mode 100644 src/pysrc/sysyc.py create mode 100644 src/pysrc/tests/test_add.ll diff --git a/.gitignore b/.gitignore index 3649ac4..1c41982 100644 --- a/.gitignore +++ b/.gitignore @@ -44,4 +44,8 @@ tmp GPATH GRTAGS -GTAGS \ No newline at end of file +GTAGS + +__init__.py + +*.pyc \ No newline at end of file diff --git a/src/pysrc/requirements.txt b/src/pysrc/requirements.txt new file mode 100644 index 0000000..e7d0682 --- /dev/null +++ b/src/pysrc/requirements.txt @@ -0,0 +1 @@ +llvmlite==0.41.0 diff --git a/src/pysrc/sysy/backend/x86_emitter.py b/src/pysrc/sysy/backend/x86_emitter.py new file mode 100644 index 0000000..a58d981 --- /dev/null +++ b/src/pysrc/sysy/backend/x86_emitter.py @@ -0,0 +1,27 @@ +class X86Emitter: + def __init__(self): + self.reg_pool = ["eax", "ebx", "ecx", "edx"] # 简化寄存器分配 + + def emit_function(self, func: MiddleFunction) -> str: + asm = [f".globl {func.name}", f"{func.name}:"] + for block in func.basic_blocks: + asm.append(f".{block.name}:") + for instr in block.instructions: + asm.append(self.emit_instruction(instr)) + return "\n".join(asm) + + def emit_instruction(self, instr: MiddleInstruction) -> str: + op = instr.opcode + if op == "add": + dest, src1, src2 = instr.operands + return f" addl {self.map_operand(src2)}, {self.map_operand(dest)}" + elif op == "ret": + return " ret" + else: + raise NotImplementedError(f"Unsupported opcode: {op}") + + def map_operand(self, operand: str) -> str: + """将虚拟寄存器映射到物理寄存器(简化版)""" + if operand.startswith('%'): + return self.reg_pool[int(operand[1:]) % len(self.reg_pool)] + return operand diff --git a/src/pysrc/sysy/middle_ir.py b/src/pysrc/sysy/middle_ir.py new file mode 100644 index 0000000..ddc5859 --- /dev/null +++ b/src/pysrc/sysy/middle_ir.py @@ -0,0 +1,14 @@ +class MiddleFunction: + def __init__(self, name: str): + self.name = name + self.basic_blocks = [] # List[MiddleBasicBlock] + +class MiddleBasicBlock: + def __init__(self, name: str): + self.name = name + self.instructions = [] # List[MiddleInstruction] + +class MiddleInstruction: + def __init__(self, opcode: str, operands: list): + self.opcode = opcode # e.g., 'add', 'ret' + self.operands = operands # e.g., ['%0', '%1', '%2'] diff --git a/src/pysrc/sysy/utils/ir_parser.py b/src/pysrc/sysy/utils/ir_parser.py new file mode 100644 index 0000000..479803f --- /dev/null +++ b/src/pysrc/sysy/utils/ir_parser.py @@ -0,0 +1,22 @@ +from llvmlite import ir + +def parse_llvm_ir(ir_text: str) -> MiddleFunction: + """将 LLVM IR 文本转换为 MiddleIR 结构(简化版)""" + module = ir.Module() + module.parse(ir_text) + + # 提取第一个函数 + func = list(module.functions)[0] + middle_func = MiddleFunction(func.name) + + # 转换基本块和指令 + for block in func.blocks: + mid_block = MiddleBasicBlock(block.name) + for instr in block.instructions: + opcode = instr.opcode + operands = [str(op) for op in instr.operands] + mid_instr = MiddleInstruction(opcode, operands) + mid_block.instructions.append(mid_instr) + middle_func.basic_blocks.append(mid_block) + + return middle_func diff --git a/src/pysrc/sysyc.py b/src/pysrc/sysyc.py new file mode 100644 index 0000000..3716b7a --- /dev/null +++ b/src/pysrc/sysyc.py @@ -0,0 +1,23 @@ +import sys +from sysy.utils.ir_parser import parse_llvm_ir +from sysy.backend.x86_emitter import X86Emitter + +def main(): + if len(sys.argv) != 3: + print("Usage: sysyc.py ") + sys.exit(1) + + # 读取 LLVM IR + with open(sys.argv[1], 'r') as f: + ir_text = f.read() + + # 解析并生成汇编 + func = parse_llvm_ir(ir_text) + asm = X86Emitter().emit_function(func) + + # 写入文件 + with open(sys.argv[2], 'w') as f: + f.write(asm) + +if __name__ == "__main__": + main() diff --git a/src/pysrc/tests/test_add.ll b/src/pysrc/tests/test_add.ll new file mode 100644 index 0000000..1ca881f --- /dev/null +++ b/src/pysrc/tests/test_add.ll @@ -0,0 +1,5 @@ +define i32 @add(i32 %a, i32 %b) { +entry: + %sum = add i32 %a, %b + ret i32 %sum +} From dc7202849cfa59afd1d2e7c85771876ceadda3cd Mon Sep 17 00:00:00 2001 From: lixuanwang Date: Mon, 26 May 2025 23:17:31 +0800 Subject: [PATCH 14/16] [lab3] add middle-end and backend with bugs to fix --- src/SysYIRGenerator.cpp | 2 +- src/pysrc/sysy/backend/x86_emitter.py | 15 ++++++--- src/pysrc/sysy/middle_ir.py | 7 ++-- src/pysrc/sysy/utils/ir_parser.py | 46 ++++++++++++++++----------- src/pysrc/tests/test_add.ll | 5 --- 5 files changed, 44 insertions(+), 31 deletions(-) delete mode 100644 src/pysrc/tests/test_add.ll diff --git a/src/SysYIRGenerator.cpp b/src/SysYIRGenerator.cpp index 27eb9af..f700363 100644 --- a/src/SysYIRGenerator.cpp +++ b/src/SysYIRGenerator.cpp @@ -12,7 +12,7 @@ std::string SysYIRGenerator::generateIR(SysYParser::CompUnitContext* unit) { } std::string SysYIRGenerator::getNextTemp() { - std::string ret = "%" + std::to_string(tempCounter++); + std::string ret = "%." + std::to_string(tempCounter++); tmpTable[ret] = "void"; return ret; } diff --git a/src/pysrc/sysy/backend/x86_emitter.py b/src/pysrc/sysy/backend/x86_emitter.py index a58d981..71c5d08 100644 --- a/src/pysrc/sysy/backend/x86_emitter.py +++ b/src/pysrc/sysy/backend/x86_emitter.py @@ -1,3 +1,5 @@ +from ..middle_ir import * + class X86Emitter: def __init__(self): self.reg_pool = ["eax", "ebx", "ecx", "edx"] # 简化寄存器分配 @@ -13,8 +15,13 @@ class X86Emitter: def emit_instruction(self, instr: MiddleInstruction) -> str: op = instr.opcode if op == "add": - dest, src1, src2 = instr.operands - return f" addl {self.map_operand(src2)}, {self.map_operand(dest)}" + src1, src2 = instr.operands + dest = instr.dest + #TODO(Lixuan Wang): src1 src2 的类型标签还没有去除,如i32 5,会出现在汇编文件中,这是不对的 + return ( + f" movl ${src1}, %{self.map_operand(dest)}\n" + f" addl ${src2}, %{self.map_operand(dest)}" + ) elif op == "ret": return " ret" else: @@ -22,6 +29,6 @@ class X86Emitter: def map_operand(self, operand: str) -> str: """将虚拟寄存器映射到物理寄存器(简化版)""" - if operand.startswith('%'): - return self.reg_pool[int(operand[1:]) % len(self.reg_pool)] + if operand.startswith('%.'): + return self.reg_pool[int(operand[2:]) % len(self.reg_pool)] return operand diff --git a/src/pysrc/sysy/middle_ir.py b/src/pysrc/sysy/middle_ir.py index ddc5859..f30a40d 100644 --- a/src/pysrc/sysy/middle_ir.py +++ b/src/pysrc/sysy/middle_ir.py @@ -9,6 +9,7 @@ class MiddleBasicBlock: self.instructions = [] # List[MiddleInstruction] class MiddleInstruction: - def __init__(self, opcode: str, operands: list): - self.opcode = opcode # e.g., 'add', 'ret' - self.operands = operands # e.g., ['%0', '%1', '%2'] + def __init__(self, opcode: str, operands: list, dest=None): + self.opcode = opcode # e.g., 'add' + self.operands = operands # e.g., ['5', '7'] + self.dest = dest # e.g., '%0' diff --git a/src/pysrc/sysy/utils/ir_parser.py b/src/pysrc/sysy/utils/ir_parser.py index 479803f..d80072a 100644 --- a/src/pysrc/sysy/utils/ir_parser.py +++ b/src/pysrc/sysy/utils/ir_parser.py @@ -1,22 +1,32 @@ from llvmlite import ir +from ..middle_ir import * + def parse_llvm_ir(ir_text: str) -> MiddleFunction: """将 LLVM IR 文本转换为 MiddleIR 结构(简化版)""" - module = ir.Module() - module.parse(ir_text) - - # 提取第一个函数 - func = list(module.functions)[0] - middle_func = MiddleFunction(func.name) - - # 转换基本块和指令 - for block in func.blocks: - mid_block = MiddleBasicBlock(block.name) - for instr in block.instructions: - opcode = instr.opcode - operands = [str(op) for op in instr.operands] - mid_instr = MiddleInstruction(opcode, operands) - mid_block.instructions.append(mid_instr) - middle_func.basic_blocks.append(mid_block) - - return middle_func + from llvmlite.binding import parse_assembly + + # 使用 binding 模块解析 LLVM IR 文本 + with parse_assembly(ir_text) as module: + # 获取第一个函数 + func = list(module.functions)[0] + middle_func = MiddleFunction(func.name) + + # 转换基本块和指令 + for block in func.blocks: + mid_block = MiddleBasicBlock(block.name) + for instr in block.instructions: + opcode = instr.opcode + operands = [str(op) for op in instr.operands] + # 调试输出 + print(f"Instruction: {instr}, Opcode: {opcode}, Operands: {operands}") + # 如果是有返回值的指令(如 add),第一个操作数是 dest + dest = None + if hasattr(instr, 'name') and instr.name: + dest = f"%{instr.name}" # 获取 LLVM IR 中的目标寄存器名 + + mid_instr = MiddleInstruction(opcode, operands, dest) + mid_block.instructions.append(mid_instr) + middle_func.basic_blocks.append(mid_block) + + return middle_func \ No newline at end of file diff --git a/src/pysrc/tests/test_add.ll b/src/pysrc/tests/test_add.ll deleted file mode 100644 index 1ca881f..0000000 --- a/src/pysrc/tests/test_add.ll +++ /dev/null @@ -1,5 +0,0 @@ -define i32 @add(i32 %a, i32 %b) { -entry: - %sum = add i32 %a, %b - ret i32 %sum -} From 29aea7781fdd665707caac5d5fb8bd7ab6f31486 Mon Sep 17 00:00:00 2001 From: lixuanwang Date: Tue, 27 May 2025 11:43:14 +0800 Subject: [PATCH 15/16] [lab3] add print support for functions, blocks and instructions --- src/pysrc/sysy/middle_ir.py | 14 +++++++++++++- src/pysrc/sysy/utils/ir_parser.py | 3 +-- src/pysrc/sysyc.py | 12 +++++++----- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/pysrc/sysy/middle_ir.py b/src/pysrc/sysy/middle_ir.py index f30a40d..d6fe352 100644 --- a/src/pysrc/sysy/middle_ir.py +++ b/src/pysrc/sysy/middle_ir.py @@ -2,14 +2,26 @@ class MiddleFunction: def __init__(self, name: str): self.name = name self.basic_blocks = [] # List[MiddleBasicBlock] - + def __repr__(self): + return f"Function({self.name}):\n" + "\n".join(str(block) for block in self.basic_blocks) + def __str__(self): + return self.__repr__() + class MiddleBasicBlock: def __init__(self, name: str): self.name = name self.instructions = [] # List[MiddleInstruction] + def __repr__(self): + return f"BasicBlock({self.name}):\n" + "\n".join(str(instr) for instr in self.instructions) + def __str__(self): + return self.__repr__() class MiddleInstruction: def __init__(self, opcode: str, operands: list, dest=None): self.opcode = opcode # e.g., 'add' self.operands = operands # e.g., ['5', '7'] self.dest = dest # e.g., '%0' + def __repr__(self): + return f"{self.dest} = {self.opcode} " + ", ".join(self.operands) if self.dest else f"{self.opcode} " + ", ".join(self.operands) + def __str__(self): + return self.__repr__() \ No newline at end of file diff --git a/src/pysrc/sysy/utils/ir_parser.py b/src/pysrc/sysy/utils/ir_parser.py index d80072a..82dea4e 100644 --- a/src/pysrc/sysy/utils/ir_parser.py +++ b/src/pysrc/sysy/utils/ir_parser.py @@ -18,8 +18,7 @@ def parse_llvm_ir(ir_text: str) -> MiddleFunction: for instr in block.instructions: opcode = instr.opcode operands = [str(op) for op in instr.operands] - # 调试输出 - print(f"Instruction: {instr}, Opcode: {opcode}, Operands: {operands}") + # 如果是有返回值的指令(如 add),第一个操作数是 dest dest = None if hasattr(instr, 'name') and instr.name: diff --git a/src/pysrc/sysyc.py b/src/pysrc/sysyc.py index 3716b7a..db62eee 100644 --- a/src/pysrc/sysyc.py +++ b/src/pysrc/sysyc.py @@ -3,8 +3,9 @@ from sysy.utils.ir_parser import parse_llvm_ir from sysy.backend.x86_emitter import X86Emitter def main(): - if len(sys.argv) != 3: - print("Usage: sysyc.py ") + if len(sys.argv) != 2: + # print("Usage: sysyc.py ") + print("Usage: sysyc.py ") sys.exit(1) # 读取 LLVM IR @@ -13,11 +14,12 @@ def main(): # 解析并生成汇编 func = parse_llvm_ir(ir_text) + print(func) asm = X86Emitter().emit_function(func) # 写入文件 - with open(sys.argv[2], 'w') as f: - f.write(asm) - + # with open(sys.argv[2], 'w') as f: + # f.write(asm) + print(asm) if __name__ == "__main__": main() From f286845463159054b293d977e9ca5ce115d7f3fe Mon Sep 17 00:00:00 2001 From: lixuanwang Date: Tue, 27 May 2025 12:03:26 +0800 Subject: [PATCH 16/16] [lab3]addl movl ret passes clang test --- src/pysrc/sysy/backend/x86_emitter.py | 64 ++++++++++++++++++++------ src/pysrc/sysy/middle_ir.py | 30 +++++++++++- src/pysrc/sysyc.py | 13 +++--- src/pysrc/test_add_exec | Bin 0 -> 15880 bytes 4 files changed, 85 insertions(+), 22 deletions(-) create mode 100755 src/pysrc/test_add_exec diff --git a/src/pysrc/sysy/backend/x86_emitter.py b/src/pysrc/sysy/backend/x86_emitter.py index 71c5d08..b4d1991 100644 --- a/src/pysrc/sysy/backend/x86_emitter.py +++ b/src/pysrc/sysy/backend/x86_emitter.py @@ -12,23 +12,57 @@ class X86Emitter: asm.append(self.emit_instruction(instr)) return "\n".join(asm) - def emit_instruction(self, instr: MiddleInstruction) -> str: - op = instr.opcode - if op == "add": - src1, src2 = instr.operands - dest = instr.dest - #TODO(Lixuan Wang): src1 src2 的类型标签还没有去除,如i32 5,会出现在汇编文件中,这是不对的 - return ( - f" movl ${src1}, %{self.map_operand(dest)}\n" - f" addl ${src2}, %{self.map_operand(dest)}" - ) - elif op == "ret": - return " ret" + def is_register(self, operand): + return operand.startswith("%") + + def get_operand_asm(self, operand): + if self.is_register(operand): + return "%" + self.map_operand(operand) else: - raise NotImplementedError(f"Unsupported opcode: {op}") + # 移除类型信息(如 'i32'),提取数值 + # 假设操作数格式为 'i32 5' 或直接为 '5' + parts = operand.split() + # 如果包含类型信息,取最后一个部分(数值) + value = parts[-1] if len(parts) > 1 else operand + try: + # 验证是有效整数 + int(value) + return "$" + value + except ValueError: + # 如果不是有效整数,抛出错误 + raise ValueError(f"Invalid immediate operand: {operand}") def map_operand(self, operand: str) -> str: """将虚拟寄存器映射到物理寄存器(简化版)""" - if operand.startswith('%.'): - return self.reg_pool[int(operand[2:]) % len(self.reg_pool)] + if operand.startswith('%'): + # 去掉 '%' 和 '.'(如果有) + reg_num = operand[1:].replace('.', '') + try: + idx = int(reg_num) + return self.reg_pool[idx % len(self.reg_pool)] + except ValueError: + return "eax" # 默认 return operand + + def emit_instruction(self, instr: MiddleInstruction) -> str: + op = instr.opcode + if op in ["add", "sub", "mul"]: + dest_reg = self.map_operand(instr.dest) + src1, src2 = instr.operands + if op == "add": + op_asm = "addl" + elif op == "sub": + op_asm = "subl" + elif op == "mul": + op_asm = "imull" + asm = f" movl {self.get_operand_asm(src1)}, %{dest_reg}\n" + asm += f" {op_asm} {self.get_operand_asm(src2)}, %{dest_reg}" + return asm + elif op == "ret": + if instr.operands: + op = instr.operands[0] + return f" movl {self.get_operand_asm(op)}, %eax\n ret" + else: + return " ret" + else: + raise NotImplementedError(f"Unsupported opcode: {op}") \ No newline at end of file diff --git a/src/pysrc/sysy/middle_ir.py b/src/pysrc/sysy/middle_ir.py index d6fe352..01fdbbc 100644 --- a/src/pysrc/sysy/middle_ir.py +++ b/src/pysrc/sysy/middle_ir.py @@ -2,17 +2,40 @@ class MiddleFunction: def __init__(self, name: str): self.name = name self.basic_blocks = [] # List[MiddleBasicBlock] + def __repr__(self): return f"Function({self.name}):\n" + "\n".join(str(block) for block in self.basic_blocks) + def __str__(self): return self.__repr__() + def collect_used_registers(self): + used = set() + for block in self.basic_blocks: + for instr in block.instructions: + for op in instr.operands: + if op.startswith("%"): + used.add(op) + # For ret, if it has operands + if instr.opcode == "ret" and instr.operands: + op = instr.operands[0] + if op.startswith("%"): + used.add(op) + return used + + def dead_code_elimination(self): + used = self.collect_used_registers() + for block in self.basic_blocks: + block.instructions = [instr for instr in block.instructions if instr.dest is None or instr.dest in used] + class MiddleBasicBlock: def __init__(self, name: str): self.name = name self.instructions = [] # List[MiddleInstruction] + def __repr__(self): return f"BasicBlock({self.name}):\n" + "\n".join(str(instr) for instr in self.instructions) + def __str__(self): return self.__repr__() @@ -21,7 +44,12 @@ class MiddleInstruction: self.opcode = opcode # e.g., 'add' self.operands = operands # e.g., ['5', '7'] self.dest = dest # e.g., '%0' + def __repr__(self): - return f"{self.dest} = {self.opcode} " + ", ".join(self.operands) if self.dest else f"{self.opcode} " + ", ".join(self.operands) + if self.dest: + return f"{self.dest} = {self.opcode} " + ", ".join(self.operands) + else: + return f"{self.opcode} " + ", ".join(self.operands) + def __str__(self): return self.__repr__() \ No newline at end of file diff --git a/src/pysrc/sysyc.py b/src/pysrc/sysyc.py index db62eee..5de1c27 100644 --- a/src/pysrc/sysyc.py +++ b/src/pysrc/sysyc.py @@ -4,7 +4,6 @@ from sysy.backend.x86_emitter import X86Emitter def main(): if len(sys.argv) != 2: - # print("Usage: sysyc.py ") print("Usage: sysyc.py ") sys.exit(1) @@ -14,12 +13,14 @@ def main(): # 解析并生成汇编 func = parse_llvm_ir(ir_text) - print(func) + # print("Before optimization:") + # print(func) + # func.dead_code_elimination() + # print("After optimization:") + # print(func) asm = X86Emitter().emit_function(func) - # 写入文件 - # with open(sys.argv[2], 'w') as f: - # f.write(asm) print(asm) + if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/src/pysrc/test_add_exec b/src/pysrc/test_add_exec new file mode 100755 index 0000000000000000000000000000000000000000..051d8f9776904a4000ddf3d46f9e9f6d1b1f39e4 GIT binary patch literal 15880 zcmeHOTWlOx89uwYctcZr6Pn^CB^iN>5*kl@i*aZ!>-ds&C>L{NcYc6V&Av=_5G z+t^i9f(%lkDpEiQ=tHISg;o_3h)dP-v{6wBh*k;Wp-;#HDuswkP`RX~WcmL&|F<3w zYf)7Q@oDt8hZUC40gtWKX zbx?@EpoCZLDdaPQ1A7X&?n1s)o9~_<8tfh%u&ZUeFKC|o#clAII&$okil0+;=Ah^N zJ#=tb*?u$o{A0QG?|dij^^Csy!xz-UC+}^b4%V;_C-z5|xXgKOgMEVWq`pWw8Owy% zz1NBXvC0SQHn*^i5NEaEomKeKD*XG2|4@s1l;cnYvrg4_E51{7^Ce=k^R6?UFS&*M zd?LaxNrj1& z*hP+V{g5X38uB$kx*Foc*Zo?E*FD#Y*F!vyAEc!a&*Q};69E$e69E$e69E$e69E$e z6M?ym2kP_~XROfqP@`&xme3@N@d?*pZ^#^OT#u zgt}PY`-h1O*FT%S@ay#AZ*M&^HP&12{b~B*fmg|=vE@;6|I4)9vExgDg!re3Nnc#| zRfc`H{Vmk=LC#at8yZU;JI=A=%Yx*e5B&FL7UWpau=enQ3Old)|Z z+Y*=PMHch?j{f$a8jX*z!)ROZCajCH19a4h4~X{Uczfr=9e15coKuIkKJ?N4uHdyH z+dfUlbL5A2Y*aMKM8HJAM8HJAM8HJAM8HJAM8HJAM8HJgzZ?OqXTxveORoqsEGg8i>|8f7kDmPL+OyLeg_H|jO7N?jHE z``DS%c@63=!A`*~f&h`J8?rtUYltmr2>qywfEI%W3HAM>q5DT<;Ce^Ox1@jcW;p0S z;zmE0gYuHt-;y%=A=UrS0qe(CYZ&WPkBp3b+}e36Q!Dv3tGD0ow|lw=YeBK^iM|25 zXJD7mtJS1=j>lT{=SI|v;~OK(SqX?G4!n-ImH&3)8@p~yy z7Mwyj9Po6Pq(UTR`-o4f&Ssop-ADZ9c!$Ds1N z)UvWPBe$PALwu61duIxs8pnv=OxHIh<0tsv6`9V8KgJ1E=L7!Vuj57Hxj#|=r--*8 z4&nES$Fns=tJjF%9H*yQWIU^r*^1w5mubbjo5?%AJEMrG`nBn4JFAvg$2)$}$@2R6 zDtYG0&P<`4aSKk)FITFLTbozea&fNU`CiWMY3;!)^Ye~dskjS{SMng5zgfIgf|wJKWK!9bf3a7Mg4q2-o?mHQl;-R9j5 zLEvalP<5f`yBR{iqHz|ve2KO?%qhE6_C0&1RI}$QMW@;RY~4^MRS zxCq>5-Ri8ea|r|>j-)7QsU8qofjrgg7V}wZwCr=u)Fr++HU(DMG$e~OSi-l#d(QK`gKi;u zX6w``-!DMSJH#CLBG33?I(TjX{gCK^7TLlH^9FFdJua+2EqY)V90l=w0?pq~VLiSd zffgJEqxw%0|2LXzp#PXp0nt9@Q_=prr02O5^q6k}FG;)HM~*Y}m?!0l<5Pwn^EV)W zZ-x`s5l)|{0?(zOUy>69VjhbA!w>ib>3MF3GUjK%9%(GvfArxZWw=S`F+T*>#S!gC z&;J`_=W~L+`5c$$Ip)PuP0$wdjDM#ithYo5lwwnYGVtk$zDEo|^cNMN4E$C^pAtRr zZ3qR?F6eJZ^!T0!;&%i5qvMz7NqqjzIfx~mf>D2zfj=U5*5mqN-UIBC>HyH8e3dd` z{Z30;fOBvZMBG6Cf->!N$ZfwoKjh`6l%oD91Aj$69dtmC`Do%@>Ti;k#~$>U4`LrF z_KWiP=Y)1~9iJhN&mVg1SF7(~Z>4r>XnsNue3L9;J$`T95Ivp~r~o?PI}yD~iD!>S z^i$Yo|51)p<6IZ|kNH?q^k@hE+}ChwBZ4_`ZanuS>r~Lt=~+Y3|!v@9))uWJC}ts(%478H76k literal 0 HcmV?d00001