diff --git a/src/RISCv64ISel.cpp b/src/RISCv64ISel.cpp index 2da2373..fdef521 100644 --- a/src/RISCv64ISel.cpp +++ b/src/RISCv64ISel.cpp @@ -238,7 +238,52 @@ void RISCv64ISel::selectNode(DAGNode* node) { auto bin = dynamic_cast(node->value); Value* lhs = bin->getLhs(); Value* rhs = bin->getRhs(); + + // 检查是否是“基地址+偏移量”的地址计算模式 + if (bin->getKind() == BinaryInst::kAdd) { + Value* base = nullptr; + Value* offset = nullptr; + // 判断哪个是基地址(AllocaInst),哪个是偏移量 + if (dynamic_cast(lhs)) { + base = lhs; + offset = rhs; + } else if (dynamic_cast(rhs)) { + base = rhs; + offset = lhs; + } + + // 如果成功匹配到该模式 + if (base) { + // [最终修复] + // 1. 先为偏移量加载常量(如果它是常量的话) + if (auto const_offset = dynamic_cast(offset)) { + auto li = std::make_unique(RVOpcodes::LI); + li->addOperand(std::make_unique(getVReg(const_offset))); + li->addOperand(std::make_unique(const_offset->getInt())); + CurMBB->addInstruction(std::move(li)); + } + + // 2. 使用FRAME_ADDR伪指令来获取基地址 + 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指令,计算最终地址 + auto final_addr_vreg = getVReg(bin); // 这是整个二元运算的结果vreg + auto offset_vreg = getVReg(offset); + auto add_instr = std::make_unique(RVOpcodes::ADD); // 指针运算是64位 + add_instr->addOperand(std::make_unique(final_addr_vreg)); + add_instr->addOperand(std::make_unique(base_addr_vreg)); + add_instr->addOperand(std::make_unique(offset_vreg)); + CurMBB->addInstruction(std::move(add_instr)); + + return; // 地址计算处理完毕,直接返回 + } + } + // [V2优点] 在BINARY节点内部按需加载常量操作数。 auto load_val_if_const = [&](Value* val) { if (auto c = dynamic_cast(val)) {