[backend]解决了重构后数组初始化不正确的问题
This commit is contained in:
@@ -18,7 +18,7 @@ bool isMemoryOp(RVOpcodes opcode) {
|
||||
|
||||
RISCv64AsmPrinter::RISCv64AsmPrinter(MachineFunction* mfunc) : MFunc(mfunc) {}
|
||||
|
||||
void RISCv64AsmPrinter::run(std::ostream& os) {
|
||||
void RISCv64AsmPrinter::run(std::ostream& os, bool debug) {
|
||||
OS = &os;
|
||||
|
||||
*OS << ".globl " << MFunc->getName() << "\n";
|
||||
@@ -27,7 +27,7 @@ void RISCv64AsmPrinter::run(std::ostream& os) {
|
||||
printPrologue();
|
||||
|
||||
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()) {
|
||||
*OS << mbb->getName() << ":\n";
|
||||
}
|
||||
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();
|
||||
if (opcode == RVOpcodes::RET) {
|
||||
printEpilogue();
|
||||
@@ -137,9 +137,17 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr) {
|
||||
// *OS << ":";
|
||||
break;
|
||||
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:
|
||||
// These should have been eliminated by RegAlloc
|
||||
throw std::runtime_error("FRAME pseudo-instruction not eliminated before AsmPrinter");
|
||||
// It should have been eliminated by RegAlloc
|
||||
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:
|
||||
throw std::runtime_error("Unknown opcode in AsmPrinter");
|
||||
}
|
||||
|
||||
@@ -61,6 +61,10 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
|
||||
RISCv64ISel isel;
|
||||
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
|
||||
|
||||
std::stringstream ss1;
|
||||
RISCv64AsmPrinter printer1(mfunc.get());
|
||||
printer1.run(ss1, true);
|
||||
|
||||
// 阶段 2: 指令调度 (Instruction Scheduling)
|
||||
PreRA_Scheduler scheduler;
|
||||
scheduler.runOnMachineFunction(mfunc.get());
|
||||
@@ -81,7 +85,7 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
|
||||
std::stringstream ss;
|
||||
RISCv64AsmPrinter printer(mfunc.get());
|
||||
printer.run(ss);
|
||||
|
||||
if (DEBUG) ss << ss1.str(); // 将指令选择阶段的结果也包含在最终输出中
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <functional>
|
||||
#include <cmath> // For std::fabs
|
||||
#include <limits> // For std::numeric_limits
|
||||
#include <iostream>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
@@ -92,6 +93,10 @@ void RISCv64ISel::selectBasicBlock(BasicBlock* bb) {
|
||||
std::set<DAGNode*> selected_nodes;
|
||||
std::function<void(DAGNode*)> select_recursive =
|
||||
[&](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;
|
||||
for (auto operand : node->operands) {
|
||||
select_recursive(operand);
|
||||
@@ -118,24 +123,37 @@ void RISCv64ISel::selectBasicBlock(BasicBlock* bb) {
|
||||
}
|
||||
}
|
||||
|
||||
// 核心函数:为DAG节点选择并生成MachineInstr (忠实移植版)
|
||||
// 核心函数:为DAG节点选择并生成MachineInstr (已修复和增强的完整版本)
|
||||
void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
// 调用者(select_recursive)已经保证了操作数节点会先于当前节点被选择。
|
||||
// 因此,这里我们只处理当前节点。
|
||||
|
||||
switch (node->kind) {
|
||||
// [V2优点] 采纳“延迟物化”(Late Materialization)思想。
|
||||
// 这两个节点仅作为标记,不直接生成指令。它们的目的是在DAG中保留类型信息。
|
||||
// 加载其值的责任,被转移给了使用它们的父节点(如STORE, BINARY等)。
|
||||
// 这修复了之前版本中“使用未初始化虚拟寄存器”的根本性bug。
|
||||
case DAGNode::CONSTANT:
|
||||
case DAGNode::ALLOCA_ADDR:
|
||||
if (node->value) getVReg(node->value);
|
||||
if (node->value) {
|
||||
// 确保它有一个关联的虚拟寄存器即可,不生成代码。
|
||||
getVReg(node->value);
|
||||
}
|
||||
break;
|
||||
|
||||
case DAGNode::LOAD: {
|
||||
auto dest_vreg = getVReg(node->value);
|
||||
Value* ptr_val = node->operands[0]->value;
|
||||
|
||||
// [V1设计保留] 对于从栈变量加载,继续使用伪指令 FRAME_LOAD。
|
||||
// 这种设计将栈帧布局的具体计算推迟到后续的 `eliminateFrameIndices` 阶段,保持了模块化。
|
||||
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_LOAD);
|
||||
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 加载其值。
|
||||
auto addr_vreg = getNewVReg();
|
||||
auto la = std::make_unique<MachineInstr>(RVOpcodes::LA);
|
||||
la->addOperand(std::make_unique<RegOperand>(addr_vreg));
|
||||
@@ -150,6 +168,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
));
|
||||
CurMBB->addInstruction(std::move(lw));
|
||||
} else {
|
||||
// 对于已经在虚拟寄存器中的指针地址,直接通过该地址加载。
|
||||
auto ptr_vreg = getVReg(ptr_val);
|
||||
auto lw = std::make_unique<MachineInstr>(RVOpcodes::LW);
|
||||
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* ptr_val = node->operands[1]->value;
|
||||
|
||||
// [V2优点] 在STORE节点内部负责加载作为源的常量。
|
||||
// 如果要存储的值是一个常量,就在这里生成 `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()));
|
||||
@@ -174,13 +199,15 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
}
|
||||
auto val_vreg = getVReg(val_to_store);
|
||||
|
||||
// [V1设计保留] 同样,对于向栈变量的存储,使用 FRAME_STORE 伪指令。
|
||||
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_STORE);
|
||||
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 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()));
|
||||
@@ -194,6 +221,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
));
|
||||
CurMBB->addInstruction(std::move(sw));
|
||||
} else {
|
||||
// 向一个指针(存储在虚拟寄存器中)指向的地址存储。
|
||||
auto ptr_vreg = getVReg(ptr_val);
|
||||
auto sw = std::make_unique<MachineInstr>(RVOpcodes::SW);
|
||||
sw->addOperand(std::make_unique<RegOperand>(val_vreg));
|
||||
@@ -211,36 +239,53 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
Value* lhs = bin->getLhs();
|
||||
Value* rhs = bin->getRhs();
|
||||
|
||||
// [V2优点] 在BINARY节点内部按需加载常量操作数。
|
||||
auto load_val_if_const = [&](Value* 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);
|
||||
li->addOperand(std::make_unique<RegOperand>(getVReg(c)));
|
||||
li->addOperand(std::make_unique<ImmOperand>(c->getInt()));
|
||||
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);
|
||||
auto rhs_vreg = getVReg(rhs);
|
||||
|
||||
if (bin->getKind() == BinaryInst::kAdd) {
|
||||
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;
|
||||
}
|
||||
// 检查是否能应用立即数优化。
|
||||
bool rhs_is_imm_opt = false;
|
||||
if (auto rhs_const = dynamic_cast<ConstantValue*>(rhs)) {
|
||||
if (bin->getKind() == BinaryInst::kAdd && rhs_const->getInt() >= -2048 && rhs_const->getInt() < 2048) {
|
||||
rhs_is_imm_opt = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 仅在不能作为立即数操作数时才需要提前加载。
|
||||
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()) {
|
||||
case BinaryInst::kAdd: {
|
||||
// 区分指针运算(64位)和整数运算(32位)。
|
||||
RVOpcodes opcode = (lhs->getType()->isPointer() || rhs->getType()->isPointer()) ? RVOpcodes::ADD : RVOpcodes::ADDW;
|
||||
auto instr = std::make_unique<MachineInstr>(opcode);
|
||||
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
@@ -281,7 +326,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
CurMBB->addInstruction(std::move(instr));
|
||||
break;
|
||||
}
|
||||
case BinaryInst::kICmpEQ: {
|
||||
case BinaryInst::kICmpEQ: { // 等于 (a == b) -> (subw; seqz)
|
||||
auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
|
||||
sub->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
sub->addOperand(std::make_unique<RegOperand>(lhs_vreg));
|
||||
@@ -294,7 +339,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
CurMBB->addInstruction(std::move(seqz));
|
||||
break;
|
||||
}
|
||||
case BinaryInst::kICmpNE: {
|
||||
case BinaryInst::kICmpNE: { // 不等于 (a != b) -> (subw; snez)
|
||||
auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
|
||||
sub->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
sub->addOperand(std::make_unique<RegOperand>(lhs_vreg));
|
||||
@@ -307,7 +352,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
CurMBB->addInstruction(std::move(snez));
|
||||
break;
|
||||
}
|
||||
case BinaryInst::kICmpLT: {
|
||||
case BinaryInst::kICmpLT: { // 小于 (a < b) -> slt
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SLT);
|
||||
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
|
||||
@@ -315,7 +360,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
CurMBB->addInstruction(std::move(instr));
|
||||
break;
|
||||
}
|
||||
case BinaryInst::kICmpGT: {
|
||||
case BinaryInst::kICmpGT: { // 大于 (a > b) -> (b < a) -> slt
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SLT);
|
||||
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
|
||||
@@ -323,7 +368,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
CurMBB->addInstruction(std::move(instr));
|
||||
break;
|
||||
}
|
||||
case BinaryInst::kICmpLE: {
|
||||
case BinaryInst::kICmpLE: { // 小于等于 (a <= b) -> !(b < a) -> (slt; xori)
|
||||
auto slt = std::make_unique<MachineInstr>(RVOpcodes::SLT);
|
||||
slt->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
slt->addOperand(std::make_unique<RegOperand>(rhs_vreg));
|
||||
@@ -337,7 +382,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
CurMBB->addInstruction(std::move(xori));
|
||||
break;
|
||||
}
|
||||
case BinaryInst::kICmpGE: {
|
||||
case BinaryInst::kICmpGE: { // 大于等于 (a >= b) -> !(a < b) -> (slt; xori)
|
||||
auto slt = std::make_unique<MachineInstr>(RVOpcodes::SLT);
|
||||
slt->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
slt->addOperand(std::make_unique<RegOperand>(lhs_vreg));
|
||||
@@ -363,7 +408,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
auto src_vreg = getVReg(unary->getOperand());
|
||||
|
||||
switch (unary->getKind()) {
|
||||
case UnaryInst::kNeg: {
|
||||
case UnaryInst::kNeg: { // 取负: 0 - src
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
|
||||
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
|
||||
@@ -371,7 +416,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
CurMBB->addInstruction(std::move(instr));
|
||||
break;
|
||||
}
|
||||
case UnaryInst::kNot: {
|
||||
case UnaryInst::kNot: { // 逻辑非: src == 0 ? 1 : 0
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SEQZ);
|
||||
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
instr->addOperand(std::make_unique<RegOperand>(src_vreg));
|
||||
@@ -386,6 +431,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
|
||||
case DAGNode::CALL: {
|
||||
auto call = dynamic_cast<CallInst*>(node->value);
|
||||
// 处理函数参数,放入a0-a7物理寄存器
|
||||
for (size_t i = 0; i < node->operands.size() && i < 8; ++i) {
|
||||
DAGNode* arg_node = node->operands[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);
|
||||
call_instr->addOperand(std::make_unique<LabelOperand>(call->getCallee()->getName()));
|
||||
CurMBB->addInstruction(std::move(call_instr));
|
||||
|
||||
|
||||
// 处理返回值,从a0移动到目标虚拟寄存器
|
||||
if (!call->getType()->isVoid()) {
|
||||
auto mv_instr = std::make_unique<MachineInstr>(RVOpcodes::MV);
|
||||
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);
|
||||
if (ret_inst_ir && ret_inst_ir->hasReturnValue()) {
|
||||
Value* ret_val = ret_inst_ir->getReturnValue();
|
||||
// [V2优点] 在RETURN节点内加载常量返回值
|
||||
if (auto const_val = dynamic_cast<ConstantValue*>(ret_val)) {
|
||||
auto li_instr = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
||||
li_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
|
||||
@@ -435,6 +483,8 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
CurMBB->addInstruction(std::move(mv_instr));
|
||||
}
|
||||
}
|
||||
// [V1设计保留] 函数尾声(epilogue)不由RETURN节点生成,
|
||||
// 而是由后续的AsmPrinter或其它Pass统一处理,这是一种常见且有效的模块化设计。
|
||||
auto ret_mi = std::make_unique<MachineInstr>(RVOpcodes::RET);
|
||||
CurMBB->addInstruction(std::move(ret_mi));
|
||||
break;
|
||||
@@ -442,11 +492,25 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
|
||||
case DAGNode::BRANCH: {
|
||||
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);
|
||||
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<LabelOperand>(cond_br->getThenBlock()->getName()));
|
||||
br_instr->addOperand(std::make_unique<LabelOperand>(then_bb_name));
|
||||
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)) {
|
||||
auto j_instr = std::make_unique<MachineInstr>(RVOpcodes::J);
|
||||
j_instr->addOperand(std::make_unique<LabelOperand>(uncond_br->getBlock()->getName()));
|
||||
@@ -456,15 +520,58 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
}
|
||||
|
||||
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);
|
||||
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_num_bytes = getVReg(memset->getSize());
|
||||
auto r_value_byte = getVReg(memset->getValue());
|
||||
|
||||
// 为memset内部逻辑创建新的临时虚拟寄存器
|
||||
auto r_counter = getNewVReg();
|
||||
auto r_end_addr = getNewVReg();
|
||||
auto r_current_addr = getNewVReg();
|
||||
auto r_temp_val = getNewVReg();
|
||||
|
||||
// 定义一系列lambda表达式来简化指令创建
|
||||
auto add_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, unsigned rs2) {
|
||||
auto i = std::make_unique<MachineInstr>(op);
|
||||
i->addOperand(std::make_unique<RegOperand>(rd));
|
||||
@@ -503,12 +610,14 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
CurMBB->addInstruction(std::move(i));
|
||||
};
|
||||
|
||||
// 生成唯一的循环标签
|
||||
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_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 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::SLLI, r_value_byte, r_temp_val, 8);
|
||||
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);
|
||||
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::ADD, r_end_addr, r_dest_addr, r_num_bytes);
|
||||
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
|
||||
mv->addOperand(std::make_unique<RegOperand>(r_current_addr));
|
||||
@@ -523,17 +634,22 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
CurMBB->addInstruction(std::move(mv));
|
||||
addi_instr(RVOpcodes::ANDI, r_counter, r_num_bytes, -8);
|
||||
add_instr(RVOpcodes::ADD, r_counter, r_dest_addr, r_counter);
|
||||
|
||||
// 8字节主循环
|
||||
label_instr(loop_start_label);
|
||||
branch_instr(RVOpcodes::BGEU, r_current_addr, r_counter, loop_end_label);
|
||||
store_instr(RVOpcodes::SD, r_temp_val, r_current_addr, 0);
|
||||
addi_instr(RVOpcodes::ADDI, r_current_addr, r_current_addr, 8);
|
||||
jump_instr(loop_start_label);
|
||||
|
||||
// 1字节收尾循环
|
||||
label_instr(loop_end_label);
|
||||
label_instr(remainder_label);
|
||||
branch_instr(RVOpcodes::BGEU, r_current_addr, r_end_addr, done_label);
|
||||
store_instr(RVOpcodes::SB, r_temp_val, r_current_addr, 0);
|
||||
addi_instr(RVOpcodes::ADDI, r_current_addr, r_current_addr, 1);
|
||||
jump_instr(remainder_label);
|
||||
|
||||
label_instr(done_label);
|
||||
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->getSize(), 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)) {
|
||||
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));
|
||||
|
||||
@@ -94,6 +94,18 @@ void RISCv64RegAlloc::eliminateFrameIndices() {
|
||||
std::make_unique<RegOperand>(addr_vreg),
|
||||
std::make_unique<ImmOperand>(0)));
|
||||
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 {
|
||||
new_instructions.push_back(std::move(instr_ptr));
|
||||
}
|
||||
|
||||
@@ -4,20 +4,23 @@
|
||||
#include "RISCv64LLIR.h"
|
||||
#include <iostream>
|
||||
|
||||
extern int DEBUG;
|
||||
extern int DEEPDEBUG;
|
||||
|
||||
namespace sysy {
|
||||
|
||||
class RISCv64AsmPrinter {
|
||||
public:
|
||||
RISCv64AsmPrinter(MachineFunction* mfunc);
|
||||
// 主入口
|
||||
void run(std::ostream& os);
|
||||
void run(std::ostream& os, bool debug = false);
|
||||
|
||||
private:
|
||||
// 打印各个部分
|
||||
void printPrologue();
|
||||
void printEpilogue();
|
||||
void printBasicBlock(MachineBasicBlock* mbb);
|
||||
void printInstruction(MachineInstr* instr);
|
||||
void printBasicBlock(MachineBasicBlock* mbb, bool debug = false);
|
||||
void printInstruction(MachineInstr* instr, bool debug = false);
|
||||
|
||||
// 辅助函数
|
||||
std::string regToString(PhysicalReg reg);
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
#include "IR.h"
|
||||
#include <string>
|
||||
|
||||
extern int DEBUG;
|
||||
extern int DEEPDEBUG;
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// RISCv64CodeGen 现在是一个高层驱动器
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
#include "RISCv64LLIR.h"
|
||||
|
||||
extern int DEBUG;
|
||||
extern int DEEPDEBUG;
|
||||
|
||||
namespace sysy {
|
||||
|
||||
class RISCv64ISel {
|
||||
|
||||
@@ -46,6 +46,7 @@ enum class RVOpcodes {
|
||||
// 新增伪指令,用于解耦栈帧处理
|
||||
FRAME_LOAD, // 从栈帧加载 (AllocaInst)
|
||||
FRAME_STORE, // 保存到栈帧 (AllocaInst)
|
||||
FRAME_ADDR, // [新] 获取栈帧变量的地址
|
||||
};
|
||||
|
||||
class MachineOperand;
|
||||
|
||||
@@ -218,7 +218,7 @@ int main(int argc, char **argv) {
|
||||
// 设置 DEBUG 模式(如果指定了 'asmd')
|
||||
if (argStopAfter == "asmd") {
|
||||
DEBUG = 1;
|
||||
// DEEPDEBUG = 1;
|
||||
DEEPDEBUG = 1;
|
||||
}
|
||||
sysy::RISCv64CodeGen codegen(moduleIR); // 传入优化后的 moduleIR
|
||||
string asmCode = codegen.code_gen();
|
||||
|
||||
Reference in New Issue
Block a user