From 9c56bc131065f2eb73d7121d44b755ebd752a030 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 24 Jul 2025 17:02:29 +0800 Subject: [PATCH] =?UTF-8?q?[midend]=E4=BF=AE=E6=94=B9GEP=E6=8C=87=E4=BB=A4?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=EF=BC=8C=E6=9B=B4=E9=9D=A0=E8=BF=91llvm=20ir?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E6=8E=A8=E6=96=AD=E7=B1=BB=E5=9E=8B=E5=87=BD=E6=95=B0=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=E5=A4=8Dgenerator=E4=B8=AD=E9=94=99=E8=AF=AF=E7=94=9F?= =?UTF-8?q?=E6=88=90ir=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SysYIRGenerator.cpp | 69 +++++++---------------------------------- src/include/IR.h | 14 ++++----- src/include/IRBuilder.h | 56 ++++++++++++++++++++++++++++++--- 3 files changed, 70 insertions(+), 69 deletions(-) diff --git a/src/SysYIRGenerator.cpp b/src/SysYIRGenerator.cpp index eb21a1a..eaa7ad0 100644 --- a/src/SysYIRGenerator.cpp +++ b/src/SysYIRGenerator.cpp @@ -42,44 +42,15 @@ Type* SysYIRGenerator::buildArrayType(Type* baseType, const std::vector& Value* SysYIRGenerator::getGEPAddressInst(Value* basePointer, const std::vector& 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()->getBaseType(); + assert(basePointer->getType()->isPointer()); + // GEP 的第一个索引通常是0,用于“穿过”指针本身,访问其指向的对象。 + // 例如,对于全局数组 @arr,其类型为 [6 x i32]*,第一个0索引是必需的。 std::vector 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()->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& indices) + actualGEPIndices.push_back(ConstantInteger::get(0)); // 模拟 ConstantInteger::get(0) + actualGEPIndices.insert(actualGEPIndices.end(), indices.begin(), indices.end()); + + // 直接调用 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(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()->getBaseType(); // 从基指针指向的类型开始 - - // 模拟 GEP 路径,根据 dims 确定最终元素的类型 - for (int i = 0; i < dims.size(); ++i) { - if (targetElementType && targetElementType->isArray()) { - targetElementType = targetElementType->as()->getElementType(); - } else { - break; // 如果不是数组类型但还有索引,或者索引超出维度,则停止推断 - } - } + //根据 dims 确定最终元素的类型 + targetElementType = builder.getIndexedType(targetElementType, dims); // 左值右值类型不同处理:根据最终元素类型进行转换 if (targetElementType != value->getType()) { ConstantValue * constValue = dynamic_cast(value); if (constValue != nullptr) { if (targetElementType == Type::getFloatType()) { - value = ConstantFloating::get(static_cast(constValue->getInt())); + value = ConstantFloating::get(static_cast(constValue->getFloat())); } else { // 假设如果不是浮点型,就是整型 - value = ConstantInteger::get(static_cast(constValue->getFloat())); + value = ConstantInteger::get(static_cast(constValue->getInt())); } } else { if (targetElementType == Type::getFloatType()) { diff --git a/src/include/IR.h b/src/include/IR.h index 2abe3e1..1e64582 100644 --- a/src/include/IR.h +++ b/src/include/IR.h @@ -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 &indices = {}, - BasicBlock *parent = nullptr, const std::string &name = "") - : Instruction(Kind::kGetElementPtr, basePointer->getType(), parent, name) { + GetElementPtrInst(Type *resultType, + Value *basePointer, + const std::vector &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 &indices = {}, BasicBlock *parent = nullptr, const std::string &name = "") { - return new GetElementPtrInst(basePointer, indices, parent, name); + return new GetElementPtrInst(resultType, basePointer, indices, parent, name); } }; diff --git a/src/include/IRBuilder.h b/src/include/IRBuilder.h index 03df66a..c97dec5 100644 --- a/src/include/IRBuilder.h +++ b/src/include/IRBuilder.h @@ -294,15 +294,41 @@ class IRBuilder { return inst; } ///< 创建store指令 PhiInst * createPhiInst(Type *type, const std::vector &vals = {}, const std::vector &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 &indices = {}, - const std::string &name = "") { + // GetElementPtrInst* createGetElementPtrInst(Value *basePointer, + // const std::vector &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 &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 &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()->getBaseType(); + } else + if (CurrentType->isArray()) { + CurrentType = CurrentType->as()->getElementType(); + } + else { + // 如果类型不是聚合类型但仍有索引,说明索引过多,这是错误的 + CurrentType = nullptr; + } + } + return CurrentType; + } }; } // namespace sysy