|
|
|
|
@ -105,6 +105,22 @@ static std::vector<int> GetArrayStrides(const ir::ArrayType* arrayType) {
|
|
|
|
|
return strides;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 在 Lowering.cpp 中添加辅助函数
|
|
|
|
|
const ir::Value* GetOperand(const ir::Instruction& inst, size_t index) {
|
|
|
|
|
if (index < inst.GetNumOperands()) {
|
|
|
|
|
return inst.GetOperand(index);
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ir::BasicBlock* GetBasicBlockOperand(const ir::Instruction& inst, size_t index) {
|
|
|
|
|
const ir::Value* operand = GetOperand(inst, index);
|
|
|
|
|
if (operand) {
|
|
|
|
|
return dynamic_cast<const ir::BasicBlock*>(operand);
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EmitValueToReg(const ir::Value* value, PhysReg target,
|
|
|
|
|
const ValueSlotMap& slots, MachineBasicBlock& block,
|
|
|
|
|
MachineFunction& function) {
|
|
|
|
|
@ -116,23 +132,52 @@ void EmitValueToReg(const ir::Value* value, PhysReg target,
|
|
|
|
|
}
|
|
|
|
|
// 处理浮点常量
|
|
|
|
|
if (auto* fconstant = dynamic_cast<const ir::ConstantFloat*>(value)) {
|
|
|
|
|
// 浮点常量需要存储到栈槽,然后加载到寄存器
|
|
|
|
|
// 检查是否已经为这个常量分配了栈槽
|
|
|
|
|
auto it = slots.find(value);
|
|
|
|
|
int slot;
|
|
|
|
|
if (it == slots.end()) {
|
|
|
|
|
// 分配新的栈槽
|
|
|
|
|
slot = function.CreateFrameIndex(4);
|
|
|
|
|
// 将浮点常量存储到栈槽
|
|
|
|
|
float fval = fconstant->GetValue();
|
|
|
|
|
// 将浮点数作为立即数加载(使用整数表示)
|
|
|
|
|
uint32_t int_val = *reinterpret_cast<uint32_t*>(&fval);
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast<int>(int_val))});
|
|
|
|
|
block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)});
|
|
|
|
|
const_cast<ValueSlotMap&>(slots).emplace(value, slot);
|
|
|
|
|
DEBUG_MSG("Value not found: " << value->GetName());
|
|
|
|
|
// 输出所有 slots 的键名用于调试
|
|
|
|
|
for (auto& p : slots) {
|
|
|
|
|
DEBUG_MSG(" Slot key: " << p.first->GetName());
|
|
|
|
|
}
|
|
|
|
|
// 分配新的栈槽
|
|
|
|
|
slot = function.CreateFrameIndex(4);
|
|
|
|
|
// 将浮点常量存储到栈槽
|
|
|
|
|
float fval = fconstant->GetValue();
|
|
|
|
|
uint32_t int_val = FloatToBits(fval);
|
|
|
|
|
|
|
|
|
|
// 使用临时寄存器加载常量并存储
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast<int>(int_val))});
|
|
|
|
|
block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)});
|
|
|
|
|
const_cast<ValueSlotMap&>(slots).emplace(value, slot);
|
|
|
|
|
} else {
|
|
|
|
|
slot = it->second;
|
|
|
|
|
slot = it->second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 从栈槽加载到目标寄存器
|
|
|
|
|
block.Append(Opcode::LoadStack, {Operand::Reg(target), Operand::FrameIndex(slot)});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 处理全局变量
|
|
|
|
|
if (auto* global = dynamic_cast<const ir::GlobalValue*>(value)) {
|
|
|
|
|
// 全局变量:需要加载其地址
|
|
|
|
|
// 在 ARM64 中,使用 ADRP + ADD 指令获取全局变量地址
|
|
|
|
|
// 简化版本:先为全局变量分配一个栈槽,然后加载地址到该栈槽
|
|
|
|
|
|
|
|
|
|
// 检查是否已经为这个全局变量分配了栈槽
|
|
|
|
|
auto it = slots.find(value);
|
|
|
|
|
if (it == slots.end()) {
|
|
|
|
|
// 为全局变量创建栈槽
|
|
|
|
|
const_cast<ValueSlotMap&>(slots).emplace(value,
|
|
|
|
|
const_cast<MachineFunction&>(function).CreateFrameIndex(8));
|
|
|
|
|
it = slots.find(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 从栈槽加载地址到目标寄存器
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
|
|
{Operand::Reg(target), Operand::FrameIndex(it->second)});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 处理零常量
|
|
|
|
|
if (dynamic_cast<const ir::ConstantZero*>(value) ||
|
|
|
|
|
@ -145,6 +190,11 @@ void EmitValueToReg(const ir::Value* value, PhysReg target,
|
|
|
|
|
|
|
|
|
|
auto it = slots.find(value);
|
|
|
|
|
if (it == slots.end()) {
|
|
|
|
|
DEBUG_MSG("Value not found: " << value->GetName());
|
|
|
|
|
// 输出所有 slots 的键名用于调试
|
|
|
|
|
for (auto& p : slots) {
|
|
|
|
|
DEBUG_MSG(" Slot key: " << p.first->GetName());
|
|
|
|
|
}
|
|
|
|
|
throw std::runtime_error(
|
|
|
|
|
FormatError("mir", "找不到值对应的栈槽: " + value->GetName()));
|
|
|
|
|
}
|
|
|
|
|
@ -158,6 +208,8 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
std::unordered_map<const ir::BasicBlock*,
|
|
|
|
|
MachineBasicBlock*>& blockMap) {
|
|
|
|
|
//auto& block = function.GetEntry();
|
|
|
|
|
DEBUG_MSG("Processing instruction: " << inst.GetName()
|
|
|
|
|
<< " (opcode: " << static_cast<int>(inst.GetOpcode()) << ")");
|
|
|
|
|
|
|
|
|
|
switch (inst.GetOpcode()) {
|
|
|
|
|
case ir::Opcode::Alloca: {
|
|
|
|
|
@ -333,42 +385,25 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
auto& icmp = static_cast<const ir::IcmpInst&>(inst);
|
|
|
|
|
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
|
|
|
|
|
|
|
|
|
|
// 加载左右操作数到 w8, w9
|
|
|
|
|
EmitValueToReg(icmp.GetLhs(), PhysReg::W8, slots, block, function);
|
|
|
|
|
EmitValueToReg(icmp.GetRhs(), PhysReg::W9, slots, block, function);
|
|
|
|
|
|
|
|
|
|
// 生成比较指令
|
|
|
|
|
block.Append(Opcode::CmpRR, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)});
|
|
|
|
|
|
|
|
|
|
// 使用条件设置指令: CSET W8, cc
|
|
|
|
|
// 如果条件成立,W8 = 1;否则 W8 = 0
|
|
|
|
|
CondCode cc = IcmpToCondCode(icmp.GetPredicate());
|
|
|
|
|
|
|
|
|
|
// 使用 CSET 的替代实现:条件移动
|
|
|
|
|
// MOV W8, #1
|
|
|
|
|
// MOV W9, #0
|
|
|
|
|
// CSEL W8, W8, W9, cc
|
|
|
|
|
// 使用 CSET 模式
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)});
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(0)});
|
|
|
|
|
|
|
|
|
|
// TODO: 需要添加 CSEL 指令,暂时使用条件跳转
|
|
|
|
|
// 创建临时标签
|
|
|
|
|
std::string true_label = ".L_cset_true_" + std::to_string(reinterpret_cast<uintptr_t>(&icmp));
|
|
|
|
|
std::string end_label = ".L_cset_end_" + std::to_string(reinterpret_cast<uintptr_t>(&icmp));
|
|
|
|
|
|
|
|
|
|
// 设置条件成立时的值(1)
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)});
|
|
|
|
|
// 条件成立时跳转到 true_label
|
|
|
|
|
block.Append(Opcode::BCond, {Operand::Cond(cc), Operand::Label(true_label)});
|
|
|
|
|
// 条件不成立:设置 W8 = 0
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(0)});
|
|
|
|
|
// 跳转到 end_label
|
|
|
|
|
block.Append(Opcode::MovReg, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)});
|
|
|
|
|
block.Append(Opcode::B, {Operand::Label(end_label)});
|
|
|
|
|
// true_label: 值已经是 1,直接落入 end_label
|
|
|
|
|
block.Append(Opcode::Label, {Operand::Label(true_label)});
|
|
|
|
|
// end_label: 存储结果
|
|
|
|
|
block.Append(Opcode::Label, {Operand::Label(end_label)});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
@ -661,8 +696,199 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
//throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令"));
|
|
|
|
|
throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令,opcode: "
|
|
|
|
|
// 处理 Trunc 指令
|
|
|
|
|
case ir::Opcode::Trunc: {
|
|
|
|
|
auto& inst_ref = static_cast<const ir::Instruction&>(inst);
|
|
|
|
|
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
|
|
|
|
|
|
|
|
|
|
// 假设 Trunc 指令有 GetValue() 方法
|
|
|
|
|
// 如果没有,需要通过操作数列表获取
|
|
|
|
|
const ir::Value* src_val = nullptr;
|
|
|
|
|
if (inst.GetNumOperands() > 0) {
|
|
|
|
|
src_val = inst.GetOperand(0);
|
|
|
|
|
}
|
|
|
|
|
if (src_val) {
|
|
|
|
|
EmitValueToReg(src_val, PhysReg::W8, slots, block, function);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
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()));
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
block.Append(Opcode::AndRR, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 处理 Or 指令
|
|
|
|
|
case ir::Opcode::Or: {
|
|
|
|
|
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);
|
|
|
|
|
block.Append(Opcode::OrRR, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 处理 Not 指令
|
|
|
|
|
case ir::Opcode::Not: {
|
|
|
|
|
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
|
|
|
|
|
|
|
|
|
|
const ir::Value* src_val = nullptr;
|
|
|
|
|
if (inst.GetNumOperands() > 0) {
|
|
|
|
|
src_val = inst.GetOperand(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (src_val) {
|
|
|
|
|
EmitValueToReg(src_val, PhysReg::W8, slots, block, function);
|
|
|
|
|
// NOT = XOR with -1
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(-1)});
|
|
|
|
|
block.Append(Opcode::EorRR, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 处理 CondBr 指令
|
|
|
|
|
case ir::Opcode::CondBr: {
|
|
|
|
|
// CondBr 通常有两个目标基本块和一个条件
|
|
|
|
|
const ir::Value* condition = nullptr;
|
|
|
|
|
const ir::BasicBlock* trueTarget = nullptr;
|
|
|
|
|
const ir::BasicBlock* falseTarget = nullptr;
|
|
|
|
|
|
|
|
|
|
if (inst.GetNumOperands() >= 3) {
|
|
|
|
|
condition = inst.GetOperand(0);
|
|
|
|
|
// 操作数1和2应该是 BasicBlock 引用
|
|
|
|
|
// 具体获取方式取决于你的 IR 实现
|
|
|
|
|
if (auto* bb = dynamic_cast<const ir::BasicBlock*>(inst.GetOperand(1))) {
|
|
|
|
|
trueTarget = bb;
|
|
|
|
|
}
|
|
|
|
|
if (auto* bb = dynamic_cast<const ir::BasicBlock*>(inst.GetOperand(2))) {
|
|
|
|
|
falseTarget = bb;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (condition && trueTarget && falseTarget) {
|
|
|
|
|
EmitValueToReg(condition, PhysReg::W8, slots, block, function);
|
|
|
|
|
block.Append(Opcode::CmpRI, {Operand::Reg(PhysReg::W8), Operand::Imm(0)});
|
|
|
|
|
|
|
|
|
|
std::string trueLabel = GetBlockLabel(trueTarget);
|
|
|
|
|
std::string falseLabel = GetBlockLabel(falseTarget);
|
|
|
|
|
|
|
|
|
|
block.Append(Opcode::BCond, {Operand::Cond(CondCode::NE), Operand::Label(trueLabel)});
|
|
|
|
|
block.Append(Opcode::B, {Operand::Label(falseLabel)});
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 处理 FPExt(浮点扩展)
|
|
|
|
|
case ir::Opcode::FPExt: {
|
|
|
|
|
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
|
|
|
|
|
|
|
|
|
|
const ir::Value* src_val = nullptr;
|
|
|
|
|
if (inst.GetNumOperands() > 0) {
|
|
|
|
|
src_val = inst.GetOperand(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (src_val) {
|
|
|
|
|
EmitValueToReg(src_val, PhysReg::S0, slots, block, function);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 处理 FPTrunc(浮点截断)
|
|
|
|
|
case ir::Opcode::FPTrunc: {
|
|
|
|
|
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
|
|
|
|
|
|
|
|
|
|
const ir::Value* src_val = nullptr;
|
|
|
|
|
if (inst.GetNumOperands() > 0) {
|
|
|
|
|
src_val = inst.GetOperand(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (src_val) {
|
|
|
|
|
EmitValueToReg(src_val, PhysReg::S0, slots, block, function);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
//throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令"));
|
|
|
|
|
throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令,opcode: "
|
|
|
|
|
+ std::to_string(static_cast<int>(inst.GetOpcode()))));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -673,17 +899,21 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
std::unique_ptr<MachineFunction> LowerFunction(const ir::Function& func) {
|
|
|
|
|
auto machine_func = std::make_unique<MachineFunction>(func.GetName());
|
|
|
|
|
ValueSlotMap slots;
|
|
|
|
|
|
|
|
|
|
// 存储参数信息,稍后处理
|
|
|
|
|
struct ParamInfo {
|
|
|
|
|
const ir::Value* arg;
|
|
|
|
|
int slot;
|
|
|
|
|
bool isFloat;
|
|
|
|
|
};
|
|
|
|
|
std::vector<ParamInfo> paramInfos;
|
|
|
|
|
|
|
|
|
|
// 为函数参数分配栈槽
|
|
|
|
|
for (const auto& arg : func.GetArguments()) {
|
|
|
|
|
// 为每个参数分配栈槽
|
|
|
|
|
int slot = machine_func->CreateFrameIndex(GetTypeSize(arg->GetType().get()));
|
|
|
|
|
slots.emplace(arg.get(), slot);
|
|
|
|
|
|
|
|
|
|
// 注意:参数的值需要从寄存器加载到栈槽
|
|
|
|
|
// 在 ARM64 调用约定中,前 8 个整数参数在 w0-w7,前 8 个浮点参数在 s0-s7
|
|
|
|
|
// 这里需要生成指令将参数从寄存器存储到栈槽
|
|
|
|
|
// 但 MachineFunction 还没有基本块,所以需要延迟处理
|
|
|
|
|
bool isFloat = arg->GetType()->IsFloat();
|
|
|
|
|
paramInfos.push_back({arg.get(), slot, isFloat});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IR 基本块到 MIR 基本块的映射
|
|
|
|
|
@ -702,32 +932,26 @@ std::unique_ptr<MachineFunction> LowerFunction(const ir::Function& func) {
|
|
|
|
|
if (!func.GetBlocks().empty()) {
|
|
|
|
|
MachineBasicBlock* entryBB = blockMap[func.GetEntry()];
|
|
|
|
|
if (entryBB) {
|
|
|
|
|
// 为每个参数生成从寄存器到栈槽的存储指令
|
|
|
|
|
size_t intArgIdx = 0;
|
|
|
|
|
size_t fpArgIdx = 0;
|
|
|
|
|
|
|
|
|
|
for (const auto& arg : func.GetArguments()) {
|
|
|
|
|
int slot = slots[arg.get()];
|
|
|
|
|
const ir::Type* argType = arg->GetType().get();
|
|
|
|
|
size_t intArgIdx = 0;
|
|
|
|
|
size_t fpArgIdx = 0;
|
|
|
|
|
|
|
|
|
|
if (argType->IsFloat()) {
|
|
|
|
|
// 浮点参数从 s0, s1, ... 读取
|
|
|
|
|
if (fpArgIdx < 8) {
|
|
|
|
|
PhysReg reg = static_cast<PhysReg>(static_cast<int>(PhysReg::S0) + fpArgIdx);
|
|
|
|
|
entryBB->Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(reg), Operand::FrameIndex(slot)});
|
|
|
|
|
}
|
|
|
|
|
fpArgIdx++;
|
|
|
|
|
} else {
|
|
|
|
|
// 整数参数从 w0, w1, ... 读取
|
|
|
|
|
if (intArgIdx < 8) {
|
|
|
|
|
PhysReg reg = static_cast<PhysReg>(static_cast<int>(PhysReg::W0) + intArgIdx);
|
|
|
|
|
entryBB->Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(reg), Operand::FrameIndex(slot)});
|
|
|
|
|
}
|
|
|
|
|
intArgIdx++;
|
|
|
|
|
for (const auto& param : paramInfos) {
|
|
|
|
|
if (param.isFloat) {
|
|
|
|
|
if (fpArgIdx < 8) {
|
|
|
|
|
PhysReg reg = static_cast<PhysReg>(static_cast<int>(PhysReg::S0) + fpArgIdx);
|
|
|
|
|
entryBB->Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(reg), Operand::FrameIndex(param.slot)});
|
|
|
|
|
}
|
|
|
|
|
fpArgIdx++;
|
|
|
|
|
} else {
|
|
|
|
|
if (intArgIdx < 8) {
|
|
|
|
|
PhysReg reg = static_cast<PhysReg>(static_cast<int>(PhysReg::W0) + intArgIdx);
|
|
|
|
|
entryBB->Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(reg), Operand::FrameIndex(param.slot)});
|
|
|
|
|
}
|
|
|
|
|
intArgIdx++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -750,6 +974,13 @@ std::unique_ptr<MachineModule> LowerToMIR(const ir::Module& module) {
|
|
|
|
|
DefaultContext();
|
|
|
|
|
|
|
|
|
|
auto machine_module = std::make_unique<MachineModule>();
|
|
|
|
|
|
|
|
|
|
// 处理全局变量
|
|
|
|
|
for (const auto& global : module.GetGlobals()) {
|
|
|
|
|
// 为全局变量在数据段分配空间
|
|
|
|
|
// 这里需要扩展 MachineModule 来支持全局变量
|
|
|
|
|
DEBUG_MSG("Global variable: " << global->GetName());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 遍历模块中的所有函数
|
|
|
|
|
for (const auto& func : module.GetFunctions()) {
|
|
|
|
|
|