#include "mir/MIR.h" #include #include #include #include #include "ir/IR.h" #include "utils/Log.h" //#define DEBUG_Lower #ifdef DEBUG_Lower #include #define DEBUG_MSG(msg) std::cerr << "[Lower Debug] " << msg << std::endl #else #define DEBUG_MSG(msg) ((void)0) #endif namespace mir { namespace { // ========== VReg 类型 ========== enum class VRegType { kInt32, kInt64, kFloat32 }; // ========== VReg 上下文:管理虚拟寄存器分配和 IR Value 映射 ========== struct VRegContext { int next_vreg = 1; std::unordered_map value_to_vreg; std::unordered_map vreg_types; int NewVReg(VRegType type) { int id = next_vreg++; vreg_types[id] = type; return id; } VRegType GetType(int vreg) const { auto it = vreg_types.find(vreg); return it != vreg_types.end() ? it->second : VRegType::kInt32; } bool IsFloat(int vreg) const { auto it = vreg_types.find(vreg); return it != vreg_types.end() && it->second == VRegType::kFloat32; } bool IsPointer(int vreg) const { auto it = vreg_types.find(vreg); return it != vreg_types.end() && it->second == VRegType::kInt64; } void SetVReg(const ir::Value* value, int vreg) { value_to_vreg[value] = vreg; } int GetVReg(const ir::Value* value) const { auto it = value_to_vreg.find(value); return it != value_to_vreg.end() ? it->second : -1; } bool HasVReg(const ir::Value* value) const { return value_to_vreg.count(value) > 0; } }; // ========== 辅助:判断类型 ========== inline bool IsInt32Type(const ir::Type* type) { return type && type->IsInt32() && type->Size() == 4; } static uint32_t FloatToBits(float f) { uint32_t bits; memcpy(&bits, &f, sizeof(bits)); return bits; } int GetTypeSize(const ir::Type* type) { if (!type) return 4; size_t size = type->Size(); return size > 0 ? static_cast(size) : 4; } VRegType GetVRegTypeForIRType(const ir::Type* type) { if (!type) return VRegType::kInt32; if (type->IsFloat()) return VRegType::kFloat32; if (type->IsPtrInt32() || type->IsPtrFloat() || type->IsPtrInt1() || type->IsArray()) return VRegType::kInt64; return VRegType::kInt32; } // ========== 辅助:记录 MachineInstr 的 def/use ========== void RecordDefUse(MachineInstr& instr, int def, std::initializer_list uses) { if (def > 0) instr.AddDef(def); for (int u : uses) { if (u > 0) instr.AddUse(u); } } void RecordDefUseVec(MachineInstr& instr, const std::vector& defs, const std::vector& uses) { for (int d : defs) instr.AddDef(d); for (int u : uses) instr.AddUse(u); } // ========== 辅助:发射立即数到虚拟寄存器 ========== void EmitMovImm(int vreg, uint32_t imm, MachineBasicBlock& block) { auto isLegalMovImm = [](uint32_t v) -> bool { return (v & 0xFFFF) == v || (v & 0xFFFF0000) == v; }; if (isLegalMovImm(imm)) { auto& instr = block.Append(Opcode::MovImm, {Operand::VReg(vreg), Operand::Imm(static_cast(imm))}); instr.AddDef(vreg); } else { uint16_t low = imm & 0xFFFF; uint16_t high = (imm >> 16) & 0xFFFF; auto& i1 = block.Append(Opcode::MovImm, {Operand::VReg(vreg), Operand::Imm(low)}); i1.AddDef(vreg); if (high != 0) { auto& i2 = block.Append(Opcode::Movk, {Operand::VReg(vreg), Operand::Imm(high), Operand::Imm(16)}); i2.AddDef(vreg); i2.AddUse(vreg); } } } void EmitMovImm64(int vreg, uint64_t imm, MachineBasicBlock& block) { uint16_t part0 = imm & 0xFFFF; uint16_t part1 = (imm >> 16) & 0xFFFF; uint16_t part2 = (imm >> 32) & 0xFFFF; uint16_t part3 = (imm >> 48) & 0xFFFF; auto& i1 = block.Append(Opcode::MovImm, {Operand::VReg(vreg), Operand::Imm(part0)}); i1.AddDef(vreg); if (part1 != 0) { auto& i2 = block.Append(Opcode::Movk, {Operand::VReg(vreg), Operand::Imm(part1), Operand::Imm(16)}); i2.AddDef(vreg); i2.AddUse(vreg); } if (part2 != 0) { auto& i3 = block.Append(Opcode::Movk, {Operand::VReg(vreg), Operand::Imm(part2), Operand::Imm(32)}); i3.AddDef(vreg); i3.AddUse(vreg); } if (part3 != 0) { auto& i4 = block.Append(Opcode::Movk, {Operand::VReg(vreg), Operand::Imm(part3), Operand::Imm(48)}); i4.AddDef(vreg); i4.AddUse(vreg); } } // ========== 核心:将 IR Value 转换为虚拟寄存器 ========== int EmitValueToVReg(const ir::Value* value, VRegContext& ctx, MachineBasicBlock& block, MachineFunction& function) { // 整数常量:每次都生成新的 MovImm(不缓存) // 缓存会导致常量在某个条件块中定义,但其他控制流路径上的使用 // 可能不经过该定义,导致寄存器残留过期值。 if (auto* constant = dynamic_cast(value)) { uint32_t imm = static_cast(constant->GetValue()); int vreg = ctx.NewVReg(VRegType::kInt32); EmitMovImm(vreg, imm, block); return vreg; } // 浮点常量:每次都走栈槽加载(不缓存) if (auto* fconstant = dynamic_cast(value)) { float fval = fconstant->GetValue(); uint32_t bits = FloatToBits(fval); int slot = function.CreateFrameIndex(4); int tmp = ctx.NewVReg(VRegType::kInt32); EmitMovImm(tmp, bits, block); auto& s = block.Append(Opcode::StoreStack, {Operand::VReg(tmp), Operand::FrameIndex(slot)}); s.AddUse(tmp); int fvreg = ctx.NewVReg(VRegType::kFloat32); auto& l = block.Append(Opcode::LoadStack, {Operand::VReg(fvreg), Operand::FrameIndex(slot)}); l.AddDef(fvreg); return fvreg; } // 零常量 / 聚合零:每次都生成新 MovImm(不缓存) if (dynamic_cast(value) || dynamic_cast(value)) { int vreg = ctx.NewVReg(VRegType::kInt32); auto& instr = block.Append(Opcode::MovImm, {Operand::VReg(vreg), Operand::Imm(0)}); instr.AddDef(vreg); return vreg; } // 全局变量:每次都生成新的 adrp+add(不缓存) // 与常量同理:缓存会导致全局变量在某条件块中定义,但其他控制流路径 // 上的使用可能不经过该定义,导致寄存器残留过期值。 if (auto* global = dynamic_cast(value)) { int vreg = ctx.NewVReg(VRegType::kInt64); auto& i1 = block.Append(Opcode::Adrp, {Operand::VReg(vreg), Operand::Label(global->GetName())}); i1.AddDef(vreg); auto& i2 = block.Append(Opcode::AddLabel, {Operand::VReg(vreg), Operand::VReg(vreg), Operand::Label(global->GetName())}); i2.AddDef(vreg); i2.AddUse(vreg); return vreg; } // 非常量值:检查是否已有映射 if (ctx.HasVReg(value)) { return ctx.GetVReg(value); } // 未找到 std::string name = value->GetName(); if (name.empty()) name = "(anonymous)"; throw std::runtime_error( FormatError("mir", "EmitValueToVReg: 找不到值对应的 vreg: " + name)); } // ========== IR 比较谓词 → ARMv8 条件码 ========== CondCode IcmpToCondCode(ir::IcmpInst::Predicate pred) { switch (pred) { case ir::IcmpInst::Predicate::EQ: return CondCode::EQ; case ir::IcmpInst::Predicate::NE: return CondCode::NE; case ir::IcmpInst::Predicate::LT: return CondCode::LT; case ir::IcmpInst::Predicate::GT: return CondCode::GT; case ir::IcmpInst::Predicate::LE: return CondCode::LE; case ir::IcmpInst::Predicate::GE: return CondCode::GE; default: return CondCode::AL; } } CondCode FcmpToCondCode(ir::FcmpInst::Predicate pred, bool& isOrdered) { isOrdered = true; switch (pred) { case ir::FcmpInst::Predicate::OEQ: return CondCode::EQ; case ir::FcmpInst::Predicate::ONE: return CondCode::NE; case ir::FcmpInst::Predicate::OLT: return CondCode::LT; case ir::FcmpInst::Predicate::OGT: return CondCode::GT; case ir::FcmpInst::Predicate::OLE: return CondCode::LE; case ir::FcmpInst::Predicate::OGE: return CondCode::GE; case ir::FcmpInst::Predicate::UEQ: isOrdered = false; return CondCode::EQ; case ir::FcmpInst::Predicate::UNE: isOrdered = false; return CondCode::NE; case ir::FcmpInst::Predicate::ULT: isOrdered = false; return CondCode::LT; case ir::FcmpInst::Predicate::UGT: isOrdered = false; return CondCode::GT; case ir::FcmpInst::Predicate::ULE: isOrdered = false; return CondCode::LE; case ir::FcmpInst::Predicate::UGE: isOrdered = false; return CondCode::GE; default: return CondCode::AL; } } std::string GetBlockLabel(const ir::BasicBlock* bb) { if (!bb || !bb->GetParent()) return ".Lunknown"; std::string funcName = bb->GetParent()->GetName(); std::string blockName = bb->GetName(); if (blockName.empty()) blockName = std::to_string(reinterpret_cast(bb)); return ".L" + funcName + "_" + blockName; } // ========== LowerInstruction:将单条 IR 指令转换为 MIR 指令 ========== void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, VRegContext& ctx, MachineBasicBlock& block, std::unordered_map& blockMap) { DEBUG_MSG("Processing instruction: " << inst.GetName() << " (opcode: " << static_cast(inst.GetOpcode()) << ")"); switch (inst.GetOpcode()) { // ---- Alloca:在栈上分配空间,返回指针 ---- case ir::Opcode::Alloca: { int arraySlot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); int ptrVreg = ctx.NewVReg(VRegType::kInt64); auto& instr = block.Append(Opcode::LoadStackAddr, {Operand::VReg(ptrVreg), Operand::FrameIndex(arraySlot)}); instr.AddDef(ptrVreg); ctx.SetVReg(&inst, ptrVreg); return; } // ---- Store:将值存储到指针指向的地址 ---- case ir::Opcode::Store: { auto& store = static_cast(inst); const ir::Value* ptr = store.GetPtr(); const ir::Value* val = store.GetValue(); int ptrVreg = EmitValueToVReg(ptr, ctx, block, function); int valVreg = EmitValueToVReg(val, ctx, block, function); auto& instr = block.Append(Opcode::StoreStack, {Operand::VReg(valVreg), Operand::VReg(ptrVreg)}); instr.AddUse(valVreg); instr.AddUse(ptrVreg); return; } // ---- Load:从指针指向的地址加载值 ---- case ir::Opcode::Load: { auto& load = static_cast(inst); const ir::Value* ptr = load.GetPtr(); int ptrVreg = EmitValueToVReg(ptr, ctx, block, function); VRegType resultType = GetVRegTypeForIRType(inst.GetType().get()); int dstVreg = ctx.NewVReg(resultType); auto& instr = block.Append(Opcode::LoadStack, {Operand::VReg(dstVreg), Operand::VReg(ptrVreg)}); instr.AddDef(dstVreg); instr.AddUse(ptrVreg); ctx.SetVReg(&inst, dstVreg); return; } // ---- Add ---- case ir::Opcode::Add: { auto& bin = static_cast(inst); const ir::Type* lhsTy = bin.GetLhs()->GetType().get(); const ir::Type* rhsTy = bin.GetRhs()->GetType().get(); const ir::Type* resultTy = inst.GetType().get(); bool isPointer = (lhsTy->IsPtrInt32() || lhsTy->IsPtrFloat() || lhsTy->IsPtrInt1() || lhsTy->IsArray()) || (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1() || rhsTy->IsArray()) || resultTy->IsPtrInt32() || resultTy->IsPtrFloat() || resultTy->IsPtrInt1() || resultTy->IsArray(); bool isI32 = !isPointer && IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); if (isI32) { // i32 加法:用 64 位运算避免溢出 int vl = EmitValueToVReg(bin.GetLhs(), ctx, block, function); int vr = EmitValueToVReg(bin.GetRhs(), ctx, block, function); int vxl = ctx.NewVReg(VRegType::kInt64); int vxr = ctx.NewVReg(VRegType::kInt64); int vxd = ctx.NewVReg(VRegType::kInt64); auto& s1 = block.Append(Opcode::Sxtw, {Operand::VReg(vxl), Operand::VReg(vl)}); s1.AddDef(vxl); s1.AddUse(vl); auto& s2 = block.Append(Opcode::Sxtw, {Operand::VReg(vxr), Operand::VReg(vr)}); s2.AddDef(vxr); s2.AddUse(vr); auto& a = block.Append(Opcode::AddRR, {Operand::VReg(vxd), Operand::VReg(vxl), Operand::VReg(vxr)}); a.AddDef(vxd); a.AddUse(vxl); a.AddUse(vxr); // 结果用 32 位 vreg(低 32 位正确) int vd = ctx.NewVReg(VRegType::kInt32); auto& mv = block.Append(Opcode::MovReg, {Operand::VReg(vd), Operand::VReg(vxd)}); mv.AddDef(vd); mv.AddUse(vxd); ctx.SetVReg(&inst, vd); } else { VRegType ty = isPointer ? VRegType::kInt64 : VRegType::kInt32; int vl = EmitValueToVReg(bin.GetLhs(), ctx, block, function); int vr = EmitValueToVReg(bin.GetRhs(), ctx, block, function); int vd = ctx.NewVReg(ty); auto& a = block.Append(Opcode::AddRR, {Operand::VReg(vd), Operand::VReg(vl), Operand::VReg(vr)}); a.AddDef(vd); a.AddUse(vl); a.AddUse(vr); ctx.SetVReg(&inst, vd); } return; } // ---- Sub ---- case ir::Opcode::Sub: { auto& bin = static_cast(inst); // 浮点减法 if (bin.GetLhs()->GetType()->IsFloat() && bin.GetRhs()->GetType()->IsFloat()) { int vl = EmitValueToVReg(bin.GetLhs(), ctx, block, function); int vr = EmitValueToVReg(bin.GetRhs(), ctx, block, function); int vd = ctx.NewVReg(VRegType::kFloat32); auto& a = block.Append(Opcode::FSubRR, {Operand::VReg(vd), Operand::VReg(vl), Operand::VReg(vr)}); a.AddDef(vd); a.AddUse(vl); a.AddUse(vr); ctx.SetVReg(&inst, vd); return; } const ir::Type* lhsTy = bin.GetLhs()->GetType().get(); const ir::Type* rhsTy = bin.GetRhs()->GetType().get(); const ir::Type* resultTy = inst.GetType().get(); bool isPointer = (lhsTy->IsPtrInt32() || lhsTy->IsPtrFloat() || lhsTy->IsPtrInt1() || lhsTy->IsArray()) || (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1() || rhsTy->IsArray()) || resultTy->IsPtrInt32() || resultTy->IsPtrFloat() || resultTy->IsPtrInt1() || resultTy->IsArray(); bool isI32 = !isPointer && IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); if (isI32) { int vl = EmitValueToVReg(bin.GetLhs(), ctx, block, function); int vr = EmitValueToVReg(bin.GetRhs(), ctx, block, function); int vxl = ctx.NewVReg(VRegType::kInt64); int vxr = ctx.NewVReg(VRegType::kInt64); int vxd = ctx.NewVReg(VRegType::kInt64); auto& s1 = block.Append(Opcode::Sxtw, {Operand::VReg(vxl), Operand::VReg(vl)}); s1.AddDef(vxl); s1.AddUse(vl); auto& s2 = block.Append(Opcode::Sxtw, {Operand::VReg(vxr), Operand::VReg(vr)}); s2.AddDef(vxr); s2.AddUse(vr); auto& a = block.Append(Opcode::SubRR, {Operand::VReg(vxd), Operand::VReg(vxl), Operand::VReg(vxr)}); a.AddDef(vxd); a.AddUse(vxl); a.AddUse(vxr); int vd = ctx.NewVReg(VRegType::kInt32); auto& mv = block.Append(Opcode::MovReg, {Operand::VReg(vd), Operand::VReg(vxd)}); mv.AddDef(vd); mv.AddUse(vxd); ctx.SetVReg(&inst, vd); } else { VRegType ty = isPointer ? VRegType::kInt64 : VRegType::kInt32; int vl = EmitValueToVReg(bin.GetLhs(), ctx, block, function); int vr = EmitValueToVReg(bin.GetRhs(), ctx, block, function); int vd = ctx.NewVReg(ty); auto& a = block.Append(Opcode::SubRR, {Operand::VReg(vd), Operand::VReg(vl), Operand::VReg(vr)}); a.AddDef(vd); a.AddUse(vl); a.AddUse(vr); ctx.SetVReg(&inst, vd); } return; } // ---- Mul ---- case ir::Opcode::Mul: { auto& bin = static_cast(inst); const ir::Type* lhsTy = bin.GetLhs()->GetType().get(); const ir::Type* rhsTy = bin.GetRhs()->GetType().get(); const ir::Type* resultTy = inst.GetType().get(); bool isPointer = (lhsTy->IsPtrInt32() || lhsTy->IsPtrFloat() || lhsTy->IsPtrInt1()) || (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1()) || resultTy->IsPtrInt32() || resultTy->IsPtrFloat() || resultTy->IsPtrInt1(); bool isI32 = !isPointer && IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); if (isI32) { int vl = EmitValueToVReg(bin.GetLhs(), ctx, block, function); int vr = EmitValueToVReg(bin.GetRhs(), ctx, block, function); int vxl = ctx.NewVReg(VRegType::kInt64); int vxr = ctx.NewVReg(VRegType::kInt64); int vxd = ctx.NewVReg(VRegType::kInt64); auto& s1 = block.Append(Opcode::Sxtw, {Operand::VReg(vxl), Operand::VReg(vl)}); s1.AddDef(vxl); s1.AddUse(vl); auto& s2 = block.Append(Opcode::Sxtw, {Operand::VReg(vxr), Operand::VReg(vr)}); s2.AddDef(vxr); s2.AddUse(vr); auto& a = block.Append(Opcode::MulRR, {Operand::VReg(vxd), Operand::VReg(vxl), Operand::VReg(vxr)}); a.AddDef(vxd); a.AddUse(vxl); a.AddUse(vxr); int vd = ctx.NewVReg(VRegType::kInt32); auto& mv = block.Append(Opcode::MovReg, {Operand::VReg(vd), Operand::VReg(vxd)}); mv.AddDef(vd); mv.AddUse(vxd); ctx.SetVReg(&inst, vd); } else { VRegType ty = isPointer ? VRegType::kInt64 : VRegType::kInt32; int vl = EmitValueToVReg(bin.GetLhs(), ctx, block, function); int vr = EmitValueToVReg(bin.GetRhs(), ctx, block, function); int vd = ctx.NewVReg(ty); auto& a = block.Append(Opcode::MulRR, {Operand::VReg(vd), Operand::VReg(vl), Operand::VReg(vr)}); a.AddDef(vd); a.AddUse(vl); a.AddUse(vr); ctx.SetVReg(&inst, vd); } return; } // ---- Div ---- case ir::Opcode::Div: { auto& bin = static_cast(inst); const ir::Type* lhsTy = bin.GetLhs()->GetType().get(); const ir::Type* rhsTy = bin.GetRhs()->GetType().get(); const ir::Type* resultTy = inst.GetType().get(); bool isPointer = (lhsTy->IsPtrInt32() || lhsTy->IsPtrFloat() || lhsTy->IsPtrInt1()) || (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1()) || resultTy->IsPtrInt32() || resultTy->IsPtrFloat() || resultTy->IsPtrInt1(); bool isI32 = !isPointer && IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); if (isI32) { int vl = EmitValueToVReg(bin.GetLhs(), ctx, block, function); int vr = EmitValueToVReg(bin.GetRhs(), ctx, block, function); int vxl = ctx.NewVReg(VRegType::kInt64); int vxr = ctx.NewVReg(VRegType::kInt64); int vxd = ctx.NewVReg(VRegType::kInt64); auto& s1 = block.Append(Opcode::Sxtw, {Operand::VReg(vxl), Operand::VReg(vl)}); s1.AddDef(vxl); s1.AddUse(vl); auto& s2 = block.Append(Opcode::Sxtw, {Operand::VReg(vxr), Operand::VReg(vr)}); s2.AddDef(vxr); s2.AddUse(vr); auto& a = block.Append(Opcode::SDivRR, {Operand::VReg(vxd), Operand::VReg(vxl), Operand::VReg(vxr)}); a.AddDef(vxd); a.AddUse(vxl); a.AddUse(vxr); int vd = ctx.NewVReg(VRegType::kInt32); auto& mv = block.Append(Opcode::MovReg, {Operand::VReg(vd), Operand::VReg(vxd)}); mv.AddDef(vd); mv.AddUse(vxd); ctx.SetVReg(&inst, vd); } else { VRegType ty = isPointer ? VRegType::kInt64 : VRegType::kInt32; int vl = EmitValueToVReg(bin.GetLhs(), ctx, block, function); int vr = EmitValueToVReg(bin.GetRhs(), ctx, block, function); int vd = ctx.NewVReg(ty); auto& a = block.Append(Opcode::SDivRR, {Operand::VReg(vd), Operand::VReg(vl), Operand::VReg(vr)}); a.AddDef(vd); a.AddUse(vl); a.AddUse(vr); ctx.SetVReg(&inst, vd); } return; } // ---- Mod: a % b = a - (a / b) * b ---- case ir::Opcode::Mod: { const ir::Value* lhs = inst.GetOperand(0); const ir::Value* rhs = inst.GetOperand(1); const ir::Type* lhsTy = lhs->GetType().get(); const ir::Type* rhsTy = rhs->GetType().get(); const ir::Type* resultTy = inst.GetType().get(); bool isI32 = IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); if (isI32) { int vl = EmitValueToVReg(lhs, ctx, block, function); int vr = EmitValueToVReg(rhs, ctx, block, function); int vxl = ctx.NewVReg(VRegType::kInt64); int vxr = ctx.NewVReg(VRegType::kInt64); auto& s1 = block.Append(Opcode::Sxtw, {Operand::VReg(vxl), Operand::VReg(vl)}); s1.AddDef(vxl); s1.AddUse(vl); auto& s2 = block.Append(Opcode::Sxtw, {Operand::VReg(vxr), Operand::VReg(vr)}); s2.AddDef(vxr); s2.AddUse(vr); int vxdiv = ctx.NewVReg(VRegType::kInt64); int vxtmp = ctx.NewVReg(VRegType::kInt64); int vxd = ctx.NewVReg(VRegType::kInt64); auto& d = block.Append(Opcode::SDivRR, {Operand::VReg(vxdiv), Operand::VReg(vxl), Operand::VReg(vxr)}); d.AddDef(vxdiv); d.AddUse(vxl); d.AddUse(vxr); auto& m = block.Append(Opcode::MulRR, {Operand::VReg(vxtmp), Operand::VReg(vxdiv), Operand::VReg(vxr)}); m.AddDef(vxtmp); m.AddUse(vxdiv); m.AddUse(vxr); auto& sub = block.Append(Opcode::SubRR, {Operand::VReg(vxd), Operand::VReg(vxl), Operand::VReg(vxtmp)}); sub.AddDef(vxd); sub.AddUse(vxl); sub.AddUse(vxtmp); int vd = ctx.NewVReg(VRegType::kInt32); auto& mv = block.Append(Opcode::MovReg, {Operand::VReg(vd), Operand::VReg(vxd)}); mv.AddDef(vd); mv.AddUse(vxd); ctx.SetVReg(&inst, vd); } else { int vl = EmitValueToVReg(lhs, ctx, block, function); int vr = EmitValueToVReg(rhs, ctx, block, function); int vdiv = ctx.NewVReg(VRegType::kInt32); int vtmp = ctx.NewVReg(VRegType::kInt32); int vd = ctx.NewVReg(VRegType::kInt32); auto& d = block.Append(Opcode::SDivRR, {Operand::VReg(vdiv), Operand::VReg(vl), Operand::VReg(vr)}); d.AddDef(vdiv); d.AddUse(vl); d.AddUse(vr); auto& m = block.Append(Opcode::MulRR, {Operand::VReg(vtmp), Operand::VReg(vdiv), Operand::VReg(vr)}); m.AddDef(vtmp); m.AddUse(vdiv); m.AddUse(vr); auto& s = block.Append(Opcode::SubRR, {Operand::VReg(vd), Operand::VReg(vl), Operand::VReg(vtmp)}); s.AddDef(vd); s.AddUse(vl); s.AddUse(vtmp); ctx.SetVReg(&inst, vd); } return; } // ---- Ret ---- case ir::Opcode::Ret: { auto& ret = static_cast(inst); const ir::Value* retVal = ret.GetValue(); if (retVal != nullptr) { const ir::Type* retType = retVal->GetType().get(); int valVreg = EmitValueToVReg(retVal, ctx, block, function); PhysReg retReg = PhysReg::W0; if (retType->IsFloat()) retReg = PhysReg::S0; else if (retType->IsPtrInt32() || retType->IsPtrFloat() || retType->IsPtrInt1()) retReg = PhysReg::X0; auto& mv = block.Append(Opcode::MovReg, {Operand::Reg(retReg), Operand::VReg(valVreg)}); mv.AddUse(valVreg); } auto& r = block.Append(Opcode::Ret); return; } // ---- FAdd ---- case ir::Opcode::FAdd: { auto& bin = static_cast(inst); int vl = EmitValueToVReg(bin.GetLhs(), ctx, block, function); int vr = EmitValueToVReg(bin.GetRhs(), ctx, block, function); int vd = ctx.NewVReg(VRegType::kFloat32); auto& a = block.Append(Opcode::FAddRR, {Operand::VReg(vd), Operand::VReg(vl), Operand::VReg(vr)}); a.AddDef(vd); a.AddUse(vl); a.AddUse(vr); ctx.SetVReg(&inst, vd); return; } case ir::Opcode::FSub: { auto& bin = static_cast(inst); int vl = EmitValueToVReg(bin.GetLhs(), ctx, block, function); int vr = EmitValueToVReg(bin.GetRhs(), ctx, block, function); int vd = ctx.NewVReg(VRegType::kFloat32); auto& a = block.Append(Opcode::FSubRR, {Operand::VReg(vd), Operand::VReg(vl), Operand::VReg(vr)}); a.AddDef(vd); a.AddUse(vl); a.AddUse(vr); ctx.SetVReg(&inst, vd); return; } case ir::Opcode::FMul: { auto& bin = static_cast(inst); int vl = EmitValueToVReg(bin.GetLhs(), ctx, block, function); int vr = EmitValueToVReg(bin.GetRhs(), ctx, block, function); int vd = ctx.NewVReg(VRegType::kFloat32); auto& a = block.Append(Opcode::FMulRR, {Operand::VReg(vd), Operand::VReg(vl), Operand::VReg(vr)}); a.AddDef(vd); a.AddUse(vl); a.AddUse(vr); ctx.SetVReg(&inst, vd); return; } case ir::Opcode::FDiv: { auto& bin = static_cast(inst); int vl = EmitValueToVReg(bin.GetLhs(), ctx, block, function); int vr = EmitValueToVReg(bin.GetRhs(), ctx, block, function); int vd = ctx.NewVReg(VRegType::kFloat32); auto& a = block.Append(Opcode::FDivRR, {Operand::VReg(vd), Operand::VReg(vl), Operand::VReg(vr)}); a.AddDef(vd); a.AddUse(vl); a.AddUse(vr); ctx.SetVReg(&inst, vd); return; } // ---- Icmp(整数比较) ---- case ir::Opcode::Icmp: { auto& icmp = static_cast(inst); int vl = EmitValueToVReg(icmp.GetLhs(), ctx, block, function); int vr = EmitValueToVReg(icmp.GetRhs(), ctx, block, function); CondCode cc = IcmpToCondCode(icmp.GetPredicate()); auto& cmp = block.Append(Opcode::CmpRR, {Operand::VReg(vl), Operand::VReg(vr)}); cmp.AddUse(vl); cmp.AddUse(vr); int vd = ctx.NewVReg(VRegType::kInt32); auto& set1 = block.Append(Opcode::MovImm, {Operand::VReg(vd), Operand::Imm(1)}); set1.AddDef(vd); std::string trueLabel = ".L_cset_true_" + std::to_string(reinterpret_cast(&icmp)); std::string endLabel = ".L_cset_end_" + std::to_string(reinterpret_cast(&icmp)); auto& bc = block.Append(Opcode::BCond, {Operand::Cond(cc), Operand::Label(trueLabel)}); auto& mv0 = block.Append(Opcode::MovImm, {Operand::VReg(vd), Operand::Imm(0)}); mv0.AddDef(vd); auto& b = block.Append(Opcode::B, {Operand::Label(endLabel)}); auto& lt = block.Append(Opcode::Label, {Operand::Label(trueLabel)}); auto& le = block.Append(Opcode::Label, {Operand::Label(endLabel)}); ctx.SetVReg(&inst, vd); return; } // ---- FCmp(浮点比较) ---- case ir::Opcode::FCmp: { auto& fcmp = static_cast(inst); int vl = EmitValueToVReg(fcmp.GetLhs(), ctx, block, function); int vr = EmitValueToVReg(fcmp.GetRhs(), ctx, block, function); bool isOrdered; CondCode cc = FcmpToCondCode(fcmp.GetPredicate(), isOrdered); auto& cmp = block.Append(Opcode::FCmpRR, {Operand::VReg(vl), Operand::VReg(vr)}); cmp.AddUse(vl); cmp.AddUse(vr); int vd = ctx.NewVReg(VRegType::kInt32); auto& zero = block.Append(Opcode::MovImm, {Operand::VReg(vd), Operand::Imm(0)}); zero.AddDef(vd); std::string set1Label = ".L_fcset_true_" + std::to_string(reinterpret_cast(&fcmp)); std::string endLabel = ".L_fcset_end_" + std::to_string(reinterpret_cast(&fcmp)); if (isOrdered) { auto& bc_vs = block.Append(Opcode::BCond, {Operand::Cond(CondCode::VS), Operand::Label(endLabel)}); } else { auto& bc_vs = block.Append(Opcode::BCond, {Operand::Cond(CondCode::VS), Operand::Label(set1Label)}); } auto& bc = block.Append(Opcode::BCond, {Operand::Cond(cc), Operand::Label(set1Label)}); auto& b = block.Append(Opcode::B, {Operand::Label(endLabel)}); auto& lt = block.Append(Opcode::Label, {Operand::Label(set1Label)}); auto& s1 = block.Append(Opcode::MovImm, {Operand::VReg(vd), Operand::Imm(1)}); s1.AddDef(vd); auto& le = block.Append(Opcode::Label, {Operand::Label(endLabel)}); ctx.SetVReg(&inst, vd); return; } // ---- Br / CondBr ---- case ir::Opcode::Br: case ir::Opcode::CondBr: { auto& br = static_cast(inst); if (br.IsConditional()) { int condVreg = EmitValueToVReg(br.GetCondition(), ctx, block, function); auto& cmp = block.Append(Opcode::CmpRI, {Operand::VReg(condVreg), Operand::Imm(0)}); cmp.AddUse(condVreg); std::string trueLabel = GetBlockLabel(br.GetTrueTarget()); std::string falseLabel = GetBlockLabel(br.GetFalseTarget()); auto& bc = block.Append(Opcode::BCond, {Operand::Cond(CondCode::NE), Operand::Label(trueLabel)}); auto& b = block.Append(Opcode::B, {Operand::Label(falseLabel)}); } else { std::string targetLabel = GetBlockLabel(br.GetTarget()); auto& b = block.Append(Opcode::B, {Operand::Label(targetLabel)}); } return; } // ---- Call ---- case ir::Opcode::Call: { auto& call = static_cast(inst); const ir::Function* callee = call.GetCallee(); const std::string& calleeName = callee->GetName(); // 传递参数(vreg → 物理寄存器) const auto& args = call.GetArgs(); size_t intArgCount = 0; size_t fpArgCount = 0; for (size_t i = 0; i < args.size(); ++i) { const auto* arg = args[i]; const ir::Type* argType = arg->GetType().get(); int argVreg = EmitValueToVReg(arg, ctx, block, function); if (argType->IsFloat()) { PhysReg reg = static_cast(static_cast(PhysReg::S0) + fpArgCount); auto& mv = block.Append(Opcode::MovReg, {Operand::Reg(reg), Operand::VReg(argVreg)}); mv.AddUse(argVreg); fpArgCount++; } else if (argType->IsPtrInt32() || argType->IsPtrFloat() || argType->IsPtrInt1()) { PhysReg reg = static_cast(static_cast(PhysReg::X0) + intArgCount); auto& mv = block.Append(Opcode::MovReg, {Operand::Reg(reg), Operand::VReg(argVreg)}); mv.AddUse(argVreg); intArgCount++; } else { PhysReg reg = static_cast(static_cast(PhysReg::W0) + intArgCount); auto& mv = block.Append(Opcode::MovReg, {Operand::Reg(reg), Operand::VReg(argVreg)}); mv.AddUse(argVreg); intArgCount++; } } auto& callInst = block.Append(Opcode::Call, {Operand::Label(calleeName)}); // 返回值:物理寄存器 → vreg if (!inst.GetType()->IsVoid()) { const ir::Type* retType = inst.GetType().get(); VRegType vtype = GetVRegTypeForIRType(retType); int dstVreg = ctx.NewVReg(vtype); PhysReg srcReg = PhysReg::W0; if (retType->IsFloat()) srcReg = PhysReg::S0; else if (retType->IsPtrInt32() || retType->IsPtrFloat() || retType->IsPtrInt1()) srcReg = PhysReg::X0; auto& mv = block.Append(Opcode::MovReg, {Operand::VReg(dstVreg), Operand::Reg(srcReg)}); mv.AddDef(dstVreg); ctx.SetVReg(&inst, dstVreg); } return; } // ---- ZExt (i1 → i32) ---- case ir::Opcode::ZExt: { auto& zext = static_cast(inst); int src = EmitValueToVReg(zext.GetValue(), ctx, block, function); int dst = ctx.NewVReg(VRegType::kInt32); auto& mv = block.Append(Opcode::MovReg, {Operand::VReg(dst), Operand::VReg(src)}); mv.AddDef(dst); mv.AddUse(src); ctx.SetVReg(&inst, dst); return; } // ---- SIToFP ---- case ir::Opcode::SIToFP: { auto& sitofp = static_cast(inst); int src = EmitValueToVReg(sitofp.GetValue(), ctx, block, function); int dst = ctx.NewVReg(VRegType::kFloat32); auto& cvt = block.Append(Opcode::SIToFP, {Operand::VReg(dst), Operand::VReg(src)}); cvt.AddDef(dst); cvt.AddUse(src); ctx.SetVReg(&inst, dst); return; } // ---- FPToSI ---- case ir::Opcode::FPToSI: { auto& fptosi = static_cast(inst); int src = EmitValueToVReg(fptosi.GetValue(), ctx, block, function); int dst = ctx.NewVReg(VRegType::kInt32); auto& cvt = block.Append(Opcode::FPToSI, {Operand::VReg(dst), Operand::VReg(src)}); cvt.AddDef(dst); cvt.AddUse(src); ctx.SetVReg(&inst, dst); return; } // ---- Trunc ---- case ir::Opcode::Trunc: { const ir::Value* srcVal = inst.GetNumOperands() > 0 ? inst.GetOperand(0) : nullptr; if (srcVal) { int src = EmitValueToVReg(srcVal, ctx, block, function); int dst = ctx.NewVReg(VRegType::kInt32); auto& mv = block.Append(Opcode::MovReg, {Operand::VReg(dst), Operand::VReg(src)}); mv.AddDef(dst); mv.AddUse(src); ctx.SetVReg(&inst, dst); } return; } // ---- And ---- case ir::Opcode::And: { const ir::Value* lhs = inst.GetNumOperands() >= 2 ? inst.GetOperand(0) : nullptr; const ir::Value* rhs = inst.GetNumOperands() >= 2 ? inst.GetOperand(1) : nullptr; if (lhs && rhs) { int vl = EmitValueToVReg(lhs, ctx, block, function); int vr = EmitValueToVReg(rhs, ctx, block, function); int vd = ctx.NewVReg(VRegType::kInt32); auto& a = block.Append(Opcode::AndRR, {Operand::VReg(vd), Operand::VReg(vl), Operand::VReg(vr)}); a.AddDef(vd); a.AddUse(vl); a.AddUse(vr); ctx.SetVReg(&inst, vd); } return; } // ---- Or ---- case ir::Opcode::Or: { const ir::Value* lhs = inst.GetNumOperands() >= 2 ? inst.GetOperand(0) : nullptr; const ir::Value* rhs = inst.GetNumOperands() >= 2 ? inst.GetOperand(1) : nullptr; if (lhs && rhs) { int vl = EmitValueToVReg(lhs, ctx, block, function); int vr = EmitValueToVReg(rhs, ctx, block, function); int vd = ctx.NewVReg(VRegType::kInt32); auto& a = block.Append(Opcode::OrRR, {Operand::VReg(vd), Operand::VReg(vl), Operand::VReg(vr)}); a.AddDef(vd); a.AddUse(vl); a.AddUse(vr); ctx.SetVReg(&inst, vd); } return; } // ---- Not ---- case ir::Opcode::Not: { const ir::Value* srcVal = inst.GetNumOperands() > 0 ? inst.GetOperand(0) : nullptr; if (srcVal) { int src = EmitValueToVReg(srcVal, ctx, block, function); int m1 = ctx.NewVReg(VRegType::kInt32); auto& mv1 = block.Append(Opcode::MovImm, {Operand::VReg(m1), Operand::Imm(-1)}); mv1.AddDef(m1); int vd = ctx.NewVReg(VRegType::kInt32); auto& eor = block.Append(Opcode::EorRR, {Operand::VReg(vd), Operand::VReg(src), Operand::VReg(m1)}); eor.AddDef(vd); eor.AddUse(src); eor.AddUse(m1); ctx.SetVReg(&inst, vd); } return; } // ---- FPExt ---- case ir::Opcode::FPExt: { const ir::Value* srcVal = inst.GetNumOperands() > 0 ? inst.GetOperand(0) : nullptr; if (srcVal) { int src = EmitValueToVReg(srcVal, ctx, block, function); int dst = ctx.NewVReg(VRegType::kFloat32); auto& mv = block.Append(Opcode::MovReg, {Operand::VReg(dst), Operand::VReg(src)}); mv.AddDef(dst); mv.AddUse(src); ctx.SetVReg(&inst, dst); } return; } // ---- FPTrunc ---- case ir::Opcode::FPTrunc: { const ir::Value* srcVal = inst.GetNumOperands() > 0 ? inst.GetOperand(0) : nullptr; if (srcVal) { int src = EmitValueToVReg(srcVal, ctx, block, function); int dst = ctx.NewVReg(VRegType::kFloat32); auto& mv = block.Append(Opcode::MovReg, {Operand::VReg(dst), Operand::VReg(src)}); mv.AddDef(dst); mv.AddUse(src); ctx.SetVReg(&inst, dst); } return; } // ---- GEP ---- case ir::Opcode::GEP: { auto& gep = static_cast(inst); ir::Value* base = gep.GetBase(); const auto& indices = gep.GetIndices(); int baseVreg = EmitValueToVReg(base, ctx, block, function); if (indices.empty()) { ctx.SetVReg(&inst, baseVreg); return; } const ir::Type* baseType = base->GetType().get(); size_t startIndex = 0; if (baseType->IsArray()) { startIndex = 1; // 跳过数组解码的第一个索引 } if (baseType->IsArray() && indices.size() > startIndex) { const ir::ArrayType* arrayType = static_cast(baseType); const std::vector& dims = arrayType->GetDimensions(); std::vector strides(dims.size()); int elementSize = 4; for (int i = static_cast(dims.size()) - 1; i >= 0; --i) { if (i == static_cast(dims.size()) - 1) strides[i] = elementSize; else strides[i] = strides[i + 1] * dims[i + 1]; } size_t numIndices = indices.size(); size_t effectiveIndices = numIndices - startIndex; if (effectiveIndices > dims.size()) effectiveIndices = dims.size(); // 偏移累加器初始化为 0 int offsetVreg = ctx.NewVReg(VRegType::kInt64); auto& zero = block.Append(Opcode::MovImm, {Operand::VReg(offsetVreg), Operand::Imm(0)}); zero.AddDef(offsetVreg); for (size_t i = 0; i < effectiveIndices; ++i) { size_t idxPos = startIndex + i; int idxVreg = EmitValueToVReg(indices[idxPos], ctx, block, function); // 确保索引是 Int64(地址计算必须是 64 位) if (ctx.GetType(idxVreg) == VRegType::kInt32) { int idxVreg64 = ctx.NewVReg(VRegType::kInt64); auto& sxt = block.Append(Opcode::Sxtw, {Operand::VReg(idxVreg64), Operand::VReg(idxVreg)}); sxt.AddDef(idxVreg64); sxt.AddUse(idxVreg); idxVreg = idxVreg64; } int strideVreg = ctx.NewVReg(VRegType::kInt64); auto& stride = block.Append(Opcode::MovImm, {Operand::VReg(strideVreg), Operand::Imm(strides[i])}); stride.AddDef(strideVreg); int prodVreg = ctx.NewVReg(VRegType::kInt64); auto& mul = block.Append(Opcode::MulRR, {Operand::VReg(prodVreg), Operand::VReg(idxVreg), Operand::VReg(strideVreg)}); mul.AddDef(prodVreg); mul.AddUse(idxVreg); mul.AddUse(strideVreg); int newOff = ctx.NewVReg(VRegType::kInt64); auto& add = block.Append(Opcode::AddRR, {Operand::VReg(newOff), Operand::VReg(offsetVreg), Operand::VReg(prodVreg)}); add.AddDef(newOff); add.AddUse(offsetVreg); add.AddUse(prodVreg); offsetVreg = newOff; } int resultVreg = ctx.NewVReg(VRegType::kInt64); auto& finalAdd = block.Append(Opcode::AddRR, {Operand::VReg(resultVreg), Operand::VReg(baseVreg), Operand::VReg(offsetVreg)}); finalAdd.AddDef(resultVreg); finalAdd.AddUse(baseVreg); finalAdd.AddUse(offsetVreg); ctx.SetVReg(&inst, resultVreg); } else if (indices.size() >= 1) { // 简单指针运算 int idxVreg = EmitValueToVReg(indices[0], ctx, block, function); if (ctx.GetType(idxVreg) == VRegType::kInt32) { int idxVreg64 = ctx.NewVReg(VRegType::kInt64); auto& sxt = block.Append(Opcode::Sxtw, {Operand::VReg(idxVreg64), Operand::VReg(idxVreg)}); sxt.AddDef(idxVreg64); sxt.AddUse(idxVreg); idxVreg = idxVreg64; } int strideVreg = ctx.NewVReg(VRegType::kInt64); int elemSize = 4; if (baseType->IsArray()) { const ir::ArrayType* arrType = static_cast(baseType); elemSize = GetTypeSize(arrType->GetElementType().get()); } auto& stride = block.Append(Opcode::MovImm, {Operand::VReg(strideVreg), Operand::Imm(elemSize)}); stride.AddDef(strideVreg); int prodVreg = ctx.NewVReg(VRegType::kInt64); auto& mul = block.Append(Opcode::MulRR, {Operand::VReg(prodVreg), Operand::VReg(idxVreg), Operand::VReg(strideVreg)}); mul.AddDef(prodVreg); mul.AddUse(idxVreg); mul.AddUse(strideVreg); int resultVreg = ctx.NewVReg(VRegType::kInt64); auto& add = block.Append(Opcode::AddRR, {Operand::VReg(resultVreg), Operand::VReg(baseVreg), Operand::VReg(prodVreg)}); add.AddDef(resultVreg); add.AddUse(baseVreg); add.AddUse(prodVreg); ctx.SetVReg(&inst, resultVreg); } return; } default: throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令,opcode: " + std::to_string(static_cast(inst.GetOpcode())))); } } // ========== LowerFunction:将 IR 函数转换为 MachineFunction ========== std::unique_ptr LowerFunction(const ir::Function& func) { auto machineFunc = std::make_unique(func.GetName()); VRegContext ctx; // 为函数参数分配 vreg struct ParamInfo { const ir::Value* arg; int vreg; bool isFloat; bool isPointer; }; std::vector paramInfos; for (const auto& arg : func.GetArguments()) { bool isFloat = arg->GetType()->IsFloat(); bool isPointer = arg->GetType()->IsPtrInt32() || arg->GetType()->IsPtrFloat() || arg->GetType()->IsPtrInt1(); VRegType ty = isFloat ? VRegType::kFloat32 : (isPointer ? VRegType::kInt64 : VRegType::kInt32); int vreg = ctx.NewVReg(ty); ctx.SetVReg(arg.get(), vreg); paramInfos.push_back({arg.get(), vreg, isFloat, isPointer}); } // IR 基本块 → MIR 基本块 映射 std::unordered_map blockMap; std::string funcName = func.GetName(); for (const auto& bb : func.GetBlocks()) { auto mirBB = std::make_unique(".L" + funcName + "_" + bb->GetName()); blockMap[bb.get()] = mirBB.get(); machineFunc->AddBasicBlock(std::move(mirBB)); } // 在入口基本块开头:从物理参数寄存器加载参数到 vreg if (!func.GetBlocks().empty()) { MachineBasicBlock* entryBB = blockMap[func.GetEntry()]; if (entryBB) { size_t intArgIdx = 0; size_t fpArgIdx = 0; for (const auto& param : paramInfos) { if (param.isFloat) { if (fpArgIdx < 8) { PhysReg reg = static_cast( static_cast(PhysReg::S0) + fpArgIdx); auto& mv = entryBB->Append(Opcode::MovReg, {Operand::VReg(param.vreg), Operand::Reg(reg)}); mv.AddDef(param.vreg); } fpArgIdx++; } else if (param.isPointer) { if (intArgIdx < 8) { PhysReg reg = static_cast( static_cast(PhysReg::X0) + intArgIdx); auto& mv = entryBB->Append(Opcode::MovReg, {Operand::VReg(param.vreg), Operand::Reg(reg)}); mv.AddDef(param.vreg); } intArgIdx++; } else { if (intArgIdx < 8) { PhysReg reg = static_cast( static_cast(PhysReg::W0) + intArgIdx); auto& mv = entryBB->Append(Opcode::MovReg, {Operand::VReg(param.vreg), Operand::Reg(reg)}); mv.AddDef(param.vreg); } intArgIdx++; } } } } // 转换每个基本块的指令 for (const auto& bb : func.GetBlocks()) { MachineBasicBlock* mirBB = blockMap[bb.get()]; if (!mirBB) throw std::runtime_error(FormatError("mir", "找不到基本块对应的 MIR 基本块")); for (const auto& inst : bb->GetInstructions()) { LowerInstruction(*inst, *machineFunc, ctx, *mirBB, blockMap); } } // 将 vreg 类型信息存入 MachineFunction(RA 阶段使用) for (const auto& [vreg, type] : ctx.vreg_types) { switch (type) { case VRegType::kInt32: machineFunc->SetVRegType(vreg, MachineFunction::VRegType::kInt32); break; case VRegType::kInt64: machineFunc->SetVRegType(vreg, MachineFunction::VRegType::kInt64); break; case VRegType::kFloat32: machineFunc->SetVRegType(vreg, MachineFunction::VRegType::kFloat32); break; } } // 构建 CFG 边(解析 B/BCond 中的 Label 目标) for (const auto& bb : func.GetBlocks()) { MachineBasicBlock* mirBB = blockMap[bb.get()]; auto& insts = mirBB->GetInstructions(); if (insts.empty()) continue; // 辅助:从指令中提取 Label 操作数并添加边 auto addLabelSuccessors = [&](const MachineInstr& inst) { for (const auto& op : inst.GetOperands()) { if (op.GetKind() == Operand::Kind::Label) { MachineBasicBlock* target = machineFunc->GetBlockByName(op.GetLabel()); if (target) { mirBB->AddSuccessor(target); target->AddPredecessor(mirBB); } } } }; // 辅助:添加 fallthrough 到下一个 IR 基本块 auto addFallthrough = [&]() { for (size_t i = 0; i + 1 < func.GetBlocks().size(); ++i) { if (func.GetBlocks()[i].get() == bb.get()) { const auto* nextBB = func.GetBlocks()[i + 1].get(); MachineBasicBlock* nextMIR = blockMap[nextBB]; if (nextMIR) { mirBB->AddSuccessor(nextMIR); nextMIR->AddPredecessor(mirBB); } break; } } }; const auto& last = insts.back(); if (last.GetOpcode() == Opcode::B) { // B 为最后一条指令:添加 B 的目标 addLabelSuccessors(last); // 若倒数第二条是 BCond,则 BCond 的目标也是后继(BCond; B 模式) if (insts.size() >= 2) { const auto& prev = insts[insts.size() - 2]; if (prev.GetOpcode() == Opcode::BCond) { addLabelSuccessors(prev); } } } else if (last.GetOpcode() == Opcode::BCond) { // BCond 为最后一条指令:添加 BCond 目标 + fallthrough addLabelSuccessors(last); // 若倒数第二条是 B(罕见:B; BCond),也添加 B 目标 if (insts.size() >= 2) { const auto& prev = insts[insts.size() - 2]; if (prev.GetOpcode() == Opcode::B) { addLabelSuccessors(prev); } } // BCond 之后无 B,则 false 分支 fallthrough addFallthrough(); } else if (last.GetOpcode() == Opcode::Ret) { // Ret 无后继 } else { // 非终结指令:fall-through 到下一个基本块 addFallthrough(); } } return machineFunc; } } // namespace // ========== LowerToMIR:入口函数 ========== std::unique_ptr LowerToMIR(const ir::Module& module) { DefaultContext(); auto machineModule = std::make_unique(); // 收集全局变量信息 for (const auto& global : module.GetGlobals()) { int size = GetTypeSize(global->GetType().get()); int alignment = global->GetType()->Alignment(); bool isZeroInit = !global->HasInitializer(); bool hasInitData = false; uint64_t initData = 0; if (!isZeroInit) { const auto& init = global->GetInitializer(); if (init.size() == 1) { if (auto* cf = dynamic_cast(init[0])) { float fval = cf->GetValue(); uint32_t bits; memcpy(&bits, &fval, sizeof(bits)); initData = bits; hasInitData = true; } else if (auto* ci = dynamic_cast(init[0])) { initData = static_cast(ci->GetValue()); hasInitData = true; } } } machineModule->AddGlobal(global->GetName(), size, alignment, isZeroInit, hasInitData, initData); } // 转换所有函数 for (const auto& func : module.GetFunctions()) { try { auto machineFunc = LowerFunction(*func); machineModule->AddFunction(std::move(machineFunc)); } catch (const std::runtime_error& e) { throw std::runtime_error( FormatError("mir", "转换函数失败: " + func->GetName() + " - " + e.what())); } } if (machineModule->GetFunctions().empty()) { throw std::runtime_error(FormatError("mir", "模块中没有成功转换的函数")); } return machineModule; } } // namespace mir