|
|
|
|
@ -1,5 +1,7 @@
|
|
|
|
|
#include "mir/MIR.h"
|
|
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
#include <cstring>
|
|
|
|
|
#include <stdexcept>
|
|
|
|
|
#include <unordered_map>
|
|
|
|
|
|
|
|
|
|
@ -23,8 +25,12 @@ struct GepInfo {
|
|
|
|
|
};
|
|
|
|
|
using GepMap = std::unordered_map<const ir::Value*, GepInfo>;
|
|
|
|
|
|
|
|
|
|
void EmitValueToReg(const ir::Value* value, PhysReg target,
|
|
|
|
|
const ValueSlotMap& slots, MachineBasicBlock& block) {
|
|
|
|
|
bool IsPointerType(const std::shared_ptr<ir::Type>& type) {
|
|
|
|
|
return type && (type->IsPtrInt32() || type->IsPtrFloat32());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EmitIntValueToReg(const ir::Value* value, PhysReg target,
|
|
|
|
|
const ValueSlotMap& slots, MachineBasicBlock& block) {
|
|
|
|
|
if (auto* constant = dynamic_cast<const ir::ConstantInt*>(value)) {
|
|
|
|
|
block.Append(Opcode::MovImm,
|
|
|
|
|
{Operand::Reg(target), Operand::Imm(constant->GetValue())});
|
|
|
|
|
@ -48,6 +54,36 @@ void EmitValueToReg(const ir::Value* value, PhysReg target,
|
|
|
|
|
{Operand::Reg(target), Operand::FrameIndex(it->second)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EmitFloatValueToReg(const ir::Value* value, PhysReg target,
|
|
|
|
|
const ValueSlotMap& slots, MachineBasicBlock& block) {
|
|
|
|
|
if (auto* constant = dynamic_cast<const ir::ConstantFloat*>(value)) {
|
|
|
|
|
std::int32_t bits = 0;
|
|
|
|
|
float fv = constant->GetValue();
|
|
|
|
|
std::memcpy(&bits, &fv, sizeof(bits));
|
|
|
|
|
block.Append(Opcode::FMovImm,
|
|
|
|
|
{Operand::Reg(target), Operand::Imm(static_cast<int>(bits))});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto it = slots.find(value);
|
|
|
|
|
if (it == slots.end()) {
|
|
|
|
|
throw std::runtime_error(
|
|
|
|
|
FormatError("mir", "找不到浮点值对应的栈槽: " + value->GetName()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
|
|
{Operand::Reg(target), Operand::FrameIndex(it->second)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EmitValueToReg(const ir::Value* value, PhysReg target,
|
|
|
|
|
const ValueSlotMap& slots, MachineBasicBlock& block) {
|
|
|
|
|
if (value->GetType() && value->GetType()->IsFloat32()) {
|
|
|
|
|
EmitFloatValueToReg(value, target, slots, block);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
EmitIntValueToReg(value, target, slots, block);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
MachineBasicBlock& block, ValueSlotMap& slots,
|
|
|
|
|
GepMap& geps) {
|
|
|
|
|
@ -120,7 +156,7 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查 base 是否是指针参数:如果是 Argument 且类型是指针
|
|
|
|
|
if (dynamic_cast<const ir::Argument*>(base) && base->GetType()->IsPtrInt32()) {
|
|
|
|
|
if (dynamic_cast<const ir::Argument*>(base) && IsPointerType(base->GetType())) {
|
|
|
|
|
// 指针参数:从栈加载指针值,然后加上索引
|
|
|
|
|
if (auto* const_index = dynamic_cast<const ir::ConstantInt*>(index)) {
|
|
|
|
|
// 常量索引
|
|
|
|
|
@ -212,12 +248,15 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
case ir::Opcode::Store: {
|
|
|
|
|
auto& store = static_cast<const ir::StoreInst&>(inst);
|
|
|
|
|
auto* ptr = store.GetPtr();
|
|
|
|
|
const bool is_float_value =
|
|
|
|
|
store.GetValue()->GetType() && store.GetValue()->GetType()->IsFloat32();
|
|
|
|
|
const PhysReg src_reg = is_float_value ? PhysReg::S0 : PhysReg::W8;
|
|
|
|
|
|
|
|
|
|
// 检查是否是 GEP 结果(数组元素)
|
|
|
|
|
auto gep_it = geps.find(ptr);
|
|
|
|
|
if (gep_it != geps.end()) {
|
|
|
|
|
const auto& gep_info = gep_it->second;
|
|
|
|
|
EmitValueToReg(store.GetValue(), PhysReg::W8, slots, block);
|
|
|
|
|
EmitValueToReg(store.GetValue(), src_reg, slots, block);
|
|
|
|
|
|
|
|
|
|
if (gep_info.base_slot == -1) {
|
|
|
|
|
// 全局数组
|
|
|
|
|
@ -233,7 +272,7 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
}
|
|
|
|
|
block.Append(Opcode::StoreIndirect,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
{Operand::Reg(src_reg), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
} else {
|
|
|
|
|
// 变量索引:global_array[var_idx]
|
|
|
|
|
int index_slot = -1 - gep_info.byte_offset;
|
|
|
|
|
@ -254,12 +293,12 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
// 5. 存储
|
|
|
|
|
block.Append(Opcode::StoreIndirect,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
{Operand::Reg(src_reg), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
}
|
|
|
|
|
} else if (gep_info.byte_offset >= 0) {
|
|
|
|
|
// 本地数组,常量索引
|
|
|
|
|
block.Append(Opcode::StoreStackOffset,
|
|
|
|
|
{Operand::Reg(PhysReg::W8),
|
|
|
|
|
{Operand::Reg(src_reg),
|
|
|
|
|
Operand::FrameIndex(gep_info.base_slot),
|
|
|
|
|
Operand::Imm(gep_info.byte_offset)});
|
|
|
|
|
} else {
|
|
|
|
|
@ -278,16 +317,16 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
block.Append(Opcode::StoreIndirect,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
{Operand::Reg(src_reg), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查是否是全局变量
|
|
|
|
|
if (auto* gv = dynamic_cast<const ir::GlobalVariable*>(ptr)) {
|
|
|
|
|
EmitValueToReg(store.GetValue(), PhysReg::W8, slots, block);
|
|
|
|
|
EmitValueToReg(store.GetValue(), src_reg, slots, block);
|
|
|
|
|
block.Append(Opcode::StoreGlobal,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::Symbol(gv->GetName())});
|
|
|
|
|
{Operand::Reg(src_reg), Operand::Symbol(gv->GetName())});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -298,26 +337,28 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
FormatError("mir", "暂不支持对非栈/全局变量地址进行写入"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EmitValueToReg(store.GetValue(), PhysReg::W8, slots, block);
|
|
|
|
|
EmitValueToReg(store.GetValue(), src_reg, slots, block);
|
|
|
|
|
|
|
|
|
|
// 检查是否是GEP结果:如果ptr的类型是指针且slot大小是8字节,说明存储的是地址
|
|
|
|
|
const auto& dst_slot = function.GetFrameSlot(dst->second);
|
|
|
|
|
if (ptr->GetType()->IsPtrInt32() && dst_slot.size == 8) {
|
|
|
|
|
if (IsPointerType(ptr->GetType()) && dst_slot.size == 8) {
|
|
|
|
|
// GEP结果:先加载指针地址,再通过指针存储值
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(dst->second)});
|
|
|
|
|
block.Append(Opcode::StoreIndirect,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
{Operand::Reg(src_reg), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
} else {
|
|
|
|
|
// 普通栈变量:直接存储
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst->second)});
|
|
|
|
|
{Operand::Reg(src_reg), Operand::FrameIndex(dst->second)});
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
case ir::Opcode::Load: {
|
|
|
|
|
auto& load = static_cast<const ir::LoadInst&>(inst);
|
|
|
|
|
auto* ptr = load.GetPtr();
|
|
|
|
|
const bool is_float_load = load.GetType() && load.GetType()->IsFloat32();
|
|
|
|
|
const PhysReg value_reg = is_float_load ? PhysReg::S0 : PhysReg::W8;
|
|
|
|
|
|
|
|
|
|
// 检查是否是 GEP 结果(数组元素)
|
|
|
|
|
auto gep_it = geps.find(ptr);
|
|
|
|
|
@ -338,7 +379,7 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
}
|
|
|
|
|
block.Append(Opcode::LoadIndirect,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
{Operand::Reg(value_reg), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
} else {
|
|
|
|
|
// 变量索引
|
|
|
|
|
int index_slot = -1 - gep_info.byte_offset;
|
|
|
|
|
@ -354,12 +395,12 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
block.Append(Opcode::LoadIndirect,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
{Operand::Reg(value_reg), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
}
|
|
|
|
|
} else if (gep_info.byte_offset >= 0) {
|
|
|
|
|
// 本地数组,常量索引
|
|
|
|
|
block.Append(Opcode::LoadStackOffset,
|
|
|
|
|
{Operand::Reg(PhysReg::W8),
|
|
|
|
|
{Operand::Reg(value_reg),
|
|
|
|
|
Operand::FrameIndex(gep_info.base_slot),
|
|
|
|
|
Operand::Imm(gep_info.byte_offset)});
|
|
|
|
|
} else {
|
|
|
|
|
@ -378,11 +419,11 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
block.Append(Opcode::LoadIndirect,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
{Operand::Reg(value_reg), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
{Operand::Reg(value_reg), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
@ -391,9 +432,9 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
if (auto* gv = dynamic_cast<const ir::GlobalVariable*>(ptr)) {
|
|
|
|
|
int dst_slot = function.CreateFrameIndex();
|
|
|
|
|
block.Append(Opcode::LoadGlobal,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::Symbol(gv->GetName())});
|
|
|
|
|
{Operand::Reg(value_reg), Operand::Symbol(gv->GetName())});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
{Operand::Reg(value_reg), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
@ -409,72 +450,112 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
|
|
|
|
|
// 检查是否是GEP结果:如果ptr的类型是指针且slot大小是8字节,说明存储的是地址
|
|
|
|
|
const auto& src_slot = function.GetFrameSlot(src->second);
|
|
|
|
|
if (ptr->GetType()->IsPtrInt32() && src_slot.size == 8) {
|
|
|
|
|
if (IsPointerType(ptr->GetType()) && src_slot.size == 8) {
|
|
|
|
|
// GEP结果:先加载指针地址,再通过指针加载值
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(src->second)});
|
|
|
|
|
block.Append(Opcode::LoadIndirect,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
{Operand::Reg(value_reg), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
} else {
|
|
|
|
|
// 普通栈变量:直接加载
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(src->second)});
|
|
|
|
|
{Operand::Reg(value_reg), Operand::FrameIndex(src->second)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
{Operand::Reg(value_reg), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
case ir::Opcode::Add: {
|
|
|
|
|
auto& bin = static_cast<const ir::BinaryInst&>(inst);
|
|
|
|
|
int dst_slot = function.CreateFrameIndex();
|
|
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block);
|
|
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block);
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
if (bin.GetType()->IsFloat32()) {
|
|
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block);
|
|
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block);
|
|
|
|
|
block.Append(Opcode::FAddRR, {Operand::Reg(PhysReg::S0),
|
|
|
|
|
Operand::Reg(PhysReg::S0),
|
|
|
|
|
Operand::Reg(PhysReg::S1)});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
} else {
|
|
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block);
|
|
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block);
|
|
|
|
|
block.Append(Opcode::AddRR, {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;
|
|
|
|
|
}
|
|
|
|
|
case ir::Opcode::Sub: {
|
|
|
|
|
auto& bin = static_cast<const ir::BinaryInst&>(inst);
|
|
|
|
|
int dst_slot = function.CreateFrameIndex();
|
|
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block);
|
|
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block);
|
|
|
|
|
block.Append(Opcode::SubRR, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
if (bin.GetType()->IsFloat32()) {
|
|
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block);
|
|
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block);
|
|
|
|
|
block.Append(Opcode::FSubRR, {Operand::Reg(PhysReg::S0),
|
|
|
|
|
Operand::Reg(PhysReg::S0),
|
|
|
|
|
Operand::Reg(PhysReg::S1)});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
} else {
|
|
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block);
|
|
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block);
|
|
|
|
|
block.Append(Opcode::SubRR, {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;
|
|
|
|
|
}
|
|
|
|
|
case ir::Opcode::Mul: {
|
|
|
|
|
auto& bin = static_cast<const ir::BinaryInst&>(inst);
|
|
|
|
|
int dst_slot = function.CreateFrameIndex();
|
|
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block);
|
|
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block);
|
|
|
|
|
block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
if (bin.GetType()->IsFloat32()) {
|
|
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block);
|
|
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block);
|
|
|
|
|
block.Append(Opcode::FMulRR, {Operand::Reg(PhysReg::S0),
|
|
|
|
|
Operand::Reg(PhysReg::S0),
|
|
|
|
|
Operand::Reg(PhysReg::S1)});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
} else {
|
|
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block);
|
|
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block);
|
|
|
|
|
block.Append(Opcode::MulRR, {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;
|
|
|
|
|
}
|
|
|
|
|
case ir::Opcode::Div: {
|
|
|
|
|
auto& bin = static_cast<const ir::BinaryInst&>(inst);
|
|
|
|
|
int dst_slot = function.CreateFrameIndex();
|
|
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block);
|
|
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block);
|
|
|
|
|
block.Append(Opcode::DivRR, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
if (bin.GetType()->IsFloat32()) {
|
|
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block);
|
|
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block);
|
|
|
|
|
block.Append(Opcode::FDivRR, {Operand::Reg(PhysReg::S0),
|
|
|
|
|
Operand::Reg(PhysReg::S0),
|
|
|
|
|
Operand::Reg(PhysReg::S1)});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
} else {
|
|
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block);
|
|
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block);
|
|
|
|
|
block.Append(Opcode::DivRR, {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;
|
|
|
|
|
}
|
|
|
|
|
@ -502,23 +583,53 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
case ir::Opcode::Cmp: {
|
|
|
|
|
auto& cmp = static_cast<const ir::CmpInst&>(inst);
|
|
|
|
|
int dst_slot = function.CreateFrameIndex();
|
|
|
|
|
EmitValueToReg(cmp.GetLhs(), PhysReg::W8, slots, block);
|
|
|
|
|
EmitValueToReg(cmp.GetRhs(), PhysReg::W9, slots, block);
|
|
|
|
|
// cmp 操作符通过 operand 传递
|
|
|
|
|
block.Append(Opcode::CmpRR, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W9),
|
|
|
|
|
Operand::Imm(static_cast<int>(cmp.GetCmpOp()))});
|
|
|
|
|
if (cmp.GetLhs()->GetType()->IsFloat32()) {
|
|
|
|
|
EmitValueToReg(cmp.GetLhs(), PhysReg::S0, slots, block);
|
|
|
|
|
EmitValueToReg(cmp.GetRhs(), PhysReg::S1, slots, block);
|
|
|
|
|
block.Append(Opcode::FCmpRR, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::S0),
|
|
|
|
|
Operand::Reg(PhysReg::S1),
|
|
|
|
|
Operand::Imm(static_cast<int>(cmp.GetCmpOp()))});
|
|
|
|
|
} else {
|
|
|
|
|
EmitValueToReg(cmp.GetLhs(), PhysReg::W8, slots, block);
|
|
|
|
|
EmitValueToReg(cmp.GetRhs(), PhysReg::W9, slots, block);
|
|
|
|
|
// cmp 操作符通过 operand 传递
|
|
|
|
|
block.Append(Opcode::CmpRR, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W9),
|
|
|
|
|
Operand::Imm(static_cast<int>(cmp.GetCmpOp()))});
|
|
|
|
|
}
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
case ir::Opcode::Cast: {
|
|
|
|
|
auto& cast = static_cast<const ir::CastInst&>(inst);
|
|
|
|
|
int dst_slot = function.CreateFrameIndex();
|
|
|
|
|
if (cast.GetCastOp() == ir::CastOp::IntToFloat) {
|
|
|
|
|
EmitValueToReg(cast.GetValue(), PhysReg::W8, slots, block);
|
|
|
|
|
block.Append(Opcode::SIToFP,
|
|
|
|
|
{Operand::Reg(PhysReg::S0), Operand::Reg(PhysReg::W8)});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
} else {
|
|
|
|
|
EmitValueToReg(cast.GetValue(), PhysReg::S0, slots, block);
|
|
|
|
|
block.Append(Opcode::FPToSI,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::S0)});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
}
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
case ir::Opcode::Ret: {
|
|
|
|
|
auto& ret = static_cast<const ir::ReturnInst&>(inst);
|
|
|
|
|
if (ret.GetValue()) {
|
|
|
|
|
// int/float 返回值
|
|
|
|
|
EmitValueToReg(ret.GetValue(), PhysReg::W0, slots, block);
|
|
|
|
|
PhysReg ret_reg = ret.GetValue()->GetType()->IsFloat32() ? PhysReg::S0
|
|
|
|
|
: PhysReg::W0;
|
|
|
|
|
EmitValueToReg(ret.GetValue(), ret_reg, slots, block);
|
|
|
|
|
}
|
|
|
|
|
// void 返回:不设置 w0
|
|
|
|
|
block.Append(Opcode::Ret);
|
|
|
|
|
@ -531,7 +642,7 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
throw std::runtime_error(FormatError("mir", "Call 指令缺少被调用函数"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 参数传递:根据类型使用 w0-w7(整数)或 x0-x7(指针)
|
|
|
|
|
// 参数传递:根据类型使用 w0-w7(整数)、s0-s7(浮点)或 x0-x7(指针)
|
|
|
|
|
size_t num_args = call.GetNumArgs();
|
|
|
|
|
if (num_args > 8) {
|
|
|
|
|
throw std::runtime_error(FormatError("mir", "暂不支持超过 8 个参数的函数调用"));
|
|
|
|
|
@ -540,8 +651,10 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
const auto& param_types = callee->GetParamTypes();
|
|
|
|
|
for (size_t i = 0; i < num_args; i++) {
|
|
|
|
|
auto* arg_value = call.GetArg(i);
|
|
|
|
|
// 检查参数类型是否是指针
|
|
|
|
|
bool is_ptr = (i < param_types.size() && param_types[i]->IsPtrInt32());
|
|
|
|
|
bool is_ptr =
|
|
|
|
|
(i < param_types.size() &&
|
|
|
|
|
(param_types[i]->IsPtrInt32() || param_types[i]->IsPtrFloat32()));
|
|
|
|
|
bool is_float = (i < param_types.size() && param_types[i]->IsFloat32());
|
|
|
|
|
|
|
|
|
|
if (is_ptr) {
|
|
|
|
|
// 指针参数:加载到 x 寄存器
|
|
|
|
|
@ -564,8 +677,10 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
FormatError("mir", "找不到指针参数的值: " + arg_value->GetName()));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 整数参数:加载到 w 寄存器
|
|
|
|
|
PhysReg arg_reg = static_cast<PhysReg>(static_cast<int>(PhysReg::W0) + i);
|
|
|
|
|
// 标量参数:整数用 w,浮点用 s
|
|
|
|
|
PhysReg arg_reg = is_float
|
|
|
|
|
? static_cast<PhysReg>(static_cast<int>(PhysReg::S0) + i)
|
|
|
|
|
: static_cast<PhysReg>(static_cast<int>(PhysReg::W0) + i);
|
|
|
|
|
EmitValueToReg(arg_value, arg_reg, slots, block);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -576,8 +691,9 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
// 处理返回值
|
|
|
|
|
if (!call.GetType()->IsVoid()) {
|
|
|
|
|
int dst_slot = function.CreateFrameIndex();
|
|
|
|
|
PhysReg ret_reg = call.GetType()->IsFloat32() ? PhysReg::S0 : PhysReg::W0;
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W0), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
{Operand::Reg(ret_reg), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
@ -597,7 +713,8 @@ std::unique_ptr<MachineModule> LowerToMIR(const ir::Module& module) {
|
|
|
|
|
// 复制全局变量信息
|
|
|
|
|
for (const auto& gv_ptr : module.GetGlobalVars()) {
|
|
|
|
|
const auto& gv = *gv_ptr;
|
|
|
|
|
machine_module->AddGlobalVar(gv.GetName(), gv.GetInitValue(), gv.GetCount());
|
|
|
|
|
machine_module->AddGlobalVar(gv.GetName(), gv.GetInitValue(), gv.GetCount(),
|
|
|
|
|
gv.IsFloat(), gv.GetInitElements());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const auto& func_ptr : module.GetFunctions()) {
|
|
|
|
|
@ -632,15 +749,18 @@ std::unique_ptr<MachineModule> LowerToMIR(const ir::Module& module) {
|
|
|
|
|
auto& entry_block = machine_func->GetEntry();
|
|
|
|
|
for (size_t i = 0; i < num_params; i++) {
|
|
|
|
|
auto* arg = func.GetArgument(i);
|
|
|
|
|
bool is_ptr = arg->GetType()->IsPtrInt32();
|
|
|
|
|
bool is_ptr = arg->GetType()->IsPtrInt32() || arg->GetType()->IsPtrFloat32();
|
|
|
|
|
bool is_float = arg->GetType()->IsFloat32();
|
|
|
|
|
int slot_size = is_ptr ? 8 : 4; // 指针 8 字节,整数 4 字节
|
|
|
|
|
int slot = machine_func->CreateFrameIndex(slot_size);
|
|
|
|
|
slots.emplace(arg, slot);
|
|
|
|
|
|
|
|
|
|
// 根据参数类型选择寄存器:指针用 x0-x7,整数用 w0-w7
|
|
|
|
|
// 根据参数类型选择寄存器:指针用 x0-x7,整数用 w0-w7,浮点用 s0-s7
|
|
|
|
|
PhysReg param_reg;
|
|
|
|
|
if (is_ptr) {
|
|
|
|
|
param_reg = static_cast<PhysReg>(static_cast<int>(PhysReg::X0) + i);
|
|
|
|
|
} else if (is_float) {
|
|
|
|
|
param_reg = static_cast<PhysReg>(static_cast<int>(PhysReg::S0) + i);
|
|
|
|
|
} else {
|
|
|
|
|
param_reg = static_cast<PhysReg>(static_cast<int>(PhysReg::W0) + i);
|
|
|
|
|
}
|
|
|
|
|
|