674 lines
26 KiB
C++
674 lines
26 KiB
C++
// 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;
|
||
}
|
||
} |