From 35885f3eba511373021db8336fbdfab012837508 Mon Sep 17 00:00:00 2001 From: mxr <> Date: Wed, 22 Apr 2026 19:51:33 +0800 Subject: [PATCH] =?UTF-8?q?(mir)=E4=BF=AE=E6=AD=A3=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E6=AD=BB=E5=BE=AA=E7=8E=AF=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/mir/MIR.h | 18 ++- src/mir/AsmPrinter.cpp | 15 ++- src/mir/Lowering.cpp | 299 +++++++++++++++++++++++++++++------------ 3 files changed, 244 insertions(+), 88 deletions(-) diff --git a/include/mir/MIR.h b/include/mir/MIR.h index a879bef..67ef476 100644 --- a/include/mir/MIR.h +++ b/include/mir/MIR.h @@ -140,6 +140,9 @@ enum class Opcode { // 用于全局变量地址计算 Adrp, // ADRP Xd, label AddLabel, // ADD Xd, Xn, :lo12:label + + // 新增 + Sxtw, // 符号扩展字到双字:sxtw Xd, Wn }; // ========== 操作数类 ========== @@ -298,12 +301,21 @@ class MachineModule { int size; // 字节大小 int alignment; // 对齐要求(通常为 4 或 8) bool is_zero_init; // 是否为零初始化 + bool has_init_data; // 是否包含初始化数据(用于标量常量) + uint64_t init_data; // 初始化数据(≤8字节) + // 构造函数,默认零初始化 + GlobalDecl(const std::string& n, int sz, int align, bool zero = true, + bool has_data = false, uint64_t data = 0) + : name(n), size(sz), alignment(align), is_zero_init(zero), + has_init_data(has_data), init_data(data) {} }; - void AddGlobal(const std::string& name, int size, int alignment, bool is_zero_init = true) { - globals_.push_back({name, size, alignment, is_zero_init}); + void AddGlobal(const std::string& name, int size, int alignment, + bool is_zero_init = true, + bool has_init_data = false, uint64_t init_data = 0) { + globals_.emplace_back(name, size, alignment, is_zero_init, + has_init_data, init_data); } - const std::vector& GetGlobals() const { return globals_; } private: diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index 5a45801..b5d04f7 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -384,6 +384,10 @@ void PrintInstruction(std::ostream& os, const MachineInstr& instr, << ops.at(2).GetLabel() << "\n"; break; } + case Opcode::Sxtw: + os << " sxtw " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; default: os << " // unknown instruction\n"; break; @@ -441,8 +445,17 @@ void PrintAsm(const MachineModule& module, std::ostream& os) { os << g.name << ":\n"; if (g.is_zero_init) { os << " .zero " << g.size << "\n"; + } else if (g.has_init_data) { + if (g.size == 4) { + os << " .word " << static_cast(g.init_data) << "\n"; + } else if (g.size == 8) { + os << " .quad " << g.init_data << "\n"; + } else { + // 暂不支持的标量大小,回退为零初始化 + os << " .zero " << g.size << " // unhandled init size\n"; + } } else { - // TODO: 处理非零初始化值(需要从 IR 提取 initializer) + // 有初始值但无法提取(例如数组、结构体) os << " .zero " << g.size << " // unhandled initializer\n"; } os << ".size " << g.name << ", " << g.size << "\n\n"; diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 21935d3..ab5ddd8 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -21,6 +21,10 @@ namespace { using ValueSlotMap = std::unordered_map; +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)); @@ -364,83 +368,224 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, 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()) || - inst.GetType()->IsPtrInt32() || inst.GetType()->IsPtrFloat() || inst.GetType()->IsPtrInt1() || inst.GetType()->IsArray(); + (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1() || rhsTy->IsArray()) || + resultTy->IsPtrInt32() || resultTy->IsPtrFloat() || resultTy->IsPtrInt1() || resultTy->IsArray(); + + // 判断是否为纯 32 位有符号整数加法(需要提升为 64 位以避免溢出) + bool isI32 = !isPointer && IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); + int slotSize = isPointer ? 8 : 4; - PhysReg lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; - PhysReg rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; - PhysReg dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; - - int dst_slot = function.CreateFrameIndex(slotSize); // 使用计算出的 slotSize - EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); - EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + int dst_slot = function.CreateFrameIndex(slotSize); + + PhysReg lhsReg, rhsReg, dstReg; + if (isI32) { + // 使用 64 位寄存器,先符号扩展 + lhsReg = PhysReg::X8; + rhsReg = PhysReg::X9; + dstReg = PhysReg::X8; + + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)}); + + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X9), Operand::Reg(PhysReg::W9)}); + } else { + lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + } + block.Append(Opcode::AddRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)}); - block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + + if (isI32) { + // 结果在 X8 中,只需存储低 32 位(W8) + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } else { + block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + } slots.emplace(&inst, dst_slot); return; } + case ir::Opcode::Sub: { 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()) || - inst.GetType()->IsPtrInt32() || inst.GetType()->IsPtrFloat() || inst.GetType()->IsPtrInt1() || inst.GetType()->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); + int slotSize = isPointer ? 8 : 4; - PhysReg lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; - PhysReg rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; - PhysReg dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; - - int dst_slot = function.CreateFrameIndex(slotSize); // 使用计算出的 slotSize - EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); - EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + int dst_slot = function.CreateFrameIndex(slotSize); + + PhysReg lhsReg, rhsReg, dstReg; + if (isI32) { + lhsReg = PhysReg::X8; + rhsReg = PhysReg::X9; + dstReg = PhysReg::X8; + + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)}); + + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X9), Operand::Reg(PhysReg::W9)}); + } else { + lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + } + block.Append(Opcode::SubRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)}); - block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + + if (isI32) { + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } else { + block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + } slots.emplace(&inst, dst_slot); return; } + case ir::Opcode::Mul: { auto& bin = static_cast(inst); - const ir::Type* ty = inst.GetType().get(); - bool isPointer = ty->IsPtrInt32() || ty->IsPtrFloat() || ty->IsPtrInt1(); + 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); + int slotSize = isPointer ? 8 : 4; - PhysReg lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; - PhysReg rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; - PhysReg dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; // 可复用 lhsReg + int dst_slot = function.CreateFrameIndex(slotSize); - int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 - EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); - EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); - block.Append(Opcode::MulRR, {Operand::Reg(dstReg), - Operand::Reg(lhsReg), - Operand::Reg(rhsReg)}); - block.Append(Opcode::StoreStack, - {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + PhysReg lhsReg, rhsReg, dstReg; + if (isI32) { + lhsReg = PhysReg::X8; + rhsReg = PhysReg::X9; + dstReg = PhysReg::X8; + + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)}); + + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X9), Operand::Reg(PhysReg::W9)}); + } else { + lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + } + + block.Append(Opcode::MulRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)}); + + if (isI32) { + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } else { + block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + } slots.emplace(&inst, dst_slot); return; } + case ir::Opcode::Div: { auto& bin = static_cast(inst); - const ir::Type* ty = inst.GetType().get(); - bool isPointer = ty->IsPtrInt32() || ty->IsPtrFloat() || ty->IsPtrInt1(); + 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); + int slotSize = isPointer ? 8 : 4; - PhysReg lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; - PhysReg rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; - PhysReg dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; // 可复用 lhsReg + int dst_slot = function.CreateFrameIndex(slotSize); - int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 - EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); - EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); - block.Append(Opcode::SDivRR, {Operand::Reg(dstReg), - Operand::Reg(lhsReg), - Operand::Reg(rhsReg)}); - block.Append(Opcode::StoreStack, - {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + PhysReg lhsReg, rhsReg, dstReg; + if (isI32) { + lhsReg = PhysReg::X8; + rhsReg = PhysReg::X9; + dstReg = PhysReg::X8; + + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)}); + + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X9), Operand::Reg(PhysReg::W9)}); + } else { + lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + } + + block.Append(Opcode::SDivRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)}); + + if (isI32) { + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } else { + block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + } + slots.emplace(&inst, dst_slot); + return; + } + + case ir::Opcode::Mod: { + // Mod 指令:a % b = a - (a / b) * b + // 我们直接复用提升策略:使用 64 位运算 + 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); + + int dst_slot = function.CreateFrameIndex(4); // 结果总是 32 位 + if (isI32) { + // 加载并扩展 lhs + EmitValueToReg(lhs, PhysReg::W8, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)}); + // 加载并扩展 rhs + EmitValueToReg(rhs, PhysReg::W9, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X9), Operand::Reg(PhysReg::W9)}); + + // X10 = X8 / X9 + block.Append(Opcode::SDivRR, {Operand::Reg(PhysReg::X10), Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::X9)}); + // X10 = X10 * X9 + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X10), Operand::Reg(PhysReg::X10), Operand::Reg(PhysReg::X9)}); + // X8 = X8 - X10 + block.Append(Opcode::SubRR, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::X10)}); + // 存储低 32 位 + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } else { + // 原有逻辑(假设不会用于指针或 64 位整数) + EmitValueToReg(lhs, PhysReg::W8, slots, block, function); + EmitValueToReg(rhs, PhysReg::W9, slots, block, function); + block.Append(Opcode::SDivRR, {Operand::Reg(PhysReg::W10), Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)}); + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::W10), Operand::Reg(PhysReg::W10), Operand::Reg(PhysReg::W9)}); + block.Append(Opcode::SubRR, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W10)}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } slots.emplace(&inst, dst_slot); return; } @@ -900,39 +1045,6 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, slots.emplace(&inst, dst_slot); return; } - // 处理 Mod 指令 - case ir::Opcode::Mod: { - int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); - - // 通过操作数获取左右值 - const ir::Value* lhs = nullptr; - const ir::Value* rhs = nullptr; - if (inst.GetNumOperands() >= 2) { - lhs = inst.GetOperand(0); - rhs = inst.GetOperand(1); - } - - if (lhs && rhs) { - EmitValueToReg(lhs, PhysReg::W8, slots, block, function); - EmitValueToReg(rhs, PhysReg::W9, slots, block, function); - - // a % b = a - (a / b) * b - block.Append(Opcode::SDivRR, {Operand::Reg(PhysReg::W10), - Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W9)}); - block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::W10), - Operand::Reg(PhysReg::W10), - Operand::Reg(PhysReg::W9)}); - block.Append(Opcode::SubRR, {Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W10)}); - } - - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); - slots.emplace(&inst, dst_slot); - return; - } // 处理 And 指令 case ir::Opcode::And: { int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); @@ -1144,9 +1256,28 @@ std::unique_ptr LowerToMIR(const ir::Module& module) { for (const auto& global : module.GetGlobals()) { int size = GetTypeSize(global->GetType().get()); int alignment = global->GetType()->Alignment(); - // 简化:假设无显式初始化的全局变量都是零初始化 bool is_zero_init = !global->HasInitializer(); - machine_module->AddGlobal(global->GetName(), size, alignment, is_zero_init); + bool has_init_data = false; + uint64_t init_data = 0; + + if (!is_zero_init) { + const auto& init = global->GetInitializer(); + // 简单处理:只支持单个元素的标量初始化(float 或 int) + if (init.size() == 1) { + if (auto* cf = dynamic_cast(init[0])) { + float fval = cf->GetValue(); + uint32_t bits; + memcpy(&bits, &fval, sizeof(bits)); + init_data = bits; + has_init_data = true; + } else if (auto* ci = dynamic_cast(init[0])) { + init_data = static_cast(ci->GetValue()); + has_init_data = true; + } + } + } + machine_module->AddGlobal(global->GetName(), size, alignment, + is_zero_init, has_init_data, init_data); } std::vector globals;