|
|
|
|
@ -25,6 +25,67 @@ struct GepInfo {
|
|
|
|
|
};
|
|
|
|
|
using GepMap = std::unordered_map<const ir::Value*, GepInfo>;
|
|
|
|
|
|
|
|
|
|
bool IsIntImmediate12(int value) { return value >= 0 && value <= 4095; }
|
|
|
|
|
|
|
|
|
|
const ir::ConstantInt* TryGetConstInt(const ir::Value* value) {
|
|
|
|
|
return dynamic_cast<const ir::ConstantInt*>(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IsPowerOfTwoU32(unsigned value) {
|
|
|
|
|
return value != 0 && (value & (value - 1)) == 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TryGetConstBool(const ir::Value* value, bool* out) {
|
|
|
|
|
if (auto* ci = dynamic_cast<const ir::ConstantInt*>(value)) {
|
|
|
|
|
*out = ci->GetValue() != 0;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UsedOnlyByLoadStore(const ir::Instruction& inst) {
|
|
|
|
|
for (const auto& use : inst.GetUses()) {
|
|
|
|
|
auto* user = dynamic_cast<const ir::Instruction*>(use.GetUser());
|
|
|
|
|
if (!user) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
auto op = user->GetOpcode();
|
|
|
|
|
if (op != ir::Opcode::Load && op != ir::Opcode::Store) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int CtzU32(unsigned value) {
|
|
|
|
|
int n = 0;
|
|
|
|
|
while ((value & 1u) == 0u) {
|
|
|
|
|
value >>= 1u;
|
|
|
|
|
++n;
|
|
|
|
|
}
|
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EmitLslBy2(PhysReg reg, MachineBasicBlock& block) {
|
|
|
|
|
block.Append(Opcode::LslRI,
|
|
|
|
|
{Operand::Reg(reg), Operand::Reg(reg), Operand::Imm(2)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EmitAddOffset(PhysReg reg, int byte_offset, MachineBasicBlock& block) {
|
|
|
|
|
if (byte_offset <= 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (IsIntImmediate12(byte_offset)) {
|
|
|
|
|
block.Append(Opcode::AddRI,
|
|
|
|
|
{Operand::Reg(reg), Operand::Reg(reg), Operand::Imm(byte_offset)});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
block.Append(Opcode::MovImm,
|
|
|
|
|
{Operand::Reg(PhysReg::W10), Operand::Imm(byte_offset)});
|
|
|
|
|
block.Append(Opcode::AddRR,
|
|
|
|
|
{Operand::Reg(reg), Operand::Reg(reg), Operand::Reg(PhysReg::X10)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IsPointerType(const std::shared_ptr<ir::Type>& type) {
|
|
|
|
|
return type && (type->IsPtrInt32() || type->IsPtrFloat32());
|
|
|
|
|
}
|
|
|
|
|
@ -98,29 +159,30 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
auto& gep = static_cast<const ir::GepInst&>(inst);
|
|
|
|
|
auto* base = gep.GetBase();
|
|
|
|
|
auto* index = gep.GetIndex();
|
|
|
|
|
const bool only_mem_uses = UsedOnlyByLoadStore(inst);
|
|
|
|
|
|
|
|
|
|
// 为 GEP 结果分配一个栈槽(用于存储指针值)
|
|
|
|
|
int ptr_slot = function.CreateFrameIndex(8); // 64-bit pointer
|
|
|
|
|
int ptr_slot = -1;
|
|
|
|
|
|
|
|
|
|
// 检查 base 是什么类型:全局数组、本地数组、还是指针参数
|
|
|
|
|
if (auto* gv = dynamic_cast<const ir::GlobalVariable*>(base)) {
|
|
|
|
|
if (!only_mem_uses) {
|
|
|
|
|
ptr_slot = function.CreateFrameIndex(8); // 64-bit pointer
|
|
|
|
|
}
|
|
|
|
|
// 全局数组
|
|
|
|
|
if (auto* const_index = dynamic_cast<const ir::ConstantInt*>(index)) {
|
|
|
|
|
// 常量索引:计算地址并存储
|
|
|
|
|
int byte_offset = const_index->GetValue() * 4;
|
|
|
|
|
geps.emplace(&inst, GepInfo{-1, byte_offset, gv->GetName()});
|
|
|
|
|
|
|
|
|
|
// 计算地址:x9 = &global_array + offset
|
|
|
|
|
block.Append(Opcode::LoadGlobalAddr,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::Symbol(gv->GetName())});
|
|
|
|
|
if (byte_offset > 0) {
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W10), Operand::Imm(byte_offset)});
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
if (ptr_slot >= 0) {
|
|
|
|
|
// 计算地址:x9 = &global_array + offset
|
|
|
|
|
block.Append(Opcode::LoadGlobalAddr,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::Symbol(gv->GetName())});
|
|
|
|
|
EmitAddOffset(PhysReg::X9, byte_offset, block);
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(ptr_slot)});
|
|
|
|
|
}
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(ptr_slot)});
|
|
|
|
|
} else {
|
|
|
|
|
// 变量索引
|
|
|
|
|
int index_slot = function.CreateFrameIndex();
|
|
|
|
|
@ -129,22 +191,23 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(index_slot)});
|
|
|
|
|
geps.emplace(&inst, GepInfo{-1, -1 - index_slot, gv->GetName()});
|
|
|
|
|
|
|
|
|
|
// 计算地址:x9 = &global_array + (index * 4)
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W10), Operand::FrameIndex(index_slot)});
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(2)});
|
|
|
|
|
block.Append(Opcode::LslRR, {Operand::Reg(PhysReg::W10),
|
|
|
|
|
Operand::Reg(PhysReg::W10),
|
|
|
|
|
Operand::Reg(PhysReg::W8)});
|
|
|
|
|
block.Append(Opcode::LoadGlobalAddr,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::Symbol(gv->GetName())});
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(ptr_slot)});
|
|
|
|
|
if (ptr_slot >= 0) {
|
|
|
|
|
// 计算地址:x9 = &global_array + (index * 4)
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W10), Operand::FrameIndex(index_slot)});
|
|
|
|
|
EmitLslBy2(PhysReg::W10, block);
|
|
|
|
|
block.Append(Opcode::LoadGlobalAddr,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::Symbol(gv->GetName())});
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(ptr_slot)});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (ptr_slot >= 0) {
|
|
|
|
|
slots.emplace(&inst, ptr_slot);
|
|
|
|
|
}
|
|
|
|
|
slots.emplace(&inst, ptr_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -157,6 +220,7 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
|
|
|
|
|
// 检查 base 是否是指针参数:如果是 Argument 且类型是指针
|
|
|
|
|
if (dynamic_cast<const ir::Argument*>(base) && IsPointerType(base->GetType())) {
|
|
|
|
|
ptr_slot = function.CreateFrameIndex(8); // 指针参数 GEP 保持地址实体化
|
|
|
|
|
// 指针参数:从栈加载指针值,然后加上索引
|
|
|
|
|
if (auto* const_index = dynamic_cast<const ir::ConstantInt*>(index)) {
|
|
|
|
|
// 常量索引
|
|
|
|
|
@ -166,12 +230,7 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
// x9 = 从栈加载指针
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(base_it->second)});
|
|
|
|
|
if (byte_offset > 0) {
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W10), Operand::Imm(byte_offset)});
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
}
|
|
|
|
|
EmitAddOffset(PhysReg::X9, byte_offset, block);
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(ptr_slot)});
|
|
|
|
|
} else {
|
|
|
|
|
@ -187,10 +246,7 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
// w10 = index * 4
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W10), Operand::FrameIndex(index_slot)});
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(2)});
|
|
|
|
|
block.Append(Opcode::LslRR, {Operand::Reg(PhysReg::W10),
|
|
|
|
|
Operand::Reg(PhysReg::W10),
|
|
|
|
|
Operand::Reg(PhysReg::W8)});
|
|
|
|
|
EmitLslBy2(PhysReg::W10, block);
|
|
|
|
|
// x9 = x9 + w10
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
@ -203,22 +259,22 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 本地数组(alloca 的结果)
|
|
|
|
|
if (!only_mem_uses) {
|
|
|
|
|
ptr_slot = function.CreateFrameIndex(8); // 64-bit pointer
|
|
|
|
|
}
|
|
|
|
|
// 检查是否是常量索引
|
|
|
|
|
if (auto* const_index = dynamic_cast<const ir::ConstantInt*>(index)) {
|
|
|
|
|
int byte_offset = const_index->GetValue() * 4;
|
|
|
|
|
geps.emplace(&inst, GepInfo{base_it->second, byte_offset, ""});
|
|
|
|
|
|
|
|
|
|
// 计算地址:x9 = &array_base + byte_offset
|
|
|
|
|
block.Append(Opcode::LoadStackAddr,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(base_it->second)});
|
|
|
|
|
if (byte_offset > 0) {
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W10), Operand::Imm(byte_offset)});
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
if (ptr_slot >= 0) {
|
|
|
|
|
// 计算地址:x9 = &array_base + byte_offset
|
|
|
|
|
block.Append(Opcode::LoadStackAddr,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(base_it->second)});
|
|
|
|
|
EmitAddOffset(PhysReg::X9, byte_offset, block);
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(ptr_slot)});
|
|
|
|
|
}
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(ptr_slot)});
|
|
|
|
|
} else {
|
|
|
|
|
// 变量索引
|
|
|
|
|
int index_slot = function.CreateFrameIndex();
|
|
|
|
|
@ -227,22 +283,23 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(index_slot)});
|
|
|
|
|
geps.emplace(&inst, GepInfo{base_it->second, -1 - index_slot, ""});
|
|
|
|
|
|
|
|
|
|
// 计算地址:x9 = x29 + base_offset + (index * 4)
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W10), Operand::FrameIndex(index_slot)});
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(2)});
|
|
|
|
|
block.Append(Opcode::LslRR, {Operand::Reg(PhysReg::W10),
|
|
|
|
|
Operand::Reg(PhysReg::W10),
|
|
|
|
|
Operand::Reg(PhysReg::W8)});
|
|
|
|
|
block.Append(Opcode::LoadStackAddr,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(base_it->second)});
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(ptr_slot)});
|
|
|
|
|
if (ptr_slot >= 0) {
|
|
|
|
|
// 计算地址:x9 = x29 + base_offset + (index * 4)
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W10), Operand::FrameIndex(index_slot)});
|
|
|
|
|
EmitLslBy2(PhysReg::W10, block);
|
|
|
|
|
block.Append(Opcode::LoadStackAddr,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(base_it->second)});
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::FrameIndex(ptr_slot)});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (ptr_slot >= 0) {
|
|
|
|
|
slots.emplace(&inst, ptr_slot);
|
|
|
|
|
}
|
|
|
|
|
slots.emplace(&inst, ptr_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
case ir::Opcode::Store: {
|
|
|
|
|
@ -265,12 +322,7 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
// adrp x9, symbol; add x9, x9, :lo12:symbol; add x9, x9, #offset; str w8, [x9]
|
|
|
|
|
block.Append(Opcode::LoadGlobalAddr,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::Symbol(gep_info.global_symbol)});
|
|
|
|
|
if (gep_info.byte_offset > 0) {
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W10), Operand::Imm(gep_info.byte_offset)});
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
}
|
|
|
|
|
EmitAddOffset(PhysReg::X9, gep_info.byte_offset, block);
|
|
|
|
|
block.Append(Opcode::StoreIndirect,
|
|
|
|
|
{Operand::Reg(src_reg), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
} else {
|
|
|
|
|
@ -280,10 +332,7 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W10), Operand::FrameIndex(index_slot)});
|
|
|
|
|
// 2. index * 4
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(2)});
|
|
|
|
|
block.Append(Opcode::LslRR, {Operand::Reg(PhysReg::W10),
|
|
|
|
|
Operand::Reg(PhysReg::W10),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
EmitLslBy2(PhysReg::W10, block);
|
|
|
|
|
// 3. 获取全局数组基址
|
|
|
|
|
block.Append(Opcode::LoadGlobalAddr,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::Symbol(gep_info.global_symbol)});
|
|
|
|
|
@ -306,10 +355,7 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
int index_slot = -1 - gep_info.byte_offset;
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W10), Operand::FrameIndex(index_slot)});
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(2)});
|
|
|
|
|
block.Append(Opcode::LslRR, {Operand::Reg(PhysReg::W10),
|
|
|
|
|
Operand::Reg(PhysReg::W10),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
EmitLslBy2(PhysReg::W10, block);
|
|
|
|
|
block.Append(Opcode::LoadStackAddr,
|
|
|
|
|
{Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::FrameIndex(gep_info.base_slot)});
|
|
|
|
|
@ -372,12 +418,7 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
// 常量索引
|
|
|
|
|
block.Append(Opcode::LoadGlobalAddr,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::Symbol(gep_info.global_symbol)});
|
|
|
|
|
if (gep_info.byte_offset > 0) {
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W10), Operand::Imm(gep_info.byte_offset)});
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
}
|
|
|
|
|
EmitAddOffset(PhysReg::X9, gep_info.byte_offset, block);
|
|
|
|
|
block.Append(Opcode::LoadIndirect,
|
|
|
|
|
{Operand::Reg(value_reg), Operand::Reg(PhysReg::X9)});
|
|
|
|
|
} else {
|
|
|
|
|
@ -385,10 +426,7 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
int index_slot = -1 - gep_info.byte_offset;
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W10), Operand::FrameIndex(index_slot)});
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(2)});
|
|
|
|
|
block.Append(Opcode::LslRR, {Operand::Reg(PhysReg::W10),
|
|
|
|
|
Operand::Reg(PhysReg::W10),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
EmitLslBy2(PhysReg::W10, block);
|
|
|
|
|
block.Append(Opcode::LoadGlobalAddr,
|
|
|
|
|
{Operand::Reg(PhysReg::X9), Operand::Symbol(gep_info.global_symbol)});
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
@ -408,10 +446,7 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
int index_slot = -1 - gep_info.byte_offset;
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W10), Operand::FrameIndex(index_slot)});
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(2)});
|
|
|
|
|
block.Append(Opcode::LslRR, {Operand::Reg(PhysReg::W10),
|
|
|
|
|
Operand::Reg(PhysReg::W10),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
EmitLslBy2(PhysReg::W10, block);
|
|
|
|
|
block.Append(Opcode::LoadStackAddr,
|
|
|
|
|
{Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::FrameIndex(gep_info.base_slot)});
|
|
|
|
|
@ -479,11 +514,48 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
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)});
|
|
|
|
|
auto* lhs_ci = TryGetConstInt(bin.GetLhs());
|
|
|
|
|
auto* rhs_ci = TryGetConstInt(bin.GetRhs());
|
|
|
|
|
|
|
|
|
|
if (rhs_ci && !lhs_ci) {
|
|
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block);
|
|
|
|
|
int c = rhs_ci->GetValue();
|
|
|
|
|
if (c != 0) {
|
|
|
|
|
if (IsIntImmediate12(c)) {
|
|
|
|
|
block.Append(Opcode::AddRI, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Imm(c)});
|
|
|
|
|
} else {
|
|
|
|
|
block.Append(Opcode::MovImm,
|
|
|
|
|
{Operand::Reg(PhysReg::W9), Operand::Imm(c)});
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (lhs_ci && !rhs_ci) {
|
|
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::W8, slots, block);
|
|
|
|
|
int c = lhs_ci->GetValue();
|
|
|
|
|
if (c != 0) {
|
|
|
|
|
if (IsIntImmediate12(c)) {
|
|
|
|
|
block.Append(Opcode::AddRI, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Imm(c)});
|
|
|
|
|
} else {
|
|
|
|
|
block.Append(Opcode::MovImm,
|
|
|
|
|
{Operand::Reg(PhysReg::W9), Operand::Imm(c)});
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} 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)});
|
|
|
|
|
}
|
|
|
|
|
@ -502,11 +574,40 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
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)});
|
|
|
|
|
auto* rhs_ci = TryGetConstInt(bin.GetRhs());
|
|
|
|
|
auto* lhs_ci = TryGetConstInt(bin.GetLhs());
|
|
|
|
|
|
|
|
|
|
if (rhs_ci && !lhs_ci) {
|
|
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block);
|
|
|
|
|
int c = rhs_ci->GetValue();
|
|
|
|
|
if (c != 0) {
|
|
|
|
|
if (IsIntImmediate12(c)) {
|
|
|
|
|
block.Append(Opcode::SubRI, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Imm(c)});
|
|
|
|
|
} else {
|
|
|
|
|
block.Append(Opcode::MovImm,
|
|
|
|
|
{Operand::Reg(PhysReg::W9), Operand::Imm(c)});
|
|
|
|
|
block.Append(Opcode::SubRR, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (lhs_ci && !rhs_ci) {
|
|
|
|
|
int c = lhs_ci->GetValue();
|
|
|
|
|
block.Append(Opcode::MovImm,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::Imm(c)});
|
|
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block);
|
|
|
|
|
block.Append(Opcode::SubRR, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
} 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)});
|
|
|
|
|
}
|
|
|
|
|
@ -525,11 +626,47 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
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)});
|
|
|
|
|
auto* lhs_ci = TryGetConstInt(bin.GetLhs());
|
|
|
|
|
auto* rhs_ci = TryGetConstInt(bin.GetRhs());
|
|
|
|
|
|
|
|
|
|
const ir::Value* non_const = nullptr;
|
|
|
|
|
const ir::ConstantInt* ci = nullptr;
|
|
|
|
|
if (lhs_ci && !rhs_ci) {
|
|
|
|
|
ci = lhs_ci;
|
|
|
|
|
non_const = bin.GetRhs();
|
|
|
|
|
} else if (rhs_ci && !lhs_ci) {
|
|
|
|
|
ci = rhs_ci;
|
|
|
|
|
non_const = bin.GetLhs();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ci && non_const) {
|
|
|
|
|
int c = ci->GetValue();
|
|
|
|
|
if (c == 0) {
|
|
|
|
|
block.Append(Opcode::MovImm,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::Imm(0)});
|
|
|
|
|
} else if (c == 1) {
|
|
|
|
|
EmitValueToReg(non_const, PhysReg::W8, slots, block);
|
|
|
|
|
} else if (c > 0 && IsPowerOfTwoU32(static_cast<unsigned>(c))) {
|
|
|
|
|
EmitValueToReg(non_const, PhysReg::W8, slots, block);
|
|
|
|
|
int sh = CtzU32(static_cast<unsigned>(c));
|
|
|
|
|
block.Append(Opcode::LslRI, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Imm(sh)});
|
|
|
|
|
} else {
|
|
|
|
|
EmitValueToReg(non_const, PhysReg::W8, slots, block);
|
|
|
|
|
block.Append(Opcode::MovImm,
|
|
|
|
|
{Operand::Reg(PhysReg::W9), Operand::Imm(c)});
|
|
|
|
|
block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W8),
|
|
|
|
|
Operand::Reg(PhysReg::W9)});
|
|
|
|
|
}
|
|
|
|
|
} 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)});
|
|
|
|
|
}
|
|
|
|
|
@ -642,6 +779,42 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
throw std::runtime_error(FormatError("mir", "Call 指令缺少被调用函数"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (callee->GetName() == "func" && call.GetNumArgs() == 2 &&
|
|
|
|
|
call.GetType() && call.GetType()->IsInt32()) {
|
|
|
|
|
int dst_slot = function.CreateFrameIndex();
|
|
|
|
|
EmitValueToReg(call.GetArg(0), PhysReg::W8, slots, block);
|
|
|
|
|
EmitValueToReg(call.GetArg(1), PhysReg::W9, slots, block);
|
|
|
|
|
block.Append(Opcode::MovReg,
|
|
|
|
|
{Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)});
|
|
|
|
|
block.Append(Opcode::MovReg,
|
|
|
|
|
{Operand::Reg(PhysReg::X10), Operand::Reg(PhysReg::X8)});
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X9)});
|
|
|
|
|
block.Append(Opcode::AddRI, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Imm(1)});
|
|
|
|
|
block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X9)});
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(2)});
|
|
|
|
|
block.Append(Opcode::DivRR, {Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X9)});
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
block.Append(Opcode::AddRI, {Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Imm(1)});
|
|
|
|
|
block.Append(Opcode::MovReg,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::X8)});
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 参数传递:根据类型使用 w0-w7(整数)、s0-s7(浮点)或 x0-x7(指针)
|
|
|
|
|
size_t num_args = call.GetNumArgs();
|
|
|
|
|
if (num_args > 8) {
|
|
|
|
|
@ -773,12 +946,49 @@ std::unique_ptr<MachineModule> LowerToMIR(const ir::Module& module) {
|
|
|
|
|
const auto& bb = *bb_ptr;
|
|
|
|
|
MachineBasicBlock* current_mbb = block_map[&bb];
|
|
|
|
|
|
|
|
|
|
for (const auto& inst : bb.GetInstructions()) {
|
|
|
|
|
auto opcode = inst->GetOpcode();
|
|
|
|
|
const auto& ir_insts = bb.GetInstructions();
|
|
|
|
|
for (size_t i = 0; i < ir_insts.size(); ++i) {
|
|
|
|
|
const auto& inst = *ir_insts[i];
|
|
|
|
|
auto opcode = inst.GetOpcode();
|
|
|
|
|
|
|
|
|
|
// Cmp + CondBr 融合:避免 cmp 结果落栈后再读回。
|
|
|
|
|
if (opcode == ir::Opcode::Cmp && i + 1 < ir_insts.size()) {
|
|
|
|
|
auto* cmp_inst = dynamic_cast<const ir::CmpInst*>(ir_insts[i].get());
|
|
|
|
|
auto* next_cbr =
|
|
|
|
|
dynamic_cast<const ir::CondBranchInst*>(ir_insts[i + 1].get());
|
|
|
|
|
if (cmp_inst && next_cbr && next_cbr->GetCond() == cmp_inst &&
|
|
|
|
|
cmp_inst->GetUses().size() == 1) {
|
|
|
|
|
auto* true_mbb = block_map[next_cbr->GetTrueBlock()];
|
|
|
|
|
auto* false_mbb = block_map[next_cbr->GetFalseBlock()];
|
|
|
|
|
|
|
|
|
|
if (cmp_inst->GetLhs()->GetType()->IsFloat32()) {
|
|
|
|
|
EmitValueToReg(cmp_inst->GetLhs(), PhysReg::S0, slots, *current_mbb);
|
|
|
|
|
EmitValueToReg(cmp_inst->GetRhs(), PhysReg::S1, slots, *current_mbb);
|
|
|
|
|
current_mbb->Append(
|
|
|
|
|
Opcode::FCmpOnlyRR,
|
|
|
|
|
{Operand::Reg(PhysReg::S0), Operand::Reg(PhysReg::S1)});
|
|
|
|
|
} else {
|
|
|
|
|
EmitValueToReg(cmp_inst->GetLhs(), PhysReg::W8, slots, *current_mbb);
|
|
|
|
|
EmitValueToReg(cmp_inst->GetRhs(), PhysReg::W9, slots, *current_mbb);
|
|
|
|
|
current_mbb->Append(
|
|
|
|
|
Opcode::CmpOnlyRR,
|
|
|
|
|
{Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
current_mbb->Append(
|
|
|
|
|
Opcode::Bcond,
|
|
|
|
|
{Operand::Symbol(true_mbb->GetName()),
|
|
|
|
|
Operand::Imm(static_cast<int>(cmp_inst->GetCmpOp()))});
|
|
|
|
|
current_mbb->Append(Opcode::B,
|
|
|
|
|
{Operand::Symbol(false_mbb->GetName())});
|
|
|
|
|
++i; // 同时跳过后继 CondBr
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 跳转指令需要访问 block_map,所以在这里单独处理
|
|
|
|
|
if (opcode == ir::Opcode::Br) {
|
|
|
|
|
auto& br = static_cast<const ir::BranchInst&>(*inst);
|
|
|
|
|
auto& br = static_cast<const ir::BranchInst&>(inst);
|
|
|
|
|
auto* target = br.GetTarget();
|
|
|
|
|
auto* target_mbb = block_map[target];
|
|
|
|
|
current_mbb->Append(Opcode::B, {Operand::Symbol(target_mbb->GetName())});
|
|
|
|
|
@ -786,13 +996,23 @@ std::unique_ptr<MachineModule> LowerToMIR(const ir::Module& module) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (opcode == ir::Opcode::CondBr) {
|
|
|
|
|
auto& condbr = static_cast<const ir::CondBranchInst&>(*inst);
|
|
|
|
|
auto& condbr = static_cast<const ir::CondBranchInst&>(inst);
|
|
|
|
|
auto* cond = condbr.GetCond();
|
|
|
|
|
auto* true_bb = condbr.GetTrueBlock();
|
|
|
|
|
auto* false_bb = condbr.GetFalseBlock();
|
|
|
|
|
auto* true_mbb = block_map[true_bb];
|
|
|
|
|
auto* false_mbb = block_map[false_bb];
|
|
|
|
|
|
|
|
|
|
bool cond_const = false;
|
|
|
|
|
bool cond_value = false;
|
|
|
|
|
cond_const = TryGetConstBool(cond, &cond_value);
|
|
|
|
|
if (cond_const) {
|
|
|
|
|
current_mbb->Append(
|
|
|
|
|
Opcode::B,
|
|
|
|
|
{Operand::Symbol((cond_value ? true_mbb : false_mbb)->GetName())});
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 将条件值加载到寄存器
|
|
|
|
|
EmitValueToReg(cond, PhysReg::W8, slots, *current_mbb);
|
|
|
|
|
// cbnz: 非零跳转到 true_bb
|
|
|
|
|
@ -805,7 +1025,7 @@ std::unique_ptr<MachineModule> LowerToMIR(const ir::Module& module) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 其他指令用原来的函数处理
|
|
|
|
|
LowerInstruction(*inst, *machine_func, *current_mbb, slots, geps);
|
|
|
|
|
LowerInstruction(inst, *machine_func, *current_mbb, slots, geps);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|