From 1993380d4a1f34aa519a2de156929c1ec633c9d1 Mon Sep 17 00:00:00 2001 From: lzkk <956449176@qq.com> Date: Thu, 28 May 2026 01:12:52 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E7=A7=BB=E9=99=A4=20git=20=E5=86=B2?= =?UTF-8?q?=E7=AA=81=E6=AE=8B=E7=95=99=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mir/Lowering.cpp.orig | 1811 ------------------------------------- src/mir/Lowering.cpp.rej | 26 - 2 files changed, 1837 deletions(-) delete mode 100644 src/mir/Lowering.cpp.orig delete mode 100644 src/mir/Lowering.cpp.rej diff --git a/src/mir/Lowering.cpp.orig b/src/mir/Lowering.cpp.orig deleted file mode 100644 index 29bb154a..00000000 --- a/src/mir/Lowering.cpp.orig +++ /dev/null @@ -1,1811 +0,0 @@ -#include "mir/MIR.h" - -#include -#include -#include -#include - -#include "ir/IR.h" -#include "utils/Log.h" - -namespace mir -{ - namespace - { - - using ValueVRegMap = std::unordered_map; - using LocalScalarMap = std::unordered_map; - using LocalArrayMap = std::unordered_map; - using BlockMap = std::unordered_map; - - static bool TryGetConstantInt(const ir::Value *value, int &out); - - static int GetTypeSize(const std::shared_ptr &type) - { - if (!type) - return 4; - if (type->IsPtrInt32() || type->IsPtrFloat32()) - return 8; - return 4; - } - - static int AlignTo(int value, int align) - { - return ((value + align - 1) / align) * align; - } - - static bool IsPointerValue(const ir::Value *value) - { - if (!value) - return false; - auto type = value->GetType(); - return type && (type->IsPtrInt32() || type->IsPtrFloat32()); - } - - static bool IsPointerType(const std::shared_ptr &type) - { - return type && (type->IsPtrInt32() || type->IsPtrFloat32()); - } - - static bool IsFloatType(const std::shared_ptr &type) - { - return type && type->IsFloat32(); - } - - static bool IsFloatValue(const ir::Value *value) - { - return value && IsFloatType(value->GetType()); - } - - static bool IsIntegerCompareOpcode(ir::Opcode opcode) - { - switch (opcode) - { - case ir::Opcode::Eq: - case ir::Opcode::Ne: - case ir::Opcode::Lt: - case ir::Opcode::Le: - case ir::Opcode::Gt: - case ir::Opcode::Ge: - return true; - default: - return false; - } - } - - static CondCode GetCondCodeForCompareOpcode(ir::Opcode opcode) - { - switch (opcode) - { - case ir::Opcode::Eq: - return CondCode::EQ; - case ir::Opcode::Ne: - return CondCode::NE; - case ir::Opcode::Lt: - return CondCode::LT; - case ir::Opcode::Le: - return CondCode::LE; - case ir::Opcode::Gt: - return CondCode::GT; - case ir::Opcode::Ge: - return CondCode::GE; - default: - throw std::runtime_error(FormatError("mir", "不支持的比较 opcode")); - } - } - - static CondCode NegateCondCode(CondCode cond) - { - switch (cond) - { - case CondCode::EQ: - return CondCode::NE; - case CondCode::NE: - return CondCode::EQ; - case CondCode::LT: - return CondCode::GE; - case CondCode::LE: - return CondCode::GT; - case CondCode::GT: - return CondCode::LE; - case CondCode::GE: - return CondCode::LT; - default: - return CondCode::NE; - } - } - - // 交换比较操作数时反转条件码(aa) - static CondCode SwapCondCode(CondCode cond) - { - switch (cond) - { - case CondCode::LT: - return CondCode::GT; - case CondCode::LE: - return CondCode::GE; - case CondCode::GT: - return CondCode::LT; - case CondCode::GE: - return CondCode::LE; - default: - return cond; // EQ/NE 对称 - } - } - - static PhysReg GetArgWReg(size_t index) - { - static const PhysReg regs[] = { - PhysReg::W0, PhysReg::W1, PhysReg::W2, PhysReg::W3, - PhysReg::W4, PhysReg::W5, PhysReg::W6, PhysReg::W7}; - return index < 8 ? regs[index] : PhysReg::W0; - } - - static PhysReg GetArgXReg(size_t index) - { - static const PhysReg regs[] = { - PhysReg::X0, PhysReg::X1, PhysReg::X2, PhysReg::X3, - PhysReg::X4, PhysReg::X5, PhysReg::X6, PhysReg::X7}; - return index < 8 ? regs[index] : PhysReg::X0; - } - - static PhysReg GetArgSReg(size_t index) - { - static const PhysReg regs[] = { - PhysReg::S0, PhysReg::S1, PhysReg::S2, PhysReg::S3, - PhysReg::S4, PhysReg::S5, PhysReg::S6, PhysReg::S7}; - return index < 8 ? regs[index] : PhysReg::S0; - } - - static bool TryGetConstantInt(const ir::Value *value, int &out) - { - if (auto *constant = dynamic_cast(value)) - { - out = constant->GetValue(); - return true; - } - return false; - } - - static int FloatToBits(float value) - { - int bits = 0; - std::memcpy(&bits, &value, sizeof(bits)); - return bits; - } - - static bool TryGetConstantFloatBits(const ir::Value *value, int &out) - { - if (auto *constant = dynamic_cast(value)) - { - out = FloatToBits(static_cast(constant->GetValue())); - return true; - } - return false; - } - - static const ir::GlobalVariable *AsGlobalScalarObject(const ir::Value *value) - { - auto *global = dynamic_cast(value); - if (!global) - return nullptr; - if (global->IsArray()) - return nullptr; - if (!IsPointerValue(global)) - return nullptr; - return global; - } - - static const ir::GlobalVariable *AsGlobalArrayObject(const ir::Value *value) - { - auto *global = dynamic_cast(value); - if (!global) - return nullptr; - if (!global->IsArray()) - return nullptr; - if (!IsPointerValue(global)) - return nullptr; - return global; - } - - static bool IsZeroIntConstant(const ir::Value *value) - { - int imm = 0; - return TryGetConstantInt(value, imm) && imm == 0; - } - - [[maybe_unused]] static bool IsSolelyConsumedByCondBr(const ir::Instruction &inst) - { - const auto &uses = inst.GetUses(); - if (uses.size() != 1) - return false; - auto *user = uses.front().GetUser(); - return dynamic_cast(user) != nullptr; - } - - static bool IsSolelyConsumedByCanonicalBoolUse(const ir::Instruction &inst) - { - const auto &uses = inst.GetUses(); - if (uses.size() != 1) - return false; - auto *user_inst = dynamic_cast(uses.front().GetUser()); - if (!user_inst) - return false; - if (dynamic_cast(user_inst)) - return true; - if (auto *cast = dynamic_cast(user_inst)) - return cast->GetOpcode() == ir::Opcode::ZExt; - auto *bin = dynamic_cast(user_inst); - if (!bin) - return false; - if (bin->GetOpcode() != ir::Opcode::Eq && bin->GetOpcode() != ir::Opcode::Ne) - return false; - return (bin->GetLhs() == &inst && IsZeroIntConstant(bin->GetRhs())) || - (bin->GetRhs() == &inst && IsZeroIntConstant(bin->GetLhs())); - } - - static bool TryResolveDirectScalarSlot(const ir::Value *ptr, - const LocalScalarMap &scalar_slots, - int &out_slot) - { - auto it = scalar_slots.find(ptr); - if (it != scalar_slots.end()) - { - out_slot = it->second; - return true; - } - auto *gep = dynamic_cast(ptr); - if (!gep) - return false; - int idx = 0; - if (!TryGetConstantInt(gep->GetIndex(), idx)) - return false; - if (idx != 0) - return false; - auto base_it = scalar_slots.find(gep->GetBasePtr()); - if (base_it != scalar_slots.end()) - { - out_slot = base_it->second; - return true; - } - return false; - } - - static int EmitIntValue(const ir::Value *value, MachineFunction &function, - ValueVRegMap &value_vregs, const LocalScalarMap &scalar_slots, - const LocalArrayMap &array_slots, MachineBasicBlock &block); - - static int EmitFloatValue(const ir::Value *value, MachineFunction &function, - ValueVRegMap &value_vregs, MachineBasicBlock &block); - - static int EmitPtrValue(const ir::Value *value, MachineFunction &function, - ValueVRegMap &value_vregs, const LocalScalarMap &scalar_slots, - const LocalArrayMap &array_slots, MachineBasicBlock &block); - - static int EmitIntValue(const ir::Value *value, MachineFunction &function, - ValueVRegMap &value_vregs, const LocalScalarMap &scalar_slots, - const LocalArrayMap &array_slots, MachineBasicBlock &block) - { - if (!value) - { - int vreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::MovImm, {Operand::VReg(vreg, VRegClass::Int), Operand::Imm(0)}).SetRematerializable(true).SetRematImm(0); - return vreg; - } - - auto it = value_vregs.find(value); - if (it != value_vregs.end()) - { - if (function.GetVRegClass(it->second) == VRegClass::Float) - { - int dst = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::FCvtzs, - {Operand::VReg(dst, VRegClass::Int), Operand::VReg(it->second, VRegClass::Float)}); - return dst; - } - return it->second; - } - - int imm = 0; - if (TryGetConstantInt(value, imm)) - { - int vreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::MovImm, {Operand::VReg(vreg, VRegClass::Int), Operand::Imm(imm)}).SetRematerializable(true).SetRematImm(imm); - value_vregs[value] = vreg; - return vreg; - } - - if (TryGetConstantFloatBits(value, imm)) - { - int vreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::MovImm, {Operand::VReg(vreg, VRegClass::Int), Operand::Imm(imm)}).SetRematerializable(true).SetRematImm(imm); - value_vregs[value] = vreg; - return vreg; - } - - if (auto *global = AsGlobalScalarObject(value)) - { - int vreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::LoadGlobal, - {Operand::VReg(vreg, VRegClass::Int), Operand::Symbol(global->GetName())}); - value_vregs[value] = vreg; - return vreg; - } - - if (auto *cast = dynamic_cast(value)) - { - if (cast->GetOpcode() == ir::Opcode::ZExt) - { - int src = EmitIntValue(cast->GetOperandValue(), function, value_vregs, - scalar_slots, array_slots, block); - value_vregs[value] = src; - return src; - } - if (cast->GetOpcode() == ir::Opcode::FPToSI) - { - int src = EmitFloatValue(cast->GetOperandValue(), function, value_vregs, block); - int dst = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::FCvtzs, - {Operand::VReg(dst, VRegClass::Int), Operand::VReg(src, VRegClass::Float)}); - value_vregs[value] = dst; - return dst; - } - } - - if (auto *bin = dynamic_cast(value)) - { - if (IsIntegerCompareOpcode(bin->GetOpcode())) - { - // 常量折叠到 CmpImm,消除冗余 MovImm - int lhs_imm, rhs_imm; - bool lhs_const = TryGetConstantInt(bin->GetLhs(), lhs_imm); - bool rhs_const = TryGetConstantInt(bin->GetRhs(), rhs_imm); - auto imm_fits = [](int imm) { return imm >= 0 && imm <= 4095; }; - - CondCode cond = GetCondCodeForCompareOpcode(bin->GetOpcode()); - - if (rhs_const && imm_fits(rhs_imm)) - { - int lhs = EmitIntValue(bin->GetLhs(), function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::CmpImm, - {Operand::VReg(lhs, VRegClass::Int), Operand::Imm(rhs_imm)}); - } - else if (lhs_const && imm_fits(lhs_imm)) - { - int rhs = EmitIntValue(bin->GetRhs(), function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::CmpImm, - {Operand::VReg(rhs, VRegClass::Int), Operand::Imm(lhs_imm)}); - cond = SwapCondCode(cond); - } - else - { - int lhs = EmitIntValue(bin->GetLhs(), function, value_vregs, - scalar_slots, array_slots, block); - int rhs = EmitIntValue(bin->GetRhs(), function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::CmpRR, - {Operand::VReg(lhs, VRegClass::Int), Operand::VReg(rhs, VRegClass::Int)}); - } - - int dst = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::CSet, - {Operand::VReg(dst, VRegClass::Int), - Operand::Imm(static_cast(cond))}); - value_vregs[value] = dst; - return dst; - } - - if (IsFloatType(bin->GetType())) - { - return EmitFloatValue(value, function, value_vregs, block); - } - - Opcode opcode = Opcode::AddRR; - switch (bin->GetOpcode()) - { - case ir::Opcode::Add: - opcode = Opcode::AddRR; - break; - case ir::Opcode::Sub: - opcode = Opcode::SubRR; - break; - case ir::Opcode::Mul: - opcode = Opcode::MulRR; - break; - case ir::Opcode::Div: - opcode = Opcode::DivRR; - break; - case ir::Opcode::Mod: - opcode = Opcode::ModRR; - break; - default: - break; - } - - int lhs = EmitIntValue(bin->GetLhs(), function, value_vregs, - scalar_slots, array_slots, block); - int rhs = EmitIntValue(bin->GetRhs(), function, value_vregs, - scalar_slots, array_slots, block); - int dst = function.CreateVReg(VRegClass::Int); - - if (opcode == Opcode::MulRR) - { - auto *rhs_const = dynamic_cast(bin->GetRhs()); - if (rhs_const) - { - int val = rhs_const->GetValue(); - if (val > 0 && (val & (val - 1)) == 0) - { - int shift = 0; - while (val > 1) - { - val >>= 1; - ++shift; - } - block.Append(Opcode::ShlRR, - {Operand::VReg(dst, VRegClass::Int), - Operand::VReg(lhs, VRegClass::Int), - Operand::Imm(shift)}); - value_vregs[value] = dst; - return dst; - } - } - } - - if (opcode == Opcode::DivRR) - { - auto *rhs_const = dynamic_cast(bin->GetRhs()); - if (rhs_const) - { - int val = rhs_const->GetValue(); - if (val == 1) - { - value_vregs[value] = lhs; - return lhs; - } - if (val == -1) - { - block.Append(Opcode::NegRR, - {Operand::VReg(dst, VRegClass::Int), - Operand::VReg(lhs, VRegClass::Int)}); - value_vregs[value] = dst; - return dst; - } - // 2的幂次除法(含正负)改用 sdiv,比移位序列更短 - } - } - - if (opcode == Opcode::ModRR) - { - auto *rhs_const = dynamic_cast(bin->GetRhs()); - if (rhs_const) - { - int val = rhs_const->GetValue(); - // x % 1 == 0, x % -1 == 0 - if (val == 1 || val == -1) - { - block.Append(Opcode::MovImm, - {Operand::VReg(dst, VRegClass::Int), - Operand::Imm(0)}).SetRematerializable(true).SetRematImm(0); - value_vregs[value] = dst; - return dst; - } - // 2的幂次取模(含正负)改用 ModRR(sdiv+msub),比移位序列更短 - } - } - - // Add/Sub 常量折叠到立即数操作码 - int rhs_imm_val; - bool rhs_is_imm = false; - if ((opcode == Opcode::AddRR || opcode == Opcode::SubRR) && - bin->GetRhs() && TryGetConstantInt(bin->GetRhs(), rhs_imm_val) && - rhs_imm_val >= 0 && rhs_imm_val <= 4095) - { - rhs_is_imm = true; - if (opcode == Opcode::AddRR) - opcode = Opcode::AddImm; - else - opcode = Opcode::SubImm; - block.Append(opcode, - {Operand::VReg(dst, VRegClass::Int), - Operand::VReg(lhs, VRegClass::Int), - Operand::Imm(rhs_imm_val)}); - } - else - { - block.Append(opcode, - {Operand::VReg(dst, VRegClass::Int), - Operand::VReg(lhs, VRegClass::Int), - Operand::VReg(rhs, VRegClass::Int)}); - } - value_vregs[value] = dst; - return dst; - } - - if (auto *phi = dynamic_cast(value)) - { - auto phi_it = value_vregs.find(value); - if (phi_it != value_vregs.end()) - return phi_it->second; - } - - if (auto *load = dynamic_cast(value)) - { - int scalar_slot = -1; - if (TryResolveDirectScalarSlot(load->GetPtr(), scalar_slots, scalar_slot)) - { - int vreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::LoadStack, - {Operand::VReg(vreg, VRegClass::Int), Operand::FrameIndex(scalar_slot)}); - value_vregs[value] = vreg; - return vreg; - } - - if (auto *global = AsGlobalScalarObject(load->GetPtr())) - { - int vreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::LoadGlobal, - {Operand::VReg(vreg, VRegClass::Int), Operand::Symbol(global->GetName())}); - value_vregs[value] = vreg; - return vreg; - } - - int addr = EmitPtrValue(load->GetPtr(), function, value_vregs, - scalar_slots, array_slots, block); - int vreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::LoadMem, - {Operand::VReg(vreg, VRegClass::Int), Operand::VReg(addr, VRegClass::Ptr)}); - value_vregs[value] = vreg; - return vreg; - } - - int vreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::MovImm, {Operand::VReg(vreg, VRegClass::Int), Operand::Imm(0)}).SetRematerializable(true).SetRematImm(0); - value_vregs[value] = vreg; - return vreg; - } - - static int EmitFloatValue(const ir::Value *value, MachineFunction &function, - ValueVRegMap &value_vregs, MachineBasicBlock &block) - { - if (!value) - { - int vreg = function.CreateVReg(VRegClass::Float); - int wvreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::MovImm, {Operand::VReg(wvreg, VRegClass::Int), Operand::Imm(0)}).SetRematerializable(true).SetRematImm(0); - block.Append(Opcode::FMovWS, - {Operand::VReg(vreg, VRegClass::Float), Operand::VReg(wvreg, VRegClass::Int)}); - return vreg; - } - - auto it = value_vregs.find(value); - if (it != value_vregs.end()) - { - if (function.GetVRegClass(it->second) != VRegClass::Float) - { - int dst = function.CreateVReg(VRegClass::Float); - block.Append(Opcode::Scvtf, - {Operand::VReg(dst, VRegClass::Float), Operand::VReg(it->second, VRegClass::Int)}); - return dst; - } - return it->second; - } - - int bits = 0; - if (TryGetConstantFloatBits(value, bits)) - { - int wvreg = function.CreateVReg(VRegClass::Int); - int vreg = function.CreateVReg(VRegClass::Float); - block.Append(Opcode::MovImm, {Operand::VReg(wvreg, VRegClass::Int), Operand::Imm(bits)}).SetRematerializable(true).SetRematImm(bits); - block.Append(Opcode::FMovWS, - {Operand::VReg(vreg, VRegClass::Float), Operand::VReg(wvreg, VRegClass::Int)}); - value_vregs[value] = vreg; - return vreg; - } - - if (auto *global = AsGlobalScalarObject(value)) - { - int vreg = function.CreateVReg(VRegClass::Float); - block.Append(Opcode::LoadGlobal, - {Operand::VReg(vreg, VRegClass::Float), Operand::Symbol(global->GetName())}); - value_vregs[value] = vreg; - return vreg; - } - - if (auto *cast = dynamic_cast(value)) - { - if (cast->GetOpcode() == ir::Opcode::SIToFP) - { - int src = EmitIntValue(cast->GetOperandValue(), function, value_vregs, - LocalScalarMap(), LocalArrayMap(), block); - int dst = function.CreateVReg(VRegClass::Float); - block.Append(Opcode::Scvtf, - {Operand::VReg(dst, VRegClass::Float), Operand::VReg(src, VRegClass::Int)}); - value_vregs[value] = dst; - return dst; - } - } - - if (auto *bin = dynamic_cast(value)) - { - if (IsFloatType(bin->GetType())) - { - Opcode opcode = Opcode::FAddRR; - switch (bin->GetOpcode()) - { - case ir::Opcode::Add: - opcode = Opcode::FAddRR; - break; - case ir::Opcode::Sub: - opcode = Opcode::FSubRR; - break; - case ir::Opcode::Mul: - opcode = Opcode::FMulRR; - break; - case ir::Opcode::Div: - opcode = Opcode::FDivRR; - break; - default: - break; - } - - int lhs = EmitFloatValue(bin->GetLhs(), function, value_vregs, block); - int rhs = EmitFloatValue(bin->GetRhs(), function, value_vregs, block); - int dst = function.CreateVReg(VRegClass::Float); - block.Append(opcode, - {Operand::VReg(dst, VRegClass::Float), - Operand::VReg(lhs, VRegClass::Float), - Operand::VReg(rhs, VRegClass::Float)}); - value_vregs[value] = dst; - return dst; - } - } - - if (auto *phi = dynamic_cast(value)) - { - auto phi_it = value_vregs.find(value); - if (phi_it != value_vregs.end()) - return phi_it->second; - } - - if (auto *load = dynamic_cast(value)) - { - int scalar_slot = -1; - LocalScalarMap dummy_scalar; - if (TryResolveDirectScalarSlot(load->GetPtr(), dummy_scalar, scalar_slot)) - { - int vreg = function.CreateVReg(VRegClass::Float); - block.Append(Opcode::LoadStack, - {Operand::VReg(vreg, VRegClass::Float), Operand::FrameIndex(scalar_slot)}); - value_vregs[value] = vreg; - return vreg; - } - } - - int vreg = function.CreateVReg(VRegClass::Float); - int wvreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::MovImm, {Operand::VReg(wvreg, VRegClass::Int), Operand::Imm(0)}).SetRematerializable(true).SetRematImm(0); - block.Append(Opcode::FMovWS, - {Operand::VReg(vreg, VRegClass::Float), Operand::VReg(wvreg, VRegClass::Int)}); - value_vregs[value] = vreg; - return vreg; - } - - static int EmitPtrValue(const ir::Value *value, MachineFunction &function, - ValueVRegMap &value_vregs, const LocalScalarMap &scalar_slots, - const LocalArrayMap &array_slots, MachineBasicBlock &block) - { - auto it = value_vregs.find(value); - if (it != value_vregs.end()) - return it->second; - - if (auto *global_scalar = AsGlobalScalarObject(value)) - { - int vreg = function.CreateVReg(VRegClass::Ptr); - block.Append(Opcode::LoadGlobalAddr, - {Operand::VReg(vreg, VRegClass::Ptr), Operand::Symbol(global_scalar->GetName())}); - value_vregs[value] = vreg; - return vreg; - } - - if (auto *global_array = AsGlobalArrayObject(value)) - { - int vreg = function.CreateVReg(VRegClass::Ptr); - block.Append(Opcode::LoadGlobalAddr, - {Operand::VReg(vreg, VRegClass::Ptr), Operand::Symbol(global_array->GetName())}); - value_vregs[value] = vreg; - return vreg; - } - - auto scalar_it = scalar_slots.find(value); - if (scalar_it != scalar_slots.end()) - { - int vreg = function.CreateVReg(VRegClass::Ptr); - block.Append(Opcode::LoadStackAddr, - {Operand::VReg(vreg, VRegClass::Ptr), Operand::FrameIndex(scalar_it->second)}); - value_vregs[value] = vreg; - return vreg; - } - - auto array_it = array_slots.find(value); - if (array_it != array_slots.end()) - { - int vreg = function.CreateVReg(VRegClass::Ptr); - block.Append(Opcode::LoadStackAddr, - {Operand::VReg(vreg, VRegClass::Ptr), Operand::FrameIndex(array_it->second)}); - value_vregs[value] = vreg; - return vreg; - } - - auto *gep = dynamic_cast(value); - if (gep) - { - int base = EmitPtrValue(gep->GetBasePtr(), function, value_vregs, - scalar_slots, array_slots, block); - - int idx_imm = 0; - if (TryGetConstantInt(gep->GetIndex(), idx_imm)) - { - const int byte_offset = static_cast(static_cast(idx_imm) * 4u); - if (byte_offset == 0) - { - value_vregs[value] = base; - return base; - } - int dst = function.CreateVReg(VRegClass::Ptr); - int offset_vreg = function.CreateVReg(VRegClass::Ptr); - int abs_off = byte_offset > 0 ? byte_offset : -byte_offset; - block.Append(Opcode::MovImm, {Operand::VReg(offset_vreg, VRegClass::Ptr), Operand::Imm(abs_off)}).SetRematerializable(true).SetRematImm(abs_off); - if (byte_offset > 0) - { - block.Append(Opcode::AddRR, - {Operand::VReg(dst, VRegClass::Ptr), - Operand::VReg(base, VRegClass::Ptr), - Operand::VReg(offset_vreg, VRegClass::Ptr)}); - } - else - { - block.Append(Opcode::SubRR, - {Operand::VReg(dst, VRegClass::Ptr), - Operand::VReg(base, VRegClass::Ptr), - Operand::VReg(offset_vreg, VRegClass::Ptr)}); - } - value_vregs[value] = dst; - return dst; - } - - int idx = EmitIntValue(gep->GetIndex(), function, value_vregs, - scalar_slots, array_slots, block); - int sext = function.CreateVReg(VRegClass::Ptr); - block.Append(Opcode::Sxtw, - {Operand::VReg(sext, VRegClass::Ptr), Operand::VReg(idx, VRegClass::Int)}); - int shifted = function.CreateVReg(VRegClass::Ptr); - block.Append(Opcode::ShlRR, - {Operand::VReg(shifted, VRegClass::Ptr), - Operand::VReg(sext, VRegClass::Ptr), - Operand::Imm(2)}); - int dst = function.CreateVReg(VRegClass::Ptr); - block.Append(Opcode::AddRR, - {Operand::VReg(dst, VRegClass::Ptr), - Operand::VReg(base, VRegClass::Ptr), - Operand::VReg(shifted, VRegClass::Ptr)}); - value_vregs[value] = dst; - return dst; - } - - if (IsPointerValue(value)) - { - auto vreg_it = value_vregs.find(value); - if (vreg_it != value_vregs.end()) - return vreg_it->second; - } - - int vreg = function.CreateVReg(VRegClass::Ptr); - block.Append(Opcode::MovImm, {Operand::VReg(vreg, VRegClass::Ptr), Operand::Imm(0)}).SetRematerializable(true).SetRematImm(0); - value_vregs[value] = vreg; - return vreg; - } - - static void EmitCompareToFlags(const ir::BinaryInst &bin, - MachineFunction &function, - ValueVRegMap &value_vregs, - const LocalScalarMap &scalar_slots, - const LocalArrayMap &array_slots, - MachineBasicBlock &block) - { - if (IsFloatValue(bin.GetLhs()) || IsFloatValue(bin.GetRhs())) - { - int lhs = EmitFloatValue(bin.GetLhs(), function, value_vregs, block); - int rhs = EmitFloatValue(bin.GetRhs(), function, value_vregs, block); - block.Append(Opcode::FCmpRR, - {Operand::VReg(lhs, VRegClass::Float), Operand::VReg(rhs, VRegClass::Float)}); - return; - } - - // 常量折叠到 CmpImm - int lhs_imm, rhs_imm; - bool lhs_const = TryGetConstantInt(bin.GetLhs(), lhs_imm); - bool rhs_const = TryGetConstantInt(bin.GetRhs(), rhs_imm); - auto imm_fits = [](int imm) { return imm >= 0 && imm <= 4095; }; - - if (rhs_const && imm_fits(rhs_imm)) - { - int lhs = EmitIntValue(bin.GetLhs(), function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::CmpImm, - {Operand::VReg(lhs, VRegClass::Int), Operand::Imm(rhs_imm)}); - } - else if (lhs_const && imm_fits(lhs_imm)) - { - int rhs = EmitIntValue(bin.GetRhs(), function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::CmpImm, - {Operand::VReg(rhs, VRegClass::Int), Operand::Imm(lhs_imm)}); - } - else - { - int lhs = EmitIntValue(bin.GetLhs(), function, value_vregs, - scalar_slots, array_slots, block); - int rhs = EmitIntValue(bin.GetRhs(), function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::CmpRR, - {Operand::VReg(lhs, VRegClass::Int), Operand::VReg(rhs, VRegClass::Int)}); - } - } - - static bool TryEmitCondValueToFlags(const ir::Value *value, - MachineFunction &function, - ValueVRegMap &value_vregs, - const LocalScalarMap &scalar_slots, - const LocalArrayMap &array_slots, - MachineBasicBlock &block, - CondCode &true_cond, int depth = 0) - { - if (!value || depth > 8) - return false; - - if (auto *cast = dynamic_cast(value)) - { - if (cast->GetOpcode() == ir::Opcode::ZExt) - { - return TryEmitCondValueToFlags(cast->GetOperandValue(), - function, value_vregs, scalar_slots, array_slots, - block, true_cond, depth + 1); - } - } - - if (auto *bin = dynamic_cast(value)) - { - if (IsIntegerCompareOpcode(bin->GetOpcode())) - { - if (bin->GetOpcode() == ir::Opcode::Eq || bin->GetOpcode() == ir::Opcode::Ne) - { - const ir::Value *inner = nullptr; - if (IsZeroIntConstant(bin->GetLhs())) - inner = bin->GetRhs(); - else if (IsZeroIntConstant(bin->GetRhs())) - inner = bin->GetLhs(); - - if (inner) - { - CondCode inner_cond = CondCode::NE; - if (TryEmitCondValueToFlags(inner, function, value_vregs, - scalar_slots, array_slots, - block, inner_cond, depth + 1)) - { - true_cond = (bin->GetOpcode() == ir::Opcode::Eq) - ? NegateCondCode(inner_cond) - : inner_cond; - return true; - } - } - } - - EmitCompareToFlags(*bin, function, value_vregs, scalar_slots, array_slots, block); - true_cond = GetCondCodeForCompareOpcode(bin->GetOpcode()); - return true; - } - } - - if (IsFloatValue(value)) - { - int vreg = EmitFloatValue(value, function, value_vregs, block); - int zero_w = function.CreateVReg(VRegClass::Int); - int zero_s = function.CreateVReg(VRegClass::Float); - block.Append(Opcode::MovImm, {Operand::VReg(zero_w, VRegClass::Int), Operand::Imm(0)}).SetRematerializable(true).SetRematImm(0); - block.Append(Opcode::FMovWS, - {Operand::VReg(zero_s, VRegClass::Float), Operand::VReg(zero_w, VRegClass::Int)}); - block.Append(Opcode::FCmpRR, - {Operand::VReg(vreg, VRegClass::Float), Operand::VReg(zero_s, VRegClass::Float)}); - true_cond = CondCode::NE; - return true; - } - - int vreg = EmitIntValue(value, function, value_vregs, scalar_slots, array_slots, block); - int zero = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::MovImm, {Operand::VReg(zero, VRegClass::Int), Operand::Imm(0)}).SetRematerializable(true).SetRematImm(0); - block.Append(Opcode::CmpRR, - {Operand::VReg(vreg, VRegClass::Int), Operand::VReg(zero, VRegClass::Int)}); - true_cond = CondCode::NE; - return true; - } - - static void EmitStackPointerAdjust(MachineBasicBlock &block, Opcode opcode, int amount) - { - if (amount <= 0) - return; - block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X14), Operand::Imm(amount)}); - block.Append(opcode, {Operand::Reg(PhysReg::SP), Operand::Reg(PhysReg::SP), Operand::Reg(PhysReg::X14)}); - } - - static int ComputeStackArgumentBytes(const ir::CallInst &call) - { - int total = 0; - size_t gp_idx = 0; - size_t fp_idx = 0; - for (size_t i = 0; i < call.GetNumArgs(); ++i) - { - auto *arg = call.GetArg(i); - auto type = arg ? arg->GetType() : nullptr; - if (IsFloatType(type)) - { - if (fp_idx < 8) - ++fp_idx; - else - total += 8; - } - else - { - if (gp_idx < 8) - ++gp_idx; - else - total += 8; - } - } - return total; - } - - static void LowerFunctionParams(const ir::Function &function, - MachineFunction &machine_func, - ValueVRegMap &value_vregs) - { - if (!machine_func.GetEntryPtr()) - return; - - auto &entry = machine_func.GetEntry(); - const auto ¶ms = function.GetParams(); - size_t gp_idx = 0; - size_t fp_idx = 0; - int callee_stack_offset = 0; - - for (const auto ¶m : params) - { - if (!param) - continue; - - if (IsFloatType(param->GetType())) - { - if (fp_idx < 8) - { - int vreg = machine_func.CreateVReg(VRegClass::Float); - entry.Append(Opcode::MovReg, - {Operand::VReg(vreg, VRegClass::Float), - Operand::Reg(GetArgSReg(fp_idx))}); - value_vregs[param.get()] = vreg; - ++fp_idx; - } - else - { - const int arg_slot = machine_func.CreateCalleeStackArgFrameIndex(GetTypeSize(param->GetType())); - machine_func.GetFrameSlot(arg_slot).offset = callee_stack_offset; - callee_stack_offset += 8; - int vreg = machine_func.CreateVReg(VRegClass::Float); - entry.Append(Opcode::LoadStack, - {Operand::VReg(vreg, VRegClass::Float), Operand::FrameIndex(arg_slot)}); - value_vregs[param.get()] = vreg; - } - } - else if (IsPointerType(param->GetType())) - { - if (gp_idx < 8) - { - int vreg = machine_func.CreateVReg(VRegClass::Ptr); - entry.Append(Opcode::MovReg, - {Operand::VReg(vreg, VRegClass::Ptr), - Operand::Reg(GetArgXReg(gp_idx))}); - value_vregs[param.get()] = vreg; - ++gp_idx; - } - else - { - const int arg_slot = machine_func.CreateCalleeStackArgFrameIndex(GetTypeSize(param->GetType())); - machine_func.GetFrameSlot(arg_slot).offset = callee_stack_offset; - callee_stack_offset += 8; - int vreg = machine_func.CreateVReg(VRegClass::Ptr); - entry.Append(Opcode::LoadStack, - {Operand::VReg(vreg, VRegClass::Ptr), Operand::FrameIndex(arg_slot)}); - value_vregs[param.get()] = vreg; - } - } - else - { - if (gp_idx < 8) - { - int vreg = machine_func.CreateVReg(VRegClass::Int); - entry.Append(Opcode::MovReg, - {Operand::VReg(vreg, VRegClass::Int), - Operand::Reg(GetArgWReg(gp_idx))}); - value_vregs[param.get()] = vreg; - ++gp_idx; - } - else - { - const int arg_slot = machine_func.CreateCalleeStackArgFrameIndex(GetTypeSize(param->GetType())); - machine_func.GetFrameSlot(arg_slot).offset = callee_stack_offset; - callee_stack_offset += 8; - int vreg = machine_func.CreateVReg(VRegClass::Int); - entry.Append(Opcode::LoadStack, - {Operand::VReg(vreg, VRegClass::Int), Operand::FrameIndex(arg_slot)}); - value_vregs[param.get()] = vreg; - } - } - } - } - - static void EmitPhiValueStores(const ir::BasicBlock *src_bb, - const ir::BasicBlock *dst_bb, - MachineFunction &function, - const ValueVRegMap &value_vregs, - const LocalScalarMap &scalar_slots, - const LocalArrayMap &array_slots, - MachineBasicBlock &mir_block) - { - if (!src_bb || !dst_bb) - return; - - for (const auto &inst_ptr : dst_bb->GetInstructions()) - { - auto *phi = dynamic_cast(inst_ptr.get()); - if (!phi) - break; - - auto phi_it = value_vregs.find(phi); - if (phi_it == value_vregs.end()) - continue; - int phi_vreg = phi_it->second; - - const ir::Value *incoming_value = nullptr; - size_t num_ops = phi->GetNumOperands(); - for (size_t i = 0; i + 1 < num_ops; i += 2) - { - auto *val = phi->GetOperand(i); - auto *bb_ptr = dynamic_cast(phi->GetOperand(i + 1)); - if (bb_ptr && bb_ptr == src_bb) - { - incoming_value = val; - break; - } - } - - if (!incoming_value) - continue; - - VRegClass phi_class = function.GetVRegClass(phi_vreg); - - if (phi_class == VRegClass::Float) - { - int src = EmitFloatValue(incoming_value, function, - const_cast(value_vregs), mir_block); - if (phi_vreg == src) { - // self-referencing PHI, skip - } else { - mir_block.Append(Opcode::MovReg, - {Operand::VReg(phi_vreg, VRegClass::Float), - Operand::VReg(src, VRegClass::Float)}); - } - } - else if (phi_class == VRegClass::Ptr) - { - int src = EmitPtrValue(incoming_value, function, - const_cast(value_vregs), - scalar_slots, array_slots, mir_block); - if (phi_vreg == src) { - // self-referencing PHI, skip - } else { - mir_block.Append(Opcode::MovReg, - {Operand::VReg(phi_vreg, VRegClass::Ptr), - Operand::VReg(src, VRegClass::Ptr)}); - } - } - else - { - int src = EmitIntValue(incoming_value, function, - const_cast(value_vregs), - scalar_slots, array_slots, mir_block); - if (phi_vreg == src) { - // self-referencing PHI, skip - } else { - mir_block.Append(Opcode::MovReg, - {Operand::VReg(phi_vreg, VRegClass::Int), - Operand::VReg(src, VRegClass::Int)}); - } - } - } - } - - static void LowerInstruction(const ir::Instruction &inst, - MachineFunction &function, - ValueVRegMap &value_vregs, - LocalScalarMap &scalar_slots, - LocalArrayMap &array_slots, - const BlockMap &block_map, - MachineBasicBlock &block) - { - switch (inst.GetOpcode()) - { - case ir::Opcode::Alloca: - { - auto &alloca = static_cast(inst); - const int elem_size = GetTypeSize(alloca.GetElementType()); - - if (alloca.IsArrayAlloca()) - { - int count = 0; - if (TryGetConstantInt(alloca.GetCount(), count) && count > 0) - array_slots[&inst] = function.CreateFrameIndex(elem_size * count); - else - array_slots[&inst] = function.CreateFrameIndex(elem_size); - } - else - { - const int slot = function.CreateFrameIndex(elem_size); - scalar_slots[&inst] = slot; - } - return; - } - - case ir::Opcode::Load: - { - auto &load = static_cast(inst); - const bool is_ptr = IsPointerType(load.GetType()); - const bool is_float = IsFloatType(load.GetType()); - - int scalar_slot = -1; - if (TryResolveDirectScalarSlot(load.GetPtr(), scalar_slots, scalar_slot)) - { - if (is_ptr) - { - int vreg = function.CreateVReg(VRegClass::Ptr); - block.Append(Opcode::LoadStack, - {Operand::VReg(vreg, VRegClass::Ptr), Operand::FrameIndex(scalar_slot)}); - value_vregs[&load] = vreg; - } - else if (is_float) - { - int vreg = function.CreateVReg(VRegClass::Float); - block.Append(Opcode::LoadStack, - {Operand::VReg(vreg, VRegClass::Float), Operand::FrameIndex(scalar_slot)}); - value_vregs[&load] = vreg; - } - else - { - int vreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::LoadStack, - {Operand::VReg(vreg, VRegClass::Int), Operand::FrameIndex(scalar_slot)}); - value_vregs[&load] = vreg; - } - return; - } - - if (!is_ptr) - { - if (auto *global = AsGlobalScalarObject(load.GetPtr())) - { - if (is_float) - { - int vreg = function.CreateVReg(VRegClass::Float); - block.Append(Opcode::LoadGlobal, - {Operand::VReg(vreg, VRegClass::Float), Operand::Symbol(global->GetName())}); - value_vregs[&load] = vreg; - } - else - { - int vreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::LoadGlobal, - {Operand::VReg(vreg, VRegClass::Int), Operand::Symbol(global->GetName())}); - value_vregs[&load] = vreg; - } - return; - } - } - - int addr = EmitPtrValue(load.GetPtr(), function, value_vregs, - scalar_slots, array_slots, block); - if (is_ptr) - { - int vreg = function.CreateVReg(VRegClass::Ptr); - block.Append(Opcode::LoadMem, - {Operand::VReg(vreg, VRegClass::Ptr), Operand::VReg(addr, VRegClass::Ptr)}); - value_vregs[&load] = vreg; - } - else if (is_float) - { - int vreg = function.CreateVReg(VRegClass::Float); - block.Append(Opcode::LoadMem, - {Operand::VReg(vreg, VRegClass::Float), Operand::VReg(addr, VRegClass::Ptr)}); - value_vregs[&load] = vreg; - } - else - { - int vreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::LoadMem, - {Operand::VReg(vreg, VRegClass::Int), Operand::VReg(addr, VRegClass::Ptr)}); - value_vregs[&load] = vreg; - } - return; - } - - case ir::Opcode::Store: - { - auto &store = static_cast(inst); - const bool value_is_ptr = IsPointerType(store.GetValue()->GetType()); - const bool value_is_float = IsFloatType(store.GetValue()->GetType()); - - int scalar_slot = -1; - if (TryResolveDirectScalarSlot(store.GetPtr(), scalar_slots, scalar_slot)) - { - if (value_is_ptr) - { - int vreg = EmitPtrValue(store.GetValue(), function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::StoreStack, - {Operand::VReg(vreg, VRegClass::Ptr), Operand::FrameIndex(scalar_slot)}); - } - else if (value_is_float) - { - int vreg = EmitFloatValue(store.GetValue(), function, value_vregs, block); - block.Append(Opcode::StoreStack, - {Operand::VReg(vreg, VRegClass::Float), Operand::FrameIndex(scalar_slot)}); - } - else - { - int vreg = EmitIntValue(store.GetValue(), function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::StoreStack, - {Operand::VReg(vreg, VRegClass::Int), Operand::FrameIndex(scalar_slot)}); - } - return; - } - - if (!value_is_ptr) - { - if (auto *global = AsGlobalScalarObject(store.GetPtr())) - { - if (value_is_float) - { - int vreg = EmitFloatValue(store.GetValue(), function, value_vregs, block); - block.Append(Opcode::StoreGlobal, - {Operand::VReg(vreg, VRegClass::Float), Operand::Symbol(global->GetName())}); - } - else - { - int vreg = EmitIntValue(store.GetValue(), function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::StoreGlobal, - {Operand::VReg(vreg, VRegClass::Int), Operand::Symbol(global->GetName())}); - } - return; - } - } - - int addr = EmitPtrValue(store.GetPtr(), function, value_vregs, - scalar_slots, array_slots, block); - if (value_is_ptr) - { - int val = EmitPtrValue(store.GetValue(), function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::StoreMem, - {Operand::VReg(val, VRegClass::Ptr), Operand::VReg(addr, VRegClass::Ptr)}); - } - else if (value_is_float) - { - int val = EmitFloatValue(store.GetValue(), function, value_vregs, block); - block.Append(Opcode::StoreMem, - {Operand::VReg(val, VRegClass::Float), Operand::VReg(addr, VRegClass::Ptr)}); - } - else - { - int val = EmitIntValue(store.GetValue(), function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::StoreMem, - {Operand::VReg(val, VRegClass::Int), Operand::VReg(addr, VRegClass::Ptr)}); - } - return; - } - - case ir::Opcode::GEP: - return; - - case ir::Opcode::Add: - case ir::Opcode::Sub: - case ir::Opcode::Mul: - case ir::Opcode::Div: - case ir::Opcode::Mod: - { - auto &bin = static_cast(inst); - if (IsFloatType(bin.GetType())) - { - EmitFloatValue(&bin, function, value_vregs, block); - return; - } - EmitIntValue(&bin, function, value_vregs, scalar_slots, array_slots, block); - return; - } - - case ir::Opcode::Eq: - case ir::Opcode::Ne: - case ir::Opcode::Lt: - case ir::Opcode::Le: - case ir::Opcode::Gt: - case ir::Opcode::Ge: - { - auto &bin = static_cast(inst); - if (IsSolelyConsumedByCanonicalBoolUse(bin)) - return; - EmitIntValue(&bin, function, value_vregs, scalar_slots, array_slots, block); - return; - } - - case ir::Opcode::SIToFP: - case ir::Opcode::FPToSI: - case ir::Opcode::ZExt: - { - auto &cast = static_cast(inst); - if (inst.GetOpcode() == ir::Opcode::ZExt) - { - if (IsSolelyConsumedByCanonicalBoolUse(cast)) - return; - } - if (inst.GetOpcode() == ir::Opcode::SIToFP) - { - EmitFloatValue(&inst, function, value_vregs, block); - return; - } - if (inst.GetOpcode() == ir::Opcode::FPToSI) - { - EmitIntValue(&inst, function, value_vregs, scalar_slots, array_slots, block); - return; - } - if (inst.GetOpcode() == ir::Opcode::ZExt) - { - EmitIntValue(&inst, function, value_vregs, scalar_slots, array_slots, block); - return; - } - return; - } - - case ir::Opcode::Phi: - return; - - case ir::Opcode::Br: - { - auto &br = static_cast(inst); - auto it = block_map.find(br.GetTarget()); - if (it != block_map.end() && it->second) - { - EmitPhiValueStores(inst.GetParent(), br.GetTarget(), function, - value_vregs, scalar_slots, array_slots, block); - block.Append(Opcode::Br, {Operand::Label(it->second->GetLabelId())}); - } - return; - } - - case ir::Opcode::CondBr: - { - auto &br = static_cast(inst); - CondCode true_cond = CondCode::NE; - TryEmitCondValueToFlags(br.GetCond(), function, value_vregs, - scalar_slots, array_slots, block, true_cond); - - auto true_it = block_map.find(br.GetTrueTarget()); - if (true_it != block_map.end() && true_it->second) - { - EmitPhiValueStores(inst.GetParent(), br.GetTrueTarget(), function, - value_vregs, scalar_slots, array_slots, block); - block.Append(Opcode::CondBr, - {Operand::Imm(static_cast(true_cond)), - Operand::Label(true_it->second->GetLabelId())}); - } - - auto false_it = block_map.find(br.GetFalseTarget()); - if (false_it != block_map.end() && false_it->second) - { - EmitPhiValueStores(inst.GetParent(), br.GetFalseTarget(), function, - value_vregs, scalar_slots, array_slots, block); - block.Append(Opcode::Br, - {Operand::Label(false_it->second->GetLabelId())}); - } - return; - } - - case ir::Opcode::Call: - { - auto &call = static_cast(inst); - auto *callee = call.GetCallee(); - if (!callee) - { - if (!call.GetType()->IsVoid()) - { - if (IsPointerType(call.GetType())) - { - int vreg = function.CreateVReg(VRegClass::Ptr); - block.Append(Opcode::MovImm, {Operand::VReg(vreg, VRegClass::Ptr), Operand::Imm(0)}).SetRematerializable(true).SetRematImm(0); - value_vregs[&call] = vreg; - } - else if (IsFloatType(call.GetType())) - { - int vreg = function.CreateVReg(VRegClass::Float); - int wvreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::MovImm, {Operand::VReg(wvreg, VRegClass::Int), Operand::Imm(0)}).SetRematerializable(true).SetRematImm(0); - block.Append(Opcode::FMovWS, - {Operand::VReg(vreg, VRegClass::Float), Operand::VReg(wvreg, VRegClass::Int)}); - value_vregs[&call] = vreg; - } - else - { - int vreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::MovImm, {Operand::VReg(vreg, VRegClass::Int), Operand::Imm(0)}).SetRematerializable(true).SetRematImm(0); - value_vregs[&call] = vreg; - } - } - return; - } - - std::vector stack_arg_indices; - size_t gp_idx = 0; - size_t fp_idx = 0; - for (size_t i = 0; i < call.GetNumArgs(); ++i) - { - auto *arg = call.GetArg(i); - if (!arg) - continue; - - if (IsFloatType(arg->GetType())) - { - if (fp_idx < 8) - { - int vreg = EmitFloatValue(arg, function, value_vregs, block); - block.Append(Opcode::MovReg, - {Operand::Reg(GetArgSReg(fp_idx)), - Operand::VReg(vreg, VRegClass::Float)}); - ++fp_idx; - } - else - { - stack_arg_indices.push_back(i); - } - } - else if (IsPointerValue(arg)) - { - if (gp_idx < 8) - { - int vreg = EmitPtrValue(arg, function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::MovReg, - {Operand::Reg(GetArgXReg(gp_idx)), - Operand::VReg(vreg, VRegClass::Ptr)}); - ++gp_idx; - } - else - { - stack_arg_indices.push_back(i); - } - } - else - { - if (gp_idx < 8) - { - int vreg = EmitIntValue(arg, function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::MovReg, - {Operand::Reg(GetArgWReg(gp_idx)), - Operand::VReg(vreg, VRegClass::Int)}); - ++gp_idx; - } - else - { - stack_arg_indices.push_back(i); - } - } - } - - const int raw_stack_arg_bytes = ComputeStackArgumentBytes(call); - const int aligned_stack_arg_bytes = AlignTo(raw_stack_arg_bytes, 16); - if (aligned_stack_arg_bytes > 0) - { - EmitStackPointerAdjust(block, Opcode::SubRR, aligned_stack_arg_bytes); - - int offset = 0; - for (size_t idx : stack_arg_indices) - { - auto *arg = call.GetArg(idx); - const int arg_size = GetTypeSize(arg ? arg->GetType() : nullptr); - if (!arg) - { - offset += 8; - continue; - } - - const int slot = function.CreateStackArgFrameIndex(arg_size); - function.GetFrameSlot(slot).offset = offset; - if (IsFloatType(arg->GetType())) - { - int vreg = EmitFloatValue(arg, function, value_vregs, block); - block.Append(Opcode::StoreStack, - {Operand::VReg(vreg, VRegClass::Float), Operand::FrameIndex(slot)}); - } - else if (IsPointerValue(arg)) - { - int vreg = EmitPtrValue(arg, function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::StoreStack, - {Operand::VReg(vreg, VRegClass::Ptr), Operand::FrameIndex(slot)}); - } - else - { - int vreg = EmitIntValue(arg, function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::StoreStack, - {Operand::VReg(vreg, VRegClass::Int), Operand::FrameIndex(slot)}); - } - offset += 8; - } - } - - block.Append(Opcode::Call, {Operand::Symbol(callee->GetName())}); - function.SetHasCall(); - - if (aligned_stack_arg_bytes > 0) - { - EmitStackPointerAdjust(block, Opcode::AddRR, aligned_stack_arg_bytes); - } - - if (!call.GetType()->IsVoid()) - { - if (IsPointerType(call.GetType())) - { - int vreg = function.CreateVReg(VRegClass::Ptr); - block.Append(Opcode::MovReg, - {Operand::VReg(vreg, VRegClass::Ptr), Operand::Reg(PhysReg::X0)}); - value_vregs[&call] = vreg; - } - else if (IsFloatType(call.GetType())) - { - int vreg = function.CreateVReg(VRegClass::Float); - block.Append(Opcode::MovReg, - {Operand::VReg(vreg, VRegClass::Float), Operand::Reg(PhysReg::S0)}); - value_vregs[&call] = vreg; - } - else - { - int vreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::MovReg, - {Operand::VReg(vreg, VRegClass::Int), Operand::Reg(PhysReg::W0)}); - value_vregs[&call] = vreg; - } - } - return; - } - - case ir::Opcode::Ret: - { - auto &ret = static_cast(inst); - if (ret.HasValue()) - { - if (ret.GetValue()->GetType()->IsPtrInt32() || - ret.GetValue()->GetType()->IsPtrFloat32()) - { - int vreg = EmitPtrValue(ret.GetValue(), function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::MovReg, - {Operand::Reg(PhysReg::X0), Operand::VReg(vreg, VRegClass::Ptr)}); - } - else if (IsFloatValue(ret.GetValue())) - { - int vreg = EmitFloatValue(ret.GetValue(), function, value_vregs, block); - block.Append(Opcode::MovReg, - {Operand::Reg(PhysReg::S0), Operand::VReg(vreg, VRegClass::Float)}); - } - else - { - int vreg = EmitIntValue(ret.GetValue(), function, value_vregs, - scalar_slots, array_slots, block); - block.Append(Opcode::MovReg, - {Operand::Reg(PhysReg::W0), Operand::VReg(vreg, VRegClass::Int)}); - } - } - block.Append(Opcode::Ret); - return; - } - - default: - return; - } - } - - static void LowerOneFunction(const ir::Function &ir_function, - MachineFunction &machine_func) - { - ValueVRegMap value_vregs; - LocalScalarMap scalar_slots; - LocalArrayMap array_slots; - BlockMap block_map; - - const auto *entry = ir_function.GetEntry(); - if (!entry) - { - throw std::runtime_error( - FormatError("mir", "IR 函数缺少入口基本块: " + ir_function.GetName())); - } - - block_map.emplace(entry, &machine_func.GetEntry()); - for (const auto &bb : ir_function.GetBlocks()) - { - if (!bb || bb.get() == entry) - continue; - block_map.emplace(bb.get(), &machine_func.CreateBlock(bb->GetName())); - } - - LowerFunctionParams(ir_function, machine_func, value_vregs); - - for (const auto &bb : ir_function.GetBlocks()) - { - if (!bb) - continue; - for (const auto &inst : bb->GetInstructions()) - { - auto *phi = dynamic_cast(inst.get()); - if (!phi) - break; - VRegClass vc = VRegClass::Int; - if (IsFloatType(phi->GetType())) - vc = VRegClass::Float; - else if (IsPointerType(phi->GetType())) - vc = VRegClass::Ptr; - int phi_vreg = machine_func.CreateVReg(vc); - value_vregs[phi] = phi_vreg; - } - } - - for (const auto &bb : ir_function.GetBlocks()) - { - if (!bb) - continue; - auto it = block_map.find(bb.get()); - if (it == block_map.end() || !it->second) - continue; - auto &mir_block = *it->second; - - std::vector to_remove; - for (auto &pair : value_vregs) - { - if (dynamic_cast(pair.first) || - dynamic_cast(pair.first) || - AsGlobalScalarObject(pair.first) || - AsGlobalArrayObject(pair.first) || - dynamic_cast(pair.first) || - dynamic_cast(pair.first)) - { - to_remove.push_back(pair.first); - } - } - for (auto *v : to_remove) - value_vregs.erase(v); - - for (const auto &inst : bb->GetInstructions()) - { - LowerInstruction(*inst, machine_func, - value_vregs, scalar_slots, array_slots, - block_map, mir_block); - } - } - } - - static void LowerGlobals(const ir::Module &module, - MachineModule &machine_module) - { - for (const auto &global : module.GetGlobals()) - { - if (!global) - continue; - if (!IsPointerValue(global.get())) - continue; - - if (global->IsArray()) - { - if (global->IsPtrFloat32()) - { - std::vector init_bits; - if (global->HasInitValues()) - { - const auto &init_values = global->GetInitFloatValues(); - init_bits.reserve(init_values.size()); - for (double v : init_values) - { - init_bits.push_back(FloatToBits(static_cast(v))); - } - } - machine_module.AddGlobalArrayI32(global->GetName(), - global->GetArraySize(), - std::move(init_bits)); - } - else if (global->HasInitValues()) - { - machine_module.AddGlobalArrayI32(global->GetName(), - global->GetArraySize(), - global->GetInitValues()); - } - else - { - machine_module.AddGlobalArrayI32(global->GetName(), - global->GetArraySize()); - } - continue; - } - - if (global->IsPtrFloat32()) - { - machine_module.AddGlobalI32(global->GetName(), - FloatToBits(static_cast(global->GetInitFloatValue()))); - } - else - { - machine_module.AddGlobalI32(global->GetName(), global->GetInitValue()); - } - } - } - - } // namespace - - std::unique_ptr LowerModuleToMIR(const ir::Module &module) - { - DefaultContext(); - - auto machine_module = std::make_unique(); - LowerGlobals(module, *machine_module); - - for (const auto &func : module.GetFunctions()) - { - if (!func || func->IsExternal()) - continue; - - auto &machine_func = machine_module->CreateFunction(func->GetName()); - LowerOneFunction(*func, machine_func); - } - - return machine_module; - } - - std::unique_ptr LowerToMIR(const ir::Module &module) - { - auto machine_module = LowerModuleToMIR(module); - if (!machine_module) - { - throw std::runtime_error(FormatError("mir", "LowerModuleToMIR 失败")); - } - - auto &functions = machine_module->GetFunctions(); - for (auto &func : functions) - { - if (func && func->GetName() == "main") - { - return std::move(func); - } - } - - throw std::runtime_error(FormatError("mir", "未找到 main 函数对应的 MIR")); - } - -} // namespace mir diff --git a/src/mir/Lowering.cpp.rej b/src/mir/Lowering.cpp.rej deleted file mode 100644 index aa6a3c92..00000000 --- a/src/mir/Lowering.cpp.rej +++ /dev/null @@ -1,26 +0,0 @@ ---- src/mir/Lowering.cpp -+++ src/mir/Lowering.cpp -@@ -339,10 +339,19 @@ - { - if (IsIntegerCompareOpcode(bin->GetOpcode())) - { - int lhs = EmitIntValue(bin->GetLhs(), function, value_vregs, - scalar_slots, array_slots, block); -- int rhs = EmitIntValue(bin->GetRhs(), function, value_vregs, -- scalar_slots, array_slots, block); -- block.Append(Opcode::CmpRR, -- {Operand::VReg(lhs, VRegClass::Int), Operand::VReg(rhs, VRegClass::Int)}); -+ int rhs_imm; -+ if (TryGetConstantInt(bin->GetRhs(), rhs_imm)) -+ { -+ block.Append(Opcode::CmpImm, -+ {Operand::VReg(lhs, VRegClass::Int), Operand::Imm(rhs_imm)}); -+ } -+ else -+ { -+ int rhs = EmitIntValue(bin->GetRhs(), function, value_vregs, -+ scalar_slots, array_slots, block); -+ block.Append(Opcode::CmpRR, -+ {Operand::VReg(lhs, VRegClass::Int), Operand::VReg(rhs, VRegClass::Int)}); -+ } -