|
|
#include "mir/MIR.h"
|
|
|
|
|
|
#include <stdexcept>
|
|
|
#include <unordered_map>
|
|
|
#include <cstring>
|
|
|
|
|
|
#include "ir/IR.h"
|
|
|
#include "utils/Log.h"
|
|
|
|
|
|
//#define DEBUG_Lower
|
|
|
|
|
|
#ifdef DEBUG_Lower
|
|
|
#include <iostream>
|
|
|
#define DEBUG_MSG(msg) std::cerr << "[Lower Debug] " << msg << std::endl
|
|
|
#else
|
|
|
#define DEBUG_MSG(msg) ((void)0)
|
|
|
#endif
|
|
|
|
|
|
namespace mir {
|
|
|
namespace {
|
|
|
|
|
|
using ValueSlotMap = std::unordered_map<const ir::Value*, int>;
|
|
|
|
|
|
static uint32_t FloatToBits(float f) {
|
|
|
uint32_t bits;
|
|
|
memcpy(&bits, &f, sizeof(bits));
|
|
|
return bits;
|
|
|
}
|
|
|
|
|
|
// 获取类型大小(字节)
|
|
|
int GetTypeSize(const ir::Type* type) {
|
|
|
if (!type) return 4;
|
|
|
size_t size = type->Size();
|
|
|
return size > 0 ? static_cast<int>(size) : 4;
|
|
|
}
|
|
|
|
|
|
// 将 IR 整数比较谓词转换为 ARMv8 条件码
|
|
|
CondCode IcmpToCondCode(ir::IcmpInst::Predicate pred) {
|
|
|
switch (pred) {
|
|
|
case ir::IcmpInst::Predicate::EQ: return CondCode::EQ;
|
|
|
case ir::IcmpInst::Predicate::NE: return CondCode::NE;
|
|
|
case ir::IcmpInst::Predicate::LT: return CondCode::LT;
|
|
|
case ir::IcmpInst::Predicate::GT: return CondCode::GT;
|
|
|
case ir::IcmpInst::Predicate::LE: return CondCode::LE;
|
|
|
case ir::IcmpInst::Predicate::GE: return CondCode::GE;
|
|
|
default: return CondCode::AL;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 将 IR 浮点比较谓词转换为 ARMv8 条件码
|
|
|
CondCode FcmpToCondCode(ir::FcmpInst::Predicate pred, bool& isOrdered) {
|
|
|
isOrdered = true;
|
|
|
switch (pred) {
|
|
|
case ir::FcmpInst::Predicate::OEQ: return CondCode::EQ;
|
|
|
case ir::FcmpInst::Predicate::ONE: return CondCode::NE;
|
|
|
case ir::FcmpInst::Predicate::OLT: return CondCode::LT;
|
|
|
case ir::FcmpInst::Predicate::OGT: return CondCode::GT;
|
|
|
case ir::FcmpInst::Predicate::OLE: return CondCode::LE;
|
|
|
case ir::FcmpInst::Predicate::OGE: return CondCode::GE;
|
|
|
case ir::FcmpInst::Predicate::UEQ: isOrdered = false; return CondCode::EQ;
|
|
|
case ir::FcmpInst::Predicate::UNE: isOrdered = false; return CondCode::NE;
|
|
|
case ir::FcmpInst::Predicate::ULT: isOrdered = false; return CondCode::LT;
|
|
|
case ir::FcmpInst::Predicate::UGT: isOrdered = false; return CondCode::GT;
|
|
|
case ir::FcmpInst::Predicate::ULE: isOrdered = false; return CondCode::LE;
|
|
|
case ir::FcmpInst::Predicate::UGE: isOrdered = false; return CondCode::GE;
|
|
|
default: return CondCode::AL;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 获取基本块的标签名(用于汇编输出)
|
|
|
std::string GetBlockLabel(const ir::BasicBlock* bb) {
|
|
|
if (!bb || !bb->GetParent()) {
|
|
|
return ".Lunknown";
|
|
|
}
|
|
|
// 格式:.L函数名_基本块名
|
|
|
std::string funcName = bb->GetParent()->GetName();
|
|
|
std::string blockName = bb->GetName();
|
|
|
|
|
|
// 如果基本块没有名字,使用地址作为标识
|
|
|
if (blockName.empty()) {
|
|
|
blockName = std::to_string(reinterpret_cast<uintptr_t>(bb));
|
|
|
}
|
|
|
|
|
|
return ".L" + funcName + "_" + blockName;
|
|
|
}
|
|
|
|
|
|
// 获取数组类型的维度信息
|
|
|
static const ir::ArrayType* GetArrayType(const ir::Type* type) {
|
|
|
if (type->IsArray()) {
|
|
|
return static_cast<const ir::ArrayType*>(type);
|
|
|
}
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
static std::vector<int> GetArrayStrides(const ir::ArrayType* arrayType) {
|
|
|
std::vector<int> strides;
|
|
|
const std::vector<int>& dims = arrayType->GetDimensions();
|
|
|
int stride = 4; // 元素大小(int/float 是 4 字节)
|
|
|
|
|
|
// 从最后一维向前计算步长
|
|
|
for (int i = dims.size() - 1; i >= 0; --i) {
|
|
|
strides.insert(strides.begin(), stride);
|
|
|
stride *= dims[i];
|
|
|
}
|
|
|
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) {
|
|
|
// 处理整数常量
|
|
|
if (value == nullptr) {
|
|
|
DEBUG_MSG( "EmitValueToReg called with null value\n");
|
|
|
}
|
|
|
|
|
|
// 辅助函数:判断32位立即数是否可用单条 movz/movn 编码
|
|
|
auto isLegalMovImm = [](uint32_t imm) -> bool {
|
|
|
// 检查是否可以通过 movz 或 movn 表示(16位立即数,可左移0/16/32/48位)
|
|
|
// 对于32位寄存器,只考虑 lsl 0 或 16
|
|
|
if ((imm & 0xFFFF) == imm) return true; // 低16位,lsl #0
|
|
|
if ((imm & 0xFFFF0000) == imm) return true; // 高16位,lsl #16
|
|
|
// 可选:检查 movn 情况(~imm 满足上述条件),为了简单可不做,直接返回 false
|
|
|
return false;
|
|
|
};
|
|
|
|
|
|
if (auto* constant = dynamic_cast<const ir::ConstantInt*>(value)) {
|
|
|
uint32_t imm = static_cast<uint32_t>(constant->GetValue());
|
|
|
if (isLegalMovImm(imm)) {
|
|
|
block.Append(Opcode::MovImm,
|
|
|
{Operand::Reg(target), Operand::Imm(static_cast<int64_t>(imm))});
|
|
|
} else {
|
|
|
// 分解为 movz (低16位) + movk (高16位)
|
|
|
uint16_t low = imm & 0xFFFF;
|
|
|
uint16_t high = (imm >> 16) & 0xFFFF;
|
|
|
block.Append(Opcode::MovImm,
|
|
|
{Operand::Reg(target), Operand::Imm(low)}); // 先加载低16位
|
|
|
if (high != 0) {
|
|
|
// 使用 Movk 指令写入高16位
|
|
|
block.Append(Opcode::Movk,
|
|
|
{Operand::Reg(target), Operand::Imm(high), Operand::Imm(16)});
|
|
|
}
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
// 处理浮点常量
|
|
|
if (auto* fconstant = dynamic_cast<const ir::ConstantFloat*>(value)) {
|
|
|
// 检查是否已经为这个常量分配了栈槽
|
|
|
auto it = slots.find(value);
|
|
|
int slot;
|
|
|
if (it == slots.end()) {
|
|
|
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);
|
|
|
|
|
|
// 同样需要对 int_val 进行大立即数分解
|
|
|
if (isLegalMovImm(int_val)) {
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast<int64_t>(int_val))});
|
|
|
} else {
|
|
|
uint16_t low = int_val & 0xFFFF;
|
|
|
uint16_t high = (int_val >> 16) & 0xFFFF;
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(low)});
|
|
|
if (high != 0) {
|
|
|
block.Append(Opcode::Movk, {Operand::Reg(PhysReg::W8), Operand::Imm(high), Operand::Imm(16)});
|
|
|
}
|
|
|
}
|
|
|
block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)});
|
|
|
const_cast<ValueSlotMap&>(slots).emplace(value, slot);
|
|
|
} else {
|
|
|
slot = it->second;
|
|
|
}
|
|
|
|
|
|
// 从栈槽加载到目标寄存器
|
|
|
block.Append(Opcode::LoadStack, {Operand::Reg(target), Operand::FrameIndex(slot)});
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 处理零常量
|
|
|
if (dynamic_cast<const ir::ConstantZero*>(value) ||
|
|
|
dynamic_cast<const ir::ConstantAggregateZero*>(value)) {
|
|
|
// 零常量:直接加载 0
|
|
|
block.Append(Opcode::MovImm,
|
|
|
{Operand::Reg(target), Operand::Imm(0)});
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// ========== 处理全局变量 ==========
|
|
|
if (auto* global = dynamic_cast<const ir::GlobalValue*>(value)) {
|
|
|
// 如果目标是 32 位寄存器,升级为对应的 64 位寄存器
|
|
|
PhysReg addrTarget = target;
|
|
|
if (target >= PhysReg::W0 && target <= PhysReg::W30) {
|
|
|
// 映射 Wn → Xn
|
|
|
addrTarget = static_cast<PhysReg>(
|
|
|
static_cast<int>(target) - static_cast<int>(PhysReg::W0) + static_cast<int>(PhysReg::X0));
|
|
|
}
|
|
|
// 现在 addrTarget 一定是 64 位寄存器
|
|
|
block.Append(Opcode::Adrp, {Operand::Reg(addrTarget), Operand::Label(global->GetName())});
|
|
|
block.Append(Opcode::AddLabel, {Operand::Reg(addrTarget), Operand::Reg(addrTarget), Operand::Label(global->GetName())});
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// ========== 处理从栈槽加载的值 ==========
|
|
|
auto it = slots.find(value);
|
|
|
if (it == slots.end()) {
|
|
|
// 使用值的地址作为调试信息
|
|
|
std::string valueName = value->GetName();
|
|
|
if (valueName.empty()) {
|
|
|
valueName = "(anonymous at " + std::to_string(reinterpret_cast<uintptr_t>(value)) + ")";
|
|
|
}
|
|
|
DEBUG_MSG("Value not found: " << valueName);
|
|
|
// 输出所有 slots 的键名用于调试
|
|
|
for (auto& p : slots) {
|
|
|
std::string slotName = p.first->GetName();
|
|
|
if (slotName.empty()) {
|
|
|
slotName = "(anonymous at " + std::to_string(reinterpret_cast<uintptr_t>(p.first)) + ")";
|
|
|
}
|
|
|
DEBUG_MSG(" Slot key: " << slotName);
|
|
|
}
|
|
|
throw std::runtime_error(
|
|
|
FormatError("mir", "找不到值对应的栈槽: " + valueName));
|
|
|
}
|
|
|
|
|
|
PhysReg actualTarget = target;
|
|
|
const ir::Type* ty = value->GetType().get();
|
|
|
bool isPointer = ty->IsPtrInt32() || ty->IsPtrFloat() || ty->IsPtrInt1()
|
|
|
|| ty->IsArray(); // 数组类型在地址上下文中视为指针
|
|
|
|
|
|
// 若非指针类型且目标是 64 位寄存器,降级为对应的 32 位寄存器(自动零扩展)
|
|
|
if (!isPointer && target >= PhysReg::X0 && target <= PhysReg::X30) {
|
|
|
actualTarget = static_cast<PhysReg>(
|
|
|
static_cast<int>(target) - static_cast<int>(PhysReg::X0) + static_cast<int>(PhysReg::W0));
|
|
|
}
|
|
|
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
{Operand::Reg(actualTarget), Operand::FrameIndex(it->second)});
|
|
|
}
|
|
|
|
|
|
void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
ValueSlotMap& slots, MachineBasicBlock& block,
|
|
|
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: {
|
|
|
// alloca 返回一个指针,我们需要为该指针分配一个栈槽(存放地址值)
|
|
|
int ptrSlot = function.CreateFrameIndex(8); // 指针占8字节
|
|
|
// 为数组数据分配实际栈空间
|
|
|
int arraySlot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
|
|
|
|
|
|
// 将数组基地址(sp + arraySlot_offset)加载到 x8
|
|
|
block.Append(Opcode::LoadStackAddr,
|
|
|
{Operand::Reg(PhysReg::X8), Operand::FrameIndex(arraySlot)});
|
|
|
// 将地址存储到指针槽
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
{Operand::Reg(PhysReg::X8), Operand::FrameIndex(ptrSlot)});
|
|
|
|
|
|
// 将 alloca 指令映射到指针槽,后续使用 alloca 值即获得地址
|
|
|
slots.emplace(&inst, ptrSlot);
|
|
|
return;
|
|
|
}
|
|
|
case ir::Opcode::Store: {
|
|
|
auto& store = static_cast<const ir::StoreInst&>(inst);
|
|
|
const ir::Value* ptr = store.GetPtr();
|
|
|
const ir::Value* val = store.GetValue();
|
|
|
|
|
|
// 处理全局变量作为存储目标
|
|
|
if (auto* global = dynamic_cast<const ir::GlobalValue*>(ptr)) {
|
|
|
// 生成全局变量地址到 x8
|
|
|
block.Append(Opcode::Adrp, {Operand::Reg(PhysReg::X8), Operand::Label(global->GetName())});
|
|
|
block.Append(Opcode::AddLabel, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::X8), Operand::Label(global->GetName())});
|
|
|
// 加载要存储的值到 w9
|
|
|
EmitValueToReg(val, PhysReg::W9, slots, block, function);
|
|
|
// 间接存储:str w9, [x8]
|
|
|
block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)});
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
auto dstIt = slots.find(ptr);
|
|
|
if (dstIt == slots.end()) {
|
|
|
// 指针不在 slots 中(例如直接来自函数参数的指针)
|
|
|
// 计算指针地址到 x8
|
|
|
EmitValueToReg(ptr, PhysReg::X8, slots, block, function);
|
|
|
// 加载要存储的值到 w9
|
|
|
EmitValueToReg(val, PhysReg::W9, slots, block, function);
|
|
|
// 使用 StoreStack 的寄存器间接形式(str w9, [x8])
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
{Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)});
|
|
|
} else {
|
|
|
// 指针在 slots 中(alloca 或 gep 的结果),从指针槽加载地址到 x8
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
{Operand::Reg(PhysReg::X8), Operand::FrameIndex(dstIt->second)});
|
|
|
// 加载要存储的值到 w9
|
|
|
EmitValueToReg(val, PhysReg::W9, slots, block, function);
|
|
|
// 间接存储
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
{Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)});
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
case ir::Opcode::Load: {
|
|
|
auto& load = static_cast<const ir::LoadInst&>(inst);
|
|
|
const ir::Value* ptr = load.GetPtr();
|
|
|
int dstSlot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
|
|
|
|
|
|
// 处理全局变量作为加载源
|
|
|
if (auto* global = dynamic_cast<const ir::GlobalValue*>(ptr)) {
|
|
|
// 生成全局变量地址到 x8
|
|
|
block.Append(Opcode::Adrp, {Operand::Reg(PhysReg::X8), Operand::Label(global->GetName())});
|
|
|
block.Append(Opcode::AddLabel, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::X8), Operand::Label(global->GetName())});
|
|
|
// 间接加载到 w9
|
|
|
block.Append(Opcode::LoadStack, {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)});
|
|
|
// 存储结果到栈槽
|
|
|
block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W9), Operand::FrameIndex(dstSlot)});
|
|
|
slots.emplace(&inst, dstSlot);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
auto srcIt = slots.find(ptr);
|
|
|
if (srcIt == slots.end()) {
|
|
|
// 指针不在 slots 中,计算地址到 x8
|
|
|
EmitValueToReg(ptr, PhysReg::X8, slots, block, function);
|
|
|
// 间接加载到 w9
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
{Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)});
|
|
|
} else {
|
|
|
// 从指针槽加载地址到 x8
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
{Operand::Reg(PhysReg::X8), Operand::FrameIndex(srcIt->second)});
|
|
|
// 间接加载到 w9
|
|
|
block.Append(Opcode::LoadStack,
|
|
|
{Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)});
|
|
|
}
|
|
|
// 将加载的值存入结果槽
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
{Operand::Reg(PhysReg::W9), Operand::FrameIndex(dstSlot)});
|
|
|
slots.emplace(&inst, dstSlot);
|
|
|
return;
|
|
|
}
|
|
|
case ir::Opcode::Add: {
|
|
|
auto& bin = static_cast<const ir::BinaryInst&>(inst);
|
|
|
const ir::Type* lhsTy = bin.GetLhs()->GetType().get();
|
|
|
const ir::Type* rhsTy = bin.GetRhs()->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();
|
|
|
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);
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)});
|
|
|
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<const ir::BinaryInst&>(inst);
|
|
|
const ir::Type* lhsTy = bin.GetLhs()->GetType().get();
|
|
|
const ir::Type* rhsTy = bin.GetRhs()->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();
|
|
|
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);
|
|
|
block.Append(Opcode::SubRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)});
|
|
|
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<const ir::BinaryInst&>(inst);
|
|
|
const ir::Type* ty = inst.GetType().get();
|
|
|
bool isPointer = ty->IsPtrInt32() || ty->IsPtrFloat() || ty->IsPtrInt1();
|
|
|
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(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)});
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
case ir::Opcode::Div: {
|
|
|
auto& bin = static_cast<const ir::BinaryInst&>(inst);
|
|
|
const ir::Type* ty = inst.GetType().get();
|
|
|
bool isPointer = ty->IsPtrInt32() || ty->IsPtrFloat() || ty->IsPtrInt1();
|
|
|
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(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)});
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
case ir::Opcode::Ret: {
|
|
|
auto& ret = static_cast<const ir::ReturnInst&>(inst);
|
|
|
const ir::Value* retVal = ret.GetValue();
|
|
|
if (retVal != nullptr) {
|
|
|
const ir::Type* retType = retVal->GetType().get();
|
|
|
PhysReg retReg = PhysReg::W0; // 默认整数返回值
|
|
|
if (retType->IsFloat()) {
|
|
|
retReg = PhysReg::S0;
|
|
|
} else if (retType->IsPtrInt32() || retType->IsPtrFloat() || retType->IsPtrInt1()) {
|
|
|
retReg = PhysReg::X0;
|
|
|
} else {
|
|
|
retReg = PhysReg::W0;
|
|
|
}
|
|
|
EmitValueToReg(retVal, retReg, slots, block, function);
|
|
|
}
|
|
|
block.Append(Opcode::Ret);
|
|
|
return;
|
|
|
}
|
|
|
case ir::Opcode::FAdd: {
|
|
|
auto& bin = static_cast<const ir::BinaryInst&>(inst);
|
|
|
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽
|
|
|
// 浮点值加载到 S0, S1(使用浮点寄存器)
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block, function);
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block, function);
|
|
|
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)});
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
case ir::Opcode::FSub: {
|
|
|
auto& bin = static_cast<const ir::BinaryInst&>(inst);
|
|
|
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽
|
|
|
// 浮点值加载到 S0, S1(使用浮点寄存器)
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block, function);
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block, function);
|
|
|
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)});
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
case ir::Opcode::FMul: {
|
|
|
auto& bin = static_cast<const ir::BinaryInst&>(inst);
|
|
|
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽
|
|
|
// 浮点值加载到 S0, S1(使用浮点寄存器)
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block, function);
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block, function);
|
|
|
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)});
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
case ir::Opcode::FDiv: {
|
|
|
auto& bin = static_cast<const ir::BinaryInst&>(inst);
|
|
|
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽
|
|
|
// 浮点值加载到 S0, S1(使用浮点寄存器)
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block, function);
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block, function);
|
|
|
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)});
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
// ========== 整数比较指令(修正版)==========
|
|
|
case ir::Opcode::Icmp: {
|
|
|
auto& icmp = static_cast<const ir::IcmpInst&>(inst);
|
|
|
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
|
|
|
|
|
|
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)});
|
|
|
CondCode cc = IcmpToCondCode(icmp.GetPredicate());
|
|
|
|
|
|
// 使用 CSET 模式
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)});
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(0)});
|
|
|
|
|
|
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));
|
|
|
|
|
|
block.Append(Opcode::BCond, {Operand::Cond(cc), Operand::Label(true_label)});
|
|
|
block.Append(Opcode::MovReg, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)});
|
|
|
block.Append(Opcode::B, {Operand::Label(end_label)});
|
|
|
block.Append(Opcode::Label, {Operand::Label(true_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);
|
|
|
return;
|
|
|
}
|
|
|
// ========== 浮点比较指令 ==========
|
|
|
case ir::Opcode::FCmp: {
|
|
|
auto& fcmp = static_cast<const ir::FcmpInst&>(inst);
|
|
|
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
|
|
|
|
|
|
// 加载浮点操作数到 s0, s1
|
|
|
EmitValueToReg(fcmp.GetLhs(), PhysReg::S0, slots, block, function);
|
|
|
EmitValueToReg(fcmp.GetRhs(), PhysReg::S1, slots, block, function);
|
|
|
|
|
|
// 生成浮点比较指令
|
|
|
block.Append(Opcode::FCmpRR, {Operand::Reg(PhysReg::S0), Operand::Reg(PhysReg::S1)});
|
|
|
|
|
|
// 简化实现:存储 1 作为结果
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)});
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
// ========== 跳转指令(使用标签操作数)==========
|
|
|
case ir::Opcode::Br: {
|
|
|
DEBUG_MSG("Processing Br");
|
|
|
auto& br = static_cast<const ir::BranchInst&>(inst);
|
|
|
|
|
|
if (br.IsConditional()) {
|
|
|
// 条件跳转
|
|
|
EmitValueToReg(br.GetCondition(), PhysReg::W8, slots, block, function);
|
|
|
block.Append(Opcode::CmpRI, {Operand::Reg(PhysReg::W8), Operand::Imm(0)});
|
|
|
|
|
|
std::string trueLabel = GetBlockLabel(br.GetTrueTarget());
|
|
|
std::string falseLabel = GetBlockLabel(br.GetFalseTarget());
|
|
|
|
|
|
block.Append(Opcode::BCond, {Operand::Cond(CondCode::NE), Operand::Label(trueLabel)});
|
|
|
block.Append(Opcode::B, {Operand::Label(falseLabel)});
|
|
|
} else {
|
|
|
// 无条件跳转
|
|
|
std::string targetLabel = GetBlockLabel(br.GetTarget());
|
|
|
block.Append(Opcode::B, {Operand::Label(targetLabel)});
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
case ir::Opcode::CondBr: {
|
|
|
DEBUG_MSG("Processing CondBr");
|
|
|
auto& br = static_cast<const ir::BranchInst&>(inst);
|
|
|
|
|
|
// 条件跳转处理
|
|
|
EmitValueToReg(br.GetCondition(), PhysReg::W8, slots, block, function);
|
|
|
block.Append(Opcode::CmpRI, {Operand::Reg(PhysReg::W8), Operand::Imm(0)});
|
|
|
|
|
|
std::string trueLabel = GetBlockLabel(br.GetTrueTarget());
|
|
|
std::string falseLabel = GetBlockLabel(br.GetFalseTarget());
|
|
|
|
|
|
block.Append(Opcode::BCond, {Operand::Cond(CondCode::NE), Operand::Label(trueLabel)});
|
|
|
block.Append(Opcode::B, {Operand::Label(falseLabel)});
|
|
|
return;
|
|
|
}
|
|
|
// ========== 函数调用 ==========
|
|
|
case ir::Opcode::Call: {
|
|
|
auto& call = static_cast<const ir::CallInst&>(inst);
|
|
|
const ir::Function* callee = call.GetCallee();
|
|
|
const std::string& calleeName = callee->GetName();
|
|
|
|
|
|
// 分配结果栈槽(如果有返回值)
|
|
|
int dst_slot = -1;
|
|
|
if (!inst.GetType()->IsVoid()) {
|
|
|
dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
|
|
|
}
|
|
|
|
|
|
// 按照 ARM64 调用约定传递参数
|
|
|
const auto& args = call.GetArgs();
|
|
|
size_t intArgCount = 0;
|
|
|
size_t fpArgCount = 0;
|
|
|
|
|
|
for (size_t i = 0; i < args.size(); ++i) {
|
|
|
const auto* arg = args[i];
|
|
|
const ir::Type* argType = arg->GetType().get();
|
|
|
|
|
|
if (argType->IsFloat()) {
|
|
|
// 浮点参数
|
|
|
PhysReg reg = static_cast<PhysReg>(static_cast<int>(PhysReg::S0) + fpArgCount);
|
|
|
EmitValueToReg(arg, reg, slots, block, function);
|
|
|
fpArgCount++;
|
|
|
} else if (argType->IsPtrInt32() || argType->IsPtrFloat() || argType->IsPtrInt1()) {
|
|
|
// 指针参数 → X 寄存器(占用一个整数参数槽)
|
|
|
PhysReg reg = static_cast<PhysReg>(static_cast<int>(PhysReg::X0) + intArgCount);
|
|
|
EmitValueToReg(arg, reg, slots, block, function);
|
|
|
intArgCount++;
|
|
|
} else {
|
|
|
// 普通整数 → W 寄存器
|
|
|
PhysReg reg = static_cast<PhysReg>(static_cast<int>(PhysReg::W0) + intArgCount);
|
|
|
EmitValueToReg(arg, reg, slots, block, function);
|
|
|
intArgCount++;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 生成调用指令
|
|
|
//block.Append(Opcode::Call, {Operand::Imm(0)}); // 实际需要传递函数名
|
|
|
block.Append(Opcode::Call, {Operand::Label(calleeName)});
|
|
|
// 保存返回值
|
|
|
if (dst_slot != -1) {
|
|
|
const ir::Type* retType = inst.GetType().get();
|
|
|
PhysReg srcReg = PhysReg::W0;
|
|
|
if (retType->IsFloat()) {
|
|
|
srcReg = PhysReg::S0;
|
|
|
} else if (retType->IsPtrInt32() || retType->IsPtrFloat() || retType->IsPtrInt1()) {
|
|
|
srcReg = PhysReg::X0;
|
|
|
} else {
|
|
|
srcReg = PhysReg::W0;
|
|
|
}
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
{Operand::Reg(srcReg), Operand::FrameIndex(dst_slot)});
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
// ========== 类型转换指令 ==========
|
|
|
case ir::Opcode::ZExt: {
|
|
|
auto& zext = static_cast<const ir::ZExtInst&>(inst);
|
|
|
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
|
|
|
|
|
|
// 加载源值到 w8
|
|
|
EmitValueToReg(zext.GetValue(), PhysReg::W8, slots, block, function);
|
|
|
|
|
|
// 零扩展:i1 -> i32,直接存储即可(因为 i1 已经是 0 或 1)
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
case ir::Opcode::SIToFP: {
|
|
|
auto& sitofp = static_cast<const ir::SIToFPInst&>(inst);
|
|
|
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
|
|
|
|
|
|
// 加载整数到 w8
|
|
|
EmitValueToReg(sitofp.GetValue(), PhysReg::W8, slots, block, function);
|
|
|
|
|
|
// 整数转浮点:SCVTF s0, w8
|
|
|
block.Append(Opcode::SIToFP, {Operand::Reg(PhysReg::S0), Operand::Reg(PhysReg::W8)});
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
{Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)});
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
case ir::Opcode::FPToSI: {
|
|
|
auto& fptosi = static_cast<const ir::FPToSIInst&>(inst);
|
|
|
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
|
|
|
|
|
|
// 加载浮点数到 s0
|
|
|
EmitValueToReg(fptosi.GetValue(), PhysReg::S0, slots, block, function);
|
|
|
|
|
|
// 浮点转整数:FCVTZS w8, s0
|
|
|
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::GEP: {
|
|
|
auto& gep = static_cast<const ir::GEPInst&>(inst);
|
|
|
|
|
|
DEBUG_MSG("Processing GEP instruction: " << inst.GetName());
|
|
|
|
|
|
// GEP 返回指针类型,在 ARM64 上指针是 8 字节
|
|
|
int dst_slot = function.CreateFrameIndex(8);
|
|
|
|
|
|
// 获取基地址(数组的起始地址)
|
|
|
ir::Value* base = gep.GetBase();
|
|
|
const auto& indices = gep.GetIndices();
|
|
|
|
|
|
std::string baseName = base->GetName().empty() ? "unnamed" : base->GetName();
|
|
|
DEBUG_MSG("Base value: " << baseName);
|
|
|
DEBUG_MSG("Number of indices: " << indices.size());
|
|
|
|
|
|
// 打印索引值
|
|
|
for (size_t idx_i = 0; idx_i < indices.size(); ++idx_i) {
|
|
|
if (auto* const_int = dynamic_cast<const ir::ConstantInt*>(indices[idx_i])) {
|
|
|
DEBUG_MSG(" Index[" << idx_i << "] = " << const_int->GetValue() << " (constant)");
|
|
|
} else {
|
|
|
DEBUG_MSG(" Index[" << idx_i << "] = variable");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 加载基地址到 x8
|
|
|
EmitValueToReg(base, PhysReg::X8, slots, block, function);
|
|
|
|
|
|
if (indices.empty()) {
|
|
|
DEBUG_MSG("No indices, storing base address directly");
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
{Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)});
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 获取基地址类型
|
|
|
const ir::Type* baseType = base->GetType().get();
|
|
|
DEBUG_MSG("Base type kind: " << static_cast<int>(baseType->GetKind()));
|
|
|
|
|
|
// 关键修改:对于数组指针类型,第一个索引是多余的,应该跳过
|
|
|
size_t start_index = 0;
|
|
|
if (baseType->IsPtrInt32() || baseType->IsPtrFloat() || baseType->IsPtrInt1()) {
|
|
|
// 对于指针类型,第一个索引是偏移量,不能跳过
|
|
|
DEBUG_MSG("Base is pointer type, using all indices for pointer arithmetic");
|
|
|
start_index = 0;
|
|
|
} else if (baseType->IsArray()) {
|
|
|
// 对于数组类型(非指针),第一个索引是多余的
|
|
|
// 因为 base 已经是数组本身,不需要再解引用
|
|
|
DEBUG_MSG("Base is array type, skipping first index (array decay)");
|
|
|
start_index = 1;
|
|
|
}
|
|
|
|
|
|
// 如果基地址是数组类型,需要处理多维数组
|
|
|
if (baseType->IsArray()) {
|
|
|
DEBUG_MSG("Base is array type, processing multi-dimensional array");
|
|
|
const ir::ArrayType* arrayType = static_cast<const ir::ArrayType*>(baseType);
|
|
|
const std::vector<int>& dims = arrayType->GetDimensions();
|
|
|
|
|
|
DEBUG_MSG("Array dimensions: ");
|
|
|
for (size_t i = 0; i < dims.size(); ++i) {
|
|
|
DEBUG_MSG(" dim[" << i << "] = " << dims[i]);
|
|
|
}
|
|
|
|
|
|
// 正确计算每个维度的步长
|
|
|
std::vector<int> strides(dims.size());
|
|
|
int element_size = 4; // 元素大小(int/float 是 4 字节)
|
|
|
for (int i = dims.size() - 1; i >= 0; --i) {
|
|
|
if (i == static_cast<int>(dims.size()) - 1) {
|
|
|
strides[i] = element_size;
|
|
|
DEBUG_MSG("strides[" << i << "] = " << strides[i] << " (element size)");
|
|
|
} else {
|
|
|
strides[i] = strides[i + 1] * dims[i + 1];
|
|
|
DEBUG_MSG("strides[" << i << "] = " << strides[i+1] << " * " << dims[i+1]
|
|
|
<< " = " << strides[i]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 计算总偏移,跳过第一个索引
|
|
|
size_t numIndices = indices.size();
|
|
|
size_t effective_indices = numIndices - start_index;
|
|
|
if (effective_indices > dims.size()) {
|
|
|
DEBUG_MSG("Warning: effective indices (" << effective_indices << ") > dims.size() ("
|
|
|
<< dims.size() << "), truncating");
|
|
|
effective_indices = dims.size();
|
|
|
}
|
|
|
|
|
|
DEBUG_MSG("Using " << effective_indices << " effective indices (starting from " << start_index << ")");
|
|
|
|
|
|
// 加载当前地址到 x9 作为偏移量累加器
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X9), Operand::Imm(0)});
|
|
|
|
|
|
// 用于调试的静态偏移计算
|
|
|
int debug_offset = 0;
|
|
|
|
|
|
for (size_t i = 0; i < effective_indices; ++i) {
|
|
|
size_t idx_pos = start_index + i;
|
|
|
int index_value = 0;
|
|
|
if (auto* const_int = dynamic_cast<const ir::ConstantInt*>(indices[idx_pos])) {
|
|
|
index_value = const_int->GetValue();
|
|
|
DEBUG_MSG("Index[" << idx_pos << "] = " << index_value << " (constant)");
|
|
|
debug_offset += index_value * strides[i];
|
|
|
DEBUG_MSG(" Contribution = " << index_value << " * " << strides[i]
|
|
|
<< " = " << (index_value * strides[i]));
|
|
|
DEBUG_MSG(" Running offset = " << debug_offset);
|
|
|
} else {
|
|
|
DEBUG_MSG("Index[" << idx_pos << "] = variable");
|
|
|
}
|
|
|
|
|
|
// 加载当前索引到 x10
|
|
|
EmitValueToReg(indices[idx_pos], PhysReg::X10, slots, block, function);
|
|
|
|
|
|
// 乘以步长
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X11), Operand::Imm(strides[i])});
|
|
|
block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X10),
|
|
|
Operand::Reg(PhysReg::X10),
|
|
|
Operand::Reg(PhysReg::X11)});
|
|
|
|
|
|
// 累加到偏移量
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9),
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
}
|
|
|
|
|
|
DEBUG_MSG("Total computed offset = " << debug_offset);
|
|
|
|
|
|
// 最终地址 = base + offset
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8),
|
|
|
Operand::Reg(PhysReg::X8),
|
|
|
Operand::Reg(PhysReg::X9)});
|
|
|
|
|
|
// 存储计算出的地址
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
{Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)});
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
DEBUG_MSG("Array GEP completed, result stored in slot " << dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 其他情况的处理...
|
|
|
DEBUG_MSG("Base is other type, using simple handling");
|
|
|
if (indices.size() >= 1) {
|
|
|
EmitValueToReg(indices[0], PhysReg::X9, slots, block, function);
|
|
|
|
|
|
// 乘以元素大小(默认 4 字节)
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X10), Operand::Imm(4)});
|
|
|
block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X9),
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8),
|
|
|
Operand::Reg(PhysReg::X8),
|
|
|
Operand::Reg(PhysReg::X9)});
|
|
|
}
|
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
{Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)});
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
DEBUG_MSG("Simple GEP completed");
|
|
|
return;
|
|
|
}
|
|
|
// 处理 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;
|
|
|
}
|
|
|
// 处理 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;
|
|
|
}
|
|
|
default:
|
|
|
DEBUG_MSG("Unhandled opcode: " << static_cast<int>(inst.GetOpcode())
|
|
|
<< " for instruction: " << inst.GetName());
|
|
|
throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令,opcode: "
|
|
|
+ std::to_string(static_cast<int>(inst.GetOpcode()))));
|
|
|
//throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令"));
|
|
|
//throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令,opcode: "
|
|
|
// + std::to_string(static_cast<int>(inst.GetOpcode()))));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
// 辅助函数,将单个 IR 函数转换为 MachineFunction
|
|
|
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;
|
|
|
bool isPointer;
|
|
|
};
|
|
|
std::vector<ParamInfo> paramInfos;
|
|
|
|
|
|
// 为函数参数分配栈槽
|
|
|
for (const auto& arg : func.GetArguments()) {
|
|
|
int slot = machine_func->CreateFrameIndex(GetTypeSize(arg->GetType().get()));
|
|
|
slots.emplace(arg.get(), slot);
|
|
|
bool isFloat = arg->GetType()->IsFloat();
|
|
|
bool isPointer = arg->GetType()->IsPtrInt32() || arg->GetType()->IsPtrFloat() || arg->GetType()->IsPtrInt1();
|
|
|
paramInfos.push_back({arg.get(), slot, isFloat, isPointer});
|
|
|
}
|
|
|
|
|
|
// IR 基本块到 MIR 基本块的映射
|
|
|
std::unordered_map<const ir::BasicBlock*, MachineBasicBlock*> blockMap;
|
|
|
|
|
|
// 第一遍:为每个 IR 基本块创建 MIR 基本块
|
|
|
std::string func_name = func.GetName();
|
|
|
for (const auto& bb : func.GetBlocks()) {
|
|
|
// 格式: .L函数名_基本块名
|
|
|
auto mirBB = std::make_unique<MachineBasicBlock>(".L" + func_name + "_" + bb->GetName());
|
|
|
blockMap[bb.get()] = mirBB.get();
|
|
|
machine_func->AddBasicBlock(std::move(mirBB));
|
|
|
}
|
|
|
|
|
|
// 在入口基本块的开头添加参数加载指令
|
|
|
if (!func.GetBlocks().empty()) {
|
|
|
MachineBasicBlock* entryBB = blockMap[func.GetEntry()];
|
|
|
if (entryBB) {
|
|
|
size_t intArgIdx = 0;
|
|
|
size_t fpArgIdx = 0;
|
|
|
|
|
|
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 (param.isPointer) {
|
|
|
if (intArgIdx < 8) {
|
|
|
PhysReg reg = static_cast<PhysReg>(static_cast<int>(PhysReg::X0) + intArgIdx);
|
|
|
entryBB->Append(Opcode::StoreStack, {Operand::Reg(reg), Operand::FrameIndex(param.slot)});
|
|
|
}
|
|
|
intArgIdx++;
|
|
|
} 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++;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 第二遍:遍历每个基本块,转换指令
|
|
|
for (const auto& bb : func.GetBlocks()) {
|
|
|
MachineBasicBlock* mirBB = blockMap[bb.get()];
|
|
|
if (!mirBB) {
|
|
|
throw std::runtime_error(FormatError("mir", "找不到基本块对应的 MIR 基本块"));
|
|
|
}
|
|
|
|
|
|
for (const auto& inst : bb->GetInstructions()) {
|
|
|
LowerInstruction(*inst, *machine_func, slots, *mirBB, blockMap);
|
|
|
}
|
|
|
}
|
|
|
return machine_func;
|
|
|
}
|
|
|
|
|
|
std::unique_ptr<MachineModule> LowerToMIR(const ir::Module& module) {
|
|
|
DefaultContext();
|
|
|
|
|
|
auto machine_module = std::make_unique<MachineModule>();
|
|
|
|
|
|
// 收集全局变量信息
|
|
|
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);
|
|
|
}
|
|
|
|
|
|
std::vector<const ir::GlobalValue*> globals;
|
|
|
// 处理全局变量
|
|
|
for (const auto& global : module.GetGlobals()) {
|
|
|
// 为全局变量在数据段分配空间
|
|
|
// 这里需要扩展 MachineModule 来支持全局变量
|
|
|
DEBUG_MSG("Global variable: " << global->GetName());
|
|
|
globals.push_back(global.get());
|
|
|
}
|
|
|
|
|
|
// 遍历模块中的所有函数
|
|
|
for (const auto& func : module.GetFunctions()) {
|
|
|
try {
|
|
|
auto machine_func = LowerFunction(*func);
|
|
|
machine_module->AddFunction(std::move(machine_func));
|
|
|
} catch (const std::runtime_error& e) {
|
|
|
// 记录错误但继续处理其他函数
|
|
|
throw std::runtime_error(FormatError("mir", "转换函数失败: " + func->GetName() + " - " + e.what()));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (machine_module->GetFunctions().empty()) {
|
|
|
throw std::runtime_error(FormatError("mir", "模块中没有成功转换的函数"));
|
|
|
}
|
|
|
|
|
|
return machine_module;
|
|
|
}
|
|
|
|
|
|
} // namespace mir
|