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)) {