[backend] introduced rv32 backend
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -49,4 +49,6 @@ GTAGS
|
||||
|
||||
__init__.py
|
||||
|
||||
*.pyc
|
||||
*.pyc
|
||||
|
||||
.DS_*
|
||||
@@ -17,8 +17,7 @@ add_executable(sysyc
|
||||
IR.cpp
|
||||
SysYIRGenerator.cpp
|
||||
Backend.cpp
|
||||
# LLVMIRGenerator.cpp
|
||||
LLVMIRGenerator_1.cpp
|
||||
RISCv32Backend.cpp
|
||||
)
|
||||
target_include_directories(sysyc PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_compile_options(sysyc PRIVATE -frtti)
|
||||
|
||||
@@ -1,674 +0,0 @@
|
||||
// LLVMIRGenerator.cpp
|
||||
// TODO:类型转换及其检查
|
||||
// TODO:sysy库函数处理
|
||||
// TODO:数组处理
|
||||
// TODO:对while、continue、break的测试
|
||||
#include "LLVMIRGenerator.h"
|
||||
#include <iomanip>
|
||||
using namespace std;
|
||||
namespace sysy {
|
||||
std::string LLVMIRGenerator::generateIR(SysYParser::CompUnitContext* unit) {
|
||||
// 初始化自定义IR数据结构
|
||||
irModule = std::make_unique<sysy::Module>();
|
||||
irBuilder = sysy::IRBuilder(); // 初始化IR构建器
|
||||
tempCounter = 0;
|
||||
symbolTable.clear();
|
||||
tmpTable.clear();
|
||||
globalVars.clear();
|
||||
inFunction = false;
|
||||
|
||||
visitCompUnit(unit);
|
||||
return irStream.str();
|
||||
}
|
||||
|
||||
std::string LLVMIRGenerator::getNextTemp() {
|
||||
std::string ret = "%." + std::to_string(tempCounter++);
|
||||
tmpTable[ret] = "void";
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string LLVMIRGenerator::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";
|
||||
}
|
||||
|
||||
sysy::Type* LLVMIRGenerator::getSysYType(const std::string& typeStr) {
|
||||
if (typeStr == "int") return sysy::Type::getIntType();
|
||||
if (typeStr == "float") return sysy::Type::getFloatType();
|
||||
if (typeStr == "void") return sysy::Type::getVoidType();
|
||||
// 处理指针类型等
|
||||
return sysy::Type::getIntType();
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitCompUnit(SysYParser::CompUnitContext* ctx) {
|
||||
auto type_i32 = Type::getIntType();
|
||||
auto type_f32 = Type::getFloatType();
|
||||
auto type_void = Type::getVoidType();
|
||||
auto type_i32p = Type::getPointerType(type_i32);
|
||||
auto type_f32p = Type::getPointerType(type_f32);
|
||||
|
||||
// 创建运行时库函数
|
||||
irModule->createFunction("getint", sysy::FunctionType::get(type_i32, {}));
|
||||
irModule->createFunction("getch", sysy::FunctionType::get(type_i32, {}));
|
||||
irModule->createFunction("getfloat", sysy::FunctionType::get(type_f32, {}));
|
||||
//TODO: 添加更多运行时库函数
|
||||
irStream << "declare i32 @getint()\n";
|
||||
irStream << "declare i32 @getch()\n";
|
||||
irStream << "declare float @getfloat()\n";
|
||||
//TODO: 添加更多运行时库函数的文本IR
|
||||
|
||||
for (auto decl : ctx->decl()) {
|
||||
decl->accept(this);
|
||||
}
|
||||
for (auto funcDef : ctx->funcDef()) {
|
||||
inFunction = true; // 进入函数定义
|
||||
funcDef->accept(this);
|
||||
inFunction = false; // 离开函数定义
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::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<std::string>(varDef->initVal()->accept(this));
|
||||
} else {
|
||||
std::cout << "[WR-Release-01]Warning: Global variable '" << varName
|
||||
<< "' is declared without initialization, defaulting to 0.\n";
|
||||
}
|
||||
irStream << "@" << varName << " = dso_local global " << llvmType << " " << value << ", align 4\n";
|
||||
globalVars.push_back(varName); // 记录全局变量
|
||||
} else {
|
||||
// 局部变量声明
|
||||
varDef->accept(this);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitConstDecl(SysYParser::ConstDeclContext* ctx) {
|
||||
// TODO:数组初始化
|
||||
std::string type = ctx->bType()->getText();
|
||||
for (auto constDef : ctx->constDef()) {
|
||||
if (!inFunction) {
|
||||
// 全局常量声明
|
||||
std::string varName = constDef->Ident()->getText();
|
||||
std::string llvmType = getLLVMType(type);
|
||||
std::string value = "0"; // 默认值为 0
|
||||
|
||||
try {
|
||||
value = std::any_cast<std::string>(constDef->constInitVal()->accept(this));
|
||||
} catch (...) {
|
||||
throw std::runtime_error("[ERR-Release-01]Const value must be initialized upon definition.");
|
||||
}
|
||||
// 如果是 float 类型,转换为十六进制表示
|
||||
if (llvmType == "float") {
|
||||
try {
|
||||
double floatValue = std::stod(value);
|
||||
uint64_t hexValue = reinterpret_cast<uint64_t&>(floatValue);
|
||||
std::stringstream ss;
|
||||
ss << "0x" << std::hex << std::uppercase << hexValue;
|
||||
value = ss.str();
|
||||
} catch (...) {
|
||||
throw std::runtime_error("[ERR-Release-02]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<std::string>(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);
|
||||
uint64_t hexValue = reinterpret_cast<uint64_t&>(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;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitVarDef(SysYParser::VarDefContext* ctx) {
|
||||
// TODO:数组初始化
|
||||
std::string varName = ctx->Ident()->getText();
|
||||
std::string type = currentVarType;
|
||||
std::string llvmType = getLLVMType(type);
|
||||
std::string allocaName = getNextTemp();
|
||||
|
||||
|
||||
irStream << " " << allocaName << " = alloca " << llvmType << ", align 4\n";
|
||||
|
||||
if (ctx->ASSIGN()) {
|
||||
std::string value = std::any_cast<std::string>(ctx->initVal()->accept(this));
|
||||
|
||||
if (llvmType == "float") {
|
||||
try {
|
||||
double floatValue = std::stod(value);
|
||||
uint64_t hexValue = reinterpret_cast<uint64_t&>(floatValue);
|
||||
std::stringstream ss;
|
||||
ss << "0x" << std::hex << std::uppercase << (hexValue & (0xffffffffUL << 32));
|
||||
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;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::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 << "(";
|
||||
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";
|
||||
|
||||
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";
|
||||
|
||||
symbolTable[varName] = {allocaName, llvmType};
|
||||
}
|
||||
}
|
||||
ctx->blockStmt()->accept(this);
|
||||
|
||||
if (!hasReturn) {
|
||||
if (currentReturnType == "void") {
|
||||
irStream << " ret void\n";
|
||||
} else {
|
||||
irStream << " ret " << currentReturnType << " 0\n";
|
||||
}
|
||||
}
|
||||
irStream << "}\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitBlockStmt(SysYParser::BlockStmtContext* ctx) {
|
||||
for (auto item : ctx->blockItem()) {
|
||||
item->accept(this);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
std::any LLVMIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx)
|
||||
{
|
||||
std::string lhsAlloca = std::any_cast<std::string>(ctx->lValue()->accept(this));
|
||||
std::string lhsType = symbolTable[ctx->lValue()->Ident()->getText()].second;
|
||||
std::string rhs = std::any_cast<std::string>(ctx->exp()->accept(this));
|
||||
|
||||
if (lhsType == "float") {
|
||||
try {
|
||||
double floatValue = std::stod(rhs);
|
||||
uint64_t hexValue = reinterpret_cast<uint64_t&>(floatValue);
|
||||
std::stringstream ss;
|
||||
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
|
||||
<< "* " << lhsAlloca << ", align 4\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx)
|
||||
{
|
||||
std::string cond = std::any_cast<std::string>(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";
|
||||
|
||||
irStream << trueLabel << ":\n";
|
||||
ctx->stmt(0)->accept(this);
|
||||
irStream << " br label %" << mergeLabel << "\n";
|
||||
|
||||
irStream << falseLabel << ":\n";
|
||||
if (ctx->ELSE()) {
|
||||
ctx->stmt(1)->accept(this);
|
||||
}
|
||||
irStream << " br label %" << mergeLabel << "\n";
|
||||
|
||||
irStream << mergeLabel << ":\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx)
|
||||
{
|
||||
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<std::string>(ctx->cond()->accept(this));
|
||||
irStream << " br i1 " << cond << ", label %" << loop_body << ", label %" << loop_end << "\n";
|
||||
irStream << loop_body << ":\n";
|
||||
ctx->stmt()->accept(this);
|
||||
irStream << " br label %" << loop_cond << "\n";
|
||||
irStream << loop_end << ":\n";
|
||||
|
||||
loopStack.pop();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitBreakStmt(SysYParser::BreakStmtContext *ctx)
|
||||
{
|
||||
if (loopStack.empty()) {
|
||||
throw std::runtime_error("Break statement outside of a loop.");
|
||||
}
|
||||
irStream << " br label %" << loopStack.top().breakLabel << "\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitContinueStmt(SysYParser::ContinueStmtContext *ctx)
|
||||
{
|
||||
if (loopStack.empty()) {
|
||||
throw std::runtime_error("Continue statement outside of a loop.");
|
||||
}
|
||||
irStream << " br label %" << loopStack.top().continueLabel << "\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitReturnStmt(SysYParser::ReturnStmtContext *ctx)
|
||||
{
|
||||
hasReturn = true;
|
||||
if (ctx->exp()) {
|
||||
std::string value = std::any_cast<std::string>(ctx->exp()->accept(this));
|
||||
irStream << " ret " << currentReturnType << " " << value << "\n";
|
||||
} else {
|
||||
irStream << " ret void\n";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// std::any LLVMIRGenerator::visitStmt(SysYParser::StmtContext* ctx) {
|
||||
// if (ctx->lValue() && ctx->ASSIGN()) {
|
||||
// std::string lhsAlloca = std::any_cast<std::string>(ctx->lValue()->accept(this));
|
||||
// std::string lhsType = symbolTable[ctx->lValue()->Ident()->getText()].second;
|
||||
// std::string rhs = std::any_cast<std::string>(ctx->exp()->accept(this));
|
||||
// if (lhsType == "float") {
|
||||
// try {
|
||||
// double floatValue = std::stod(rhs);
|
||||
// uint64_t hexValue = reinterpret_cast<uint64_t&>(floatValue);
|
||||
// std::stringstream ss;
|
||||
// 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
|
||||
// << "* " << lhsAlloca << ", align 4\n";
|
||||
// } else if (ctx->RETURN()) {
|
||||
// hasReturn = true;
|
||||
// if (ctx->exp()) {
|
||||
// std::string value = std::any_cast<std::string>(ctx->exp()->accept(this));
|
||||
// irStream << " ret " << currentReturnType << " " << value << "\n";
|
||||
// } else {
|
||||
// irStream << " ret void\n";
|
||||
// }
|
||||
// } else if (ctx->IF()) {
|
||||
// std::string cond = std::any_cast<std::string>(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";
|
||||
|
||||
// irStream << trueLabel << ":\n";
|
||||
// ctx->stmt(0)->accept(this);
|
||||
// irStream << " br label %" << mergeLabel << "\n";
|
||||
|
||||
// irStream << falseLabel << ":\n";
|
||||
// if (ctx->ELSE()) {
|
||||
// ctx->stmt(1)->accept(this);
|
||||
// }
|
||||
// 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<std::string>(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;
|
||||
// }
|
||||
|
||||
std::any LLVMIRGenerator::visitLValue(SysYParser::LValueContext* ctx) {
|
||||
std::string varName = ctx->Ident()->getText();
|
||||
return symbolTable[varName].first;
|
||||
}
|
||||
|
||||
// std::any LLVMIRGenerator::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) {
|
||||
// if (ctx->lValue()) {
|
||||
// std::string allocaPtr = std::any_cast<std::string>(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 4\n";
|
||||
// tmpTable[temp] = type;
|
||||
// return temp;
|
||||
// } else if (ctx->exp()) {
|
||||
// return ctx->exp()->accept(this);
|
||||
// } else {
|
||||
// return ctx->number()->accept(this);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
std::any LLVMIRGenerator::visitPrimExp(SysYParser::PrimExpContext *ctx){
|
||||
// irStream << "visitPrimExp\n";
|
||||
// std::cout << "Type name: " << typeid(*(ctx->primaryExp())).name() << std::endl;
|
||||
SysYParser::PrimaryExpContext* pExpCtx = ctx->primaryExp();
|
||||
if (auto* lvalCtx = dynamic_cast<SysYParser::LValContext*>(pExpCtx)) {
|
||||
std::string allocaPtr = std::any_cast<std::string>(lvalCtx->lValue()->accept(this));
|
||||
std::string varName = lvalCtx->lValue()->Ident()->getText();
|
||||
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 (auto* expCtx = dynamic_cast<SysYParser::ParenExpContext*>(pExpCtx)) {
|
||||
return expCtx->exp()->accept(this);
|
||||
} else if (auto* strCtx = dynamic_cast<SysYParser::StrContext*>(pExpCtx)) {
|
||||
return strCtx->string()->accept(this);
|
||||
} else if (auto* numCtx = dynamic_cast<SysYParser::NumContext*>(pExpCtx)) {
|
||||
return numCtx->number()->accept(this);
|
||||
} else {
|
||||
// 没有成功转换,说明 ctx->primaryExp() 不是 NumContext 或其他已知类型
|
||||
// 可能是其他类型的表达式,或者是一个空的 PrimaryExpContext
|
||||
std::cout << "Unknown primary expression type." << std::endl;
|
||||
throw std::runtime_error("Unknown primary expression type.");
|
||||
}
|
||||
// return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitParenExp(SysYParser::ParenExpContext* ctx) {
|
||||
return ctx->exp()->accept(this);
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitNumber(SysYParser::NumberContext* ctx) {
|
||||
if (ctx->ILITERAL()) {
|
||||
return ctx->ILITERAL()->getText();
|
||||
} else if (ctx->FLITERAL()) {
|
||||
return ctx->FLITERAL()->getText();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitString(SysYParser::StringContext *ctx)
|
||||
{
|
||||
if (ctx->STRING()) {
|
||||
// 处理字符串常量
|
||||
std::string str = ctx->STRING()->getText();
|
||||
// 去掉引号
|
||||
str = str.substr(1, str.size() - 2);
|
||||
// 转义处理
|
||||
std::string escapedStr;
|
||||
for (char c : str) {
|
||||
if (c == '\\') {
|
||||
escapedStr += "\\\\";
|
||||
} else if (c == '"') {
|
||||
escapedStr += "\\\"";
|
||||
} else {
|
||||
escapedStr += c;
|
||||
}
|
||||
}
|
||||
return "\"" + escapedStr + "\"";
|
||||
}
|
||||
return ctx->STRING()->getText();
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitUnExp(SysYParser::UnExpContext* ctx) {
|
||||
if (ctx->unaryOp()) {
|
||||
std::string operand = std::any_cast<std::string>(ctx->unaryExp()->accept(this));
|
||||
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 == "!") {
|
||||
irStream << " " << temp << " = xor " << type << " " << operand << ", 1\n";
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
return ctx->unaryExp()->accept(this);
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitCall(SysYParser::CallContext *ctx)
|
||||
{
|
||||
std::string funcName = ctx->Ident()->getText();
|
||||
std::vector<std::string> args;
|
||||
if (ctx->funcRParams()) {
|
||||
for (auto argCtx : ctx->funcRParams()->exp()) {
|
||||
args.push_back(std::any_cast<std::string>(argCtx->accept(this)));
|
||||
}
|
||||
}
|
||||
std::string temp = getNextTemp();
|
||||
std::string argList = "";
|
||||
for (size_t i = 0; i < args.size(); ++i) {
|
||||
if (i > 0) argList += ", ";
|
||||
argList +=tmpTable[args[i]] + " noundef " + args[i];
|
||||
}
|
||||
irStream << " " << temp << " = call " << currentReturnType << " @" << funcName << "(" << argList << ")\n";
|
||||
tmpTable[temp] = currentReturnType;
|
||||
return temp;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitMulExp(SysYParser::MulExpContext* ctx) {
|
||||
auto unaryExps = ctx->unaryExp();
|
||||
std::string left = std::any_cast<std::string>(unaryExps[0]->accept(this));
|
||||
for (size_t i = 1; i < unaryExps.size(); ++i) {
|
||||
std::string right = std::any_cast<std::string>(unaryExps[i]->accept(this));
|
||||
std::string op = ctx->children[2*i-1]->getText();
|
||||
std::string temp = getNextTemp();
|
||||
std::string type = tmpTable[left];
|
||||
if (op == "*") {
|
||||
irStream << " " << temp << " = mul nsw " << type << " " << left << ", " << right << "\n";
|
||||
} else if (op == "/") {
|
||||
irStream << " " << temp << " = sdiv " << type << " " << left << ", " << right << "\n";
|
||||
} else if (op == "%") {
|
||||
irStream << " " << temp << " = srem " << type << " " << left << ", " << right << "\n";
|
||||
}
|
||||
left = temp;
|
||||
tmpTable[temp] = type;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitAddExp(SysYParser::AddExpContext* ctx) {
|
||||
auto mulExps = ctx->mulExp();
|
||||
std::string left = std::any_cast<std::string>(mulExps[0]->accept(this));
|
||||
for (size_t i = 1; i < mulExps.size(); ++i) {
|
||||
std::string right = std::any_cast<std::string>(mulExps[i]->accept(this));
|
||||
std::string op = ctx->children[2*i-1]->getText();
|
||||
std::string temp = getNextTemp();
|
||||
std::string type = tmpTable[left];
|
||||
if (op == "+") {
|
||||
irStream << " " << temp << " = add nsw " << type << " " << left << ", " << right << "\n";
|
||||
} else if (op == "-") {
|
||||
irStream << " " << temp << " = sub nsw " << type << " " << left << ", " << right << "\n";
|
||||
}
|
||||
left = temp;
|
||||
tmpTable[temp] = type;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitRelExp(SysYParser::RelExpContext* ctx) {
|
||||
auto addExps = ctx->addExp();
|
||||
std::string left = std::any_cast<std::string>(addExps[0]->accept(this));
|
||||
for (size_t i = 1; i < addExps.size(); ++i) {
|
||||
std::string right = std::any_cast<std::string>(addExps[i]->accept(this));
|
||||
std::string op = ctx->children[2*i-1]->getText();
|
||||
std::string temp = getNextTemp();
|
||||
std::string type = tmpTable[left];
|
||||
if (op == "<") {
|
||||
irStream << " " << temp << " = icmp slt " << type << " " << left << ", " << right << "\n";
|
||||
} else if (op == ">") {
|
||||
irStream << " " << temp << " = icmp sgt " << type << " " << left << ", " << right << "\n";
|
||||
} else if (op == "<=") {
|
||||
irStream << " " << temp << " = icmp sle " << type << " " << left << ", " << right << "\n";
|
||||
} else if (op == ">=") {
|
||||
irStream << " " << temp << " = icmp sge " << type << " " << left << ", " << right << "\n";
|
||||
}
|
||||
left = temp;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitEqExp(SysYParser::EqExpContext* ctx) {
|
||||
auto relExps = ctx->relExp();
|
||||
std::string left = std::any_cast<std::string>(relExps[0]->accept(this));
|
||||
for (size_t i = 1; i < relExps.size(); ++i) {
|
||||
std::string right = std::any_cast<std::string>(relExps[i]->accept(this));
|
||||
std::string op = ctx->children[2*i-1]->getText();
|
||||
std::string temp = getNextTemp();
|
||||
std::string type = tmpTable[left];
|
||||
if (op == "==") {
|
||||
irStream << " " << temp << " = icmp eq " << type << " " << left << ", " << right << "\n";
|
||||
} else if (op == "!=") {
|
||||
irStream << " " << temp << " = icmp ne " << type << " " << left << ", " << right << "\n";
|
||||
}
|
||||
left = temp;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitLAndExp(SysYParser::LAndExpContext* ctx) {
|
||||
auto eqExps = ctx->eqExp();
|
||||
std::string left = std::any_cast<std::string>(eqExps[0]->accept(this));
|
||||
for (size_t i = 1; i < eqExps.size(); ++i) {
|
||||
std::string falseLabel = "land.false." + std::to_string(tempCounter);
|
||||
std::string endLabel = "land.end." + std::to_string(tempCounter++);
|
||||
std::string temp = getNextTemp();
|
||||
|
||||
irStream << " br label %" << falseLabel << "\n";
|
||||
irStream << falseLabel << ":\n";
|
||||
std::string right = std::any_cast<std::string>(eqExps[i]->accept(this));
|
||||
irStream << " " << temp << " = and i1 " << left << ", " << right << "\n";
|
||||
irStream << " br label %" << endLabel << "\n";
|
||||
irStream << endLabel << ":\n";
|
||||
left = temp;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitLOrExp(SysYParser::LOrExpContext* ctx) {
|
||||
auto lAndExps = ctx->lAndExp();
|
||||
std::string left = std::any_cast<std::string>(lAndExps[0]->accept(this));
|
||||
for (size_t i = 1; i < lAndExps.size(); ++i) {
|
||||
std::string trueLabel = "lor.true." + std::to_string(tempCounter);
|
||||
std::string endLabel = "lor.end." + std::to_string(tempCounter++);
|
||||
std::string temp = getNextTemp();
|
||||
|
||||
irStream << " br label %" << trueLabel << "\n";
|
||||
irStream << trueLabel << ":\n";
|
||||
std::string right = std::any_cast<std::string>(lAndExps[i]->accept(this));
|
||||
irStream << " " << temp << " = or i1 " << left << ", " << right << "\n";
|
||||
irStream << " br label %" << endLabel << "\n";
|
||||
irStream << endLabel << ":\n";
|
||||
left = temp;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
#pragma once
|
||||
#include "SysYBaseVisitor.h"
|
||||
#include "SysYParser.h"
|
||||
#include "IR.h"
|
||||
#include "IRBuilder.h"
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
|
||||
class LLVMIRGenerator : public SysYBaseVisitor {
|
||||
public:
|
||||
sysy::Module* getIRModule() const { return irModule.get(); }
|
||||
|
||||
std::string generateIR(SysYParser::CompUnitContext* unit);
|
||||
std::string getIR() const { return irStream.str(); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<sysy::Module> irModule; // IR数据结构
|
||||
std::stringstream irStream; // 文本输出流
|
||||
sysy::IRBuilder irBuilder; // IR构建器
|
||||
int tempCounter = 0;
|
||||
std::string currentVarType;
|
||||
// std::map<std::string, sysy::Value*> symbolTable;
|
||||
std::map<std::string, std::pair<std::string, std::string>> symbolTable;
|
||||
std::map<std::string, std::string> tmpTable;
|
||||
std::vector<std::string> globalVars;
|
||||
std::string currentFunction;
|
||||
std::string currentReturnType;
|
||||
std::vector<std::string> breakStack;
|
||||
std::vector<std::string> continueStack;
|
||||
bool hasReturn = false;
|
||||
|
||||
struct LoopLabels {
|
||||
std::string breakLabel; // break跳转的目标标签
|
||||
std::string continueLabel; // continue跳转的目标标签
|
||||
};
|
||||
std::stack<LoopLabels> loopStack; // 用于管理循环的break和continue标签
|
||||
std::string getNextTemp();
|
||||
std::string getLLVMType(const std::string&);
|
||||
sysy::Type* getSysYType(const std::string&);
|
||||
|
||||
bool inFunction = false; // 标识当前是否处于函数内部
|
||||
|
||||
// 访问方法
|
||||
std::any visitCompUnit(SysYParser::CompUnitContext* ctx);
|
||||
std::any visitConstDecl(SysYParser::ConstDeclContext* ctx);
|
||||
std::any visitVarDecl(SysYParser::VarDeclContext* ctx);
|
||||
std::any visitVarDef(SysYParser::VarDefContext* ctx);
|
||||
std::any visitFuncDef(SysYParser::FuncDefContext* ctx);
|
||||
std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx);
|
||||
// std::any visitStmt(SysYParser::StmtContext* ctx);
|
||||
std::any visitLValue(SysYParser::LValueContext* ctx);
|
||||
std::any visitPrimaryExp(SysYParser::PrimaryExpContext* ctx);
|
||||
std::any visitPrimExp(SysYParser::PrimExpContext* ctx);
|
||||
std::any visitParenExp(SysYParser::ParenExpContext* ctx);
|
||||
std::any visitNumber(SysYParser::NumberContext* ctx);
|
||||
std::any visitString(SysYParser::StringContext* ctx);
|
||||
std::any visitCall(SysYParser::CallContext *ctx);
|
||||
std::any visitUnExp(SysYParser::UnExpContext* ctx);
|
||||
std::any visitMulExp(SysYParser::MulExpContext* ctx);
|
||||
std::any visitAddExp(SysYParser::AddExpContext* ctx);
|
||||
std::any visitRelExp(SysYParser::RelExpContext* ctx);
|
||||
std::any visitEqExp(SysYParser::EqExpContext* ctx);
|
||||
std::any visitLAndExp(SysYParser::LAndExpContext* ctx);
|
||||
std::any visitLOrExp(SysYParser::LOrExpContext* ctx);
|
||||
std::any visitAssignStmt(SysYParser::AssignStmtContext *ctx) override;
|
||||
std::any visitIfStmt(SysYParser::IfStmtContext *ctx) override;
|
||||
std::any visitWhileStmt(SysYParser::WhileStmtContext *ctx) override;
|
||||
std::any visitBreakStmt(SysYParser::BreakStmtContext *ctx) override;
|
||||
std::any visitContinueStmt(SysYParser::ContinueStmtContext *ctx) override;
|
||||
std::any visitReturnStmt(SysYParser::ReturnStmtContext *ctx) override;
|
||||
|
||||
// 统一创建二元操作(同时生成数据结构和文本)
|
||||
sysy::Value* createBinaryOp(SysYParser::ExpContext* lhs,
|
||||
SysYParser::ExpContext* rhs,
|
||||
sysy::Instruction::Kind opKind);
|
||||
};
|
||||
@@ -1,859 +0,0 @@
|
||||
// LLVMIRGenerator.cpp
|
||||
// TODO:类型转换及其检查
|
||||
// TODO:sysy库函数处理
|
||||
// TODO:数组处理
|
||||
// TODO:对while、continue、break的测试
|
||||
#include "LLVMIRGenerator_1.h"
|
||||
#include <iomanip>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
|
||||
// namespace sysy {
|
||||
|
||||
std::string LLVMIRGenerator::generateIR(SysYParser::CompUnitContext* unit) {
|
||||
// 初始化 SysY IR 模块
|
||||
module = std::make_unique<sysy::Module>();
|
||||
// 清空符号表和临时变量表
|
||||
symbolTable.clear();
|
||||
tmpTable.clear();
|
||||
irSymbolTable.clear();
|
||||
irTmpTable.clear();
|
||||
tempCounter = 0;
|
||||
globalVars.clear();
|
||||
hasReturn = false;
|
||||
loopStack = std::stack<LoopLabels>();
|
||||
inFunction = false;
|
||||
|
||||
// 访问编译单元
|
||||
visitCompUnit(unit);
|
||||
return irStream.str();
|
||||
}
|
||||
|
||||
std::string LLVMIRGenerator::getNextTemp() {
|
||||
std::string ret = "%." + std::to_string(tempCounter++);
|
||||
tmpTable[ret] = "void";
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string LLVMIRGenerator::getIRTempName() {
|
||||
return "%" + std::to_string(tempCounter++);
|
||||
}
|
||||
|
||||
std::string LLVMIRGenerator::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";
|
||||
}
|
||||
|
||||
sysy::Type* LLVMIRGenerator::getIRType(const std::string& type) {
|
||||
if (type == "int") return sysy::Type::getIntType();
|
||||
if (type == "float") return sysy::Type::getFloatType();
|
||||
if (type == "void") return sysy::Type::getVoidType();
|
||||
if (type.find("[]") != std::string::npos) {
|
||||
std::string baseType = type.substr(0, type.size() - 2);
|
||||
return sysy::Type::getPointerType(getIRType(baseType));
|
||||
}
|
||||
return sysy::Type::getIntType(); // 默认 int
|
||||
}
|
||||
|
||||
void LLVMIRGenerator::setIRPosition(sysy::BasicBlock* block) {
|
||||
currentIRBlock = block;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitCompUnit(SysYParser::CompUnitContext* ctx) {
|
||||
for (auto decl : ctx->decl()) {
|
||||
decl->accept(this);
|
||||
}
|
||||
for (auto funcDef : ctx->funcDef()) {
|
||||
inFunction = true;
|
||||
funcDef->accept(this);
|
||||
inFunction = false;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
std::any LLVMIRGenerator::visitVarDecl(SysYParser::VarDeclContext* ctx) {
|
||||
// TODO:数组初始化
|
||||
std::string type = ctx->bType()->getText();
|
||||
currentVarType = getLLVMType(type);
|
||||
sysy::Type* irType = sysy::Type::getPointerType(getIRType(type));
|
||||
|
||||
for (auto varDef : ctx->varDef()) {
|
||||
if (!inFunction) {
|
||||
// 全局变量(文本 IR)
|
||||
std::string varName = varDef->Ident()->getText();
|
||||
std::string llvmType = getLLVMType(type);
|
||||
std::string value = "0";
|
||||
sysy::Value* initValue = nullptr;
|
||||
|
||||
if (varDef->ASSIGN()) {
|
||||
value = std::any_cast<std::string>(varDef->initVal()->accept(this));
|
||||
if (irTmpTable.find(value) != irTmpTable.end() && isa<sysy::ConstantValue>(irTmpTable[value])) {
|
||||
initValue = irTmpTable[value];
|
||||
}
|
||||
}
|
||||
|
||||
if (llvmType == "float" && initValue) {
|
||||
try {
|
||||
double floatValue = std::stod(value);
|
||||
uint64_t hexValue = reinterpret_cast<uint64_t&>(floatValue);
|
||||
std::stringstream ss;
|
||||
ss << "0x" << std::hex << std::uppercase << hexValue;
|
||||
value = ss.str();
|
||||
} catch (...) {
|
||||
throw std::runtime_error("[ERR-Release-02]Invalid float literal: " + value);
|
||||
}
|
||||
}
|
||||
irStream << "@" << varName << " = dso_local global " << llvmType << " " << value << ", align 4\n";
|
||||
globalVars.push_back(varName);
|
||||
|
||||
// 全局变量(SysY IR)
|
||||
auto globalValue = module->createGlobalValue(varName, irType, {}, initValue);
|
||||
irSymbolTable[varName] = globalValue;
|
||||
} else {
|
||||
varDef->accept(this);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitConstDecl(SysYParser::ConstDeclContext* ctx) {
|
||||
// TODO:数组初始化
|
||||
std::string type = ctx->bType()->getText();
|
||||
currentVarType = getLLVMType(type);
|
||||
sysy::Type* irType = sysy::Type::getPointerType(getIRType(type)); // 全局变量为指针类型
|
||||
|
||||
for (auto constDef : ctx->constDef()) {
|
||||
std::string varName = constDef->Ident()->getText();
|
||||
std::string llvmType = getLLVMType(type);
|
||||
std::string value = "0";
|
||||
sysy::Value* initValue = nullptr;
|
||||
|
||||
try {
|
||||
value = std::any_cast<std::string>(constDef->constInitVal()->accept(this));
|
||||
if (isa<sysy::ConstantValue>(irTmpTable[value])) {
|
||||
initValue = irTmpTable[value];
|
||||
}
|
||||
} catch (...) {
|
||||
throw std::runtime_error("Const value must be initialized upon definition.");
|
||||
}
|
||||
|
||||
if (!inFunction) {
|
||||
// 全局常量(文本 IR)
|
||||
if (llvmType == "float") {
|
||||
try {
|
||||
double floatValue = std::stod(value);
|
||||
uint64_t hexValue = reinterpret_cast<uint64_t&>(floatValue);
|
||||
std::stringstream ss;
|
||||
ss << "0x" << std::hex << std::uppercase << hexValue;
|
||||
value = ss.str();
|
||||
} catch (...) {
|
||||
throw std::runtime_error("[ERR-Release-03]Invalid float literal: " + value);
|
||||
}
|
||||
}
|
||||
irStream << "@" << varName << " = dso_local constant " << llvmType << " " << value << ", align 4\n";
|
||||
globalVars.push_back(varName);
|
||||
|
||||
// 全局常量(SysY IR)
|
||||
auto globalValue = module->createGlobalValue(varName, irType, {}, initValue);
|
||||
irSymbolTable[varName] = globalValue;
|
||||
} else {
|
||||
// 局部常量(文本 IR)
|
||||
std::string allocaName = getNextTemp();
|
||||
if (llvmType == "float") {
|
||||
try {
|
||||
double floatValue = std::stod(value);
|
||||
uint64_t hexValue = reinterpret_cast<uint64_t&>(floatValue);
|
||||
std::stringstream ss;
|
||||
ss << "0x" << std::hex << std::uppercase << hexValue;
|
||||
value = ss.str();
|
||||
} catch (...) {
|
||||
throw std::runtime_error("Invalid float literal: " + value);
|
||||
}
|
||||
}
|
||||
irStream << " " << allocaName << " = alloca " << llvmType << ", align 4\n";
|
||||
irStream << " store " << llvmType << " " << value << ", " << llvmType
|
||||
<< "* " << allocaName << ", align 4\n";
|
||||
symbolTable[varName] = {allocaName, llvmType};
|
||||
tmpTable[allocaName] = llvmType;
|
||||
|
||||
// 局部常量(SysY IR)TODO:这里可能有bug,AI在犯蠢
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
auto allocaInst = builder.createAllocaInst(irType, {}, varName);
|
||||
builder.createStoreInst(initValue, allocaInst);
|
||||
irSymbolTable[varName] = allocaInst;
|
||||
irTmpTable[allocaName] = allocaInst;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitVarDef(SysYParser::VarDefContext* ctx) {
|
||||
// TODO:数组初始化
|
||||
std::string varName = ctx->Ident()->getText();
|
||||
std::string llvmType = currentVarType;
|
||||
sysy::Type* irType = sysy::Type::getPointerType(getIRType(currentVarType == "i32" ? "int" : "float"));
|
||||
std::string allocaName = getNextTemp();
|
||||
|
||||
// 局部变量(文本 IR)
|
||||
irStream << " " << allocaName << " = alloca " << llvmType << ", align 4\n";
|
||||
|
||||
// 局部变量(SysY IR)
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
auto allocaInst = builder.createAllocaInst(irType, {}, varName);
|
||||
sysy::Value* initValue = nullptr;
|
||||
|
||||
if (ctx->ASSIGN()) {
|
||||
std::string value = std::any_cast<std::string>(ctx->initVal()->accept(this));
|
||||
if (llvmType == "float") {
|
||||
try {
|
||||
double floatValue = std::stod(value);
|
||||
uint64_t hexValue = reinterpret_cast<uint64_t&>(floatValue);
|
||||
std::stringstream ss;
|
||||
ss << "0x" << std::hex << std::uppercase << (hexValue & (0xffffffffUL << 32));
|
||||
value = ss.str();
|
||||
} catch (...) {
|
||||
throw std::runtime_error("Invalid float literal: " + value);
|
||||
}
|
||||
}
|
||||
irStream << " store " << llvmType << " " << value << ", " << llvmType
|
||||
<< "* " << allocaName << ", align 4\n";
|
||||
|
||||
if (irTmpTable.find(value) != irTmpTable.end()) {
|
||||
initValue = irTmpTable[value];
|
||||
}
|
||||
builder.createStoreInst(initValue, allocaInst);
|
||||
}
|
||||
|
||||
symbolTable[varName] = {allocaName, llvmType};
|
||||
tmpTable[allocaName] = llvmType;
|
||||
irSymbolTable[varName] = allocaInst;//TODO:这里没看懂在干嘛
|
||||
irTmpTable[allocaName] = allocaInst;//TODO:这里没看懂在干嘛
|
||||
builder.createStoreInst(initValue, allocaInst);//TODO:这里没看懂在干嘛
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitFuncDef(SysYParser::FuncDefContext* ctx) {
|
||||
currentFunction = ctx->Ident()->getText();
|
||||
currentReturnType = getLLVMType(ctx->funcType()->getText());
|
||||
sysy::Type* irReturnType = getIRType(ctx->funcType()->getText());
|
||||
std::vector<sysy::Type*> paramTypes;
|
||||
|
||||
// 清空符号表
|
||||
symbolTable.clear();
|
||||
tmpTable.clear();
|
||||
irSymbolTable.clear();
|
||||
irTmpTable.clear();
|
||||
tempCounter = 0;
|
||||
hasReturn = false;
|
||||
|
||||
// 处理函数参数(文本 IR 和 SysY IR)
|
||||
if (ctx->funcFParams()) {
|
||||
auto params = ctx->funcFParams()->funcFParam();
|
||||
for (size_t i = 0; i < params.size(); ++i) {
|
||||
std::string paramType = getLLVMType(params[i]->bType()->getText());
|
||||
if (i > 0) irStream << ", ";
|
||||
irStream << paramType << " noundef %" << i;
|
||||
symbolTable[params[i]->Ident()->getText()] = {"%" + std::to_string(i), paramType};
|
||||
tmpTable["%" + std::to_string(i)] = paramType;
|
||||
paramTypes.push_back(getIRType(params[i]->bType()->getText()));
|
||||
}
|
||||
tempCounter += params.size();
|
||||
}
|
||||
tempCounter++;
|
||||
|
||||
// 文本 IR 函数定义
|
||||
irStream << "define dso_local " << currentReturnType << " @" << currentFunction << "(";
|
||||
irStream << ") #0 {\n";
|
||||
|
||||
// SysY IR 函数定义
|
||||
sysy::Type* funcType = sysy::Type::getFunctionType(irReturnType, paramTypes);
|
||||
currentIRFunction = module->createFunction(currentFunction, funcType);
|
||||
setIRPosition(currentIRFunction->getEntryBlock());
|
||||
|
||||
// 处理函数参数分配
|
||||
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 llvmType = getLLVMType(params[i]->bType()->getText());
|
||||
sysy::Type* irType = getIRType(params[i]->bType()->getText());
|
||||
std::string allocaName = getNextTemp();
|
||||
tmpTable[allocaName] = llvmType;
|
||||
|
||||
// 文本 IR 分配
|
||||
irStream << " " << allocaName << " = alloca " << llvmType << ", align 4\n";
|
||||
irStream << " store " << llvmType << " %" << i << ", " << llvmType
|
||||
<< "* " << allocaName << ", align 4\n";
|
||||
|
||||
// SysY IR 分配
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
auto arg = currentIRBlock->createArgument(irType, varName);
|
||||
auto allocaInst = builder.createAllocaInst(sysy::Type::getPointerType(irType), {}, varName);
|
||||
builder.createStoreInst(arg, allocaInst);
|
||||
symbolTable[varName] = {allocaName, llvmType};
|
||||
irSymbolTable[varName] = allocaInst;
|
||||
irTmpTable[allocaName] = allocaInst;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->blockStmt()->accept(this);
|
||||
|
||||
if (!hasReturn) {
|
||||
if (currentReturnType == "void") {
|
||||
irStream << " ret void\n";
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
builder.createReturnInst();
|
||||
} else {
|
||||
irStream << " ret " << currentReturnType << " 0\n";
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
builder.createReturnInst(sysy::ConstantValue::get(0));
|
||||
}
|
||||
}
|
||||
irStream << "}\n";
|
||||
currentIRFunction = nullptr;
|
||||
currentIRBlock = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitBlockStmt(SysYParser::BlockStmtContext* ctx) {
|
||||
for (auto item : ctx->blockItem()) {
|
||||
item->accept(this);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext* ctx) {
|
||||
std::string lhsAlloca = std::any_cast<std::string>(ctx->lValue()->accept(this));
|
||||
std::string lhsType = symbolTable[ctx->lValue()->Ident()->getText()].second;
|
||||
std::string rhs = std::any_cast<std::string>(ctx->exp()->accept(this));
|
||||
sysy::Value* rhsValue = irTmpTable[rhs];
|
||||
|
||||
// 文本 IR
|
||||
if (lhsType == "float") {
|
||||
try {
|
||||
double floatValue = std::stod(rhs);
|
||||
uint64_t hexValue = reinterpret_cast<uint64_t&>(floatValue);
|
||||
std::stringstream ss;
|
||||
ss << "0x" << std::hex << std::uppercase << (hexValue & (0xffffffffUL << 32));
|
||||
rhs = ss.str();
|
||||
} catch (...) {
|
||||
// 如果 rhs 不是字面量,假设已正确处理
|
||||
throw std::runtime_error("Invalid float literal: " + rhs);
|
||||
}
|
||||
}
|
||||
irStream << " store " << lhsType << " " << rhs << ", " << lhsType
|
||||
<< "* " << lhsAlloca << ", align 4\n";
|
||||
|
||||
// SysY IR
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
builder.createStoreInst(rhsValue, irSymbolTable[ctx->lValue()->Ident()->getText()]);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitIfStmt(SysYParser::IfStmtContext* ctx) {
|
||||
std::string cond = std::any_cast<std::string>(ctx->cond()->accept(this));
|
||||
sysy::Value* condValue = irTmpTable[cond];
|
||||
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++);
|
||||
|
||||
// SysY IR 基本块
|
||||
sysy::BasicBlock* thenBlock = currentIRFunction->addBasicBlock(trueLabel);
|
||||
sysy::BasicBlock* elseBlock = ctx->ELSE() ? currentIRFunction->addBasicBlock(falseLabel) : nullptr;
|
||||
sysy::BasicBlock* mergeBlock = currentIRFunction->addBasicBlock(mergeLabel);
|
||||
|
||||
// 文本 IR
|
||||
irStream << " br i1 " << cond << ", label %" << trueLabel << ", label %"
|
||||
<< (ctx->ELSE() ? falseLabel : mergeLabel) << "\n";
|
||||
|
||||
// SysY IR 条件分支
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
builder.createCondBrInst(condValue, thenBlock, ctx->ELSE() ? elseBlock : mergeBlock, {}, {});
|
||||
|
||||
// 处理 then 分支
|
||||
setIRPosition(thenBlock);
|
||||
irStream << trueLabel << ":\n";
|
||||
ctx->stmt(0)->accept(this);
|
||||
irStream << " br label %" << mergeLabel << "\n";
|
||||
builder.setPosition(thenBlock, thenBlock->end());
|
||||
builder.createUncondBrInst(mergeBlock, {});
|
||||
|
||||
// 处理 else 分支
|
||||
if (ctx->ELSE()) {
|
||||
setIRPosition(elseBlock);
|
||||
irStream << falseLabel << ":\n";
|
||||
ctx->stmt(1)->accept(this);
|
||||
irStream << " br label %" << mergeLabel << "\n";
|
||||
builder.setPosition(elseBlock, elseBlock->end());
|
||||
builder.createUncondBrInst(mergeBlock, {});
|
||||
}
|
||||
|
||||
// 合并点
|
||||
setIRPosition(mergeBlock);
|
||||
irStream << mergeLabel << ":\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext* ctx) {
|
||||
std::string loopCond = "while.cond." + std::to_string(tempCounter);
|
||||
std::string loopBody = "while.body." + std::to_string(tempCounter);
|
||||
std::string loopEnd = "while.end." + std::to_string(tempCounter++);
|
||||
|
||||
// SysY IR 基本块
|
||||
sysy::BasicBlock* condBlock = currentIRFunction->addBasicBlock(loopCond);
|
||||
sysy::BasicBlock* bodyBlock = currentIRFunction->addBasicBlock(loopBody);
|
||||
sysy::BasicBlock* endBlock = currentIRFunction->addBasicBlock(loopEnd);
|
||||
|
||||
loopStack.push({loopEnd, loopCond, endBlock, condBlock});
|
||||
|
||||
// 跳转到条件块
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
builder.createUncondBrInst(condBlock, {});
|
||||
irStream << " br label %" << loopCond << "\n";
|
||||
|
||||
// 条件块
|
||||
setIRPosition(condBlock);
|
||||
irStream << loopCond << ":\n";
|
||||
std::string cond = std::any_cast<std::string>(ctx->cond()->accept(this));
|
||||
sysy::Value* condValue = irTmpTable[cond];
|
||||
irStream << " br i1 " << cond << ", label %" << loopBody << ", label %" << loopEnd << "\n";
|
||||
builder.setPosition(condBlock, condBlock->end());
|
||||
builder.createCondBrInst(condValue, bodyBlock, endBlock, {}, {});
|
||||
|
||||
// 循环体
|
||||
setIRPosition(bodyBlock);
|
||||
irStream << loopBody << ":\n";
|
||||
ctx->stmt()->accept(this);
|
||||
irStream << " br label %" << loopCond << "\n";
|
||||
builder.setPosition(bodyBlock, bodyBlock->end());
|
||||
builder.createUncondBrInst(condBlock, {});
|
||||
|
||||
// 结束块
|
||||
setIRPosition(endBlock);
|
||||
irStream << loopEnd << ":\n";
|
||||
loopStack.pop();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitBreakStmt(SysYParser::BreakStmtContext* ctx) {
|
||||
if (loopStack.empty()) {
|
||||
throw std::runtime_error("Break statement outside of a loop.");
|
||||
}
|
||||
irStream << " br label %" << loopStack.top().breakLabel << "\n";
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
builder.createUncondBrInst(loopStack.top().irBreakBlock, {});
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitContinueStmt(SysYParser::ContinueStmtContext* ctx) {
|
||||
if (loopStack.empty()) {
|
||||
throw std::runtime_error("Continue statement outside of a loop.");
|
||||
}
|
||||
irStream << " br label %" << loopStack.top().continueLabel << "\n";
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
builder.createUncondBrInst(loopStack.top().irContinueBlock, {});
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) {
|
||||
hasReturn = true;
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
if (ctx->exp()) {
|
||||
std::string value = std::any_cast<std::string>(ctx->exp()->accept(this));
|
||||
sysy::Value* irValue = irTmpTable[value];
|
||||
irStream << " ret " << currentReturnType << " " << value << "\n";
|
||||
builder.createReturnInst(irValue);
|
||||
} else {
|
||||
irStream << " ret void\n";
|
||||
builder.createReturnInst();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitLValue(SysYParser::LValueContext* ctx) {
|
||||
std::string varName = ctx->Ident()->getText();
|
||||
if (irSymbolTable.find(varName) == irSymbolTable.end()) {
|
||||
throw std::runtime_error("Undefined variable: " + varName);
|
||||
}
|
||||
// 对于 LValue,返回分配的指针(文本 IR 和 SysY IR 一致)
|
||||
return symbolTable[varName].first;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitPrimExp(SysYParser::PrimExpContext* ctx) {
|
||||
SysYParser::PrimaryExpContext* pExpCtx = ctx->primaryExp();
|
||||
if (auto* lvalCtx = dynamic_cast<SysYParser::LValContext*>(pExpCtx)) {
|
||||
std::string allocaPtr = std::any_cast<std::string>(lvalCtx->lValue()->accept(this));
|
||||
std::string varName = lvalCtx->lValue()->Ident()->getText();
|
||||
std::string type = symbolTable[varName].second;
|
||||
std::string temp = getNextTemp();
|
||||
sysy::Type* irType = getIRType(type == "i32" ? "int" : "float");
|
||||
|
||||
// 文本 IR
|
||||
irStream << " " << temp << " = load " << type << ", " << type << "* " << allocaPtr << ", align 4\n";
|
||||
tmpTable[temp] = type;
|
||||
|
||||
// SysY IR
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
auto loadInst = builder.createLoadInst(irSymbolTable[varName], {});
|
||||
irTmpTable[temp] = loadInst;
|
||||
return temp;
|
||||
} else if (auto* expCtx = dynamic_cast<SysYParser::ParenExpContext*>(pExpCtx)) {
|
||||
return expCtx->exp()->accept(this);
|
||||
} else if (auto* strCtx = dynamic_cast<SysYParser::StrContext*>(pExpCtx)) {
|
||||
return strCtx->string()->accept(this);
|
||||
} else if (auto* numCtx = dynamic_cast<SysYParser::NumContext*>(pExpCtx)) {
|
||||
return numCtx->number()->accept(this);
|
||||
} else {
|
||||
// 没有成功转换,说明 ctx->primaryExp() 不是 NumContext 或其他已知类型
|
||||
// 可能是其他类型的表达式,或者是一个空的 PrimaryExpContext
|
||||
std::cout << "Unknown primary expression type." << std::endl;
|
||||
throw std::runtime_error("Unknown primary expression type.");
|
||||
}
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitParenExp(SysYParser::ParenExpContext* ctx) {
|
||||
return ctx->exp()->accept(this);
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitNumber(SysYParser::NumberContext* ctx) {
|
||||
std::string value;
|
||||
sysy::Value* irValue = nullptr;
|
||||
if (ctx->ILITERAL()) {
|
||||
value = ctx->ILITERAL()->getText();
|
||||
irValue = sysy::ConstantValue::get(std::stoi(value));
|
||||
} else if (ctx->FLITERAL()) {
|
||||
value = ctx->FLITERAL()->getText();
|
||||
irValue = sysy::ConstantValue::get(std::stof(value));
|
||||
} else {
|
||||
value = "";
|
||||
}
|
||||
std::string temp = getNextTemp();
|
||||
tmpTable[temp] = ctx->ILITERAL() ? "i32" : "float";
|
||||
irTmpTable[temp] = irValue;
|
||||
return value;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitString(SysYParser::StringContext* ctx) {
|
||||
if (ctx->STRING()) {
|
||||
std::string str = ctx->STRING()->getText();
|
||||
str = str.substr(1, str.size() - 2);
|
||||
std::string escapedStr;
|
||||
for (char c : str) {
|
||||
if (c == '\\') {
|
||||
escapedStr += "\\\\";
|
||||
} else if (c == '"') {
|
||||
escapedStr += "\\\"";
|
||||
} else {
|
||||
escapedStr += c;
|
||||
}
|
||||
}
|
||||
// TODO: SysY IR 暂不支持字符串常量,返回文本 IR 结果
|
||||
return "\"" + escapedStr + "\"";
|
||||
}
|
||||
return ctx->STRING()->getText();
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::any LLVMIRGenerator::visitUnExp(SysYParser::UnExpContext* ctx) {
|
||||
if (ctx->unaryOp()) {
|
||||
std::string operand = std::any_cast<std::string>(ctx->unaryExp()->accept(this));
|
||||
sysy::Value* irOperand = irTmpTable[operand];
|
||||
std::string op = ctx->unaryOp()->getText();
|
||||
std::string temp = getNextTemp();
|
||||
std::string type = tmpTable[operand];
|
||||
sysy::Type* irType = getIRType(type == "i32" ? "int" : "float");
|
||||
tmpTable[temp] = type;
|
||||
|
||||
// 文本 IR
|
||||
if (op == "-") {
|
||||
irStream << " " << temp << " = sub " << type << " 0, " << operand << "\n";
|
||||
} else if (op == "!") {
|
||||
irStream << " " << temp << " = xor " << type << " " << operand << ", 1\n";
|
||||
}
|
||||
|
||||
// SysY IR
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
sysy::Instruction::Kind kind = (op == "-") ? (type == "i32" ? sysy::Instruction::kNeg : sysy::Instruction::kFNeg)
|
||||
: sysy::Instruction::kNot;
|
||||
auto unaryInst = builder.createUnaryInst(kind, irType, irOperand, temp);
|
||||
irTmpTable[temp] = unaryInst;
|
||||
return temp;
|
||||
}
|
||||
return ctx->unaryExp()->accept(this);
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitCall(SysYParser::CallContext* ctx) {
|
||||
std::string funcName = ctx->Ident()->getText();
|
||||
std::vector<std::string> args;
|
||||
std::vector<sysy::Value*> irArgs;
|
||||
if (ctx->funcRParams()) {
|
||||
for (auto argCtx : ctx->funcRParams()->exp()) {
|
||||
std::string arg = std::any_cast<std::string>(argCtx->accept(this));
|
||||
args.push_back(arg);
|
||||
irArgs.push_back(irTmpTable[arg]);
|
||||
}
|
||||
}
|
||||
std::string temp = getNextTemp();
|
||||
std::string argList;
|
||||
for (size_t i = 0; i < args.size(); ++i) {
|
||||
if (i > 0) argList += ", ";
|
||||
argList += tmpTable[args[i]] + " noundef " + args[i];
|
||||
}
|
||||
|
||||
// 文本 IR
|
||||
irStream << " " << temp << " = call " << currentReturnType << " @" << funcName << "(" << argList << ")\n";
|
||||
tmpTable[temp] = currentReturnType;
|
||||
|
||||
// SysY IR
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
sysy::Function* callee = module->getFunction(funcName);
|
||||
if (!callee) {
|
||||
throw std::runtime_error("Undefined function: " + funcName);
|
||||
}
|
||||
auto callInst = builder.createCallInst(callee, irArgs, temp);
|
||||
irTmpTable[temp] = callInst;
|
||||
return temp;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitMulExp(SysYParser::MulExpContext* ctx) {
|
||||
auto unaryExps = ctx->unaryExp();
|
||||
std::string left = std::any_cast<std::string>(unaryExps[0]->accept(this));
|
||||
sysy::Value* irLeft = irTmpTable[left];
|
||||
sysy::Type* irType = irLeft->getType();
|
||||
|
||||
for (size_t i = 1; i < unaryExps.size(); ++i) {
|
||||
std::string right = std::any_cast<std::string>(unaryExps[i]->accept(this));
|
||||
sysy::Value* irRight = irTmpTable[right];
|
||||
std::string op = ctx->children[2 * i - 1]->getText();
|
||||
std::string temp = getNextTemp();
|
||||
std::string type = tmpTable[left];
|
||||
tmpTable[temp] = type;
|
||||
|
||||
// 文本 IR
|
||||
if (op == "*") {
|
||||
irStream << " " << temp << " = mul nsw " << type << " " << left << ", " << right << "\n";
|
||||
} else if (op == "/") {
|
||||
irStream << " " << temp << " = sdiv " << type << " " << left << ", " << right << "\n";
|
||||
} else if (op == "%") {
|
||||
irStream << " " << temp << " = srem " << type << " " << left << ", " << right << "\n";
|
||||
}
|
||||
|
||||
// SysY IR
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
sysy::Instruction::Kind kind;
|
||||
if (type == "i32") {
|
||||
if (op == "*") kind = sysy::Instruction::kMul;
|
||||
else if (op == "/") kind = sysy::Instruction::kDiv;
|
||||
else kind = sysy::Instruction::kRem;
|
||||
} else {
|
||||
if (op == "*") kind = sysy::Instruction::kFMul;
|
||||
else if (op == "/") kind = sysy::Instruction::kFDiv;
|
||||
else kind = sysy::Instruction::kFRem;
|
||||
}
|
||||
auto binaryInst = builder.createBinaryInst(kind, irType, irLeft, irRight, temp);
|
||||
irTmpTable[temp] = binaryInst;
|
||||
left = temp;
|
||||
irLeft = binaryInst;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitAddExp(SysYParser::AddExpContext* ctx) {
|
||||
auto mulExps = ctx->mulExp();
|
||||
std::string left = std::any_cast<std::string>(mulExps[0]->accept(this));
|
||||
sysy::Value* irLeft = irTmpTable[left];
|
||||
sysy::Type* irType = irLeft->getType();
|
||||
|
||||
for (size_t i = 1; i < mulExps.size(); ++i) {
|
||||
std::string right = std::any_cast<std::string>(mulExps[i]->accept(this));
|
||||
sysy::Value* irRight = irTmpTable[right];
|
||||
std::string op = ctx->children[2 * i - 1]->getText();
|
||||
std::string temp = getNextTemp();
|
||||
std::string type = tmpTable[left];
|
||||
tmpTable[temp] = type;
|
||||
|
||||
// 文本 IR
|
||||
if (op == "+") {
|
||||
irStream << " " << temp << " = add nsw " << type << " " << left << ", " << right << "\n";
|
||||
} else if (op == "-") {
|
||||
irStream << " " << temp << " = sub nsw " << type << " " << left << ", " << right << "\n";
|
||||
}
|
||||
|
||||
// SysY IR
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
sysy::Instruction::Kind kind = (type == "i32") ? (op == "+" ? sysy::Instruction::kAdd : sysy::Instruction::kSub)
|
||||
: (op == "+" ? sysy::Instruction::kFAdd : sysy::Instruction::kFSub);
|
||||
auto binaryInst = builder.createBinaryInst(kind, irType, irLeft, irRight, temp);
|
||||
irTmpTable[temp] = binaryInst;
|
||||
left = temp;
|
||||
irLeft = binaryInst;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitRelExp(SysYParser::RelExpContext* ctx) {
|
||||
auto addExps = ctx->addExp();
|
||||
std::string left = std::any_cast<std::string>(addExps[0]->accept(this));
|
||||
sysy::Value* irLeft = irTmpTable[left];
|
||||
sysy::Type* irType = sysy::Type::getIntType(); // 比较结果为 i1
|
||||
|
||||
for (size_t i = 1; i < addExps.size(); ++i) {
|
||||
std::string right = std::any_cast<std::string>(addExps[i]->accept(this));
|
||||
sysy::Value* irRight = irTmpTable[right];
|
||||
std::string op = ctx->children[2 * i - 1]->getText();
|
||||
std::string temp = getNextTemp();
|
||||
std::string type = tmpTable[left];
|
||||
tmpTable[temp] = "i1";
|
||||
|
||||
// 文本 IR
|
||||
if (op == "<") {
|
||||
irStream << " " << temp << " = icmp slt " << type << " " << left << ", " << right << "\n";
|
||||
} else if (op == ">") {
|
||||
irStream << " " << temp << " = icmp sgt " << type << " " << left << ", " << right << "\n";
|
||||
} else if (op == "<=") {
|
||||
irStream << " " << temp << " = icmp sle " << type << " " << left << ", " << right << "\n";
|
||||
} else if (op == ">=") {
|
||||
irStream << " " << temp << " = icmp sge " << type << " " << left << ", " << right << "\n";
|
||||
}
|
||||
|
||||
// SysY IR
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
sysy::Instruction::Kind kind;
|
||||
if (type == "i32") {
|
||||
if (op == "<") kind = sysy::Instruction::kICmpLT;
|
||||
else if (op == ">") kind = sysy::Instruction::kICmpGT;
|
||||
else if (op == "<=") kind = sysy::Instruction::kICmpLE;
|
||||
else kind = sysy::Instruction::kICmpGE;
|
||||
} else {
|
||||
if (op == "<") kind = sysy::Instruction::kFCmpLT;
|
||||
else if (op == ">") kind = sysy::Instruction::kFCmpGT;
|
||||
else if (op == "<=") kind = sysy::Instruction::kFCmpLE;
|
||||
else kind = sysy::Instruction::kFCmpGE;
|
||||
}
|
||||
auto cmpInst = builder.createBinaryInst(kind, irType, irLeft, irRight, temp);
|
||||
irTmpTable[temp] = cmpInst;
|
||||
left = temp;
|
||||
irLeft = cmpInst;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitEqExp(SysYParser::EqExpContext* ctx) {
|
||||
auto relExps = ctx->relExp();
|
||||
std::string left = std::any_cast<std::string>(relExps[0]->accept(this));
|
||||
sysy::Value* irLeft = irTmpTable[left];
|
||||
sysy::Type* irType = sysy::Type::getIntType(); // 比较结果为 i1
|
||||
|
||||
for (size_t i = 1; i < relExps.size(); ++i) {
|
||||
std::string right = std::any_cast<std::string>(relExps[i]->accept(this));
|
||||
sysy::Value* irRight = irTmpTable[right];
|
||||
std::string op = ctx->children[2 * i - 1]->getText();
|
||||
std::string temp = getNextTemp();
|
||||
std::string type = tmpTable[left];
|
||||
tmpTable[temp] = "i1";
|
||||
|
||||
// 文本 IR
|
||||
if (op == "==") {
|
||||
irStream << " " << temp << " = icmp eq " << type << " " << left << ", " << right << "\n";
|
||||
} else if (op == "!=") {
|
||||
irStream << " " << temp << " = icmp ne " << type << " " << left << ", " << right << "\n";
|
||||
}
|
||||
|
||||
// SysY IR
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
sysy::Instruction::Kind kind = (type == "i32") ? (op == "==" ? sysy::Instruction::kICmpEQ : sysy::Instruction::kICmpNE)
|
||||
: (op == "==" ? sysy::Instruction::kFCmpEQ : sysy::Instruction::kFCmpNE);
|
||||
auto cmpInst = builder.createBinaryInst(kind, irType, irLeft, irRight, temp);
|
||||
irTmpTable[temp] = cmpInst;
|
||||
left = temp;
|
||||
irLeft = cmpInst;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitLAndExp(SysYParser::LAndExpContext* ctx) {
|
||||
auto eqExps = ctx->eqExp();
|
||||
std::string left = std::any_cast<std::string>(eqExps[0]->accept(this));
|
||||
sysy::Value* irLeft = irTmpTable[left];
|
||||
|
||||
for (size_t i = 1; i < eqExps.size(); ++i) {
|
||||
std::string falseLabel = "land.false." + std::to_string(tempCounter);
|
||||
std::string endLabel = "land.end." + std::to_string(tempCounter++);
|
||||
sysy::BasicBlock* falseBlock = currentIRFunction->addBasicBlock(falseLabel);
|
||||
sysy::BasicBlock* endBlock = currentIRFunction->addBasicBlock(endLabel);
|
||||
std::string temp = getNextTemp();
|
||||
tmpTable[temp] = "i1";
|
||||
|
||||
// 文本 IR
|
||||
irStream << " br i1 " << left << ", label %" << falseLabel << ", label %" << endLabel << "\n";
|
||||
irStream << falseLabel << ":\n";
|
||||
|
||||
// SysY IR
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
builder.createCondBrInst(irLeft, falseBlock, endBlock, {}, {});
|
||||
setIRPosition(falseBlock);
|
||||
|
||||
std::string right = std::any_cast<std::string>(eqExps[i]->accept(this));
|
||||
sysy::Value* irRight = irTmpTable[right];
|
||||
irStream << " " << temp << " = and i1 " << left << ", " << right << "\n";
|
||||
irStream << " br label %" << endLabel << "\n";
|
||||
irStream << endLabel << ":\n";
|
||||
|
||||
// SysY IR 逻辑与(通过基本块实现短路求值)
|
||||
builder.setPosition(falseBlock, falseBlock->end());
|
||||
auto andInst = builder.createBinaryInst(sysy::Instruction::kICmpEQ, sysy::Type::getIntType(), irLeft, irRight, temp);
|
||||
builder.createUncondBrInst(endBlock, {});
|
||||
irTmpTable[temp] = andInst;
|
||||
left = temp;
|
||||
irLeft = andInst;
|
||||
setIRPosition(endBlock);
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
std::any LLVMIRGenerator::visitLOrExp(SysYParser::LOrExpContext* ctx) {
|
||||
auto lAndExps = ctx->lAndExp();
|
||||
std::string left = std::any_cast<std::string>(lAndExps[0]->accept(this));
|
||||
sysy::Value* irLeft = irTmpTable[left];
|
||||
|
||||
for (size_t i = 1; i < lAndExps.size(); ++i) {
|
||||
std::string trueLabel = "lor.true." + std::to_string(tempCounter);
|
||||
std::string endLabel = "lor.end." + std::to_string(tempCounter++);
|
||||
sysy::BasicBlock* trueBlock = currentIRFunction->addBasicBlock(trueLabel);
|
||||
sysy::BasicBlock* endBlock = currentIRFunction->addBasicBlock(endLabel);
|
||||
std::string temp = getNextTemp();
|
||||
tmpTable[temp] = "i1";
|
||||
|
||||
// 文本 IR
|
||||
irStream << " br i1 " << left << ", label %" << trueLabel << ", label %" << endLabel << "\n";
|
||||
irStream << trueLabel << ":\n";
|
||||
|
||||
// SysY IR
|
||||
sysy::IRBuilder builder(currentIRBlock);
|
||||
builder.createCondBrInst(irLeft, trueBlock, endBlock, {}, {});
|
||||
setIRPosition(trueBlock);
|
||||
|
||||
std::string right = std::any_cast<std::string>(lAndExps[i]->accept(this));
|
||||
sysy::Value* irRight = irTmpTable[right];
|
||||
irStream << " " << temp << " = or i1 " << left << ", " << right << "\n";
|
||||
irStream << " br label %" << endLabel << "\n";
|
||||
irStream << endLabel << ":\n";
|
||||
|
||||
// SysY IR 逻辑或(通过基本块实现短路求值)
|
||||
builder.setPosition(trueBlock, trueBlock->end());
|
||||
auto orInst = builder.createBinaryInst(sysy::Instruction::kICmpEQ, sysy::Type::getIntType(), irLeft, irRight, temp);
|
||||
builder.createUncondBrInst(endBlock, {});
|
||||
irTmpTable[temp] = orInst;
|
||||
left = temp;
|
||||
irLeft = orInst;
|
||||
setIRPosition(endBlock);
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
// } // namespace sysy
|
||||
@@ -1,99 +0,0 @@
|
||||
#pragma once
|
||||
#include "SysYBaseVisitor.h"
|
||||
#include "SysYParser.h"
|
||||
#include "IR.h" // 引入 SysY IR 头文件
|
||||
#include "IRBuilder.h"
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <memory>
|
||||
|
||||
class LLVMIRGenerator : public SysYBaseVisitor {
|
||||
public:
|
||||
// 生成 IR(文本和数据结构)
|
||||
std::string generateIR(SysYParser::CompUnitContext* unit);
|
||||
|
||||
// 获取文本格式的 LLVM IR
|
||||
std::string getIR() const { return irStream.str(); }
|
||||
|
||||
// 获取 SysY IR 数据结构
|
||||
sysy::Module* getModule() const { return module.get(); }
|
||||
|
||||
private:
|
||||
// 文本输出相关
|
||||
std::stringstream irStream;
|
||||
int tempCounter = 0; // 临时变量计数器
|
||||
std::string currentVarType; // 当前变量类型(文本 IR 用)
|
||||
|
||||
// 符号表:映射变量名到 {分配地址/寄存器, 类型}(文本 IR)
|
||||
std::map<std::string, std::pair<std::string, std::string>> symbolTable;
|
||||
// 临时变量表:映射临时变量名到类型(文本 IR)
|
||||
std::map<std::string, std::string> tmpTable;
|
||||
std::vector<std::string> globalVars; // 全局变量列表(文本 IR)
|
||||
|
||||
// SysY IR 数据结构
|
||||
std::unique_ptr<sysy::Module> module; // SysY IR 模块
|
||||
// 符号表:映射变量名到 SysY IR 的 Value 指针
|
||||
std::map<std::string, sysy::Value*> irSymbolTable;
|
||||
// 临时变量表:映射临时变量名到 SysY IR 的 Value 指针
|
||||
std::map<std::string, sysy::Value*> irTmpTable;
|
||||
|
||||
// 当前上下文
|
||||
std::string currentFunction; // 当前函数名(文本 IR)
|
||||
std::string currentReturnType; // 当前函数返回类型(文本 IR)
|
||||
sysy::Function* currentIRFunction = nullptr; // 当前 SysY IR 函数
|
||||
sysy::BasicBlock* currentIRBlock = nullptr; // 当前 SysY IR 基本块
|
||||
|
||||
// 循环控制
|
||||
std::vector<std::string> breakStack; // break 标签栈(文本 IR)
|
||||
std::vector<std::string> continueStack; // continue 标签栈(文本 IR)
|
||||
bool hasReturn = false; // 是否有返回语句(文本 IR)
|
||||
|
||||
struct LoopLabels {
|
||||
std::string breakLabel; // break 跳转目标标签(文本 IR)
|
||||
std::string continueLabel; // continue 跳转目标标签(文本 IR)
|
||||
sysy::BasicBlock* irBreakBlock = nullptr; // break 跳转目标块(SysY IR)
|
||||
sysy::BasicBlock* irContinueBlock = nullptr; // continue 跳转目标块(SysY IR)
|
||||
};
|
||||
std::stack<LoopLabels> loopStack; // 管理循环的 break 和 continue 标签
|
||||
|
||||
bool inFunction = false; // 标记是否在函数内部
|
||||
|
||||
// 辅助函数(文本 IR)
|
||||
std::string getNextTemp(); // 获取下一个临时变量名
|
||||
std::string getLLVMType(const std::string& type); // 转换 SysY 类型到 LLVM 类型
|
||||
|
||||
// 辅助函数(SysY IR)
|
||||
sysy::Type* getIRType(const std::string& type); // 转换 SysY 类型到 SysY IR 类型
|
||||
std::string getIRTempName(); // 获取 SysY IR 临时变量名
|
||||
void setIRPosition(sysy::BasicBlock* block); // 设置当前 IR 插入点
|
||||
|
||||
// 访问方法
|
||||
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 visitLValue(SysYParser::LValueContext* ctx) override;
|
||||
// std::any visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) override;
|
||||
std::any visitPrimExp(SysYParser::PrimExpContext* ctx) override;
|
||||
std::any visitParenExp(SysYParser::ParenExpContext* ctx) override;
|
||||
std::any visitNumber(SysYParser::NumberContext* ctx) override;
|
||||
std::any visitString(SysYParser::StringContext* ctx) override;
|
||||
std::any visitCall(SysYParser::CallContext* ctx) override;
|
||||
std::any visitUnExp(SysYParser::UnExpContext* 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;
|
||||
std::any visitAssignStmt(SysYParser::AssignStmtContext* ctx) override;
|
||||
std::any visitIfStmt(SysYParser::IfStmtContext* ctx) override;
|
||||
std::any visitWhileStmt(SysYParser::WhileStmtContext* ctx) override;
|
||||
std::any visitBreakStmt(SysYParser::BreakStmtContext* ctx) override;
|
||||
std::any visitContinueStmt(SysYParser::ContinueStmtContext* ctx) override;
|
||||
std::any visitReturnStmt(SysYParser::ReturnStmtContext* ctx) override;
|
||||
};
|
||||
169
src/RISCv32Backend.cpp
Normal file
169
src/RISCv32Backend.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
#include "RISCv32Backend.h"
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
namespace sysy {
|
||||
const std::vector<RISCv32CodeGen::PhysicalReg> RISCv32CodeGen::allocable_regs = {
|
||||
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3,
|
||||
PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6,
|
||||
PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3,
|
||||
PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7
|
||||
};
|
||||
|
||||
std::string RISCv32CodeGen::reg_to_string(PhysicalReg reg) {
|
||||
switch (reg) {
|
||||
case PhysicalReg::T0: return "t0"; case PhysicalReg::T1: return "t1";
|
||||
case PhysicalReg::T2: return "t2"; case PhysicalReg::T3: return "t3";
|
||||
case PhysicalReg::T4: return "t4"; case PhysicalReg::T5: return "t5";
|
||||
case PhysicalReg::T6: return "t6"; case PhysicalReg::A0: return "a0";
|
||||
case PhysicalReg::A1: return "a1"; case PhysicalReg::A2: return "a2";
|
||||
case PhysicalReg::A3: return "a3"; case PhysicalReg::A4: return "a4";
|
||||
case PhysicalReg::A5: return "a5"; case PhysicalReg::A6: return "a6";
|
||||
case PhysicalReg::A7: return "a7";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string RISCv32CodeGen::code_gen() {
|
||||
std::stringstream ss;
|
||||
ss << ".text\n";
|
||||
ss << module_gen();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string RISCv32CodeGen::module_gen() {
|
||||
std::stringstream ss;
|
||||
// 生成全局变量(数据段)
|
||||
for (auto global : *module->getGlobalValues()) {
|
||||
ss << ".data\n";
|
||||
ss << ".globl " << global->getName() << "\n";
|
||||
ss << global->getName() << ":\n";
|
||||
ss << " .word 0\n"; // 假设初始化为0
|
||||
}
|
||||
// 生成函数
|
||||
ss << ".text\n";
|
||||
for (auto func : *module->getFunctions()) {
|
||||
ss << function_gen(func);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string RISCv32CodeGen::function_gen(Function* func) {
|
||||
std::stringstream ss;
|
||||
// 函数标签
|
||||
ss << ".globl " << func->getName() << "\n";
|
||||
ss << func->getName() << ":\n";
|
||||
// 序言:保存ra,分配堆栈
|
||||
bool is_leaf = true; // 简单假设,实际需检查是否调用其他函数
|
||||
ss << " addi sp, sp, -16\n"; // 分配堆栈空间
|
||||
ss << " sw ra, 12(sp)\n"; // 保存返回地址
|
||||
// 寄存器分配
|
||||
auto alloc = register_allocation(func);
|
||||
// 生成基本块代码
|
||||
for (auto bb : func->getBasicBlocks()) {
|
||||
ss << basicBlock_gen(bb, alloc);
|
||||
}
|
||||
// 结尾:恢复ra,释放堆栈
|
||||
ss << " lw ra, 12(sp)\n";
|
||||
ss << " addi sp, sp, 16\n";
|
||||
ss << " ret\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string RISCv32CodeGen::basicBlock_gen(BasicBlock* bb, const RegAllocResult& alloc) {
|
||||
std::stringstream ss;
|
||||
ss << bb->getName() << ":\n";
|
||||
for (auto inst : bb->getInstructions()) {
|
||||
auto riscv_insts = instruction_gen(inst);
|
||||
for (const auto& riscv_inst : riscv_insts) {
|
||||
ss << " " << riscv_inst.opcode;
|
||||
for (size_t i = 0; i < riscv_inst.operands.size(); ++i) {
|
||||
if (i > 0) ss << ", ";
|
||||
if (riscv_inst.operands[i].kind == Operand::Reg) {
|
||||
auto it = alloc.reg_map.find((Value*)riscv_inst.operands[i].value.c_str());
|
||||
if (it != alloc.reg_map.end()) {
|
||||
ss << reg_to_string(it->second);
|
||||
} else {
|
||||
// 溢出到堆栈
|
||||
auto stack_it = alloc.stack_map.find((Value*)riscv_inst.operands[i].value.c_str());
|
||||
ss << "[sp+" << stack_it->second << "]";
|
||||
}
|
||||
} else {
|
||||
ss << riscv_inst.operands[i].value;
|
||||
}
|
||||
}
|
||||
ss << "\n";
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::vector<RISCv32CodeGen::RISCv32Inst> RISCv32CodeGen::instruction_gen(Instruction* inst) {
|
||||
std::vector<RISCv32Inst> insts;
|
||||
if (auto bin = dynamic_cast<BinaryInst*>(inst)) {
|
||||
std::string opcode;
|
||||
if (bin->getOpcode() == BinaryInst::Add) opcode = "add";
|
||||
else if (bin->getOpcode() == BinaryInst::Sub) opcode = "sub";
|
||||
else if (bin->getOpcode() == BinaryInst::Mul) opcode = "mul";
|
||||
else return insts; // 未实现其他操作
|
||||
insts.emplace_back(opcode, std::vector<Operand>{
|
||||
{Operand::Reg, std::string((const char*)bin->getResult())},
|
||||
{Operand::Reg, std::string((const char*)bin->getLHS())},
|
||||
{Operand::Reg, std::string((const char*)bin->getRHS())}
|
||||
});
|
||||
} else if (auto load = dynamic_cast<LoadInst*>(inst)) {
|
||||
insts.emplace_back("lw", std::vector<Operand>{
|
||||
{Operand::Reg, std::string((const char*)load->getResult())},
|
||||
{Operand::Label, load->getPointer()->getName()}
|
||||
});
|
||||
} else if (auto store = dynamic_cast<StoreInst*>(inst)) {
|
||||
insts.emplace_back("sw", std::vector<Operand>{
|
||||
{Operand::Reg, std::string((const char*)store->getValue())},
|
||||
{Operand::Label, store->getPointer()->getName()}
|
||||
});
|
||||
} // 其他指令类型待实现
|
||||
return insts;
|
||||
}
|
||||
|
||||
void RISCv32CodeGen::eliminate_phi(Function* func) {
|
||||
// 简单实现:假设CopyInst存在
|
||||
for (auto bb : func->getBasicBlocks()) {
|
||||
for (auto inst : bb->getInstructions()) {
|
||||
if (/* inst is PhiInst */) {
|
||||
// 插入CopyInst到前驱块
|
||||
// 移除phi指令
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::map<Instruction*, std::set<Value*>> RISCv32CodeGen::liveness_analysis(Function* func) {
|
||||
std::map<Instruction*, std::set<Value*>> live_sets;
|
||||
// 简单实现:需实际计算活跃性
|
||||
return live_sets;
|
||||
}
|
||||
|
||||
std::map<Value*, std::set<Value*>> RISCv32CodeGen::build_interference_graph(
|
||||
const std::map<Instruction*, std::set<Value*>>& live_sets) {
|
||||
std::map<Value*, std::set<Value*>> graph;
|
||||
// 简单实现:需实际构建干扰图
|
||||
return graph;
|
||||
}
|
||||
|
||||
RISCv32CodeGen::RegAllocResult RISCv32CodeGen::register_allocation(Function* func) {
|
||||
RegAllocResult result;
|
||||
eliminate_phi(func);
|
||||
auto live_sets = liveness_analysis(func);
|
||||
auto graph = build_interference_graph(live_sets);
|
||||
// 图着色算法
|
||||
std::vector<Value*> stack;
|
||||
std::map<Value*, int> degrees;
|
||||
for (const auto& pair : graph) {
|
||||
degrees[pair.first] = pair.second.size();
|
||||
if (degrees[pair.first] < allocable_regs.size()) {
|
||||
stack.push_back(pair.first);
|
||||
}
|
||||
}
|
||||
// 简单实现:需完成图着色和溢出处理
|
||||
return result;
|
||||
}
|
||||
}
|
||||
63
src/RISCv32Backend.h
Normal file
63
src/RISCv32Backend.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef RISCV32_BACKEND_H
|
||||
#define RISCV32_BACKEND_H
|
||||
|
||||
#include "IR.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace sysy {
|
||||
class RISCv32CodeGen {
|
||||
public:
|
||||
explicit RISCv32CodeGen(Module* mod) : module(mod) {}
|
||||
std::string code_gen(); // 生成整个模块的汇编代码
|
||||
|
||||
private:
|
||||
Module* module;
|
||||
|
||||
// 物理寄存器
|
||||
enum class PhysicalReg {
|
||||
T0, T1, T2, T3, T4, T5, T6, // x5-x7, x28-x31
|
||||
A0, A1, A2, A3, A4, A5, A6, A7 // x10-x17
|
||||
};
|
||||
static const std::vector<PhysicalReg> allocable_regs;
|
||||
|
||||
// 操作数
|
||||
struct Operand {
|
||||
enum class Kind { Reg, Imm, Label };
|
||||
Kind kind;
|
||||
std::string value; // 寄存器名、立即数或标签
|
||||
Operand(Kind k, const std::string& v) : kind(k), value(v) {}
|
||||
};
|
||||
|
||||
// RISC-V指令
|
||||
struct RISCv32Inst {
|
||||
std::string opcode;
|
||||
std::vector<Operand> operands;
|
||||
RISCv32Inst(const std::string& op, const std::vector<Operand>& ops)
|
||||
: opcode(op), operands(ops) {}
|
||||
};
|
||||
|
||||
// 寄存器分配结果
|
||||
struct RegAllocResult {
|
||||
std::map<Value*, PhysicalReg> reg_map; // 虚拟寄存器到物理寄存器的映射
|
||||
std::map<Value*, int> stack_map; // 虚拟寄存器到堆栈槽的映射
|
||||
int stack_size; // 堆栈帧大小
|
||||
};
|
||||
|
||||
// 后端方法
|
||||
std::string module_gen();
|
||||
std::string function_gen(Function* func);
|
||||
std::string basicBlock_gen(BasicBlock* bb, const RegAllocResult& alloc);
|
||||
std::vector<RISCv32Inst> instruction_gen(Instruction* inst);
|
||||
RegAllocResult register_allocation(Function* func);
|
||||
void eliminate_phi(Function* func);
|
||||
std::map<Instruction*, std::set<Value*>> liveness_analysis(Function* func);
|
||||
std::map<Value*, std::set<Value*>> build_interference_graph(
|
||||
const std::map<Instruction*, std::set<Value*>>& live_sets);
|
||||
std::string reg_to_string(PhysicalReg reg);
|
||||
};
|
||||
|
||||
#endif // RISCV32_BACKEND_H
|
||||
}
|
||||
@@ -9,7 +9,6 @@ using namespace antlr4;
|
||||
#include "ASTPrinter.h"
|
||||
#include "Backend.h"
|
||||
#include "SysYIRGenerator.h"
|
||||
#include "LLVMIRGenerator.h"
|
||||
using namespace sysy;
|
||||
|
||||
static string argStopAfter;
|
||||
@@ -78,26 +77,22 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
// visit AST to generate IR
|
||||
|
||||
SysYIRGenerator generator;
|
||||
generator.visitCompUnit(moduleAST);
|
||||
if (argStopAfter == "ir") {
|
||||
SysYIRGenerator generator;
|
||||
generator.visitCompUnit(moduleAST);
|
||||
auto moduleIR = generator.get();
|
||||
moduleIR->print(cout);
|
||||
return EXIT_SUCCESS;
|
||||
} else if (argStopAfter == "llvmir") {
|
||||
LLVMIRGenerator llvmirGenerator;
|
||||
llvmirGenerator.generateIR(moduleAST); // 使用公共接口生成 IR
|
||||
cout << llvmirGenerator.getIR();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// // generate assembly
|
||||
// CodeGen codegen(moduleIR);
|
||||
// string asmCode = codegen.code_gen();
|
||||
// cout << asmCode << endl;
|
||||
// if (argStopAfter == "asm")
|
||||
// return EXIT_SUCCESS;
|
||||
// generate assembly
|
||||
RISCv32CodeGen codegen(moduleIR);
|
||||
string asmCode = codegen.code_gen();
|
||||
cout << asmCode << endl;
|
||||
if (argStopAfter == "asm")
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user