[backend]解决了重构后数组初始化不正确的问题

This commit is contained in:
Lixuanwang
2025-07-21 16:27:47 +08:00
parent f7e811b756
commit bbfbf96b5e
9 changed files with 198 additions and 42 deletions

View File

@@ -18,7 +18,7 @@ bool isMemoryOp(RVOpcodes opcode) {
RISCv64AsmPrinter::RISCv64AsmPrinter(MachineFunction* mfunc) : MFunc(mfunc) {} RISCv64AsmPrinter::RISCv64AsmPrinter(MachineFunction* mfunc) : MFunc(mfunc) {}
void RISCv64AsmPrinter::run(std::ostream& os) { void RISCv64AsmPrinter::run(std::ostream& os, bool debug) {
OS = &os; OS = &os;
*OS << ".globl " << MFunc->getName() << "\n"; *OS << ".globl " << MFunc->getName() << "\n";
@@ -27,7 +27,7 @@ void RISCv64AsmPrinter::run(std::ostream& os) {
printPrologue(); printPrologue();
for (auto& mbb : MFunc->getBlocks()) { for (auto& mbb : MFunc->getBlocks()) {
printBasicBlock(mbb.get()); printBasicBlock(mbb.get(), debug);
} }
} }
@@ -73,16 +73,16 @@ void RISCv64AsmPrinter::printEpilogue() {
} }
} }
void RISCv64AsmPrinter::printBasicBlock(MachineBasicBlock* mbb) { void RISCv64AsmPrinter::printBasicBlock(MachineBasicBlock* mbb, bool debug) {
if (!mbb->getName().empty()) { if (!mbb->getName().empty()) {
*OS << mbb->getName() << ":\n"; *OS << mbb->getName() << ":\n";
} }
for (auto& instr : mbb->getInstructions()) { for (auto& instr : mbb->getInstructions()) {
printInstruction(instr.get()); printInstruction(instr.get(), debug);
} }
} }
void RISCv64AsmPrinter::printInstruction(MachineInstr* instr) { void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
auto opcode = instr->getOpcode(); auto opcode = instr->getOpcode();
if (opcode == RVOpcodes::RET) { if (opcode == RVOpcodes::RET) {
printEpilogue(); printEpilogue();
@@ -137,9 +137,17 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr) {
// *OS << ":"; // *OS << ":";
break; break;
case RVOpcodes::FRAME_LOAD: case RVOpcodes::FRAME_LOAD:
// It should have been eliminated by RegAlloc
if (!debug) throw std::runtime_error("FRAME pseudo-instruction not eliminated before AsmPrinter");
*OS << "frame_load "; break;
case RVOpcodes::FRAME_STORE: case RVOpcodes::FRAME_STORE:
// These should have been eliminated by RegAlloc // It should have been eliminated by RegAlloc
throw std::runtime_error("FRAME pseudo-instruction not eliminated before AsmPrinter"); if (!debug) throw std::runtime_error("FRAME pseudo-instruction not eliminated before AsmPrinter");
*OS << "frame_store "; break;
case RVOpcodes::FRAME_ADDR:
// It should have been eliminated by RegAlloc
if (!debug) throw std::runtime_error("FRAME pseudo-instruction not eliminated before AsmPrinter");
*OS << "frame_addr "; break;
default: default:
throw std::runtime_error("Unknown opcode in AsmPrinter"); throw std::runtime_error("Unknown opcode in AsmPrinter");
} }

View File

@@ -61,6 +61,10 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
RISCv64ISel isel; RISCv64ISel isel;
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func); std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
std::stringstream ss1;
RISCv64AsmPrinter printer1(mfunc.get());
printer1.run(ss1, true);
// 阶段 2: 指令调度 (Instruction Scheduling) // 阶段 2: 指令调度 (Instruction Scheduling)
PreRA_Scheduler scheduler; PreRA_Scheduler scheduler;
scheduler.runOnMachineFunction(mfunc.get()); scheduler.runOnMachineFunction(mfunc.get());
@@ -81,7 +85,7 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
std::stringstream ss; std::stringstream ss;
RISCv64AsmPrinter printer(mfunc.get()); RISCv64AsmPrinter printer(mfunc.get());
printer.run(ss); printer.run(ss);
if (DEBUG) ss << ss1.str(); // 将指令选择阶段的结果也包含在最终输出中
return ss.str(); return ss.str();
} }

View File

