注册遍模板函数重构(针对遍的不同构造方法), 修复phi指令更新引起的旧代码错误, 将CFG优化适配到现有终端框架中, 独立CFG优化方法使得其他优化遍能独立调用, usedelete方法回调取消删除功能。 IRGenerator代码风格修改。
1412 lines
52 KiB
C++
1412 lines
52 KiB
C++
// SysYIRGenerator.cpp
|
||
// TODO:类型转换及其检查
|
||
// TODO:sysy库函数处理
|
||
// TODO:数组处理
|
||
// TODO:对while、continue、break的测试
|
||
#include "IR.h"
|
||
#include <any>
|
||
#include <memory>
|
||
#include <iterator>
|
||
#include <sstream>
|
||
#include <string>
|
||
#include <vector>
|
||
#include "SysYIRGenerator.h"
|
||
|
||
using namespace std;
|
||
namespace sysy {
|
||
|
||
|
||
Type* SysYIRGenerator::buildArrayType(Type* baseType, const std::vector<Value*>& dims){
|
||
Type* currentType = baseType;
|
||
// 从最内层维度开始构建 ArrayType
|
||
// 例如对于 int arr[2][3],先处理 [3],再处理 [2]
|
||
// 注意:SysY 的 dims 是从最外层到最内层,所以我们需要反向迭代
|
||
// 或者调整逻辑,使得从内到外构建 ArrayType
|
||
// 假设 dims 列表是 [dim1, dim2, dim3...] (例如 [2, 3] for int[2][3])
|
||
// 我们需要从最内层维度开始向外构建 ArrayType
|
||
for (int i = dims.size() - 1; i >= 0; --i) {
|
||
// 维度大小必须是常量,否则无法构建 ArrayType
|
||
ConstantInteger* constDim = dynamic_cast<ConstantInteger*>(dims[i]);
|
||
if (constDim == nullptr) {
|
||
// 如果维度不是常量,可能需要特殊处理,例如将其视为指针
|
||
// 对于函数参数 int arr[] 这种,第一个维度可以为未知
|
||
// 在这里,我们假设所有声明的数组维度都是常量
|
||
assert(false && "Array dimension must be a constant integer!");
|
||
return nullptr;
|
||
}
|
||
unsigned dimSize = constDim->getInt();
|
||
currentType = Type::getArrayType(currentType, dimSize);
|
||
}
|
||
return currentType;
|
||
}
|
||
|
||
Value* SysYIRGenerator::getGEPAddressInst(Value* basePointer, const std::vector<Value*>& indices) {
|
||
// 检查 basePointer 是否为指针类型
|
||
if (!basePointer->getType()->isPointer()) {
|
||
assert(false && "GEP base pointer must be a pointer type!");
|
||
}
|
||
|
||
// 获取基指针所指向的实际类型 (例如 int* 指向 int, int[2][3]* 指向 int[2][3])
|
||
Type* currentElementType = basePointer->getType()->as<PointerType>()->getBaseType();
|
||
|
||
std::vector<Value*> actualGEPIndices;
|
||
// GEP 指令的第一个索引通常是0,用于“跳过”基指针指向的聚合类型本身,直接指向其第一个元素。
|
||
// 例如,对于 AllocaInst 返回的 `int[2][3]*`,第一个 `0` 索引表示从数组的开始而不是指针本身开始索引。
|
||
actualGEPIndices.push_back(ConstantInteger::get(0));
|
||
|
||
// 将用户提供的索引添加到 GEP 操作数中
|
||
for (Value* index : indices) {
|
||
actualGEPIndices.push_back(index);
|
||
}
|
||
|
||
// 根据索引链计算最终的元素类型
|
||
Type* finalTargetType = currentElementType;
|
||
|
||
// 遍历用户提供的索引(不包括我们添加的第一个0),逐步确定 GEP 的最终结果类型
|
||
// 每个索引都“深入”一个维度
|
||
for (int i = 0; i < indices.size(); ++i) { // 这里遍历的是用户提供的索引
|
||
if (finalTargetType && finalTargetType->isArray()) {
|
||
finalTargetType = finalTargetType->as<ArrayType>()->getElementType();
|
||
} else {
|
||
// 如果索引链还在继续,但当前类型已经不是数组或聚合类型,这通常是一个错误
|
||
// 或者表示访问的是标量,后续索引无效。此时,finalTargetType 已经是最终的标量类型,不能再深入。
|
||
// 例如,对 int arr[5]; 访问 arr[i][j] (j 是多余的),这里会停止类型推断。
|
||
break;
|
||
}
|
||
}
|
||
|
||
// GEP 的结果总是指针类型,指向最终计算出的元素
|
||
Type* gepResultType = Type::getPointerType(finalTargetType);
|
||
|
||
// 创建 GEP 指令。假设 builder.createGetElementPtrInst 的签名为
|
||
// (Type* resultType, Value* basePointer, const std::vector<Value*>& indices)
|
||
return builder.createGetElementPtrInst(basePointer, actualGEPIndices);
|
||
}
|
||
/*
|
||
* @brief: visit compUnit
|
||
* @details:
|
||
* compUnit: (globalDecl | funcDef)+;
|
||
*/
|
||
std::any SysYIRGenerator::visitCompUnit(SysYParser::CompUnitContext *ctx) {
|
||
// create the IR module
|
||
auto pModule = new Module();
|
||
assert(pModule);
|
||
module.reset(pModule);
|
||
|
||
// SymbolTable::ModuleScope scope(symbols_table);
|
||
|
||
Utils::initExternalFunction(pModule, &builder);
|
||
|
||
pModule->enterNewScope();
|
||
visitChildren(ctx);
|
||
pModule->leaveScope();
|
||
return pModule;
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitGlobalConstDecl(SysYParser::GlobalConstDeclContext *ctx){
|
||
auto constDecl = ctx->constDecl();
|
||
Type* type = std::any_cast<Type *>(visitBType(constDecl->bType()));
|
||
for (const auto &constDef : constDecl->constDef()) {
|
||
std::vector<Value *> dims = {};
|
||
std::string name = constDef->Ident()->getText();
|
||
auto constExps = constDef->constExp();
|
||
if (!constExps.empty()) {
|
||
for (const auto &constExp : constExps) {
|
||
dims.push_back(std::any_cast<Value *>(visitConstExp(constExp)));
|
||
}
|
||
}
|
||
|
||
ArrayValueTree* root = std::any_cast<ArrayValueTree *>(constDef->constInitVal()->accept(this));
|
||
ValueCounter values;
|
||
Utils::tree2Array(type, root, dims, dims.size(), values, &builder);
|
||
delete root;
|
||
// 创建全局常量变量,并更新符号表
|
||
module->createConstVar(name, Type::getPointerType(type), values, dims);
|
||
}
|
||
return std::any();
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitGlobalVarDecl(SysYParser::GlobalVarDeclContext *ctx) {
|
||
auto varDecl = ctx->varDecl();
|
||
Type* type = std::any_cast<Type *>(visitBType(varDecl->bType()));
|
||
for (const auto &varDef : varDecl->varDef()) {
|
||
std::vector<Value *> dims = {};
|
||
std::string name = varDef->Ident()->getText();
|
||
auto constExps = varDef->constExp();
|
||
if (!constExps.empty()) {
|
||
for (const auto &constExp : constExps) {
|
||
dims.push_back(std::any_cast<Value *>(visitConstExp(constExp)));
|
||
}
|
||
}
|
||
|
||
ValueCounter values = {};
|
||
if (varDef->initVal() != nullptr) {
|
||
ArrayValueTree* root = std::any_cast<ArrayValueTree *>(varDef->initVal()->accept(this));
|
||
Utils::tree2Array(type, root, dims, dims.size(), values, &builder);
|
||
delete root;
|
||
}
|
||
// 创建全局变量,并更新符号表
|
||
module->createGlobalValue(name, Type::getPointerType(type), dims, values);
|
||
}
|
||
return std::any();
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext *ctx){
|
||
Type* type = std::any_cast<Type *>(visitBType(ctx->bType()));
|
||
for (const auto constDef : ctx->constDef()) {
|
||
std::vector<Value *> dims = {};
|
||
std::string name = constDef->Ident()->getText();
|
||
auto constExps = constDef->constExp();
|
||
if (!constExps.empty()) {
|
||
for (const auto constExp : constExps) {
|
||
dims.push_back(std::any_cast<Value *>(visitConstExp(constExp)));
|
||
}
|
||
}
|
||
|
||
ArrayValueTree* root = std::any_cast<ArrayValueTree *>(constDef->constInitVal()->accept(this));
|
||
ValueCounter values;
|
||
Utils::tree2Array(type, root, dims, dims.size(), values, &builder);
|
||
delete root;
|
||
|
||
module->createConstVar(name, Type::getPointerType(type), values, dims);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext *ctx) {
|
||
Type* type = std::any_cast<Type *>(visitBType(ctx->bType()));
|
||
for (const auto varDef : ctx->varDef()) {
|
||
std::vector<Value *> dims = {};
|
||
std::string name = varDef->Ident()->getText();
|
||
auto constExps = varDef->constExp();
|
||
if (!constExps.empty()) {
|
||
for (const auto &constExp : constExps) {
|
||
dims.push_back(std::any_cast<Value *>(visitConstExp(constExp)));
|
||
}
|
||
}
|
||
|
||
Type* variableType = type;
|
||
if (!dims.empty()) { // 如果有维度,说明是数组
|
||
variableType = buildArrayType(type, dims); // 构建完整的 ArrayType
|
||
}
|
||
|
||
// 对于数组,alloca 的类型将是指针指向数组类型,例如 `int[2][3]*`
|
||
// 对于标量,alloca 的类型将是指针指向标量类型,例如 `int*`
|
||
AllocaInst* alloca =
|
||
builder.createAllocaInst(Type::getPointerType(type), dims, name);
|
||
|
||
if (varDef->initVal() != nullptr) {
|
||
ValueCounter values;
|
||
ArrayValueTree* root = std::any_cast<ArrayValueTree *>(varDef->initVal()->accept(this));
|
||
Utils::tree2Array(type, root, dims, dims.size(), values, &builder);
|
||
delete root;
|
||
|
||
if (dims.empty()) { // 标量变量初始化
|
||
builder.createStoreInst(values.getValue(0), alloca);
|
||
} else { // 数组变量初始化
|
||
const std::vector<sysy::Value *> &counterValues = values.getValues();
|
||
|
||
int numElements = 1;
|
||
std::vector<int> dimSizes;
|
||
for (Value *dimVal : dims) {
|
||
if (ConstantInteger *constInt = dynamic_cast<ConstantInteger *>(dimVal)) {
|
||
int dimSize = constInt->getInt();
|
||
numElements *= dimSize;
|
||
dimSizes.push_back(dimSize);
|
||
}
|
||
// TODO else 错误处理:数组维度必须是常量(对于静态分配)
|
||
}
|
||
unsigned int elementSizeInBytes = type->getSize();
|
||
unsigned int totalSizeInBytes = numElements * elementSizeInBytes;
|
||
|
||
bool allValuesAreZero = false;
|
||
if (counterValues.empty()) {
|
||
allValuesAreZero = true;
|
||
}
|
||
else {
|
||
allValuesAreZero = true;
|
||
for (Value *val : counterValues){
|
||
if (ConstantInteger *constInt = dynamic_cast<ConstantInteger *>(val)){
|
||
if (constInt->getInt() != 0){
|
||
allValuesAreZero = false;
|
||
break;
|
||
}
|
||
}
|
||
else{
|
||
allValuesAreZero = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (allValuesAreZero) {
|
||
builder.createMemsetInst(
|
||
alloca,
|
||
ConstantInteger::get(0),
|
||
ConstantInteger::get(totalSizeInBytes),
|
||
ConstantInteger::get(0));
|
||
}
|
||
else {
|
||
for (int k = 0; k < counterValues.size(); ++k) {
|
||
std::vector<Value *> currentIndices;
|
||
int tempLinearIndex = k;
|
||
|
||
// 将线性索引转换为多维索引
|
||
for (int dimIdx = dimSizes.size() - 1; dimIdx >= 0; --dimIdx)
|
||
{
|
||
currentIndices.insert(currentIndices.begin(),
|
||
ConstantInteger::get(static_cast<int>(tempLinearIndex % dimSizes[dimIdx])));
|
||
tempLinearIndex /= dimSizes[dimIdx];
|
||
}
|
||
|
||
// 计算元素的地址
|
||
Value* elementAddress = getGEPAddressInst(alloca, currentIndices);
|
||
// 生成 store 指令 (假设 createStoreInst 接受 Value* value, Value* pointer)
|
||
builder.createStoreInst(counterValues[k], elementAddress);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else { // 如果没有显式初始化值,默认对数组进行零初始化
|
||
if (!dims.empty()) { // 只有数组才需要默认的零初始化
|
||
int numElements = 1;
|
||
for (Value *dimVal : dims) {
|
||
if (ConstantInteger *constInt = dynamic_cast<ConstantInteger *>(dimVal)) {
|
||
numElements *= constInt->getInt();
|
||
}
|
||
}
|
||
unsigned int elementSizeInBytes = type->getSize();
|
||
unsigned int totalSizeInBytes = numElements * elementSizeInBytes;
|
||
|
||
builder.createMemsetInst(
|
||
alloca,
|
||
ConstantInteger::get(0),
|
||
ConstantInteger::get(totalSizeInBytes),
|
||
ConstantInteger::get(0)
|
||
);
|
||
}
|
||
}
|
||
|
||
module->addVariable(name, alloca);
|
||
}
|
||
|
||
return std::any();
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitBType(SysYParser::BTypeContext *ctx) {
|
||
return ctx->INT() != nullptr ? Type::getIntType() : Type::getFloatType();
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitScalarInitValue(SysYParser::ScalarInitValueContext *ctx) {
|
||
Value* value = std::any_cast<Value *>(visitExp(ctx->exp()));
|
||
ArrayValueTree* result = new ArrayValueTree();
|
||
result->setValue(value);
|
||
return result;
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitArrayInitValue(SysYParser::ArrayInitValueContext *ctx) {
|
||
std::vector<ArrayValueTree *> children;
|
||
for (const auto &initVal : ctx->initVal())
|
||
children.push_back(std::any_cast<ArrayValueTree *>(initVal->accept(this)));
|
||
ArrayValueTree* result = new ArrayValueTree();
|
||
result->addChildren(children);
|
||
return result;
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitConstScalarInitValue(SysYParser::ConstScalarInitValueContext *ctx) {
|
||
Value* value = std::any_cast<Value *>(visitConstExp(ctx->constExp()));
|
||
ArrayValueTree* result = new ArrayValueTree();
|
||
result->setValue(value);
|
||
return result;
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitConstArrayInitValue(SysYParser::ConstArrayInitValueContext *ctx) {
|
||
std::vector<ArrayValueTree *> children;
|
||
for (const auto &constInitVal : ctx->constInitVal())
|
||
children.push_back(std::any_cast<ArrayValueTree *>(constInitVal->accept(this)));
|
||
ArrayValueTree* result = new ArrayValueTree();
|
||
result->addChildren(children);
|
||
return result;
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitFuncType(SysYParser::FuncTypeContext *ctx) {
|
||
if (ctx->INT() != nullptr)
|
||
return Type::getIntType();
|
||
if (ctx->FLOAT() != nullptr)
|
||
return Type::getFloatType();
|
||
return Type::getVoidType();
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){
|
||
// 更新作用域
|
||
module->enterNewScope();
|
||
|
||
auto name = ctx->Ident()->getText();
|
||
std::vector<Type *> paramTypes;
|
||
std::vector<std::string> paramNames;
|
||
std::vector<std::vector<Value *>> paramDims;
|
||
|
||
if (ctx->funcFParams() != nullptr) {
|
||
auto params = ctx->funcFParams()->funcFParam();
|
||
for (const auto ¶m : params) {
|
||
paramTypes.push_back(std::any_cast<Type *>(visitBType(param->bType())));
|
||
paramNames.push_back(param->Ident()->getText());
|
||
std::vector<Value *> dims = {};
|
||
if (!param->LBRACK().empty()) {
|
||
dims.push_back(ConstantInteger::get(-1)); // 第一个维度不确定
|
||
for (const auto &exp : param->exp()) {
|
||
dims.push_back(std::any_cast<Value *>(visitExp(exp)));
|
||
}
|
||
}
|
||
paramDims.emplace_back(dims);
|
||
}
|
||
}
|
||
|
||
Type* returnType = std::any_cast<Type *>(visitFuncType(ctx->funcType()));
|
||
Type* funcType = Type::getFunctionType(returnType, paramTypes);
|
||
Function* function = module->createFunction(name, funcType);
|
||
BasicBlock* entry = function->getEntryBlock();
|
||
builder.setPosition(entry, entry->end());
|
||
|
||
for (int i = 0; i < paramTypes.size(); ++i) {
|
||
AllocaInst* alloca = builder.createAllocaInst(Type::getPointerType(paramTypes[i]),
|
||
paramDims[i], paramNames[i]);
|
||
entry->insertArgument(alloca);
|
||
module->addVariable(paramNames[i], alloca);
|
||
}
|
||
|
||
// 在处理函数体之前,创建一个新的基本块作为函数体的实际入口
|
||
// 这样 entryBB 就可以在完成初始化后跳转到这里
|
||
BasicBlock* funcBodyEntry = function->addBasicBlock("funcBodyEntry");
|
||
|
||
// 从 entryBB 无条件跳转到 funcBodyEntry
|
||
builder.createUncondBrInst(funcBodyEntry, {});
|
||
builder.setPosition(funcBodyEntry,funcBodyEntry->end()); // 将插入点设置到 funcBodyEntry
|
||
|
||
for (auto item : ctx->blockStmt()->blockItem()) {
|
||
visitBlockItem(item);
|
||
}
|
||
|
||
// 如果函数没有显式的返回语句,且返回类型不是 void,则需要添加一个默认的返回值
|
||
ReturnInst* retinst = nullptr;
|
||
retinst = dynamic_cast<ReturnInst*>(builder.getBasicBlock()->terminator()->get());
|
||
|
||
if (!retinst) {
|
||
if (returnType->isVoid()) {
|
||
builder.createReturnInst();
|
||
} else if (returnType->isInt()) {
|
||
builder.createReturnInst(ConstantInteger::get(0)); // 默认返回 0
|
||
} else if (returnType->isFloat()) {
|
||
builder.createReturnInst(ConstantFloating::get(0.0f)); // 默认返回 0.0f
|
||
} else {
|
||
assert(false && "Function with no explicit return and non-void type should return a value.");
|
||
}
|
||
}
|
||
|
||
module->leaveScope();
|
||
|
||
return std::any();
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitBlockStmt(SysYParser::BlockStmtContext *ctx) {
|
||
module->enterNewScope();
|
||
for (auto item : ctx->blockItem())
|
||
visitBlockItem(item);
|
||
module->leaveScope();
|
||
return 0;
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx) {
|
||
auto lVal = ctx->lValue();
|
||
std::string name = lVal->Ident()->getText();
|
||
std::vector<Value *> dims;
|
||
for (const auto &exp : lVal->exp()) {
|
||
dims.push_back(std::any_cast<Value *>(visitExp(exp)));
|
||
}
|
||
|
||
auto variable = module->getVariable(name); // 获取 AllocaInst 或 GlobalValue
|
||
Value* value = std::any_cast<Value *>(visitExp(ctx->exp())); // 右值
|
||
|
||
if (variable == nullptr) {
|
||
throw std::runtime_error("Variable " + name + " not found in assignment.");
|
||
}
|
||
|
||
// 计算最终赋值目标元素的类型
|
||
// variable 本身应该是一个指针类型 (例如 int* 或 int[2][3]*)
|
||
if (!variable->getType()->isPointer()) {
|
||
assert(false && "Variable to be assigned must be a pointer type!");
|
||
return std::any();
|
||
}
|
||
Type* targetElementType = variable->getType()->as<PointerType>()->getBaseType(); // 从基指针指向的类型开始
|
||
|
||
// 模拟 GEP 路径,根据 dims 确定最终元素的类型
|
||
for (int i = 0; i < dims.size(); ++i) {
|
||
if (targetElementType && targetElementType->isArray()) {
|
||
targetElementType = targetElementType->as<ArrayType>()->getElementType();
|
||
} else {
|
||
break; // 如果不是数组类型但还有索引,或者索引超出维度,则停止推断
|
||
}
|
||
}
|
||
|
||
// 左值右值类型不同处理:根据最终元素类型进行转换
|
||
if (targetElementType != value->getType()) {
|
||
ConstantValue * constValue = dynamic_cast<ConstantValue *>(value);
|
||
if (constValue != nullptr) {
|
||
if (targetElementType == Type::getFloatType()) {
|
||
value = ConstantFloating::get(static_cast<float>(constValue->getInt()));
|
||
} else { // 假设如果不是浮点型,就是整型
|
||
value = ConstantInteger::get(static_cast<int>(constValue->getFloat()));
|
||
}
|
||
} else {
|
||
if (targetElementType == Type::getFloatType()) {
|
||
value = builder.createIToFInst(value);
|
||
} else { // 假设如果不是浮点型,就是整型
|
||
value = builder.createFtoIInst(value);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 计算目标地址:如果 dims 为空,就是变量本身地址;否则通过 GEP 计算
|
||
Value* targetAddress = variable;
|
||
if (!dims.empty()) {
|
||
targetAddress = getGEPAddressInst(variable, dims);
|
||
}
|
||
|
||
builder.createStoreInst(value, targetAddress);
|
||
|
||
return std::any();
|
||
}
|
||
|
||
|
||
std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
|
||
// labels string stream
|
||
|
||
std::stringstream labelstring;
|
||
Function * function = builder.getBasicBlock()->getParent();
|
||
|
||
BasicBlock* thenBlock = new BasicBlock(function);
|
||
BasicBlock* exitBlock = new BasicBlock(function);
|
||
|
||
if (ctx->stmt().size() > 1) {
|
||
BasicBlock* elseBlock = new BasicBlock(function);
|
||
|
||
builder.pushTrueBlock(thenBlock);
|
||
builder.pushFalseBlock(elseBlock);
|
||
// 访问条件表达式
|
||
visitCond(ctx->cond());
|
||
builder.popTrueBlock();
|
||
builder.popFalseBlock();
|
||
|
||
labelstring << "if_then.L" << builder.getLabelIndex();
|
||
thenBlock->setName(labelstring.str());
|
||
labelstring.str("");
|
||
function->addBasicBlock(thenBlock);
|
||
builder.setPosition(thenBlock, thenBlock->end());
|
||
|
||
auto block = dynamic_cast<SysYParser::BlockStmtContext *>(ctx->stmt(0));
|
||
// 如果是块语句,直接访问
|
||
// 否则访问语句
|
||
if (block != nullptr) {
|
||
visitBlockStmt(block);
|
||
} else {
|
||
module->enterNewScope();
|
||
ctx->stmt(0)->accept(this);
|
||
module->leaveScope();
|
||
}
|
||
builder.createUncondBrInst(exitBlock, {});
|
||
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
|
||
|
||
labelstring << "if_else.L" << builder.getLabelIndex();
|
||
elseBlock->setName(labelstring.str());
|
||
labelstring.str("");
|
||
function->addBasicBlock(elseBlock);
|
||
builder.setPosition(elseBlock, elseBlock->end());
|
||
|
||
block = dynamic_cast<SysYParser::BlockStmtContext *>(ctx->stmt(1));
|
||
if (block != nullptr) {
|
||
visitBlockStmt(block);
|
||
} else {
|
||
module->enterNewScope();
|
||
ctx->stmt(1)->accept(this);
|
||
module->leaveScope();
|
||
}
|
||
builder.createUncondBrInst(exitBlock, {});
|
||
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
|
||
|
||
labelstring << "if_exit.L" << builder.getLabelIndex();
|
||
exitBlock->setName(labelstring.str());
|
||
labelstring.str("");
|
||
function->addBasicBlock(exitBlock);
|
||
builder.setPosition(exitBlock, exitBlock->end());
|
||
|
||
} else {
|
||
builder.pushTrueBlock(thenBlock);
|
||
builder.pushFalseBlock(exitBlock);
|
||
visitCond(ctx->cond());
|
||
builder.popTrueBlock();
|
||
builder.popFalseBlock();
|
||
|
||
labelstring << "if_then.L" << builder.getLabelIndex();
|
||
thenBlock->setName(labelstring.str());
|
||
labelstring.str("");
|
||
function->addBasicBlock(thenBlock);
|
||
builder.setPosition(thenBlock, thenBlock->end());
|
||
|
||
auto block = dynamic_cast<SysYParser::BlockStmtContext *>(ctx->stmt(0));
|
||
if (block != nullptr) {
|
||
visitBlockStmt(block);
|
||
} else {
|
||
module->enterNewScope();
|
||
ctx->stmt(0)->accept(this);
|
||
module->leaveScope();
|
||
}
|
||
builder.createUncondBrInst(exitBlock, {});
|
||
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
|
||
|
||
labelstring << "if_exit.L" << builder.getLabelIndex();
|
||
exitBlock->setName(labelstring.str());
|
||
labelstring.str("");
|
||
function->addBasicBlock(exitBlock);
|
||
builder.setPosition(exitBlock, exitBlock->end());
|
||
}
|
||
return std::any();
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) {
|
||
// while structure:
|
||
// curblock -> headBlock -> bodyBlock -> exitBlock
|
||
BasicBlock* curBlock = builder.getBasicBlock();
|
||
Function* function = builder.getBasicBlock()->getParent();
|
||
|
||
std::stringstream labelstring;
|
||
labelstring << "while_head.L" << builder.getLabelIndex();
|
||
BasicBlock *headBlock = function->addBasicBlock(labelstring.str());
|
||
labelstring.str("");
|
||
builder.createUncondBrInst(headBlock, {});
|
||
BasicBlock::conectBlocks(curBlock, headBlock);
|
||
builder.setPosition(headBlock, headBlock->end());
|
||
|
||
BasicBlock* bodyBlock = new BasicBlock(function);
|
||
BasicBlock* exitBlock = new BasicBlock(function);
|
||
|
||
builder.pushTrueBlock(bodyBlock);
|
||
builder.pushFalseBlock(exitBlock);
|
||
// 访问条件表达式
|
||
visitCond(ctx->cond());
|
||
builder.popTrueBlock();
|
||
builder.popFalseBlock();
|
||
|
||
labelstring << "while_body.L" << builder.getLabelIndex();
|
||
bodyBlock->setName(labelstring.str());
|
||
labelstring.str("");
|
||
function->addBasicBlock(bodyBlock);
|
||
builder.setPosition(bodyBlock, bodyBlock->end());
|
||
|
||
builder.pushBreakBlock(exitBlock);
|
||
builder.pushContinueBlock(headBlock);
|
||
|
||
auto block = dynamic_cast<SysYParser::BlockStmtContext *>(ctx->stmt());
|
||
|
||
if( block != nullptr) {
|
||
visitBlockStmt(block);
|
||
} else {
|
||
module->enterNewScope();
|
||
ctx->stmt()->accept(this);
|
||
module->leaveScope();
|
||
}
|
||
|
||
builder.createUncondBrInst(headBlock, {});
|
||
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
|
||
builder.popBreakBlock();
|
||
builder.popContinueBlock();
|
||
|
||
labelstring << "while_exit.L" << builder.getLabelIndex();
|
||
exitBlock->setName(labelstring.str());
|
||
labelstring.str("");
|
||
function->addBasicBlock(exitBlock);
|
||
builder.setPosition(exitBlock, exitBlock->end());
|
||
|
||
return std::any();
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitBreakStmt(SysYParser::BreakStmtContext *ctx) {
|
||
BasicBlock* breakBlock = builder.getBreakBlock();
|
||
builder.createUncondBrInst(breakBlock, {});
|
||
BasicBlock::conectBlocks(builder.getBasicBlock(), breakBlock);
|
||
return std::any();
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitContinueStmt(SysYParser::ContinueStmtContext *ctx) {
|
||
BasicBlock* continueBlock = builder.getContinueBlock();
|
||
builder.createUncondBrInst(continueBlock, {});
|
||
BasicBlock::conectBlocks(builder.getBasicBlock(), continueBlock);
|
||
return std::any();
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitReturnStmt(SysYParser::ReturnStmtContext *ctx) {
|
||
Value* returnValue = nullptr;
|
||
if (ctx->exp() != nullptr) {
|
||
returnValue = std::any_cast<Value *>(visitExp(ctx->exp()));
|
||
}
|
||
|
||
Type* funcType = builder.getBasicBlock()->getParent()->getReturnType();
|
||
if (funcType!= returnValue->getType() && returnValue != nullptr) {
|
||
ConstantValue * constValue = dynamic_cast<ConstantValue *>(returnValue);
|
||
if (constValue != nullptr) {
|
||
if (funcType == Type::getFloatType()) {
|
||
returnValue = ConstantInteger::get(static_cast<float>(constValue->getInt()));
|
||
} else {
|
||
returnValue = ConstantFloating::get(static_cast<int>(constValue->getFloat()));
|
||
}
|
||
} else {
|
||
if (funcType == Type::getFloatType()) {
|
||
returnValue = builder.createIToFInst(returnValue);
|
||
} else {
|
||
returnValue = builder.createFtoIInst(returnValue);
|
||
}
|
||
}
|
||
}
|
||
builder.createReturnInst(returnValue);
|
||
|
||
return std::any();
|
||
}
|
||
|
||
|
||
// SysYIRGenerator.cpp (修改部分)
|
||
|
||
std::any SysYIRGenerator::visitLValue(SysYParser::LValueContext *ctx) {
|
||
std::string name = ctx->Ident()->getText();
|
||
User* variable = module->getVariable(name);
|
||
|
||
Value* value = nullptr;
|
||
if (variable == nullptr) {
|
||
throw std::runtime_error("Variable " + name + " not found.");
|
||
}
|
||
std::vector<Value *> dims;
|
||
for (const auto &exp : ctx->exp()) {
|
||
dims.push_back(std::any_cast<Value *>(visitExp(exp)));
|
||
}
|
||
|
||
// 1. 获取变量的声明维度数量
|
||
unsigned declaredNumDims = 0;
|
||
if (AllocaInst* alloc = dynamic_cast<AllocaInst*>(variable)) {
|
||
declaredNumDims = alloc->getNumDims();
|
||
} else if (GlobalValue* glob = dynamic_cast<GlobalValue*>(variable)) {
|
||
declaredNumDims = glob->getNumDims();
|
||
} else if (ConstantVariable* constV = dynamic_cast<ConstantVariable*>(variable)) {
|
||
declaredNumDims = constV->getNumDims();
|
||
}
|
||
|
||
// 2. 处理常量变量 (ConstantVariable) 且所有索引都是常量的情况
|
||
ConstantVariable* constVar = dynamic_cast<ConstantVariable *>(variable);
|
||
if (constVar != nullptr) {
|
||
bool allIndicesConstant = true;
|
||
for (const auto &dim : dims) {
|
||
if (dynamic_cast<ConstantValue *>(dim) == nullptr) {
|
||
allIndicesConstant = false;
|
||
break;
|
||
}
|
||
}
|
||
if (allIndicesConstant) {
|
||
// 如果是常量变量且所有索引都是常量,直接通过 getByIndices 获取编译时值
|
||
// 这个方法会根据索引深度返回最终的标量值或指向子数组的指针 (作为 ConstantValue/Variable)
|
||
return constVar->getByIndices(dims);
|
||
}
|
||
}
|
||
|
||
// 3. 处理可变变量 (AllocaInst/GlobalValue) 或带非常量索引的常量变量
|
||
// 这里区分标量访问和数组元素/子数组访问
|
||
|
||
// 检查是否是访问标量变量本身(没有索引,且声明维度为0)
|
||
if (dims.empty() && declaredNumDims == 0) {
|
||
// 对于标量变量,直接加载其值。
|
||
// variable 本身就是指向标量的指针 (e.g., int* %a)
|
||
if (dynamic_cast<AllocaInst*>(variable) || dynamic_cast<GlobalValue*>(variable)) {
|
||
value = builder.createLoadInst(variable);
|
||
} else {
|
||
// 如果走到这里且不是AllocaInst/GlobalValue,但dims为空且declaredNumDims为0,
|
||
// 且又不是ConstantVariable (前面已处理),则可能是错误情况。
|
||
assert(false && "Unhandled scalar variable type in LValue access.");
|
||
return static_cast<Value*>(nullptr);
|
||
}
|
||
} else {
|
||
// 访问数组元素或子数组(有索引,或变量本身是数组/多维指针)
|
||
Value* targetAddress = nullptr;
|
||
|
||
// GEP 的基指针就是变量本身(它是一个指向内存的指针)
|
||
if (dynamic_cast<AllocaInst*>(variable) || dynamic_cast<GlobalValue*>(variable) || (constVar != nullptr)) {
|
||
// 允许对 ConstantVariable (如果它代表全局数组常量) 进行 GEP
|
||
targetAddress = getGEPAddressInst(variable, dims);
|
||
} else {
|
||
// 其他情况(例如尝试对非指针类型或不支持的 LValue 进行 GEP)应报错
|
||
assert(false && "LValue variable type not supported for GEP or dynamic load.");
|
||
return static_cast<Value*>(nullptr);
|
||
}
|
||
|
||
// 现在 targetAddress 持有元素或子数组的地址。
|
||
// 需要判断是加载值,还是返回子数组的地址。
|
||
|
||
// 如果提供的索引数量少于声明的维度数量,则表示访问的是子数组,返回其地址
|
||
if (dims.size() < declaredNumDims) {
|
||
value = targetAddress;
|
||
} else {
|
||
// 否则,表示访问的是最终的标量元素,加载其值
|
||
// 假设 createLoadInst 接受 Value* pointer
|
||
value = builder.createLoadInst(targetAddress);
|
||
}
|
||
}
|
||
return value;
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitPrimaryExp(SysYParser::PrimaryExpContext *ctx) {
|
||
if (ctx->exp() != nullptr)
|
||
return visitExp(ctx->exp());
|
||
if (ctx->lValue() != nullptr)
|
||
return visitLValue(ctx->lValue());
|
||
if (ctx->number() != nullptr)
|
||
return visitNumber(ctx->number());
|
||
if (ctx->string() != nullptr) {
|
||
cout << "String literal not supported in SysYIRGenerator." << endl;
|
||
}
|
||
return visitNumber(ctx->number());
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitNumber(SysYParser::NumberContext *ctx) {
|
||
if (ctx->ILITERAL() != nullptr) {
|
||
int value = std::stol(ctx->ILITERAL()->getText(), nullptr, 0);
|
||
return static_cast<Value *>(ConstantInteger::get(value));
|
||
} else if (ctx->FLITERAL() != nullptr) {
|
||
float value = std::stof(ctx->FLITERAL()->getText());
|
||
return static_cast<Value *>(ConstantFloating::get(value));
|
||
}
|
||
throw std::runtime_error("Unknown number type.");
|
||
return std::any(); // 不会到达这里
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitCall(SysYParser::CallContext *ctx) {
|
||
std::string funcName = ctx->Ident()->getText();
|
||
Function *function = module->getFunction(funcName);
|
||
if (function == nullptr) {
|
||
function = module->getExternalFunction(funcName);
|
||
if (function == nullptr) {
|
||
std::cout << "The function " << funcName << " no defined." << std::endl;
|
||
assert(function);
|
||
}
|
||
}
|
||
|
||
std::vector<Value *> args = {};
|
||
if (funcName == "starttime" || funcName == "stoptime") {
|
||
// 如果是starttime或stoptime函数
|
||
// TODO: 这里需要处理starttime和stoptime函数的参数
|
||
// args.emplace_back()
|
||
} else {
|
||
if (ctx->funcRParams() != nullptr) {
|
||
args = std::any_cast<std::vector<Value *>>(visitFuncRParams(ctx->funcRParams()));
|
||
}
|
||
|
||
auto params = function->getEntryBlock()->getArguments();
|
||
for (int i = 0; i < args.size(); i++) {
|
||
// 参数类型转换
|
||
if (params[i]->getType() != args[i]->getType() &&
|
||
(params[i]->getNumDims() != 0 ||
|
||
params[i]->getType()->as<PointerType>()->getBaseType() != args[i]->getType())) {
|
||
ConstantValue * constValue = dynamic_cast<ConstantValue *>(args[i]);
|
||
if (constValue != nullptr) {
|
||
if (params[i]->getType() == Type::getPointerType(Type::getFloatType())) {
|
||
args[i] = ConstantInteger::get(static_cast<float>(constValue->getInt()));
|
||
} else {
|
||
args[i] = ConstantFloating::get(static_cast<int>(constValue->getFloat()));
|
||
}
|
||
} else {
|
||
if (params[i]->getType() == Type::getPointerType(Type::getFloatType())) {
|
||
args[i] = builder.createIToFInst(args[i]);
|
||
} else {
|
||
args[i] = builder.createFtoIInst(args[i]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return static_cast<Value *>(builder.createCallInst(function, args));
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitUnaryExp(SysYParser::UnaryExpContext *ctx) {
|
||
if (ctx->primaryExp() != nullptr)
|
||
return visitPrimaryExp(ctx->primaryExp());
|
||
if (ctx->call() != nullptr)
|
||
return visitCall(ctx->call());
|
||
|
||
Value* value = std::any_cast<Value *>(visitUnaryExp(ctx->unaryExp()));
|
||
Value* result = value;
|
||
if (ctx->unaryOp()->SUB() != nullptr) {
|
||
ConstantValue * constValue = dynamic_cast<ConstantValue *>(value);
|
||
if (constValue != nullptr) {
|
||
if (constValue->isFloat()) {
|
||
result = ConstantFloating::get(-constValue->getFloat());
|
||
} else {
|
||
result = ConstantInteger::get(-constValue->getInt());
|
||
}
|
||
} else if (value != nullptr) {
|
||
if (value->getType() == Type::getIntType()) {
|
||
result = builder.createNegInst(value);
|
||
} else {
|
||
result = builder.createFNegInst(value);
|
||
}
|
||
} else {
|
||
std::cout << "UnExp: value is nullptr." << std::endl;
|
||
assert(false);
|
||
}
|
||
} else if (ctx->unaryOp()->NOT() != nullptr) {
|
||
auto constValue = dynamic_cast<ConstantValue *>(value);
|
||
if (constValue != nullptr) {
|
||
if (constValue->isFloat()) {
|
||
result =
|
||
ConstantFloating::get(1 - (constValue->getFloat() != 0.0F ? 1 : 0));
|
||
} else {
|
||
result = ConstantInteger::get(1 - (constValue->getInt() != 0 ? 1 : 0));
|
||
}
|
||
} else if (value != nullptr) {
|
||
if (value->getType() == Type::getIntType()) {
|
||
result = builder.createNotInst(value);
|
||
} else {
|
||
result = builder.createFNotInst(value);
|
||
}
|
||
} else {
|
||
std::cout << "UnExp: value is nullptr." << std::endl;
|
||
assert(false);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitFuncRParams(SysYParser::FuncRParamsContext *ctx) {
|
||
std::vector<Value *> params;
|
||
for (const auto &exp : ctx->exp())
|
||
params.push_back(std::any_cast<Value *>(visitExp(exp)));
|
||
return params;
|
||
}
|
||
|
||
|
||
std::any SysYIRGenerator::visitMulExp(SysYParser::MulExpContext *ctx) {
|
||
Value * result = std::any_cast<Value *>(visitUnaryExp(ctx->unaryExp(0)));
|
||
|
||
for (int i = 1; i < ctx->unaryExp().size(); i++) {
|
||
auto opNode = dynamic_cast<antlr4::tree::TerminalNode*>(ctx->children[2*i-1]);
|
||
int opType = opNode->getSymbol()->getType();
|
||
|
||
Value* operand = std::any_cast<Value *>(visitUnaryExp(ctx->unaryExp(i)));
|
||
|
||
Type* resultType = result->getType();
|
||
Type* operandType = operand->getType();
|
||
Type* floatType = Type::getFloatType();
|
||
|
||
if (resultType == floatType || operandType == floatType) {
|
||
// 如果有一个操作数是浮点数,则将两个操作数都转换为浮点数
|
||
if (operandType != floatType) {
|
||
ConstantValue * constValue = dynamic_cast<ConstantValue *>(operand);
|
||
if (constValue != nullptr)
|
||
operand = ConstantFloating::get(static_cast<float>(constValue->getInt()));
|
||
else
|
||
operand = builder.createIToFInst(operand);
|
||
} else if (resultType != floatType) {
|
||
ConstantValue* constResult = dynamic_cast<ConstantValue *>(result);
|
||
if (constResult != nullptr)
|
||
result = ConstantFloating::get(static_cast<float>(constResult->getInt()));
|
||
else
|
||
result = builder.createIToFInst(result);
|
||
}
|
||
|
||
ConstantValue* constResult = dynamic_cast<ConstantValue *>(result);
|
||
ConstantValue* constOperand = dynamic_cast<ConstantValue *>(operand);
|
||
if (opType == SysYParser::MUL) {
|
||
if ((constOperand != nullptr) && (constResult != nullptr)) {
|
||
result = ConstantFloating::get(constResult->getFloat() *
|
||
constOperand->getFloat());
|
||
} else {
|
||
result = builder.createFMulInst(result, operand);
|
||
}
|
||
} else if (opType == SysYParser::DIV) {
|
||
if ((constOperand != nullptr) && (constResult != nullptr)) {
|
||
result = ConstantFloating::get(constResult->getFloat() /
|
||
constOperand->getFloat());
|
||
} else {
|
||
result = builder.createFDivInst(result, operand);
|
||
}
|
||
} else {
|
||
// float类型的取模操作不允许
|
||
std::cout << "MulExp: float type mod operation is not allowed." << std::endl;
|
||
assert(false);
|
||
}
|
||
} else {
|
||
ConstantValue * constResult = dynamic_cast<ConstantValue *>(result);
|
||
ConstantValue * constOperand = dynamic_cast<ConstantValue *>(operand);
|
||
if (opType == SysYParser::MUL) {
|
||
if ((constOperand != nullptr) && (constResult != nullptr))
|
||
result = ConstantInteger::get(constResult->getInt() * constOperand->getInt());
|
||
else
|
||
result = builder.createMulInst(result, operand);
|
||
} else if (opType == SysYParser::DIV) {
|
||
if ((constOperand != nullptr) && (constResult != nullptr))
|
||
result = ConstantInteger::get(constResult->getInt() / constOperand->getInt());
|
||
else
|
||
result = builder.createDivInst(result, operand);
|
||
} else {
|
||
if ((constOperand != nullptr) && (constResult != nullptr))
|
||
result = ConstantInteger::get(constResult->getInt() % constOperand->getInt());
|
||
else
|
||
result = builder.createRemInst(result, operand);
|
||
}
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
std::any SysYIRGenerator::visitAddExp(SysYParser::AddExpContext *ctx) {
|
||
Value* result = std::any_cast<Value *>(visitMulExp(ctx->mulExp(0)));
|
||
|
||
for (int i = 1; i < ctx->mulExp().size(); i++) {
|
||
auto opNode = dynamic_cast<antlr4::tree::TerminalNode*>(ctx->children[2*i-1]);
|
||
int opType = opNode->getSymbol()->getType();
|
||
|
||
Value* operand = std::any_cast<Value *>(visitMulExp(ctx->mulExp(i)));
|
||
Type* resultType = result->getType();
|
||
Type* operandType = operand->getType();
|
||
Type* floatType = Type::getFloatType();
|
||
|
||
if (resultType == floatType || operandType == floatType) {
|
||
// 类型转换
|
||
if (operandType != floatType) {
|
||
ConstantValue * constOperand = dynamic_cast<ConstantValue *>(operand);
|
||
if (constOperand != nullptr)
|
||
operand = ConstantFloating::get(static_cast<float>(constOperand->getInt()));
|
||
else
|
||
operand = builder.createIToFInst(operand);
|
||
} else if (resultType != floatType) {
|
||
ConstantValue * constResult = dynamic_cast<ConstantValue *>(result);
|
||
if (constResult != nullptr)
|
||
result = ConstantFloating::get(static_cast<float>(constResult->getInt()));
|
||
else
|
||
result = builder.createIToFInst(result);
|
||
}
|
||
|
||
ConstantValue * constResult = dynamic_cast<ConstantValue *>(result);
|
||
ConstantValue * constOperand = dynamic_cast<ConstantValue *>(operand);
|
||
if (opType == SysYParser::ADD) {
|
||
if ((constResult != nullptr) && (constOperand != nullptr))
|
||
result = ConstantFloating::get(constResult->getFloat() + constOperand->getFloat());
|
||
else
|
||
result = builder.createFAddInst(result, operand);
|
||
} else {
|
||
if ((constResult != nullptr) && (constOperand != nullptr))
|
||
result = ConstantFloating::get(constResult->getFloat() - constOperand->getFloat());
|
||
else
|
||
result = builder.createFSubInst(result, operand);
|
||
}
|
||
} else {
|
||
ConstantValue * constResult = dynamic_cast<ConstantValue *>(result);
|
||
ConstantValue * constOperand = dynamic_cast<ConstantValue *>(operand);
|
||
if (opType == SysYParser::ADD) {
|
||
if ((constResult != nullptr) && (constOperand != nullptr))
|
||
result = ConstantInteger::get(constResult->getInt() + constOperand->getInt());
|
||
else
|
||
result = builder.createAddInst(result, operand);
|
||
} else {
|
||
if ((constResult != nullptr) && (constOperand != nullptr))
|
||
result = ConstantInteger::get(constResult->getInt() - constOperand->getInt());
|
||
else
|
||
result = builder.createSubInst(result, operand);
|
||
}
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitRelExp(SysYParser::RelExpContext *ctx) {
|
||
Value* result = std::any_cast<Value *>(visitAddExp(ctx->addExp(0)));
|
||
|
||
for (int i = 1; i < ctx->addExp().size(); i++) {
|
||
auto opNode = dynamic_cast<antlr4::tree::TerminalNode*>(ctx->children[2*i-1]);
|
||
int opType = opNode->getSymbol()->getType();
|
||
|
||
Value* operand = std::any_cast<Value *>(visitAddExp(ctx->addExp(i)));
|
||
|
||
Type* resultType = result->getType();
|
||
Type* operandType = operand->getType();
|
||
|
||
ConstantValue* constResult = dynamic_cast<ConstantValue *>(result);
|
||
ConstantValue* constOperand = dynamic_cast<ConstantValue *>(operand);
|
||
|
||
// 常量比较
|
||
if ((constResult != nullptr) && (constOperand != nullptr)) {
|
||
auto operand1 = constResult->isFloat() ? constResult->getFloat()
|
||
: constResult->getInt();
|
||
auto operand2 = constOperand->isFloat() ? constOperand->getFloat()
|
||
: constOperand->getInt();
|
||
|
||
if (opType == SysYParser::LT) result = ConstantInteger::get(operand1 < operand2 ? 1 : 0);
|
||
else if (opType == SysYParser::GT) result = ConstantInteger::get(operand1 > operand2 ? 1 : 0);
|
||
else if (opType == SysYParser::LE) result = ConstantInteger::get(operand1 <= operand2 ? 1 : 0);
|
||
else if (opType == SysYParser::GE) result = ConstantInteger::get(operand1 >= operand2 ? 1 : 0);
|
||
else assert(false);
|
||
|
||
} else {
|
||
Type* resultType = result->getType();
|
||
Type* operandType = operand->getType();
|
||
Type* floatType = Type::getFloatType();
|
||
|
||
// 浮点数处理
|
||
if (resultType == floatType || operandType == floatType) {
|
||
if (resultType != floatType) {
|
||
if (constResult != nullptr)
|
||
result = ConstantFloating::get(static_cast<float>(constResult->getInt()));
|
||
else
|
||
result = builder.createIToFInst(result);
|
||
|
||
}
|
||
if (operandType != floatType) {
|
||
if (constOperand != nullptr)
|
||
operand = ConstantFloating::get(static_cast<float>(constOperand->getInt()));
|
||
else
|
||
operand = builder.createIToFInst(operand);
|
||
|
||
}
|
||
|
||
if (opType == SysYParser::LT) result = builder.createFCmpLTInst(result, operand);
|
||
else if (opType == SysYParser::GT) result = builder.createFCmpGTInst(result, operand);
|
||
else if (opType == SysYParser::LE) result = builder.createFCmpLEInst(result, operand);
|
||
else if (opType == SysYParser::GE) result = builder.createFCmpGEInst(result, operand);
|
||
else assert(false);
|
||
|
||
} else {
|
||
// 整数处理
|
||
if (opType == SysYParser::LT) result = builder.createICmpLTInst(result, operand);
|
||
else if (opType == SysYParser::GT) result = builder.createICmpGTInst(result, operand);
|
||
else if (opType == SysYParser::LE) result = builder.createICmpLEInst(result, operand);
|
||
else if (opType == SysYParser::GE) result = builder.createICmpGEInst(result, operand);
|
||
else assert(false);
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
std::any SysYIRGenerator::visitEqExp(SysYParser::EqExpContext *ctx) {
|
||
Value * result = std::any_cast<Value *>(visitRelExp(ctx->relExp(0)));
|
||
|
||
for (int i = 1; i < ctx->relExp().size(); i++) {
|
||
auto opNode = dynamic_cast<antlr4::tree::TerminalNode*>(ctx->children[2*i-1]);
|
||
int opType = opNode->getSymbol()->getType();
|
||
|
||
Value * operand = std::any_cast<Value *>(visitRelExp(ctx->relExp(i)));
|
||
|
||
ConstantValue* constResult = dynamic_cast<ConstantValue *>(result);
|
||
ConstantValue* constOperand = dynamic_cast<ConstantValue *>(operand);
|
||
|
||
if ((constResult != nullptr) && (constOperand != nullptr)) {
|
||
auto operand1 = constResult->isFloat() ? constResult->getFloat()
|
||
: constResult->getInt();
|
||
auto operand2 = constOperand->isFloat() ? constOperand->getFloat()
|
||
: constOperand->getInt();
|
||
|
||
if (opType == SysYParser::EQ) result = ConstantInteger::get(operand1 == operand2 ? 1 : 0);
|
||
else if (opType == SysYParser::NE) result = ConstantInteger::get(operand1 != operand2 ? 1 : 0);
|
||
else assert(false);
|
||
|
||
} else {
|
||
Type* resultType = result->getType();
|
||
Type* operandType = operand->getType();
|
||
Type* floatType = Type::getFloatType();
|
||
|
||
if (resultType == floatType || operandType == floatType) {
|
||
if (resultType != floatType) {
|
||
if (constResult != nullptr)
|
||
result = ConstantFloating::get(static_cast<float>(constResult->getInt()));
|
||
else
|
||
result = builder.createIToFInst(result);
|
||
}
|
||
if (operandType != floatType) {
|
||
if (constOperand != nullptr)
|
||
operand = ConstantFloating::get(static_cast<float>(constOperand->getInt()));
|
||
else
|
||
operand = builder.createIToFInst(operand);
|
||
}
|
||
|
||
if (opType == SysYParser::EQ) result = builder.createFCmpEQInst(result, operand);
|
||
else if (opType == SysYParser::NE) result = builder.createFCmpNEInst(result, operand);
|
||
else assert(false);
|
||
|
||
} else {
|
||
|
||
if (opType == SysYParser::EQ) result = builder.createICmpEQInst(result, operand);
|
||
else if (opType == SysYParser::NE) result = builder.createICmpNEInst(result, operand);
|
||
else assert(false);
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
if (ctx->relExp().size() == 1) {
|
||
ConstantValue * constResult = dynamic_cast<ConstantValue *>(result);
|
||
// 如果只有一个关系表达式,则将结果转换为0或1
|
||
if (constResult != nullptr) {
|
||
if (constResult->isFloat())
|
||
result = ConstantInteger::get(constResult->getFloat() != 0.0F ? 1 : 0);
|
||
else
|
||
result = ConstantInteger::get(constResult->getInt() != 0 ? 1 : 0);
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
std::any SysYIRGenerator::visitLAndExp(SysYParser::LAndExpContext *ctx){
|
||
std::stringstream labelstring;
|
||
BasicBlock *curBlock = builder.getBasicBlock();
|
||
Function *function = builder.getBasicBlock()->getParent();
|
||
BasicBlock *trueBlock = builder.getTrueBlock();
|
||
BasicBlock *falseBlock = builder.getFalseBlock();
|
||
auto conds = ctx->eqExp();
|
||
|
||
for (int i = 0; i < conds.size() - 1; i++) {
|
||
|
||
labelstring << "AND.L" << builder.getLabelIndex();
|
||
BasicBlock *newtrueBlock = function->addBasicBlock(labelstring.str());
|
||
labelstring.str("");
|
||
|
||
auto cond = std::any_cast<Value *>(visitEqExp(ctx->eqExp(i)));
|
||
builder.createCondBrInst(cond, newtrueBlock, falseBlock, {}, {});
|
||
|
||
BasicBlock::conectBlocks(curBlock, newtrueBlock);
|
||
BasicBlock::conectBlocks(curBlock, falseBlock);
|
||
|
||
curBlock = newtrueBlock;
|
||
builder.setPosition(curBlock, curBlock->end());
|
||
}
|
||
|
||
auto cond = std::any_cast<Value *>(visitEqExp(conds.back()));
|
||
builder.createCondBrInst(cond, trueBlock, falseBlock, {}, {});
|
||
|
||
BasicBlock::conectBlocks(curBlock, trueBlock);
|
||
BasicBlock::conectBlocks(curBlock, falseBlock);
|
||
|
||
return std::any();
|
||
}
|
||
|
||
auto SysYIRGenerator::visitLOrExp(SysYParser::LOrExpContext *ctx) -> std::any {
|
||
std::stringstream labelstring;
|
||
BasicBlock *curBlock = builder.getBasicBlock();
|
||
Function *function = curBlock->getParent();
|
||
auto conds = ctx->lAndExp();
|
||
|
||
for (int i = 0; i < conds.size() - 1; i++) {
|
||
labelstring << "OR.L" << builder.getLabelIndex();
|
||
BasicBlock *newFalseBlock = function->addBasicBlock(labelstring.str());
|
||
labelstring.str("");
|
||
|
||
builder.pushFalseBlock(newFalseBlock);
|
||
visitLAndExp(ctx->lAndExp(i));
|
||
builder.popFalseBlock();
|
||
|
||
builder.setPosition(newFalseBlock, newFalseBlock->end());
|
||
}
|
||
|
||
visitLAndExp(conds.back());
|
||
|
||
return std::any();
|
||
}
|
||
|
||
void Utils::tree2Array(Type *type, ArrayValueTree *root,
|
||
const std::vector<Value *> &dims, unsigned numDims,
|
||
ValueCounter &result, IRBuilder *builder) {
|
||
Value* value = root->getValue();
|
||
auto &children = root->getChildren();
|
||
// 类型转换
|
||
if (value != nullptr) {
|
||
if (type == value->getType()) {
|
||
result.push_back(value);
|
||
} else {
|
||
if (type == Type::getFloatType()) {
|
||
ConstantValue* constValue = dynamic_cast<ConstantValue *>(value);
|
||
if (constValue != nullptr)
|
||
result.push_back(ConstantFloating::get(static_cast<float>(constValue->getInt())));
|
||
else
|
||
result.push_back(builder->createIToFInst(value));
|
||
|
||
} else {
|
||
ConstantValue* constValue = dynamic_cast<ConstantValue *>(value);
|
||
if (constValue != nullptr)
|
||
result.push_back(ConstantInteger::get(static_cast<int>(constValue->getFloat())));
|
||
else
|
||
result.push_back(builder->createFtoIInst(value));
|
||
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
auto beforeSize = result.size();
|
||
for (const auto &child : children) {
|
||
int begin = result.size();
|
||
int newNumDims = 0;
|
||
for (unsigned i = 0; i < numDims - 1; i++) {
|
||
auto dim = dynamic_cast<ConstantValue *>(*(dims.rbegin() + i))->getInt();
|
||
if (begin % dim == 0) {
|
||
newNumDims += 1;
|
||
begin /= dim;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
tree2Array(type, child.get(), dims, newNumDims, result, builder);
|
||
}
|
||
auto afterSize = result.size();
|
||
|
||
int blockSize = 1;
|
||
for (unsigned i = 0; i < numDims; i++) {
|
||
blockSize *= dynamic_cast<ConstantValue *>(*(dims.rbegin() + i))->getInt();
|
||
}
|
||
|
||
int num = blockSize - afterSize + beforeSize;
|
||
if (num > 0) {
|
||
if (type == Type::getFloatType())
|
||
result.push_back(ConstantFloating::get(0.0F), num);
|
||
else
|
||
result.push_back(ConstantInteger::get(0), num);
|
||
}
|
||
}
|
||
|
||
void Utils::createExternalFunction(
|
||
const std::vector<Type *> ¶mTypes,
|
||
const std::vector<std::string> ¶mNames,
|
||
const std::vector<std::vector<Value *>> ¶mDims, Type *returnType,
|
||
const std::string &funcName, Module *pModule, IRBuilder *pBuilder) {
|
||
auto funcType = Type::getFunctionType(returnType, paramTypes);
|
||
auto function = pModule->createExternalFunction(funcName, funcType);
|
||
auto entry = function->getEntryBlock();
|
||
pBuilder->setPosition(entry, entry->end());
|
||
|
||
for (int i = 0; i < paramTypes.size(); ++i) {
|
||
auto alloca = pBuilder->createAllocaInst(
|
||
Type::getPointerType(paramTypes[i]), paramDims[i], paramNames[i]);
|
||
entry->insertArgument(alloca);
|
||
// pModule->addVariable(paramNames[i], alloca);
|
||
}
|
||
}
|
||
|
||
void Utils::initExternalFunction(Module *pModule, IRBuilder *pBuilder) {
|
||
std::vector<Type *> paramTypes;
|
||
std::vector<std::string> paramNames;
|
||
std::vector<std::vector<Value *>> paramDims;
|
||
Type *returnType;
|
||
std::string funcName;
|
||
|
||
returnType = Type::getIntType();
|
||
funcName = "getint";
|
||
Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType,
|
||
funcName, pModule, pBuilder);
|
||
funcName = "getch";
|
||
Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType,
|
||
funcName, pModule, pBuilder);
|
||
paramTypes.push_back(Type::getIntType());
|
||
paramNames.emplace_back("x");
|
||
paramDims.push_back(std::vector<Value *>{ConstantInteger::get(-1)});
|
||
funcName = "getarray";
|
||
Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType,
|
||
funcName, pModule, pBuilder);
|
||
|
||
returnType = Type::getFloatType();
|
||
paramTypes.clear();
|
||
paramNames.clear();
|
||
paramDims.clear();
|
||
funcName = "getfloat";
|
||
Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType,
|
||
funcName, pModule, pBuilder);
|
||
|
||
returnType = Type::getIntType();
|
||
paramTypes.push_back(Type::getFloatType());
|
||
paramNames.emplace_back("x");
|
||
paramDims.push_back(std::vector<Value *>{ConstantInteger::get(-1)});
|
||
funcName = "getfarray";
|
||
Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType,
|
||
funcName, pModule, pBuilder);
|
||
|
||
returnType = Type::getVoidType();
|
||
|
||
paramTypes.clear();
|
||
paramTypes.push_back(Type::getIntType());
|
||
paramDims.clear();
|
||
paramDims.emplace_back();
|
||
funcName = "putint";
|
||
Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType,
|
||
funcName, pModule, pBuilder);
|
||
|
||
funcName = "putch";
|
||
Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType,
|
||
funcName, pModule, pBuilder);
|
||
|
||
paramTypes.clear();
|
||
paramTypes.push_back(Type::getIntType());
|
||
paramTypes.push_back(Type::getIntType());
|
||
paramDims.clear();
|
||
paramDims.emplace_back();
|
||
paramDims.push_back(std::vector<Value *>{ConstantInteger::get(-1)});
|
||
paramNames.clear();
|
||
paramNames.emplace_back("n");
|
||
paramNames.emplace_back("a");
|
||
funcName = "putarray";
|
||
Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType,
|
||
funcName, pModule, pBuilder);
|
||
|
||
paramTypes.clear();
|
||
paramTypes.push_back(Type::getFloatType());
|
||
paramDims.clear();
|
||
paramDims.emplace_back();
|
||
paramNames.clear();
|
||
paramNames.emplace_back("a");
|
||
funcName = "putfloat";
|
||
Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType,
|
||
funcName, pModule, pBuilder);
|
||
|
||
paramTypes.clear();
|
||
paramTypes.push_back(Type::getIntType());
|
||
paramTypes.push_back(Type::getFloatType());
|
||
paramDims.clear();
|
||
paramDims.emplace_back();
|
||
paramDims.push_back(std::vector<Value *>{ConstantInteger::get(-1)});
|
||
paramNames.clear();
|
||
paramNames.emplace_back("n");
|
||
paramNames.emplace_back("a");
|
||
funcName = "putfarray";
|
||
Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType,
|
||
funcName, pModule, pBuilder);
|
||
|
||
paramTypes.clear();
|
||
paramTypes.push_back(Type::getIntType());
|
||
paramDims.clear();
|
||
paramDims.emplace_back();
|
||
paramNames.clear();
|
||
paramNames.emplace_back("__LINE__");
|
||
funcName = "starttime";
|
||
Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType,
|
||
funcName, pModule, pBuilder);
|
||
|
||
paramTypes.clear();
|
||
paramTypes.push_back(Type::getIntType());
|
||
paramDims.clear();
|
||
paramDims.emplace_back();
|
||
paramNames.clear();
|
||
paramNames.emplace_back("__LINE__");
|
||
funcName = "stoptime";
|
||
Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType,
|
||
funcName, pModule, pBuilder);
|
||
|
||
}
|
||
|
||
} // namespace sysy
|