diff --git a/src/RISCv64ISel.cpp b/src/RISCv64ISel.cpp index f8a1e8e..2ab47b5 100644 --- a/src/RISCv64ISel.cpp +++ b/src/RISCv64ISel.cpp @@ -83,6 +83,10 @@ void RISCv64ISel::selectBasicBlock(BasicBlock* bb) { CurMBB = bb_map.at(bb); auto dag = build_dag(bb); + if (DEBUG) { // 使用 DEBUG 宏或变量来控制是否打印 + print_dag(dag, bb->getName()); + } + std::map value_to_node; for(const auto& node : dag) { if (node->value) { @@ -486,7 +490,9 @@ void RISCv64ISel::selectNode(DAGNode* node) { case DAGNode::CALL: { auto call = dynamic_cast(node->value); // 处理函数参数,放入a0-a7物理寄存器 - for (size_t i = 0; i < node->operands.size() && i < 8; ++i) { + size_t num_operands = node->operands.size(); + size_t reg_arg_count = std::min(num_operands, (size_t)8); + for (size_t i = 0; i < reg_arg_count; ++i) { DAGNode* arg_node = node->operands[i]; auto arg_preg = static_cast(static_cast(PhysicalReg::A0) + i); @@ -505,11 +511,63 @@ void RISCv64ISel::selectNode(DAGNode* node) { CurMBB->addInstruction(std::move(mv)); } } + if (num_operands > 8) { + size_t stack_arg_count = num_operands - 8; + int stack_space = stack_arg_count * 8; // RV64中每个参数槽位8字节 + + // 2a. 在栈上分配空间 + auto alloc_instr = std::make_unique(RVOpcodes::ADDI); + alloc_instr->addOperand(std::make_unique(PhysicalReg::SP)); + alloc_instr->addOperand(std::make_unique(PhysicalReg::SP)); + alloc_instr->addOperand(std::make_unique(-stack_space)); + CurMBB->addInstruction(std::move(alloc_instr)); + + // 2b. 存储每个栈参数 + for (size_t i = 8; i < num_operands; ++i) { + DAGNode* arg_node = node->operands[i]; + unsigned src_vreg; + + // 准备源寄存器 + if (arg_node->kind == DAGNode::CONSTANT) { + // 如果是常量,先加载到临时寄存器 + src_vreg = getNewVReg(); + auto const_val = dynamic_cast(arg_node->value); + auto li = std::make_unique(RVOpcodes::LI); + li->addOperand(std::make_unique(src_vreg)); + li->addOperand(std::make_unique(const_val->getInt())); + CurMBB->addInstruction(std::move(li)); + } else { + src_vreg = getVReg(arg_node->value); + } + + // 计算在栈上的偏移量 + int offset = (i - 8) * 8; + + // 生成 sd 指令 + auto sd_instr = std::make_unique(RVOpcodes::SD); + sd_instr->addOperand(std::make_unique(src_vreg)); + sd_instr->addOperand(std::make_unique( + std::make_unique(PhysicalReg::SP), + std::make_unique(offset) + )); + CurMBB->addInstruction(std::move(sd_instr)); + } + } auto call_instr = std::make_unique(RVOpcodes::CALL); call_instr->addOperand(std::make_unique(call->getCallee()->getName())); CurMBB->addInstruction(std::move(call_instr)); + if (num_operands > 8) { + size_t stack_arg_count = num_operands - 8; + int stack_space = stack_arg_count * 8; + + auto dealloc_instr = std::make_unique(RVOpcodes::ADDI); + dealloc_instr->addOperand(std::make_unique(PhysicalReg::SP)); + dealloc_instr->addOperand(std::make_unique(PhysicalReg::SP)); + dealloc_instr->addOperand(std::make_unique(stack_space)); + CurMBB->addInstruction(std::move(dealloc_instr)); + } // 处理返回值,从a0移动到目标虚拟寄存器 if (!call->getType()->isVoid()) { auto mv_instr = std::make_unique(RVOpcodes::MV); @@ -545,33 +603,59 @@ void RISCv64ISel::selectNode(DAGNode* node) { } case DAGNode::BRANCH: { - if (auto cond_br = dynamic_cast(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(); + // 处理条件分支 + if (auto cond_br = dynamic_cast(node->value)) { + Value* condition = cond_br->getCondition(); + auto then_bb_name = cond_br->getThenBlock()->getName(); + auto else_bb_name = cond_br->getElseBlock()->getName(); + + // [优化] 检查分支条件是否为编译期常量 + if (auto const_cond = dynamic_cast(condition)) { + // 如果条件是常量,直接生成一个无条件跳转J,而不是BNE + if (const_cond->getInt() != 0) { // 条件为 true + auto j_instr = std::make_unique(RVOpcodes::J); + j_instr->addOperand(std::make_unique(then_bb_name)); + CurMBB->addInstruction(std::move(j_instr)); + } else { // 条件为 false + auto j_instr = std::make_unique(RVOpcodes::J); + j_instr->addOperand(std::make_unique(else_bb_name)); + CurMBB->addInstruction(std::move(j_instr)); + } + } + // 如果条件不是常量,则执行标准流程 + else { + // [修复] 为条件变量生成加载指令(如果它是常量的话,尽管上面已经处理了) + // 这一步是为了逻辑完整,以防有其他类型的常量没有被捕获 + if (auto const_val = dynamic_cast(condition)) { + auto li = std::make_unique(RVOpcodes::LI); + li->addOperand(std::make_unique(getVReg(const_val))); + li->addOperand(std::make_unique(const_val->getInt())); + CurMBB->addInstruction(std::move(li)); + } + + auto cond_vreg = getVReg(condition); - // bne cond, zero, then_label (如果cond不为0,则跳转到then) + // 生成 bne cond, zero, then_label (如果cond不为0,则跳转到then) auto br_instr = std::make_unique(RVOpcodes::BNE); br_instr->addOperand(std::make_unique(cond_vreg)); br_instr->addOperand(std::make_unique(PhysicalReg::ZERO)); br_instr->addOperand(std::make_unique(then_bb_name)); CurMBB->addInstruction(std::move(br_instr)); - // 无条件跳转到else块 (如果上面分支未发生) - // 注意:在实际的CFG中,这个J指令可能不是必须的, - // 因为else块可能是下一个块。但为了通用性,这里生成它。 + // 为else分支生成无条件跳转 (后续Pass可以优化掉不必要的跳转) auto j_instr = std::make_unique(RVOpcodes::J); j_instr->addOperand(std::make_unique(else_bb_name)); CurMBB->addInstruction(std::move(j_instr)); - - } else if (auto uncond_br = dynamic_cast(node->value)) { - auto j_instr = std::make_unique(RVOpcodes::J); - j_instr->addOperand(std::make_unique(uncond_br->getBlock()->getName())); - CurMBB->addInstruction(std::move(j_instr)); } - break; + } + // 处理无条件分支 + else if (auto uncond_br = dynamic_cast(node->value)) { + auto j_instr = std::make_unique(RVOpcodes::J); + j_instr->addOperand(std::make_unique(uncond_br->getBlock()->getName())); + CurMBB->addInstruction(std::move(j_instr)); } + break; + } case DAGNode::MEMSET: { // [V1设计保留] Memset的核心展开逻辑在虚拟寄存器层面是正确的,无需修改。 @@ -808,4 +892,98 @@ std::vector> RISCv64ISel::build_dag(BasicB return nodes_storage; } +// [新] 打印DAG图以供调试的辅助函数 +void RISCv64ISel::print_dag(const std::vector>& dag, const std::string& bb_name) { + // 检查是否有DEBUG宏或者全局变量,避免在非调试模式下打印 + // if (!DEBUG) return; + + std::cerr << "=== DAG for Basic Block: " << bb_name << " ===\n"; + std::set visited; + + // 为节点分配临时ID,方便阅读 + std::map node_to_id; + int current_id = 0; + for (const auto& node_ptr : dag) { + node_to_id[node_ptr.get()] = current_id++; + } + + // 将NodeKind枚举转换为字符串的辅助函数 + auto get_kind_string = [](DAGNode::NodeKind kind) { + switch (kind) { + case DAGNode::CONSTANT: return "CONSTANT"; + case DAGNode::LOAD: return "LOAD"; + case DAGNode::STORE: return "STORE"; + case DAGNode::BINARY: return "BINARY"; + case DAGNode::CALL: return "CALL"; + case DAGNode::RETURN: return "RETURN"; + case DAGNode::BRANCH: return "BRANCH"; + case DAGNode::ALLOCA_ADDR: return "ALLOCA_ADDR"; + case DAGNode::UNARY: return "UNARY"; + case DAGNode::MEMSET: return "MEMSET"; + default: return "UNKNOWN"; + } + }; + + // 递归打印节点的lambda表达式 + std::function print_node = + [&](DAGNode* node, int indent) { + if (!node) return; + + std::string current_indent(indent, ' '); + int node_id = node_to_id.count(node) ? node_to_id[node] : -1; + + std::cerr << current_indent << "Node#" << node_id << ": " << get_kind_string(node->kind); + + // 尝试打印关联的虚拟寄存器 + if (node->value && vreg_map.count(node->value)) { + std::cerr << " (vreg: %vreg" << vreg_map.at(node->value) << ")"; + } + + // 打印关联的IR Value信息 + if (node->value) { + std::cerr << " ["; + if (auto inst = dynamic_cast(node->value)) { + std::cerr << inst->getKindString(); + if (!inst->getName().empty()) { + std::cerr << "(" << inst->getName() << ")"; + } + } else if (auto constant = dynamic_cast(node->value)) { + std::cerr << "Const(" << constant->getInt() << ")"; + } else if (auto global = dynamic_cast(node->value)) { + std::cerr << "Global(" << global->getName() << ")"; + } else if (auto alloca = dynamic_cast(node->value)) { + std::cerr << "Alloca(" << alloca->getName() << ")"; + } + std::cerr << "]"; + } + std::cerr << "\n"; + + if (visited.count(node)) { + std::cerr << current_indent << " (已打印过子节点)\n"; + return; + } + visited.insert(node); + + if (!node->operands.empty()) { + std::cerr << current_indent << " Operands:\n"; + for (auto operand : node->operands) { + print_node(operand, indent + 4); + } + } + }; + + // 从根节点(没有用户的节点,或有副作用的节点)开始打印 + for (const auto& node_ptr : dag) { + if (node_ptr->users.empty() || + node_ptr->kind == DAGNode::STORE || + node_ptr->kind == DAGNode::RETURN || + node_ptr->kind == DAGNode::BRANCH || + node_ptr->kind == DAGNode::MEMSET) + { + print_node(node_ptr.get(), 0); + } + } + std::cerr << "======================================\n\n"; +} + } // namespace sysy \ No newline at end of file diff --git a/src/include/RISCv64ISel.h b/src/include/RISCv64ISel.h index 6c5e421..0bb977a 100644 --- a/src/include/RISCv64ISel.h +++ b/src/include/RISCv64ISel.h @@ -34,6 +34,8 @@ private: DAGNode* get_operand_node(Value* val_ir, std::map&, std::vector>&); DAGNode* create_node(int kind, Value* val, std::map&, std::vector>&); + void print_dag(const std::vector>& dag, const std::string& bb_name); + // 状态 Function* F; // 当前处理的高层IR函数 std::unique_ptr MFunc; // 正在构建的底层LLIR函数