@@ -4,6 +4,7 @@
#include <functional> #include <functional>
#include <cmath> // For std::fabs #include <cmath> // For std::fabs
#include <limits> // For std::numeric_limits #include <limits> // For std::numeric_limits
#include <iostream>
namespace sysy { namespace sysy {
@@ -92,6 +93,10 @@ void RISCv64ISel::selectBasicBlock(BasicBlock* bb) {
std::set<DAGNode*> selected_nodes; std::set<DAGNode*> selected_nodes;
std::function<void(DAGNode*)> select_recursive = std::function<void(DAGNode*)> select_recursive =
[&](DAGNode* node) { [&](DAGNode* node) {
if (DEEPDEBUG) {
std::cout << "[DEEPDEBUG] select_recursive: Visiting node with kind: " << node->kind
<< " (Value: " << (node->value ? node->value->getName() : "null") << ")" << std::endl;
}
if (!node || selected_nodes.count(node)) return; if (!node || selected_nodes.count(node)) return;
for (auto operand : node->operands) { for (auto operand : node->operands) {
select_recursive(operand); select_recursive(operand);
@@ -118,24 +123,37 @@ void RISCv64ISel::selectBasicBlock(BasicBlock* bb) {
} }
} }
// 核心函数为DAG节点选择并生成MachineInstr (忠实移植版) // 核心函数为DAG节点选择并生成MachineInstr (已修复和增强的完整版本)
void RISCv64ISel::selectNode(DAGNode* node) { void RISCv64ISel::selectNode(DAGNode* node) {
// 调用者select_recursive已经保证了操作数节点会先于当前节点被选择。
// 因此,这里我们只处理当前节点。
switch (node->kind) { switch (node->kind) {
// [V2优点] 采纳“延迟物化”Late Materialization思想。
// 这两个节点仅作为标记不直接生成指令。它们的目的是在DAG中保留类型信息。
// 加载其值的责任被转移给了使用它们的父节点如STORE, BINARY等
// 这修复了之前版本中“使用未初始化虚拟寄存器”的根本性bug。
case DAGNode::CONSTANT: case DAGNode::CONSTANT:
case DAGNode::ALLOCA_ADDR: case DAGNode::ALLOCA_ADDR:
if (node->value) getVReg(node->value); if (node->value) {
// 确保它有一个关联的虚拟寄存器即可,不生成代码。
getVReg(node->value);
}
break; break;
case DAGNode::LOAD: { case DAGNode::LOAD: {
auto dest_vreg = getVReg(node->value); auto dest_vreg = getVReg(node->value);
Value* ptr_val = node->operands[0]->value; Value* ptr_val = node->operands[0]->value;
// [V1设计保留] 对于从栈变量加载,继续使用伪指令 FRAME_LOAD。
// 这种设计将栈帧布局的具体计算推迟到后续的 `eliminateFrameIndices` 阶段,保持了模块化。
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) { if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_LOAD); auto instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_LOAD);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca))); instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca)));
CurMBB->addInstruction(std::move(instr)); CurMBB->addInstruction(std::move(instr));
} else if (auto global = dynamic_cast<GlobalValue*>(ptr_val)) { } else if (auto global = dynamic_cast<GlobalValue*>(ptr_val)) {
// 对于全局变量,先用 la 加载其地址,再用 lw 加载其值。
auto addr_vreg = getNewVReg(); auto addr_vreg = getNewVReg();
auto la = std::make_unique<MachineInstr>(RVOpcodes::LA); auto la = std::make_unique<MachineInstr>(RVOpcodes::LA);
la->addOperand(std::make_unique<RegOperand>(addr_vreg)); la->addOperand(std::make_unique<RegOperand>(addr_vreg));
@@ -150,6 +168,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
)); ));
CurMBB->addInstruction(std::move(lw)); CurMBB->addInstruction(std::move(lw));
} else { } else {
// 对于已经在虚拟寄存器中的指针地址,直接通过该地址加载。
auto ptr_vreg = getVReg(ptr_val); auto ptr_vreg = getVReg(ptr_val);
auto lw = std::make_unique<MachineInstr>(RVOpcodes::LW); auto lw = std::make_unique<MachineInstr>(RVOpcodes::LW);
lw->addOperand(std::make_unique<RegOperand>(dest_vreg)); lw->addOperand(std::make_unique<RegOperand>(dest_vreg));
@@ -166,7 +185,13 @@ void RISCv64ISel::selectNode(DAGNode* node) {
Value* val_to_store = node->operands[0]->value; Value* val_to_store = node->operands[0]->value;
Value* ptr_val = node->operands[1]->value; Value* ptr_val = node->operands[1]->value;
// [V2优点] 在STORE节点内部负责加载作为源的常量。
// 如果要存储的值是一个常量,就在这里生成 `li` 指令加载它。
if (auto val_const = dynamic_cast<ConstantValue*>(val_to_store)) { 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); auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(val_const))); li->addOperand(std::make_unique<RegOperand>(getVReg(val_const)));
li->addOperand(std::make_unique<ImmOperand>(val_const->getInt())); li->addOperand(std::make_unique<ImmOperand>(val_const->getInt()));
@@ -174,13 +199,15 @@ void RISCv64ISel::selectNode(DAGNode* node) {
} }
auto val_vreg = getVReg(val_to_store); auto val_vreg = getVReg(val_to_store);
// [V1设计保留] 同样,对于向栈变量的存储,使用 FRAME_STORE 伪指令。
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) { if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_STORE); auto instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_STORE);
instr->addOperand(std::make_unique<RegOperand>(val_vreg)); instr->addOperand(std::make_unique<RegOperand>(val_vreg));
instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca))); instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca)));
CurMBB->addInstruction(std::move(instr)); CurMBB->addInstruction(std::move(instr));
} else if (auto global = dynamic_cast<GlobalValue*>(ptr_val)) { } else if (auto global = dynamic_cast<GlobalValue*>(ptr_val)) {
auto addr_vreg = getNewVReg(); // 向全局变量存储。
auto addr_vreg = getNewVReg();
auto la = std::make_unique<MachineInstr>(RVOpcodes::LA); auto la = std::make_unique<MachineInstr>(RVOpcodes::LA);
la->addOperand(std::make_unique<RegOperand>(addr_vreg)); la->addOperand(std::make_unique<RegOperand>(addr_vreg));
la->addOperand(std::make_unique<LabelOperand>(global->getName())); la->addOperand(std::make_unique<LabelOperand>(global->getName()));
@@ -194,6 +221,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
)); ));
CurMBB->addInstruction(std::move(sw)); CurMBB->addInstruction(std::move(sw));
} else { } else {
// 向一个指针(存储在虚拟寄存器中)指向的地址存储。
auto ptr_vreg = getVReg(ptr_val); auto ptr_vreg = getVReg(ptr_val);
auto sw = std::make_unique<MachineInstr>(RVOpcodes::SW); auto sw = std::make_unique<MachineInstr>(RVOpcodes::SW);
sw->addOperand(std::make_unique<RegOperand>(val_vreg)); sw->addOperand(std::make_unique<RegOperand>(val_vreg));
@@ -211,36 +239,53 @@ void RISCv64ISel::selectNode(DAGNode* node) {
Value* lhs = bin->getLhs(); Value* lhs = bin->getLhs();
Value* rhs = bin->getRhs(); Value* rhs = bin->getRhs();
// [V2优点] 在BINARY节点内部按需加载常量操作数。
auto load_val_if_const = [&](Value* val) { auto load_val_if_const = [&](Value* val) {
if (auto c = dynamic_cast<ConstantValue*>(val)) { if (auto c = dynamic_cast<ConstantValue*>(val)) {
if (DEBUG) {
std::cout << "[DEBUG] selectNode-BINARY: Found constant operand with value " << c->getInt()
<< ". Generating LI instruction." << std::endl;
}
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI); auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(c))); li->addOperand(std::make_unique<RegOperand>(getVReg(c)));
li->addOperand(std::make_unique<ImmOperand>(c->getInt())); li->addOperand(std::make_unique<ImmOperand>(c->getInt()));
CurMBB->addInstruction(std::move(li)); CurMBB->addInstruction(std::move(li));
} }
}; };
load_val_if_const(lhs);
load_val_if_const(rhs);
auto dest_vreg = getVReg(bin); // 检查是否能应用立即数优化。
auto lhs_vreg = getVReg(lhs); bool rhs_is_imm_opt = false;
auto rhs_vreg = getVReg(rhs); if (auto rhs_const = dynamic_cast<ConstantValue*>(rhs)) {
if (bin->getKind() == BinaryInst::kAdd && rhs_const->getInt() >= -2048 && rhs_const->getInt() < 2048) {
if (bin->getKind() == BinaryInst::kAdd) { rhs_is_imm_opt = true;
if (auto rhs_const = dynamic_cast<ConstantValue*>(rhs)) {
if (rhs_const->getInt() >= -2048 && rhs_const->getInt() < 2048) {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::ADDIW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<ImmOperand>(rhs_const->getInt()));
CurMBB->addInstruction(std::move(instr));
return;
}
} }
} }
// 仅在不能作为立即数操作数时才需要提前加载。
load_val_if_const(lhs);
if (!rhs_is_imm_opt) {
load_val_if_const(rhs);
}
auto dest_vreg = getVReg(bin);
auto lhs_vreg = getVReg(lhs);
// [V2优点] 融合 ADDIW 优化。
if (rhs_is_imm_opt) {
auto rhs_const = dynamic_cast<ConstantValue*>(rhs);
auto instr = std::make_unique<MachineInstr>(RVOpcodes::ADDIW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<ImmOperand>(rhs_const->getInt()));
CurMBB->addInstruction(std::move(instr));
return; // 指令已生成,直接返回。
}
auto rhs_vreg = getVReg(rhs);
switch (bin->getKind()) { switch (bin->getKind()) {
case BinaryInst::kAdd: { case BinaryInst::kAdd: {
// 区分指针运算64位和整数运算32位
RVOpcodes opcode = (lhs->getType()->isPointer() || rhs->getType()->isPointer()) ? RVOpcodes::ADD : RVOpcodes::ADDW; RVOpcodes opcode = (lhs->getType()->isPointer() || rhs->getType()->isPointer()) ? RVOpcodes::ADD : RVOpcodes::ADDW;
auto instr = std::make_unique<MachineInstr>(opcode); auto instr = std::make_unique<MachineInstr>(opcode);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
@@ -281,7 +326,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(instr)); CurMBB->addInstruction(std::move(instr));
break; break;
} }
case BinaryInst::kICmpEQ: { case BinaryInst::kICmpEQ: { // 等于 (a == b) -> (subw; seqz)
auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW); auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
sub->addOperand(std::make_unique<RegOperand>(dest_vreg)); sub->addOperand(std::make_unique<RegOperand>(dest_vreg));
sub->addOperand(std::make_unique<RegOperand>(lhs_vreg)); sub->addOperand(std::make_unique<RegOperand>(lhs_vreg));
@@ -294,7 +339,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(seqz)); CurMBB->addInstruction(std::move(seqz));
break; break;
} }
case BinaryInst::kICmpNE: { case BinaryInst::kICmpNE: { // 不等于 (a != b) -> (subw; snez)
auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW); auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
sub->addOperand(std::make_unique<RegOperand>(dest_vreg)); sub->addOperand(std::make_unique<RegOperand>(dest_vreg));
sub->addOperand(std::make_unique<RegOperand>(lhs_vreg)); sub->addOperand(std::make_unique<RegOperand>(lhs_vreg));
@@ -307,7 +352,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(snez)); CurMBB->addInstruction(std::move(snez));
break; break;
} }
case BinaryInst::kICmpLT: { case BinaryInst::kICmpLT: { // 小于 (a < b) -> slt
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SLT); auto instr = std::make_unique<MachineInstr>(RVOpcodes::SLT);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg)); instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
@@ -315,7 +360,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(instr)); CurMBB->addInstruction(std::move(instr));
break; break;
} }
case BinaryInst::kICmpGT: { case BinaryInst::kICmpGT: { // 大于 (a > b) -> (b < a) -> slt
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SLT); auto instr = std::make_unique<MachineInstr>(RVOpcodes::SLT);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg)); instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
@@ -323,7 +368,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(instr)); CurMBB->addInstruction(std::move(instr));
break; break;
} }
case BinaryInst::kICmpLE: { case BinaryInst::kICmpLE: { // 小于等于 (a <= b) -> !(b < a) -> (slt; xori)
auto slt = std::make_unique<MachineInstr>(RVOpcodes::SLT); auto slt = std::make_unique<MachineInstr>(RVOpcodes::SLT);
slt->addOperand(std::make_unique<RegOperand>(dest_vreg)); slt->addOperand(std::make_unique<RegOperand>(dest_vreg));
slt->addOperand(std::make_unique<RegOperand>(rhs_vreg)); slt->addOperand(std::make_unique<RegOperand>(rhs_vreg));
@@ -337,7 +382,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(xori)); CurMBB->addInstruction(std::move(xori));
break; break;
} }
case BinaryInst::kICmpGE: { case BinaryInst::kICmpGE: { // 大于等于 (a >= b) -> !(a < b) -> (slt; xori)
auto slt = std::make_unique<MachineInstr>(RVOpcodes::SLT); auto slt = std::make_unique<MachineInstr>(RVOpcodes::SLT);
slt->addOperand(std::make_unique<RegOperand>(dest_vreg)); slt->addOperand(std::make_unique<RegOperand>(dest_vreg));
slt->addOperand(std::make_unique<RegOperand>(lhs_vreg)); slt->addOperand(std::make_unique<RegOperand>(lhs_vreg));
@@ -363,7 +408,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
auto src_vreg = getVReg(unary->getOperand()); auto src_vreg = getVReg(unary->getOperand());
switch (unary->getKind()) { switch (unary->getKind()) {
case UnaryInst::kNeg: { case UnaryInst::kNeg: { // 取负: 0 - src
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SUBW); auto instr = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO)); instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
@@ -371,7 +416,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(instr)); CurMBB->addInstruction(std::move(instr));
break; break;
} }
case UnaryInst::kNot: { case UnaryInst::kNot: { // 逻辑非: src == 0 ? 1 : 0
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SEQZ); auto instr = std::make_unique<MachineInstr>(RVOpcodes::SEQZ);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(src_vreg)); instr->addOperand(std::make_unique<RegOperand>(src_vreg));
@@ -386,6 +431,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
case DAGNode::CALL: { case DAGNode::CALL: {
auto call = dynamic_cast<CallInst*>(node->value); auto call = dynamic_cast<CallInst*>(node->value);
// 处理函数参数放入a0-a7物理寄存器
for (size_t i = 0; i < node->operands.size() && i < 8; ++i) { for (size_t i = 0; i < node->operands.size() && i < 8; ++i) {
DAGNode* arg_node = node->operands[i]; DAGNode* arg_node = node->operands[i];
auto arg_preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + i); auto arg_preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + i);
@@ -409,7 +455,8 @@ void RISCv64ISel::selectNode(DAGNode* node) {
auto call_instr = std::make_unique<MachineInstr>(RVOpcodes::CALL); auto call_instr = std::make_unique<MachineInstr>(RVOpcodes::CALL);
call_instr->addOperand(std::make_unique<LabelOperand>(call->getCallee()->getName())); call_instr->addOperand(std::make_unique<LabelOperand>(call->getCallee()->getName()));
CurMBB->addInstruction(std::move(call_instr)); CurMBB->addInstruction(std::move(call_instr));
// 处理返回值从a0移动到目标虚拟寄存器
if (!call->getType()->isVoid()) { if (!call->getType()->isVoid()) {
auto mv_instr = std::make_unique<MachineInstr>(RVOpcodes::MV); auto mv_instr = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv_instr->addOperand(std::make_unique<RegOperand>(getVReg(call))); mv_instr->addOperand(std::make_unique<RegOperand>(getVReg(call)));
@@ -423,6 +470,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
auto ret_inst_ir = dynamic_cast<ReturnInst*>(node->value); auto ret_inst_ir = dynamic_cast<ReturnInst*>(node->value);
if (ret_inst_ir && ret_inst_ir->hasReturnValue()) { if (ret_inst_ir && ret_inst_ir->hasReturnValue()) {
Value* ret_val = ret_inst_ir->getReturnValue(); Value* ret_val = ret_inst_ir->getReturnValue();
// [V2优点] 在RETURN节点内加载常量返回值
if (auto const_val = dynamic_cast<ConstantValue*>(ret_val)) { if (auto const_val = dynamic_cast<ConstantValue*>(ret_val)) {
auto li_instr = std::make_unique<MachineInstr>(RVOpcodes::LI); auto li_instr = std::make_unique<MachineInstr>(RVOpcodes::LI);
li_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0)); li_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
@@ -435,6 +483,8 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(mv_instr)); CurMBB->addInstruction(std::move(mv_instr));
} }
} }
// [V1设计保留] 函数尾声epilogue不由RETURN节点生成
// 而是由后续的AsmPrinter或其它Pass统一处理这是一种常见且有效的模块化设计。
auto ret_mi = std::make_unique<MachineInstr>(RVOpcodes::RET); auto ret_mi = std::make_unique<MachineInstr>(RVOpcodes::RET);
CurMBB->addInstruction(std::move(ret_mi)); CurMBB->addInstruction(std::move(ret_mi));
break; break;
@@ -442,11 +492,25 @@ void RISCv64ISel::selectNode(DAGNode* node) {
case DAGNode::BRANCH: { case DAGNode::BRANCH: {
if (auto cond_br = dynamic_cast<CondBrInst*>(node->value)) { if (auto cond_br = dynamic_cast<CondBrInst*>(node->value)) {
// [V2优点] 采用更健壮的if-then-else分支逻辑。
auto cond_vreg = getVReg(cond_br->getCondition());
auto then_bb_name = cond_br->getThenBlock()->getName();
auto else_bb_name = cond_br->getElseBlock()->getName();
// bne cond, zero, then_label (如果cond不为0则跳转到then)
auto br_instr = std::make_unique<MachineInstr>(RVOpcodes::BNE); auto br_instr = std::make_unique<MachineInstr>(RVOpcodes::BNE);
br_instr->addOperand(std::make_unique<RegOperand>(getVReg(cond_br->getCondition()))); br_instr->addOperand(std::make_unique<RegOperand>(cond_vreg));
br_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO)); br_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
br_instr->addOperand(std::make_unique<LabelOperand>(cond_br->getThenBlock()->getName())); br_instr->addOperand(std::make_unique<LabelOperand>(then_bb_name));
CurMBB->addInstruction(std::move(br_instr)); CurMBB->addInstruction(std::move(br_instr));
// 无条件跳转到else块 (如果上面分支未发生)
// 注意在实际的CFG中这个J指令可能不是必须的
// 因为else块可能是下一个块。但为了通用性这里生成它。
auto j_instr = std::make_unique<MachineInstr>(RVOpcodes::J);
j_instr->addOperand(std::make_unique<LabelOperand>(else_bb_name));
CurMBB->addInstruction(std::move(j_instr));
} else if (auto uncond_br = dynamic_cast<UncondBrInst*>(node->value)) { } else if (auto uncond_br = dynamic_cast<UncondBrInst*>(node->value)) {
auto j_instr = std::make_unique<MachineInstr>(RVOpcodes::J); auto j_instr = std::make_unique<MachineInstr>(RVOpcodes::J);
j_instr->addOperand(std::make_unique<LabelOperand>(uncond_br->getBlock()->getName())); j_instr->addOperand(std::make_unique<LabelOperand>(uncond_br->getBlock()->getName()));
@@ -456,15 +520,58 @@ void RISCv64ISel::selectNode(DAGNode* node) {
} }
case DAGNode::MEMSET: { case DAGNode::MEMSET: {
// [V1设计保留] Memset的核心展开逻辑在虚拟寄存器层面是正确的无需修改。
// 之前的bug是由于其输入地址、值、大小的虚拟寄存器未被正确初始化。
// 在修复了CONSTANT/ALLOCA_ADDR的加载问题后此处的逻辑现在可以正常工作。
if (DEBUG) {
std::cout << "[DEBUG] selectNode-MEMSET: Processing MEMSET node." << std::endl;
}
auto memset = dynamic_cast<MemsetInst*>(node->value); auto memset = dynamic_cast<MemsetInst*>(node->value);
Value* val_to_set = memset->getValue();
Value* size_to_set = memset->getSize();
Value* ptr_val = memset->getPointer();
auto dest_addr_vreg = getVReg(ptr_val);
if (auto const_val = dynamic_cast<ConstantValue*>(val_to_set)) {
if (DEBUG) {
std::cout << "[DEBUG] selectNode-MEMSET: Found constant 'value' operand (" << const_val->getInt() << "). Generating LI." << std::endl;
}
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(const_val)));
li->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li));
}
if (auto const_size = dynamic_cast<ConstantValue*>(size_to_set)) {
if (DEBUG) {
std::cout << "[DEBUG] selectNode-MEMSET: Found constant 'size' operand (" << const_size->getInt() << "). Generating LI." << std::endl;
}
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(const_size)));
li->addOperand(std::make_unique<ImmOperand>(const_size->getInt()));
CurMBB->addInstruction(std::move(li));
}
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
if (DEBUG) {
std::cout << "[DEBUG] selectNode-MEMSET: Found 'pointer' operand is an AllocaInst. Generating FRAME_ADDR." << std::endl;
}
// 生成新的伪指令来获取栈地址
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_ADDR);
instr->addOperand(std::make_unique<RegOperand>(dest_addr_vreg)); // 目标虚拟寄存器
instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca))); // 源AllocaInst
CurMBB->addInstruction(std::move(instr));
}
auto r_dest_addr = getVReg(memset->getPointer()); auto r_dest_addr = getVReg(memset->getPointer());
auto r_num_bytes = getVReg(memset->getSize()); auto r_num_bytes = getVReg(memset->getSize());
auto r_value_byte = getVReg(memset->getValue()); auto r_value_byte = getVReg(memset->getValue());
// 为memset内部逻辑创建新的临时虚拟寄存器
auto r_counter = getNewVReg(); auto r_counter = getNewVReg();
auto r_end_addr = getNewVReg(); auto r_end_addr = getNewVReg();
auto r_current_addr = getNewVReg(); auto r_current_addr = getNewVReg();
auto r_temp_val = getNewVReg(); auto r_temp_val = getNewVReg();
// 定义一系列lambda表达式来简化指令创建
auto add_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, unsigned rs2) { auto add_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, unsigned rs2) {
auto i = std::make_unique<MachineInstr>(op); auto i = std::make_unique<MachineInstr>(op);
i->addOperand(std::make_unique<RegOperand>(rd)); i->addOperand(std::make_unique<RegOperand>(rd));
@@ -503,12 +610,14 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(i)); CurMBB->addInstruction(std::move(i));
}; };
// 生成唯一的循环标签
int unique_id = this->local_label_counter++; int unique_id = this->local_label_counter++;
std::string loop_start_label = MFunc->getName() + "_memset_loop_start_" + std::to_string(unique_id); std::string loop_start_label = MFunc->getName() + "_memset_loop_start_" + std::to_string(unique_id);
std::string loop_end_label = MFunc->getName() + "_memset_loop_end_" + std::to_string(unique_id); std::string loop_end_label = MFunc->getName() + "_memset_loop_end_" + std::to_string(unique_id);
std::string remainder_label = MFunc->getName() + "_memset_remainder_" + std::to_string(unique_id); std::string remainder_label = MFunc->getName() + "_memset_remainder_" + std::to_string(unique_id);
std::string done_label = MFunc->getName() + "_memset_done_" + std::to_string(unique_id); std::string done_label = MFunc->getName() + "_memset_done_" + std::to_string(unique_id);
// 构造64位的填充值
addi_instr(RVOpcodes::ANDI, r_temp_val, r_value_byte, 255); addi_instr(RVOpcodes::ANDI, r_temp_val, r_value_byte, 255);
addi_instr(RVOpcodes::SLLI, r_value_byte, r_temp_val, 8); addi_instr(RVOpcodes::SLLI, r_value_byte, r_temp_val, 8);
add_instr(RVOpcodes::OR, r_temp_val, r_temp_val, r_value_byte); add_instr(RVOpcodes::OR, r_temp_val, r_temp_val, r_value_byte);
@@ -516,6 +625,8 @@ void RISCv64ISel::selectNode(DAGNode* node) {
add_instr(RVOpcodes::OR, r_temp_val, r_temp_val, r_value_byte); add_instr(RVOpcodes::OR, r_temp_val, r_temp_val, r_value_byte);
addi_instr(RVOpcodes::SLLI, r_value_byte, r_temp_val, 32); addi_instr(RVOpcodes::SLLI, r_value_byte, r_temp_val, 32);
add_instr(RVOpcodes::OR, r_temp_val, r_temp_val, r_value_byte); add_instr(RVOpcodes::OR, r_temp_val, r_temp_val, r_value_byte);
// 计算循环边界
add_instr(RVOpcodes::ADD, r_end_addr, r_dest_addr, r_num_bytes); add_instr(RVOpcodes::ADD, r_end_addr, r_dest_addr, r_num_bytes);
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV); auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(r_current_addr)); mv->addOperand(std::make_unique<RegOperand>(r_current_addr));
@@ -523,17 +634,22 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(mv)); CurMBB->addInstruction(std::move(mv));
addi_instr(RVOpcodes::ANDI, r_counter, r_num_bytes, -8); addi_instr(RVOpcodes::ANDI, r_counter, r_num_bytes, -8);
add_instr(RVOpcodes::ADD, r_counter, r_dest_addr, r_counter); add_instr(RVOpcodes::ADD, r_counter, r_dest_addr, r_counter);
// 8字节主循环
label_instr(loop_start_label); label_instr(loop_start_label);
branch_instr(RVOpcodes::BGEU, r_current_addr, r_counter, loop_end_label); branch_instr(RVOpcodes::BGEU, r_current_addr, r_counter, loop_end_label);
store_instr(RVOpcodes::SD, r_temp_val, r_current_addr, 0); store_instr(RVOpcodes::SD, r_temp_val, r_current_addr, 0);
addi_instr(RVOpcodes::ADDI, r_current_addr, r_current_addr, 8); addi_instr(RVOpcodes::ADDI, r_current_addr, r_current_addr, 8);
jump_instr(loop_start_label); jump_instr(loop_start_label);
// 1字节收尾循环
label_instr(loop_end_label); label_instr(loop_end_label);
label_instr(remainder_label); label_instr(remainder_label);
branch_instr(RVOpcodes::BGEU, r_current_addr, r_end_addr, done_label); branch_instr(RVOpcodes::BGEU, r_current_addr, r_end_addr, done_label);
store_instr(RVOpcodes::SB, r_temp_val, r_current_addr, 0); store_instr(RVOpcodes::SB, r_temp_val, r_current_addr, 0);
addi_instr(RVOpcodes::ADDI, r_current_addr, r_current_addr, 1); addi_instr(RVOpcodes::ADDI, r_current_addr, r_current_addr, 1);
jump_instr(remainder_label); jump_instr(remainder_label);
label_instr(done_label); label_instr(done_label);
break; break;
} }
@@ -590,6 +706,12 @@ std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicB
memset_node->operands.push_back(get_operand_node(memset->getBegin(), value_to_node, nodes_storage)); memset_node->operands.push_back(get_operand_node(memset->getBegin(), value_to_node, nodes_storage));
memset_node->operands.push_back(get_operand_node(memset->getSize(), value_to_node, nodes_storage)); memset_node->operands.push_back(get_operand_node(memset->getSize(), value_to_node, nodes_storage));
memset_node->operands.push_back(get_operand_node(memset->getValue(), value_to_node, nodes_storage)); memset_node->operands.push_back(get_operand_node(memset->getValue(), value_to_node, nodes_storage));
if (DEBUG) {
std::cout << "[DEBUG] build_dag: Created MEMSET node for: " << memset->getName() << std::endl;
for (size_t i = 0; i < memset_node->operands.size(); ++i) {
std::cout << " -> Operand " << i << " has kind: " << memset_node->operands[i]->kind << std::endl;
}
}
} else if (auto load = dynamic_cast<LoadInst*>(inst)) { } else if (auto load = dynamic_cast<LoadInst*>(inst)) {
auto load_node = create_node(DAGNode::LOAD, load, value_to_node, nodes_storage); auto load_node = create_node(DAGNode::LOAD, load, value_to_node, nodes_storage);
load_node->operands.push_back(get_operand_node(load->getPointer(), value_to_node, nodes_storage)); load_node->operands.push_back(get_operand_node(load->getPointer(), value_to_node, nodes_storage));

View File

@@ -94,6 +94,18 @@ void RISCv64RegAlloc::eliminateFrameIndices() {
std::make_unique<RegOperand>(addr_vreg), std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0))); std::make_unique<ImmOperand>(0)));
new_instructions.push_back(std::move(sw)); new_instructions.push_back(std::move(sw));
} else if (instr_ptr->getOpcode() == RVOpcodes::FRAME_ADDR) { // [新] 处理FRAME_ADDR
auto& operands = instr_ptr->getOperands();
unsigned dest_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
int offset = frame_info.alloca_offsets.at(alloca_vreg);
// 将 `frame_addr rd, rs` 展开为 `addi rd, s0, offset`
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
addi->addOperand(std::make_unique<RegOperand>(dest_vreg));
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0)); // 基地址是帧指针 s0
addi->addOperand(std::make_unique<ImmOperand>(offset));
new_instructions.push_back(std::move(addi));
} else { } else {
new_instructions.push_back(std::move(instr_ptr)); new_instructions.push_back(std::move(instr_ptr));
} }

