[midend]修改GEP指令定义,更靠近llvm ir设计,增加自动推断类型函数,修复generator中错误生成ir的逻辑

This commit is contained in:
rain2133
2025-07-24 17:02:29 +08:00
parent c68b031c01
commit 9c56bc1310
3 changed files with 70 additions and 69 deletions

View File

@@ -42,44 +42,15 @@ Type* SysYIRGenerator::buildArrayType(Type* baseType, const std::vector<Value*>&
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();
assert(basePointer->getType()->isPointer());
// GEP 的第一个索引通常是0用于“穿过”指针本身访问其指向的对象。
// 例如,对于全局数组 @arr其类型为 [6 x i32]*第一个0索引是必需的。
std::vector<Value*> actualGEPIndices;
// GEP 指令的第一个索引通常是0用于“跳过”基指针指向的聚合类型本身直接指向其第一个元素。
// 例如,对于 AllocaInst 返回的 `int[2][3]*`,第一个 `0` 索引表示从数组的开始而不是指针本身开始索引。
actualGEPIndices.push_back(ConstantInteger::get(0));
actualGEPIndices.push_back(ConstantInteger::get(0)); // 模拟 ConstantInteger::get(0)
actualGEPIndices.insert(actualGEPIndices.end(), indices.begin(), indices.end());
// 将用户提供的索引添加到 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)
// 直接调用 builder 的方法,无需再关心类型推断的细节
return builder.createGetElementPtrInst(basePointer, actualGEPIndices);
}
/*
@@ -441,35 +412,19 @@ std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx) {
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.");
}
Type* targetElementType = variable->getType(); // 从基指针指向的类型开始
// 计算最终赋值目标元素的类型
// 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; // 如果不是数组类型但还有索引,或者索引超出维度,则停止推断
}
}
//根据 dims 确定最终元素的类型
targetElementType = builder.getIndexedType(targetElementType, dims);
// 左值右值类型不同处理:根据最终元素类型进行转换
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()));
value = ConstantFloating::get(static_cast<float>(constValue->getFloat()));
} else { // 假设如果不是浮点型,就是整型
value = ConstantInteger::get(static_cast<int>(constValue->getFloat()));
value = ConstantInteger::get(static_cast<int>(constValue->getInt()));
}
} else {
if (targetElementType == Type::getFloatType()) {

View File

@@ -1124,24 +1124,24 @@ public:
class GetElementPtrInst : public Instruction {
friend class IRBuilder; // 如果您有IRBuilder来创建指令需要friend
friend class IRBuilder;
protected:
// GEP的构造函数
// resultType: GEP计算出的地址的类型 (通常是指向目标元素类型的指针)
// basePointer: 基指针 (第一个操作数)
// indices: 索引列表 (后续操作数)
GetElementPtrInst(Value *basePointer,
const std::vector<Value *> &indices = {},
BasicBlock *parent = nullptr, const std::string &name = "")
: Instruction(Kind::kGetElementPtr, basePointer->getType(), parent, name) {
GetElementPtrInst(Type *resultType,
Value *basePointer,
const std::vector<Value *> &indices = {},
BasicBlock *parent = nullptr, const std::string &name = "")
: Instruction(Kind::kGetElementPtr, resultType, parent, name) {
assert(basePointer && "GEP base pointer cannot be null!");
// TODO : 安全检查
assert(basePointer->getType()->isPointer() );
addOperand(basePointer); // 第一个操作数是基指针
addOperands(indices); // 随后的操作数是索引
}
public:
Value* getBasePointer() const { return getOperand(0); }
unsigned getNumIndices() const { return getNumOperands() - 1; }
@@ -1155,7 +1155,7 @@ public:
static GetElementPtrInst* create(Type *resultType, Value *basePointer,
const std::vector<Value *> &indices = {},
BasicBlock *parent = nullptr, const std::string &name = "") {
return new GetElementPtrInst(basePointer, indices, parent, name);
return new GetElementPtrInst(resultType, basePointer, indices, parent, name);
}
};

View File

@@ -294,15 +294,41 @@ class IRBuilder {
return inst;
} ///< 创建store指令
PhiInst * createPhiInst(Type *type, const std::vector<Value*> &vals = {}, const std::vector<BasicBlock*> &blks = {}, const std::string &name = "") {
auto predNum = block->getNumPredecessors();
auto inst = new PhiInst(type, vals, blks, block, name);
assert(inst);
block->getInstructions().emplace(block->begin(), inst);
return inst;
} ///< 创建Phi指令
GetElementPtrInst* createGetElementPtrInst(Value *basePointer,
const std::vector<Value *> &indices = {},
const std::string &name = "") {
// GetElementPtrInst* createGetElementPtrInst(Value *basePointer,
// const std::vector<Value *> &indices = {},
// const std::string &name = "") {
// std::string newName;
// if (name.empty()) {
// std::stringstream ss;
// ss << tmpIndex;
// newName = ss.str();
// tmpIndex++;
// } else {
// newName = name;
// }
// auto inst = new GetElementPtrInst(basePointer, indices, block, newName);
// assert(inst);
// block->getInstructions().emplace(position, inst);
// return inst;
// }
/**
* @brief 根据 LLVM 设计模式创建 GEP 指令。
* 它会自动推断返回类型,无需手动指定。
*/
GetElementPtrInst *createGetElementPtrInst(Value *basePointer, const std::vector<Value *> &indices,
const std::string &name = "") {
Type *ResultElementType = getIndexedType(basePointer->getType(), indices);
if (!ResultElementType) {
assert(false && "Invalid GEP indexing!");
return nullptr;
}
Type *ResultType = PointerType::get(ResultElementType);
std::string newName;
if (name.empty()) {
std::stringstream ss;
@@ -313,11 +339,31 @@ class IRBuilder {
newName = name;
}
auto inst = new GetElementPtrInst(basePointer, indices, block, newName);
auto inst = new GetElementPtrInst(ResultType, basePointer, indices, block, newName);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
}
static Type *getIndexedType(Type *pointerType, const std::vector<Value *> &indices) {
assert(pointerType->isPointer() && "base must be a pointer type!");
Type *CurrentType = pointerType;
// 遍历所有索引来深入类型层次结构Sysy只支持数组
for (int i = 0; i < indices.size(); ++i) {
if(i == 0) {
// 第一个索引是指针类型的元素类型
CurrentType = pointerType->as<PointerType>()->getBaseType();
} else
if (CurrentType->isArray()) {
CurrentType = CurrentType->as<ArrayType>()->getElementType();
}
else {
// 如果类型不是聚合类型但仍有索引,说明索引过多,这是错误的
CurrentType = nullptr;
}
}
return CurrentType;
}
};
} // namespace sysy