From cf88ca77cb22868d9922eed8e351ee1f85af4383 Mon Sep 17 00:00:00 2001 From: Lixuanwang Date: Tue, 22 Jul 2025 00:16:37 +0800 Subject: [PATCH] =?UTF-8?q?[backend]=E4=BF=AE=E5=A4=8D=E4=BA=86=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E5=85=A8=E5=B1=80=E6=95=B0=E7=BB=84=E5=9C=B0=E5=9D=80?= =?UTF-8?q?=E7=9A=84=E8=AE=A1=E7=AE=97=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RISCv64ISel.cpp | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/RISCv64ISel.cpp b/src/RISCv64ISel.cpp index fdef521..f8a1e8e 100644 --- a/src/RISCv64ISel.cpp +++ b/src/RISCv64ISel.cpp @@ -239,23 +239,21 @@ void RISCv64ISel::selectNode(DAGNode* node) { Value* lhs = bin->getLhs(); Value* rhs = bin->getRhs(); - // 检查是否是“基地址+偏移量”的地址计算模式 if (bin->getKind() == BinaryInst::kAdd) { Value* base = nullptr; Value* offset = nullptr; - // 判断哪个是基地址(AllocaInst),哪个是偏移量 - if (dynamic_cast(lhs)) { + // [修改] 扩展基地址的判断,使其可以识别 AllocaInst 或 GlobalValue + if (dynamic_cast(lhs) || dynamic_cast(lhs)) { base = lhs; offset = rhs; - } else if (dynamic_cast(rhs)) { + } else if (dynamic_cast(rhs) || dynamic_cast(rhs)) { base = rhs; offset = lhs; } - // 如果成功匹配到该模式 + // 如果成功匹配到地址计算模式 if (base) { - // [最终修复] // 1. 先为偏移量加载常量(如果它是常量的话) if (auto const_offset = dynamic_cast(offset)) { auto li = std::make_unique(RVOpcodes::LI); @@ -264,14 +262,25 @@ void RISCv64ISel::selectNode(DAGNode* node) { CurMBB->addInstruction(std::move(li)); } - // 2. 使用FRAME_ADDR伪指令来获取基地址 + // 2. [修改] 根据基地址的类型,生成不同的指令来获取基地址 auto base_addr_vreg = getNewVReg(); // 创建一个新的临时vreg来存放基地址 - auto frame_addr_instr = std::make_unique(RVOpcodes::FRAME_ADDR); - frame_addr_instr->addOperand(std::make_unique(base_addr_vreg)); - frame_addr_instr->addOperand(std::make_unique(getVReg(base))); - CurMBB->addInstruction(std::move(frame_addr_instr)); - // 3. 生成真正的add指令,计算最终地址 + // 情况一:基地址是局部栈变量 + if (auto alloca_base = dynamic_cast(base)) { + auto frame_addr_instr = std::make_unique(RVOpcodes::FRAME_ADDR); + frame_addr_instr->addOperand(std::make_unique(base_addr_vreg)); + frame_addr_instr->addOperand(std::make_unique(getVReg(alloca_base))); + CurMBB->addInstruction(std::move(frame_addr_instr)); + } + // 情况二:基地址是全局变量 + else if (auto global_base = dynamic_cast(base)) { + auto la_instr = std::make_unique(RVOpcodes::LA); + la_instr->addOperand(std::make_unique(base_addr_vreg)); + la_instr->addOperand(std::make_unique(global_base->getName())); + CurMBB->addInstruction(std::move(la_instr)); + } + + // 3. 生成真正的add指令,计算最终地址(这部分逻辑保持不变) auto final_addr_vreg = getVReg(bin); // 这是整个二元运算的结果vreg auto offset_vreg = getVReg(offset); auto add_instr = std::make_unique(RVOpcodes::ADD); // 指针运算是64位 @@ -283,7 +292,7 @@ void RISCv64ISel::selectNode(DAGNode* node) { return; // 地址计算处理完毕,直接返回 } } - + // [V2优点] 在BINARY节点内部按需加载常量操作数。 auto load_val_if_const = [&](Value* val) { if (auto c = dynamic_cast(val)) {