View File

@@ -4,20 +4,23 @@
#include "RISCv64LLIR.h" #include "RISCv64LLIR.h"
#include <iostream> #include <iostream>
extern int DEBUG;
extern int DEEPDEBUG;
namespace sysy { namespace sysy {
class RISCv64AsmPrinter { class RISCv64AsmPrinter {
public: public:
RISCv64AsmPrinter(MachineFunction* mfunc); RISCv64AsmPrinter(MachineFunction* mfunc);
// 主入口 // 主入口
void run(std::ostream& os); void run(std::ostream& os, bool debug = false);
private: private:
// 打印各个部分 // 打印各个部分
void printPrologue(); void printPrologue();
void printEpilogue(); void printEpilogue();
void printBasicBlock(MachineBasicBlock* mbb); void printBasicBlock(MachineBasicBlock* mbb, bool debug = false);
void printInstruction(MachineInstr* instr); void printInstruction(MachineInstr* instr, bool debug = false);
// 辅助函数 // 辅助函数
std::string regToString(PhysicalReg reg); std::string regToString(PhysicalReg reg);

View File

@@ -4,6 +4,9 @@
#include "IR.h" #include "IR.h"
#include <string> #include <string>
extern int DEBUG;
extern int DEEPDEBUG;
namespace sysy { namespace sysy {
// RISCv64CodeGen 现在是一个高层驱动器 // RISCv64CodeGen 现在是一个高层驱动器

View File

@@ -3,6 +3,9 @@
#include "RISCv64LLIR.h" #include "RISCv64LLIR.h"
extern int DEBUG;
extern int DEEPDEBUG;
namespace sysy { namespace sysy {
class RISCv64ISel { class RISCv64ISel {

View File

@@ -46,6 +46,7 @@ enum class RVOpcodes {
// 新增伪指令,用于解耦栈帧处理 // 新增伪指令,用于解耦栈帧处理
FRAME_LOAD, // 从栈帧加载 (AllocaInst) FRAME_LOAD, // 从栈帧加载 (AllocaInst)
FRAME_STORE, // 保存到栈帧 (AllocaInst) FRAME_STORE, // 保存到栈帧 (AllocaInst)
FRAME_ADDR, // [新] 获取栈帧变量的地址
}; };
class MachineOperand; class MachineOperand;

View File

@@ -218,7 +218,7 @@ int main(int argc, char **argv) {
// 设置 DEBUG 模式(如果指定了 'asmd' // 设置 DEBUG 模式(如果指定了 'asmd'
if (argStopAfter == "asmd") { if (argStopAfter == "asmd") {
DEBUG = 1; DEBUG = 1;
// DEEPDEBUG = 1; DEEPDEBUG = 1;
} }
sysy::RISCv64CodeGen codegen(moduleIR); // 传入优化后的 moduleIR sysy::RISCv64CodeGen codegen(moduleIR); // 传入优化后的 moduleIR
string asmCode = codegen.code_gen(); string asmCode = codegen.code_gen();