[midend][backend-GEP]解决了一个32/64位宽的错误问题

This commit is contained in:
Lixuanwang
2025-07-25 22:23:26 +08:00
parent 04c5c6b44d
commit 14fb3dbe48
6 changed files with 272 additions and 77 deletions

View File

@@ -149,38 +149,51 @@ void RISCv64ISel::selectNode(DAGNode* node) {
auto dest_vreg = getVReg(node->value);
Value* ptr_val = node->operands[0]->value;
// [V1设计保留] 对于从栈变量加载,继续使用伪指令 FRAME_LOAD。
// 这种设计将栈帧布局的具体计算推迟到后续的 `eliminateFrameIndices` 阶段,保持了模块化。
// --- 修改点 ---
// 1. 获取加载结果的类型 (即这个LOAD指令自身的类型)
Type* loaded_type = node->value->getType();
// 2. 根据类型选择正确的伪指令或真实指令操作码
RVOpcodes frame_opcode = loaded_type->isPointer() ? RVOpcodes::FRAME_LOAD_D : RVOpcodes::FRAME_LOAD_W;
RVOpcodes real_opcode = loaded_type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW;
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_LOAD);
// 3. 创建使用新的、区分宽度的伪指令
auto instr = std::make_unique<MachineInstr>(frame_opcode);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca)));
CurMBB->addInstruction(std::move(instr));
} else if (auto global = dynamic_cast<GlobalValue*>(ptr_val)) {
// 对于全局变量,先用 la 加载其地址,再用 lw 加载其值。
// 对于全局变量,先用 la 加载其地址
auto addr_vreg = getNewVReg();
auto la = std::make_unique<MachineInstr>(RVOpcodes::LA);
la->addOperand(std::make_unique<RegOperand>(addr_vreg));
la->addOperand(std::make_unique<LabelOperand>(global->getName()));
CurMBB->addInstruction(std::move(la));
auto lw = std::make_unique<MachineInstr>(RVOpcodes::LW);
lw->addOperand(std::make_unique<RegOperand>(dest_vreg));
lw->addOperand(std::make_unique<MemOperand>(
// 然后根据类型使用 ld 或 lw 加载其值
auto load_instr = std::make_unique<MachineInstr>(real_opcode);
load_instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
load_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(lw));
CurMBB->addInstruction(std::move(load_instr));
} else {
// 对于已经在虚拟寄存器中的指针地址,直接通过该地址加载
// 对于已经在虚拟寄存器中的指针地址,直接通过该地址加载
auto ptr_vreg = getVReg(ptr_val);
auto lw = std::make_unique<MachineInstr>(RVOpcodes::LW);
lw->addOperand(std::make_unique<RegOperand>(dest_vreg));
lw->addOperand(std::make_unique<MemOperand>(
// 根据类型使用 ld 或 lw
auto load_instr = std::make_unique<MachineInstr>(real_opcode);
load_instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
load_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(ptr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(lw));
CurMBB->addInstruction(std::move(load_instr));
}
break;
}
@@ -189,13 +202,8 @@ void RISCv64ISel::selectNode(DAGNode* node) {
Value* val_to_store = node->operands[0]->value;
Value* ptr_val = node->operands[1]->value;
// [V2优点] 在STORE节点内部负责加载作为源的常量。
// 如果要存储的值是一个常量,就在这里生成 `li` 指令加载它。
// 如果要存储的值是一个常量,就在这里生成 `li` 指令加载它
if (auto val_const = dynamic_cast<ConstantValue*>(val_to_store)) {
if (DEBUG) {
std::cout << "[DEBUG] selectNode-BINARY: Found constant operand with value " << val_const->getInt()
<< ". Generating LI instruction." << std::endl;
}
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(val_const)));
li->addOperand(std::make_unique<ImmOperand>(val_const->getInt()));
@@ -203,37 +211,50 @@ void RISCv64ISel::selectNode(DAGNode* node) {
}
auto val_vreg = getVReg(val_to_store);
// [V1设计保留] 同样,对于向栈变量的存储,使用 FRAME_STORE 伪指令。
// --- 修改点 ---
// 1. 获取被存储的值的类型
Type* stored_type = val_to_store->getType();
// 2. 根据类型选择正确的伪指令或真实指令操作码
RVOpcodes frame_opcode = stored_type->isPointer() ? RVOpcodes::FRAME_STORE_D : RVOpcodes::FRAME_STORE_W;
RVOpcodes real_opcode = stored_type->isPointer() ? RVOpcodes::SD : RVOpcodes::SW;
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_STORE);
// 3. 创建使用新的、区分宽度的伪指令
auto instr = std::make_unique<MachineInstr>(frame_opcode);
instr->addOperand(std::make_unique<RegOperand>(val_vreg));
instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca)));
CurMBB->addInstruction(std::move(instr));
} else if (auto global = dynamic_cast<GlobalValue*>(ptr_val)) {
// 向全局变量存储
// 向全局变量存储
auto addr_vreg = getNewVReg();
auto la = std::make_unique<MachineInstr>(RVOpcodes::LA);
la->addOperand(std::make_unique<RegOperand>(addr_vreg));
la->addOperand(std::make_unique<LabelOperand>(global->getName()));
CurMBB->addInstruction(std::move(la));
auto sw = std::make_unique<MachineInstr>(RVOpcodes::SW);
sw->addOperand(std::make_unique<RegOperand>(val_vreg));
sw->addOperand(std::make_unique<MemOperand>(
// 根据类型使用 sd 或 sw
auto store_instr = std::make_unique<MachineInstr>(real_opcode);
store_instr->addOperand(std::make_unique<RegOperand>(val_vreg));
store_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(sw));
CurMBB->addInstruction(std::move(store_instr));
} else {
// 向一个指针(存储在虚拟寄存器中)指向的地址存储
// 向一个指针(存储在虚拟寄存器中)指向的地址存储
auto ptr_vreg = getVReg(ptr_val);
auto sw = std::make_unique<MachineInstr>(RVOpcodes::SW);
sw->addOperand(std::make_unique<RegOperand>(val_vreg));
sw->addOperand(std::make_unique<MemOperand>(
// 根据类型使用 sd 或 sw
auto store_instr = std::make_unique<MachineInstr>(real_opcode);
store_instr->addOperand(std::make_unique<RegOperand>(val_vreg));
store_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(ptr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(sw));
CurMBB->addInstruction(std::move(store_instr));
}
break;
}