diff --git a/src/backend/RISCv64/RISCv64ISel.cpp b/src/backend/RISCv64/RISCv64ISel.cpp index b5686ca..49ce60d 100644 --- a/src/backend/RISCv64/RISCv64ISel.cpp +++ b/src/backend/RISCv64/RISCv64ISel.cpp @@ -48,10 +48,17 @@ unsigned RISCv64ISel::getVReg(Value* val) { unsigned new_vreg = vreg_counter++; vreg_map[val] = new_vreg; vreg_to_value_map[new_vreg] = val; + vreg_type_map[new_vreg] = val->getType(); } return vreg_map.at(val); } +unsigned RISCv64ISel::getNewVReg(Type* type) { + unsigned new_vreg = vreg_counter++; + vreg_type_map[new_vreg] = type; // 记录这个新vreg的类型 + return new_vreg; +} + // 主入口函数 std::unique_ptr RISCv64ISel::runOnFunction(Function* func) { F = func; @@ -185,7 +192,7 @@ void RISCv64ISel::selectNode(DAGNode* node) { // 2. 使用 fmv.w.x 指令将位模式从整数寄存器移动到浮点寄存器 auto const_val = dynamic_cast(node->value); auto float_vreg = getVReg(const_val); - auto temp_int_vreg = getNewVReg(); // 临时整数虚拟寄存器 + auto temp_int_vreg = getNewVReg(Type::getIntType()); // 临时整数虚拟寄存器 float f_val = const_val->getFloat(); // 使用 reinterpret_cast 获取浮点数的32位二进制表示 @@ -235,7 +242,7 @@ void RISCv64ISel::selectNode(DAGNode* node) { } else if (auto global = dynamic_cast(ptr_val)) { // 对于全局变量,先用 la 加载其地址 - auto addr_vreg = getNewVReg(); + auto addr_vreg = getNewVReg(Type::getPointerType(global->getType())); auto la = std::make_unique(RVOpcodes::LA); la->addOperand(std::make_unique(addr_vreg)); la->addOperand(std::make_unique(global->getName())); @@ -280,7 +287,7 @@ void RISCv64ISel::selectNode(DAGNode* node) { CurMBB->addInstruction(std::move(li)); } else if (val_const->isFloat()) { // 先将浮点数的位模式加载到整数vreg,再用fmv.w.x移到浮点vreg - auto temp_int_vreg = getNewVReg(); + auto temp_int_vreg = getNewVReg(Type::getIntType()); auto float_vreg = getVReg(val_const); float f_val = val_const->getFloat(); @@ -327,7 +334,7 @@ void RISCv64ISel::selectNode(DAGNode* node) { } else if (auto global = dynamic_cast(ptr_val)) { // 向全局变量存储 - auto addr_vreg = getNewVReg(); + auto addr_vreg = getNewVReg(Type::getIntType()); auto la = std::make_unique(RVOpcodes::LA); la->addOperand(std::make_unique(addr_vreg)); la->addOperand(std::make_unique(global->getName())); @@ -387,7 +394,7 @@ void RISCv64ISel::selectNode(DAGNode* node) { } // 2. [修改] 根据基地址的类型,生成不同的指令来获取基地址 - auto base_addr_vreg = getNewVReg(); // 创建一个新的临时vreg来存放基地址 + auto base_addr_vreg = getNewVReg(Type::getIntType()); // 创建一个新的临时vreg来存放基地址 // 情况一:基地址是局部栈变量 if (auto alloca_base = dynamic_cast(base)) { @@ -760,107 +767,195 @@ void RISCv64ISel::selectNode(DAGNode* node) { case DAGNode::CALL: { auto call = dynamic_cast(node->value); - // 处理函数参数,放入a0-a7物理寄存器 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); - if (arg_node->kind == DAGNode::CONSTANT) { - if (auto const_val = dynamic_cast(arg_node->value)) { - auto li = std::make_unique(RVOpcodes::LI); - li->addOperand(std::make_unique(arg_preg)); - li->addOperand(std::make_unique(const_val->getInt())); - CurMBB->addInstruction(std::move(li)); + // --- 步骤 1: 分配寄存器参数和栈参数 --- + // 根据RISC-V调用约定,前8个整数/指针参数通过a0-a7传递, + // 前8个浮点参数通过fa0-fa7传递 (物理寄存器 f10-f17)。其余参数通过栈传递。 + + int int_reg_idx = 0; // a0-a7 的索引 + int fp_reg_idx = 0; // fa0-fa7 的索引 + + // 用于存储需要通过栈传递的参数 + std::vector stack_args; + + for (size_t i = 0; i < num_operands; ++i) { + DAGNode* arg_node = node->operands[i]; + Value* arg_val = arg_node->value; + Type* arg_type = arg_val->getType(); + + // 判断参数是浮点类型还是整型/指针类型 + if (arg_type->isFloat()) { + if (fp_reg_idx < 8) { + // --- 处理浮点寄存器参数 (fa0-fa7, 对应物理寄存器 F10-F17) --- + auto arg_preg = static_cast(static_cast(PhysicalReg::F10) + fp_reg_idx); + fp_reg_idx++; + + if (auto const_val = dynamic_cast(arg_val)) { + // 如果是浮点常量,需要先物化 + // 1. 获取其32位二进制表示 + float f_val = const_val->getFloat(); + uint32_t float_bits = *reinterpret_cast(&f_val); + // 2. 将位模式加载到一个临时整数寄存器 (使用t0) + auto li = std::make_unique(RVOpcodes::LI); + li->addOperand(std::make_unique(PhysicalReg::T0)); + li->addOperand(std::make_unique(float_bits)); + CurMBB->addInstruction(std::move(li)); + // 3. 使用fmv.w.x将位模式从整数寄存器移动到目标浮点参数寄存器 + auto fmv_wx = std::make_unique(RVOpcodes::FMV_W_X); + fmv_wx->addOperand(std::make_unique(arg_preg)); + fmv_wx->addOperand(std::make_unique(PhysicalReg::T0)); + CurMBB->addInstruction(std::move(fmv_wx)); + } else { + // 如果已经是虚拟寄存器,直接用 fmv.s 移动 + auto src_vreg = getVReg(arg_val); + auto fmv_s = std::make_unique(RVOpcodes::FMV_S); + fmv_s->addOperand(std::make_unique(arg_preg)); + fmv_s->addOperand(std::make_unique(src_vreg)); + CurMBB->addInstruction(std::move(fmv_s)); + } + } else { + // 浮点寄存器已用完,放到栈上传递 + stack_args.push_back(arg_node); + } + } else { // 整数或指针参数 + if (int_reg_idx < 8) { + // --- 处理整数/指针寄存器参数 (a0-a7) --- + auto arg_preg = static_cast(static_cast(PhysicalReg::A0) + int_reg_idx); + int_reg_idx++; + + if (arg_node->kind == DAGNode::CONSTANT) { + if (auto const_val = dynamic_cast(arg_val)) { + auto li = std::make_unique(RVOpcodes::LI); + li->addOperand(std::make_unique(arg_preg)); + li->addOperand(std::make_unique(const_val->getInt())); + CurMBB->addInstruction(std::move(li)); + } + } else { + auto src_vreg = getVReg(arg_val); + auto mv = std::make_unique(RVOpcodes::MV); + mv->addOperand(std::make_unique(arg_preg)); + mv->addOperand(std::make_unique(src_vreg)); + CurMBB->addInstruction(std::move(mv)); + } + } else { + // 整数寄存器已用完,放到栈上传递 + stack_args.push_back(arg_node); } - } else { - auto src_vreg = getVReg(arg_node->value); - auto mv = std::make_unique(RVOpcodes::MV); - mv->addOperand(std::make_unique(arg_preg)); - mv->addOperand(std::make_unique(src_vreg)); - 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)); + // --- 步骤 2: 处理所有栈参数 --- + int stack_space = 0; + if (!stack_args.empty()) { + // 计算栈参数所需的总空间,RV64中每个槽位为8字节 + stack_space = stack_args.size() * 8; + // 根据ABI,为call分配的栈空间需要16字节对齐 + if (stack_space % 16 != 0) { + stack_space += 16 - (stack_space % 16); + } + + // 在栈上分配空间 + if (stack_space > 0) { + 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)); + } + + // 将每个参数存储到栈上对应的位置 + for (size_t i = 0; i < stack_args.size(); ++i) { + DAGNode* arg_node = stack_args[i]; + Value* arg_val = arg_node->value; + Type* arg_type = arg_val->getType(); + int offset = i * 8; - // 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)); + // 如果是常量,先加载到临时vreg + if (auto const_val = dynamic_cast(arg_val)) { + src_vreg = getNewVReg(arg_type); + if(arg_type->isFloat()) { + auto temp_int_vreg = getNewVReg(Type::getIntType()); + float f_val = const_val->getFloat(); + uint32_t float_bits = *reinterpret_cast(&f_val); + auto li = std::make_unique(RVOpcodes::LI); + li->addOperand(std::make_unique(temp_int_vreg)); + li->addOperand(std::make_unique(float_bits)); + CurMBB->addInstruction(std::move(li)); + auto fmv_wx = std::make_unique(RVOpcodes::FMV_W_X); + fmv_wx->addOperand(std::make_unique(src_vreg)); + fmv_wx->addOperand(std::make_unique(temp_int_vreg)); + CurMBB->addInstruction(std::move(fmv_wx)); + } else { + 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); + src_vreg = getVReg(arg_val); } - // 计算在栈上的偏移量 - 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( + // 根据类型选择 fsw (浮点) 或 sd (整型/指针) 存储指令 + std::unique_ptr store_instr; + if (arg_type->isFloat()) { + store_instr = std::make_unique(RVOpcodes::FSW); + } else { + store_instr = std::make_unique(RVOpcodes::SD); + } + store_instr->addOperand(std::make_unique(src_vreg)); + store_instr->addOperand(std::make_unique( std::make_unique(PhysicalReg::SP), std::make_unique(offset) )); - CurMBB->addInstruction(std::move(sd_instr)); + CurMBB->addInstruction(std::move(store_instr)); } } - + + // --- 步骤 3: 生成CALL指令 --- auto call_instr = std::make_unique(RVOpcodes::CALL); // [协议] 如果函数有返回值,将它的目标虚拟寄存器作为第一个操作数 if (!call->getType()->isVoid()) { unsigned dest_vreg = getVReg(call); call_instr->addOperand(std::make_unique(dest_vreg)); } - // 将函数名标签作为后续操作数 call_instr->addOperand(std::make_unique(call->getCallee()->getName())); - // 将所有参数的虚拟寄存器也作为后续操作数,供getInstrUseDef分析 for (size_t i = 0; i < num_operands; ++i) { - if (node->operands[i]->kind != DAGNode::CONSTANT) { // 常量参数已直接加载,无需作为use + if (node->operands[i]->kind != DAGNode::CONSTANT && node->operands[i]->kind != DAGNode::FP_CONSTANT) { call_instr->addOperand(std::make_unique(getVReg(node->operands[i]->value))); } } - 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; + // --- 步骤 4: 处理返回值 --- + if (!call->getType()->isVoid()) { + unsigned dest_vreg = getVReg(call); + if (call->getType()->isFloat()) { + // 浮点返回值在 fa0 (物理寄存器 F10) + auto fmv_s = std::make_unique(RVOpcodes::FMV_S); + fmv_s->addOperand(std::make_unique(dest_vreg)); + fmv_s->addOperand(std::make_unique(PhysicalReg::F10)); // fa0 + CurMBB->addInstruction(std::move(fmv_s)); + } else { + // 整数/指针返回值在 a0 + auto mv = std::make_unique(RVOpcodes::MV); + mv->addOperand(std::make_unique(dest_vreg)); + mv->addOperand(std::make_unique(PhysicalReg::A0)); + CurMBB->addInstruction(std::move(mv)); + } + } + + // --- 步骤 5: 回收为栈参数分配的空间 --- + if (stack_space > 0) { 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); - // mv_instr->addOperand(std::make_unique(getVReg(call))); - // mv_instr->addOperand(std::make_unique(PhysicalReg::A0)); - // CurMBB->addInstruction(std::move(mv_instr)); - // } break; } @@ -868,17 +963,47 @@ void RISCv64ISel::selectNode(DAGNode* node) { auto ret_inst_ir = dynamic_cast(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(ret_val)) { - auto li_instr = std::make_unique(RVOpcodes::LI); - li_instr->addOperand(std::make_unique(PhysicalReg::A0)); - li_instr->addOperand(std::make_unique(const_val->getInt())); - CurMBB->addInstruction(std::move(li_instr)); + Type* ret_type = ret_val->getType(); + + if (ret_type->isFloat()) { + // --- 处理浮点返回值 --- + // 返回值需要被放入 fa0 (物理寄存器 F10) + if (auto const_val = dynamic_cast(ret_val)) { + // 如果是浮点常量,需要先物化到fa0 + float f_val = const_val->getFloat(); + uint32_t float_bits = *reinterpret_cast(&f_val); + // 1. 加载位模式到临时整数寄存器 (t0) + auto li = std::make_unique(RVOpcodes::LI); + li->addOperand(std::make_unique(PhysicalReg::T0)); + li->addOperand(std::make_unique(float_bits)); + CurMBB->addInstruction(std::move(li)); + // 2. 将位模式从 t0 移动到 fa0 + auto fmv_wx = std::make_unique(RVOpcodes::FMV_W_X); + fmv_wx->addOperand(std::make_unique(PhysicalReg::F10)); // fa0 + fmv_wx->addOperand(std::make_unique(PhysicalReg::T0)); + CurMBB->addInstruction(std::move(fmv_wx)); + } else { + // 如果是vreg,直接用 fmv.s 移动到 fa0 + auto fmv_s = std::make_unique(RVOpcodes::FMV_S); + fmv_s->addOperand(std::make_unique(PhysicalReg::F10)); // fa0 + fmv_s->addOperand(std::make_unique(getVReg(ret_val))); + CurMBB->addInstruction(std::move(fmv_s)); + } } else { - auto mv_instr = std::make_unique(RVOpcodes::MV); - mv_instr->addOperand(std::make_unique(PhysicalReg::A0)); - mv_instr->addOperand(std::make_unique(getVReg(ret_val))); - CurMBB->addInstruction(std::move(mv_instr)); + // --- 处理整数/指针返回值 --- + // 返回值需要被放入 a0 + // [V2优点] 在RETURN节点内加载常量返回值 + if (auto const_val = dynamic_cast(ret_val)) { + auto li_instr = std::make_unique(RVOpcodes::LI); + li_instr->addOperand(std::make_unique(PhysicalReg::A0)); + li_instr->addOperand(std::make_unique(const_val->getInt())); + CurMBB->addInstruction(std::move(li_instr)); + } else { + auto mv_instr = std::make_unique(RVOpcodes::MV); + mv_instr->addOperand(std::make_unique(PhysicalReg::A0)); + mv_instr->addOperand(std::make_unique(getVReg(ret_val))); + CurMBB->addInstruction(std::move(mv_instr)); + } } } // [V1设计保留] 函数尾声(epilogue)不由RETURN节点生成, diff --git a/src/backend/RISCv64/RISCv64RegAlloc.cpp b/src/backend/RISCv64/RISCv64RegAlloc.cpp index 5073167..4bd7662 100644 --- a/src/backend/RISCv64/RISCv64RegAlloc.cpp +++ b/src/backend/RISCv64/RISCv64RegAlloc.cpp @@ -47,6 +47,13 @@ RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc) : MFunc(mfunc) { // 寄存器分配的主入口点 void RISCv64RegAlloc::run() { + // --- 在所有流程开始前,构建完整的vreg到Value的反向映射 --- + const auto& vreg_map_from_isel = MFunc->getISel()->getVRegMap(); + for (const auto& pair : vreg_map_from_isel) { + Value* val = pair.first; + unsigned vreg = pair.second; + vreg_to_value_map[vreg] = val; + } // 阶段 1: 处理函数调用约定(参数寄存器预着色) handleCallingConvention(); // 阶段 2: 消除帧索引(为局部变量和栈参数分配栈偏移) diff --git a/src/include/backend/RISCv64/RISCv64ISel.h b/src/include/backend/RISCv64/RISCv64ISel.h index d6e73c3..d24432d 100644 --- a/src/include/backend/RISCv64/RISCv64ISel.h +++ b/src/include/backend/RISCv64/RISCv64ISel.h @@ -17,9 +17,11 @@ public: // 公开接口,以便后续模块(如RegAlloc)可以查询或创建vreg unsigned getVReg(Value* val); unsigned getNewVReg() { return vreg_counter++; } + unsigned getNewVReg(Type* type); // 获取 vreg_map 的公共接口 const std::map& getVRegMap() const { return vreg_map; } const std::map& getVRegValueMap() const { return vreg_to_value_map; } + const std::map& getVRegTypeMap() const { return vreg_type_map; } private: // DAG节点定义,作为ISel的内部实现细节 @@ -50,6 +52,7 @@ private: // 映射关系 std::map vreg_map; std::map vreg_to_value_map; + std::map vreg_type_map; std::map bb_map; unsigned vreg_counter;