|
|
#include "mir/MIR.h"
|
|
|
|
|
|
#include <iostream>
|
|
|
#include <stdexcept>
|
|
|
#include <unordered_map>
|
|
|
#include <vector>
|
|
|
#include <cstring>
|
|
|
#include "ir/IR.h"
|
|
|
#include "utils/Log.h"
|
|
|
|
|
|
std::vector<mir::GlobalVarInfo> g_globalVars;
|
|
|
namespace mir {
|
|
|
namespace {
|
|
|
static bool IsFloatReg(PhysReg reg) {
|
|
|
switch (reg) {
|
|
|
case PhysReg::FT0: case PhysReg::FT1: case PhysReg::FT2: case PhysReg::FT3:
|
|
|
case PhysReg::FT4: case PhysReg::FT5: case PhysReg::FT6: case PhysReg::FT7:
|
|
|
case PhysReg::FT8: case PhysReg::FT9: case PhysReg::FT10: case PhysReg::FT11:
|
|
|
case PhysReg::FA0: case PhysReg::FA1: case PhysReg::FA2: case PhysReg::FA3:
|
|
|
case PhysReg::FA4: case PhysReg::FA5: case PhysReg::FA6: case PhysReg::FA7:
|
|
|
case PhysReg::FS0: case PhysReg::FS1:
|
|
|
return true;
|
|
|
default:
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
using ValueSlotMap = std::unordered_map<const ir::Value*, int>;
|
|
|
static std::unordered_map<const ir::BasicBlock*, MachineBasicBlock*> block_map;
|
|
|
|
|
|
|
|
|
MachineBasicBlock* GetOrCreateBlock(const ir::BasicBlock* ir_block,
|
|
|
MachineFunction& function) {
|
|
|
auto it = block_map.find(ir_block);
|
|
|
if (it != block_map.end()) {
|
|
|
return it->second;
|
|
|
}
|
|
|
|
|
|
std::string name = ir_block->GetName();
|
|
|
if (name.empty()) {
|
|
|
name = "block_" + std::to_string(block_map.size());
|
|
|
}
|
|
|
auto* block = function.CreateBlock(name);
|
|
|
block_map[ir_block] = block;
|
|
|
return block;
|
|
|
}
|
|
|
|
|
|
void EmitValueToReg(const ir::Value* value, PhysReg target,
|
|
|
const ValueSlotMap& slots, MachineBasicBlock& block,
|
|
|
MachineFunction& function, bool for_address = false){
|
|
|
// 处理参数(Argument)
|
|
|
if (auto* arg = dynamic_cast<const ir::Argument*>(value)) {
|
|
|
auto it = slots.find(arg);
|
|
|
if (it != slots.end()) {
|
|
|
bool src_is_float = value->GetType()->IsFloat32();
|
|
|
bool dst_is_float = IsFloatReg(target);
|
|
|
if (src_is_float == dst_is_float) {
|
|
|
// 同类型 → 直接加载,不转换
|
|
|
if (src_is_float)
|
|
|
block.Append(Opcode::LoadFloat, {Operand::Reg(target), Operand::FrameIndex(it->second)});
|
|
|
else
|
|
|
block.Append(Opcode::Load, {Operand::Reg(target), Operand::FrameIndex(it->second)});
|
|
|
} else if (src_is_float && !dst_is_float) {
|
|
|
// 浮点 -> 整数
|
|
|
block.Append(Opcode::LoadFloat,
|
|
|
{Operand::Reg(PhysReg::FT0), Operand::FrameIndex(it->second)});
|
|
|
block.Append(Opcode::FPToSI, {Operand::Reg(target), Operand::Reg(PhysReg::FT0)});
|
|
|
} else if (!src_is_float && dst_is_float) {
|
|
|
// 整数 -> 浮点
|
|
|
block.Append(Opcode::Load,
|
|
|
{Operand::Reg(PhysReg::T0), Operand::FrameIndex(it->second)});
|
|
|
block.Append(Opcode::SIToFP, {Operand::Reg(target), Operand::Reg(PhysReg::T0)});
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 处理整数常量
|
|
|
if (auto* constant = dynamic_cast<const ir::ConstantInt*>(value)) {
|
|
|
int64_t val = constant->GetValue();
|
|
|
block.Append(Opcode::MovImm,
|
|
|
{Operand::Reg(target), Operand::Imm(static_cast<int>(val))});
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 处理浮点常量
|
|
|
if (auto* fconstant = dynamic_cast<const ir::ConstantFloat*>(value)) {
|
|
|
// 直接使用标准的 double -> float 转换,无需特殊分支
|
|
|
float fval = static_cast<float>(fconstant->GetValue());
|
|
|
uint32_t bits;
|
|
|
std::memcpy(&bits, &fval, sizeof(fval));
|
|
|
int32_t imm = static_cast<int32_t>(bits);
|
|
|
|
|
|
if (IsFloatReg(target)) {
|
|
|
// 通过栈槽加载以保证浮点寄存器符合 NaN‑boxing 要求
|
|
|
int tmp_slot = function.CreateFrameIndex(4);
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::T4), Operand::Imm(imm)});
|
|
|
block.Append(Opcode::Store, {Operand::Reg(PhysReg::T4),
|
|
|
Operand::FrameIndex(tmp_slot)});
|
|
|
block.Append(Opcode::LoadFloat, {Operand::Reg(target),
|
|
|
Operand::FrameIndex(tmp_slot)});
|
|
|
} else {
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(target), Operand::Imm(imm)});
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 处理 GEP 指令
|
|
|
if (auto* gep = dynamic_cast<const ir::GepInst*>(value)) {
|
|
|
EmitValueToReg(gep->GetBasePtr(), target, slots, block,function, true);
|
|
|
EmitValueToReg(gep->GetIndex(), PhysReg::T1, slots, block,function);
|
|
|
block.Append(Opcode::Slli, {Operand::Reg(PhysReg::T1),
|
|
|
Operand::Reg(PhysReg::T1),
|
|
|
Operand::Imm(2)});
|
|
|
block.Append(Opcode::Add, {Operand::Reg(target),
|
|
|
Operand::Reg(target),
|
|
|
Operand::Reg(PhysReg::T1)});
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 处理 Alloca 指令
|
|
|
if (auto* alloca = dynamic_cast<const ir::AllocaInst*>(value)) {
|
|
|
auto it = slots.find(alloca);
|
|
|
if (it != slots.end()) {
|
|
|
block.Append(Opcode::LoadAddr,
|
|
|
{Operand::Reg(target), Operand::FrameIndex(it->second)});
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 处理全局变量
|
|
|
if (auto* global = dynamic_cast<const ir::GlobalVariable*>(value)) {
|
|
|
block.Append(Opcode::LoadGlobalAddr,
|
|
|
{Operand::Reg(target), Operand::Global(global->GetName())});
|
|
|
if (!for_address) {
|
|
|
if (global->IsFloat()) {
|
|
|
block.Append(Opcode::LoadFloat,
|
|
|
{Operand::Reg(target), Operand::Reg(target)});
|
|
|
} else {
|
|
|
block.Append(Opcode::LoadGlobal,
|
|
|
{Operand::Reg(target), Operand::Reg(target)});
|
|
|
}
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 处理一般栈槽中的值
|
|
|
auto it = slots.find(value);
|
|
|
if (it != slots.end()) {
|
|
|
bool src_is_float = value->GetType()->IsFloat32();
|
|
|
bool dst_is_float = IsFloatReg(target);
|
|
|
if (src_is_float && !dst_is_float) {
|
|
|
// 浮点 -> 整数
|
|
|
block.Append(Opcode::LoadFloat,
|
|
|
{Operand::Reg(PhysReg::FT0), Operand::FrameIndex(it->second)});
|
|
|
block.Append(Opcode::FPToSI, {Operand::Reg(target), Operand::Reg(PhysReg::FT0)});
|
|
|
} else if (!src_is_float && dst_is_float) {
|
|
|
// 整数 -> 浮点
|
|
|
block.Append(Opcode::Load,
|
|
|
{Operand::Reg(PhysReg::T0), Operand::FrameIndex(it->second)});
|
|
|
block.Append(Opcode::SIToFP, {Operand::Reg(target), Operand::Reg(PhysReg::T0)});
|
|
|
} else {
|
|
|
// 同类型直接加载
|
|
|
if (src_is_float) {
|
|
|
block.Append(Opcode::LoadFloat,
|
|
|
{Operand::Reg(target), Operand::FrameIndex(it->second)});
|
|
|
} else {
|
|
|
block.Append(Opcode::Load,
|
|
|
{Operand::Reg(target), Operand::FrameIndex(it->second)});
|
|
|
}
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 如果以上都未找到,报错
|
|
|
std::cerr << "未找到的值: " << value << std::endl;
|
|
|
std::cerr << " 名称: " << value->GetName() << std::endl;
|
|
|
std::cerr << " 类型: " << (value->GetType()->IsFloat32() ? "float" : "int") << std::endl;
|
|
|
throw std::runtime_error(
|
|
|
FormatError("mir", "找不到值对应的栈槽: " + value->GetName()));
|
|
|
}
|
|
|
|
|
|
void StoreRegToSlot(PhysReg reg, int slot, MachineBasicBlock& block, bool isFloat = false) {
|
|
|
if (isFloat) {
|
|
|
block.Append(Opcode::StoreFloat,
|
|
|
{Operand::Reg(reg), Operand::FrameIndex(slot)});
|
|
|
} else {
|
|
|
block.Append(Opcode::Store,
|
|
|
{Operand::Reg(reg), Operand::FrameIndex(slot)});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 将 LowerInstruction 重命名为 LowerInstructionToBlock,并添加 MachineBasicBlock 参数
|
|
|
void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& function,
|
|
|
ValueSlotMap& slots, MachineBasicBlock& block) {
|
|
|
switch (inst.GetOpcode()) {
|
|
|
case ir::Opcode::Alloca: {
|
|
|
auto& alloca = static_cast<const ir::AllocaInst&>(inst);
|
|
|
int size = 4;
|
|
|
if (alloca.GetNumElements() > 1) {
|
|
|
size = alloca.GetNumElements() * 4;
|
|
|
}
|
|
|
slots.emplace(&inst, function.CreateFrameIndex(size));
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
case ir::Opcode::Store: {
|
|
|
auto& store = static_cast<const ir::StoreInst&>(inst);
|
|
|
// 如果指针是 GEP,手动生成地址并 store,避免额外计算
|
|
|
if (auto* gep = dynamic_cast<const ir::GepInst*>(store.GetPtr())) {
|
|
|
// 判断值的类型是否为浮点
|
|
|
bool val_is_float = store.GetValue()->GetType()->IsFloat32();
|
|
|
|
|
|
if (val_is_float) {
|
|
|
// 将浮点值加载到 FT0
|
|
|
EmitValueToReg(store.GetValue(), PhysReg::FT0, slots, block, function);
|
|
|
} else {
|
|
|
// 整数值加载到 T2
|
|
|
EmitValueToReg(store.GetValue(), PhysReg::T2, slots, block, function);
|
|
|
}
|
|
|
|
|
|
// 计算基址 + 索引*4
|
|
|
EmitValueToReg(gep->GetBasePtr(), PhysReg::T0, slots, block, function, true);
|
|
|
auto idx_it = slots.find(gep->GetIndex());
|
|
|
if (idx_it != slots.end()) {
|
|
|
block.Append(Opcode::Load, {Operand::Reg(PhysReg::T1), Operand::FrameIndex(idx_it->second)});
|
|
|
} else {
|
|
|
EmitValueToReg(gep->GetIndex(), PhysReg::T1, slots, block, function);
|
|
|
}
|
|
|
block.Append(Opcode::Slli, {Operand::Reg(PhysReg::T1), Operand::Reg(PhysReg::T1), Operand::Imm(2)});
|
|
|
block.Append(Opcode::Add, {Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T1)});
|
|
|
|
|
|
// 使用正确的间接存储操作码
|
|
|
if (val_is_float) {
|
|
|
block.Append(Opcode::StoreIndirectFloat, {Operand::Reg(PhysReg::FT0), Operand::Reg(PhysReg::T0)});
|
|
|
} else {
|
|
|
block.Append(Opcode::StoreIndirect, {Operand::Reg(PhysReg::T2), Operand::Reg(PhysReg::T0)});
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
if (auto* global = dynamic_cast<const ir::GlobalVariable*>(store.GetPtr())) {
|
|
|
EmitValueToReg(store.GetValue(), PhysReg::T0, slots, block, function);
|
|
|
std::string global_name = global->GetName();
|
|
|
block.Append(Opcode::StoreGlobal, {Operand::Reg(PhysReg::T0), Operand::Global(global_name)});
|
|
|
return;
|
|
|
}
|
|
|
auto dst = slots.find(store.GetPtr());
|
|
|
if (dst != slots.end()) {
|
|
|
bool val_is_float = store.GetValue()->GetType()->IsFloat32();
|
|
|
if (val_is_float) {
|
|
|
EmitValueToReg(store.GetValue(), PhysReg::FT0, slots, block, function);
|
|
|
StoreRegToSlot(PhysReg::FT0, dst->second, block, true);
|
|
|
} else {
|
|
|
EmitValueToReg(store.GetValue(), PhysReg::T0, slots, block, function);
|
|
|
StoreRegToSlot(PhysReg::T0, dst->second, block, false);
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
throw std::runtime_error(FormatError("mir", "Store: 无法处理的指针类型"));
|
|
|
}
|
|
|
|
|
|
case ir::Opcode::Load: {
|
|
|
auto& load = static_cast<const ir::LoadInst&>(inst);
|
|
|
if (auto* gep = dynamic_cast<const ir::GepInst*>(load.GetPtr())) {
|
|
|
// 计算地址到 T0
|
|
|
EmitValueToReg(gep->GetBasePtr(), PhysReg::T0, slots, block, function, true);
|
|
|
|
|
|
auto idx_it = slots.find(gep->GetIndex());
|
|
|
if (idx_it != slots.end()) {
|
|
|
block.Append(Opcode::Load, {Operand::Reg(PhysReg::T1), Operand::FrameIndex(idx_it->second)});
|
|
|
} else {
|
|
|
EmitValueToReg(gep->GetIndex(), PhysReg::T1, slots, block, function);
|
|
|
}
|
|
|
block.Append(Opcode::Slli, {Operand::Reg(PhysReg::T1), Operand::Reg(PhysReg::T1), Operand::Imm(2)});
|
|
|
block.Append(Opcode::Add, {Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T1)});
|
|
|
|
|
|
bool load_is_float = load.GetType()->IsFloat32();
|
|
|
int dst_slot = function.CreateFrameIndex(4);
|
|
|
|
|
|
if (load_is_float) {
|
|
|
// 浮点加载:FT0 = [T0]
|
|
|
block.Append(Opcode::LoadIndirectFloat, {Operand::Reg(PhysReg::FT0), Operand::Reg(PhysReg::T0)});
|
|
|
StoreRegToSlot(PhysReg::FT0, dst_slot, block, true);
|
|
|
} else {
|
|
|
// 整数加载
|
|
|
block.Append(Opcode::LoadIndirect, {Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T0)});
|
|
|
StoreRegToSlot(PhysReg::T0, dst_slot, block, false);
|
|
|
}
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
if (dynamic_cast<const ir::GepInst*>(load.GetPtr())) {
|
|
|
EmitValueToReg(load.GetPtr(), PhysReg::T0, slots, block, function, true);
|
|
|
block.Append(Opcode::LoadIndirect,
|
|
|
{Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T0)});
|
|
|
int dst_slot = function.CreateFrameIndex(4);
|
|
|
StoreRegToSlot(PhysReg::T0, dst_slot, block, false);
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (auto* global = dynamic_cast<const ir::GlobalVariable*>(load.GetPtr())) {
|
|
|
int dst_slot = function.CreateFrameIndex(4);
|
|
|
std::string global_name = global->GetName();
|
|
|
block.Append(Opcode::LoadGlobalAddr,
|
|
|
{Operand::Reg(PhysReg::T0), Operand::Global(global_name)});
|
|
|
if (global->IsFloat()) {
|
|
|
block.Append(Opcode::LoadFloat,
|
|
|
{Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T0)});
|
|
|
StoreRegToSlot(PhysReg::T0, dst_slot, block, true);
|
|
|
} else {
|
|
|
block.Append(Opcode::LoadGlobal,
|
|
|
{Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T0)});
|
|
|
StoreRegToSlot(PhysReg::T0, dst_slot, block, false);
|
|
|
}
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
auto src = slots.find(load.GetPtr());
|
|
|
if (src != slots.end()) {
|
|
|
int dst_slot = function.CreateFrameIndex(4);
|
|
|
|
|
|
if (load.GetType()->IsFloat32()) {
|
|
|
block.Append(Opcode::LoadFloat,
|
|
|
{Operand::Reg(PhysReg::FT0), Operand::FrameIndex(src->second)});
|
|
|
StoreRegToSlot(PhysReg::FT0, dst_slot, block, true);
|
|
|
} else {
|
|
|
block.Append(Opcode::Load,
|
|
|
{Operand::Reg(PhysReg::T0), Operand::FrameIndex(src->second)});
|
|
|
StoreRegToSlot(PhysReg::T0, dst_slot, block, false);
|
|
|
}
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
throw std::runtime_error(FormatError("mir", "Load: 无法处理的指针类型"));
|
|
|
}
|
|
|
|
|
|
case ir::Opcode::Add:
|
|
|
case ir::Opcode::Sub:
|
|
|
case ir::Opcode::Mul:
|
|
|
case ir::Opcode::Div:
|
|
|
case ir::Opcode::Mod:
|
|
|
case ir::Opcode::FAdd:
|
|
|
case ir::Opcode::FSub:
|
|
|
case ir::Opcode::FMul:
|
|
|
case ir::Opcode::FDiv: {
|
|
|
auto& bin = static_cast<const ir::BinaryInst&>(inst);
|
|
|
bool lhs_is_float = bin.GetLhs()->GetType()->IsFloat32();
|
|
|
bool rhs_is_float = bin.GetRhs()->GetType()->IsFloat32();
|
|
|
bool result_is_float = lhs_is_float || rhs_is_float;
|
|
|
|
|
|
int dst_slot = function.CreateFrameIndex(4);
|
|
|
|
|
|
if (result_is_float) {
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::FT0, slots, block, function);
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::FT1, slots, block, function);
|
|
|
|
|
|
Opcode op;
|
|
|
switch (inst.GetOpcode()) {
|
|
|
case ir::Opcode::Add: case ir::Opcode::FAdd: op = Opcode::FAdd; break;
|
|
|
case ir::Opcode::Sub: case ir::Opcode::FSub: op = Opcode::FSub; break;
|
|
|
case ir::Opcode::Mul: case ir::Opcode::FMul: op = Opcode::FMul; break;
|
|
|
case ir::Opcode::Div: case ir::Opcode::FDiv: op = Opcode::FDiv; break;
|
|
|
default: op = Opcode::FAdd; break;
|
|
|
}
|
|
|
block.Append(op, {Operand::Reg(PhysReg::FT0),
|
|
|
Operand::Reg(PhysReg::FT0),
|
|
|
Operand::Reg(PhysReg::FT1)});
|
|
|
StoreRegToSlot(PhysReg::FT0, dst_slot, block, true);
|
|
|
} else {
|
|
|
EmitValueToReg(bin.GetLhs(), PhysReg::T0, slots, block, function);
|
|
|
EmitValueToReg(bin.GetRhs(), PhysReg::T1, slots, block, function);
|
|
|
|
|
|
Opcode op;
|
|
|
switch (inst.GetOpcode()) {
|
|
|
case ir::Opcode::Add: op = Opcode::Add; break;
|
|
|
case ir::Opcode::Sub: op = Opcode::Sub; break;
|
|
|
case ir::Opcode::Mul: op = Opcode::Mul; break;
|
|
|
case ir::Opcode::Div: op = Opcode::Div; break;
|
|
|
case ir::Opcode::Mod: op = Opcode::Rem; break;
|
|
|
default: op = Opcode::Add; break;
|
|
|
}
|
|
|
block.Append(op, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T1)});
|
|
|
StoreRegToSlot(PhysReg::T0, dst_slot, block, false);
|
|
|
}
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
case ir::Opcode::Gep: {
|
|
|
int dst_slot = function.CreateFrameIndex();
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
case ir::Opcode::Call: {
|
|
|
auto& call = static_cast<const ir::CallInst&>(inst);
|
|
|
int numArgs = static_cast<int>(call.GetNumArgs());
|
|
|
|
|
|
int ireg = 0, freg = 0;
|
|
|
std::vector<std::pair<bool, ir::Value*>> stack_args; // (is_float, value)
|
|
|
|
|
|
for (int i = 0; i < numArgs; ++i) {
|
|
|
bool arg_is_float = call.GetArg(i)->GetType()->IsFloat32();
|
|
|
if (arg_is_float) {
|
|
|
if (freg < 8) {
|
|
|
PhysReg fregnum = static_cast<PhysReg>(static_cast<int>(PhysReg::FA0) + freg);
|
|
|
EmitValueToReg(call.GetArg(i), fregnum, slots, block, function);
|
|
|
freg++;
|
|
|
} else {
|
|
|
stack_args.push_back({true, call.GetArg(i)});
|
|
|
}
|
|
|
} else { // integer or pointer
|
|
|
if (ireg < 8) {
|
|
|
PhysReg iregnum = static_cast<PhysReg>(static_cast<int>(PhysReg::A0) + ireg);
|
|
|
EmitValueToReg(call.GetArg(i), iregnum, slots, block, function);
|
|
|
ireg++;
|
|
|
} else {
|
|
|
stack_args.push_back({false, call.GetArg(i)});
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int stackArgs = static_cast<int>(stack_args.size());
|
|
|
if (stackArgs > 0) {
|
|
|
int stackSpace = (stackArgs * 8 + 15) & ~15;
|
|
|
// sp -= stackSpace
|
|
|
if (stackSpace <= 2047) {
|
|
|
block.Append(Opcode::Addi, {Operand::Reg(PhysReg::SP),
|
|
|
Operand::Reg(PhysReg::SP),
|
|
|
Operand::Imm(-stackSpace)});
|
|
|
} else {
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::T4), Operand::Imm(-stackSpace)});
|
|
|
block.Append(Opcode::Add, {Operand::Reg(PhysReg::SP),
|
|
|
Operand::Reg(PhysReg::SP),
|
|
|
Operand::Reg(PhysReg::T4)});
|
|
|
}
|
|
|
|
|
|
for (int idx = 0; idx < stackArgs; ++idx) {
|
|
|
bool is_float = stack_args[idx].first;
|
|
|
ir::Value* val = stack_args[idx].second;
|
|
|
int offset = idx * 8;
|
|
|
|
|
|
// 1. 先加载值
|
|
|
if (is_float) {
|
|
|
EmitValueToReg(val, PhysReg::FT0, slots, block, function);
|
|
|
} else {
|
|
|
EmitValueToReg(val, PhysReg::T0, slots, block, function);
|
|
|
}
|
|
|
|
|
|
// 2. 再计算栈地址到 T4
|
|
|
if (offset == 0) {
|
|
|
block.Append(Opcode::Add, {Operand::Reg(PhysReg::T4),
|
|
|
Operand::Reg(PhysReg::SP),
|
|
|
Operand::Reg(PhysReg::ZERO)});
|
|
|
} else if (offset <= 2047) {
|
|
|
block.Append(Opcode::Addi, {Operand::Reg(PhysReg::T4),
|
|
|
Operand::Reg(PhysReg::SP),
|
|
|
Operand::Imm(offset)});
|
|
|
} else {
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::T4), Operand::Imm(offset)});
|
|
|
block.Append(Opcode::Add, {Operand::Reg(PhysReg::T4),
|
|
|
Operand::Reg(PhysReg::SP),
|
|
|
Operand::Reg(PhysReg::T4)});
|
|
|
}
|
|
|
|
|
|
// 3. 存储
|
|
|
if (is_float) {
|
|
|
block.Append(Opcode::StoreFloat, {Operand::Reg(PhysReg::FT0), Operand::Reg(PhysReg::T4)});
|
|
|
} else {
|
|
|
block.Append(Opcode::Store, {Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T4)});
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 调用目标
|
|
|
std::string func_name = call.GetCalleeName();
|
|
|
block.Append(Opcode::Call, {Operand::Func(func_name)});
|
|
|
|
|
|
// 恢复 sp
|
|
|
if (stackArgs > 0) {
|
|
|
int stackSpace = (stackArgs * 8 + 15) & ~15;
|
|
|
if (stackSpace <= 2047) {
|
|
|
block.Append(Opcode::Addi, {Operand::Reg(PhysReg::SP),
|
|
|
Operand::Reg(PhysReg::SP),
|
|
|
Operand::Imm(stackSpace)});
|
|
|
} else {
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::T4), Operand::Imm(stackSpace)});
|
|
|
block.Append(Opcode::Add, {Operand::Reg(PhysReg::SP),
|
|
|
Operand::Reg(PhysReg::SP),
|
|
|
Operand::Reg(PhysReg::T4)});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 返回值处理(原有代码保持不变)
|
|
|
if (!call.GetType()->IsVoid()) {
|
|
|
int dst_slot = function.CreateFrameIndex();
|
|
|
bool ret_is_float = call.GetType()->IsFloat32();
|
|
|
if (ret_is_float) {
|
|
|
StoreRegToSlot(PhysReg::FA0, dst_slot, block, true);
|
|
|
} else {
|
|
|
StoreRegToSlot(PhysReg::A0, dst_slot, block, false);
|
|
|
}
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
case ir::Opcode::ICmp: {
|
|
|
auto& icmp = static_cast<const ir::ICmpInst&>(inst);
|
|
|
int dst_slot = function.CreateFrameIndex();
|
|
|
|
|
|
EmitValueToReg(icmp.GetLhs(), PhysReg::T0, slots, block, function);
|
|
|
EmitValueToReg(icmp.GetRhs(), PhysReg::T1, slots, block, function);
|
|
|
|
|
|
ir::ICmpPredicate pred = icmp.GetPredicate();
|
|
|
|
|
|
switch (pred) {
|
|
|
case ir::ICmpPredicate::EQ:
|
|
|
block.Append(Opcode::Sub, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T1)});
|
|
|
block.Append(Opcode::Sltiu, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T0),
|
|
|
Operand::Imm(1)});
|
|
|
break;
|
|
|
|
|
|
case ir::ICmpPredicate::NE:
|
|
|
block.Append(Opcode::Sub, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T1)});
|
|
|
block.Append(Opcode::Sltiu, {Operand::Reg(PhysReg::T1),
|
|
|
Operand::Reg(PhysReg::T0),
|
|
|
Operand::Imm(1)});
|
|
|
block.Append(Opcode::Xori, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T1),
|
|
|
Operand::Imm(1)});
|
|
|
break;
|
|
|
|
|
|
case ir::ICmpPredicate::SLT:
|
|
|
block.Append(Opcode::Slt, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T1)});
|
|
|
break;
|
|
|
case ir::ICmpPredicate::SGT:
|
|
|
block.Append(Opcode::Slt, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T1),
|
|
|
Operand::Reg(PhysReg::T0)});
|
|
|
break;
|
|
|
case ir::ICmpPredicate::SGE:
|
|
|
// lhs >= rhs 等价于 !(lhs < rhs)
|
|
|
block.Append(Opcode::Slt, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T1)});
|
|
|
block.Append(Opcode::Xori, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T0),
|
|
|
Operand::Imm(1)});
|
|
|
break;
|
|
|
|
|
|
case ir::ICmpPredicate::SLE:
|
|
|
// lhs <= rhs 等价于 !(rhs < lhs)
|
|
|
block.Append(Opcode::Slt, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T1),
|
|
|
Operand::Reg(PhysReg::T0)}); // 注意操作数顺序:rhs < lhs
|
|
|
block.Append(Opcode::Xori, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T0),
|
|
|
Operand::Imm(1)});
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
StoreRegToSlot(PhysReg::T0, dst_slot, block);
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
case ir::Opcode::ZExt: {
|
|
|
auto& zext = static_cast<const ir::ZExtInst&>(inst);
|
|
|
int dst_slot = function.CreateFrameIndex(4);
|
|
|
|
|
|
EmitValueToReg(zext.GetSrc(), PhysReg::T0, slots, block, function);
|
|
|
StoreRegToSlot(PhysReg::T0, dst_slot, block);
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
case ir::Opcode::FCmp: {
|
|
|
auto& fcmp = static_cast<const ir::FCmpInst&>(inst);
|
|
|
int dst_slot = function.CreateFrameIndex(4);
|
|
|
|
|
|
EmitValueToReg(fcmp.GetLhs(), PhysReg::FT0, slots, block, function);
|
|
|
EmitValueToReg(fcmp.GetRhs(), PhysReg::FT1, slots, block, function);
|
|
|
|
|
|
ir::FCmpPredicate pred = fcmp.GetPredicate();
|
|
|
|
|
|
switch (pred) {
|
|
|
case ir::FCmpPredicate::OEQ:
|
|
|
block.Append(Opcode::FEq, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::FT0),
|
|
|
Operand::Reg(PhysReg::FT1)});
|
|
|
break;
|
|
|
case ir::FCmpPredicate::ONE:
|
|
|
block.Append(Opcode::FEq, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::FT0),
|
|
|
Operand::Reg(PhysReg::FT1)});
|
|
|
block.Append(Opcode::Xori, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::T0),
|
|
|
Operand::Imm(1)});
|
|
|
break;
|
|
|
case ir::FCmpPredicate::OLT:
|
|
|
block.Append(Opcode::FLt, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::FT0),
|
|
|
Operand::Reg(PhysReg::FT1)});
|
|
|
break;
|
|
|
case ir::FCmpPredicate::OGT:
|
|
|
block.Append(Opcode::FLt, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::FT1),
|
|
|
Operand::Reg(PhysReg::FT0)});
|
|
|
break;
|
|
|
case ir::FCmpPredicate::OLE:
|
|
|
block.Append(Opcode::FLe, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::FT0),
|
|
|
Operand::Reg(PhysReg::FT1)});
|
|
|
break;
|
|
|
case ir::FCmpPredicate::OGE:
|
|
|
block.Append(Opcode::FLe, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::FT1),
|
|
|
Operand::Reg(PhysReg::FT0)});
|
|
|
break;
|
|
|
default:
|
|
|
block.Append(Opcode::FEq, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::FT0),
|
|
|
Operand::Reg(PhysReg::FT1)});
|
|
|
break;
|
|
|
}
|
|
|
StoreRegToSlot(PhysReg::T0, dst_slot, block);
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
case ir::Opcode::SIToFP: {
|
|
|
auto& conv = static_cast<const ir::SIToFPInst&>(inst);
|
|
|
int dst_slot = function.CreateFrameIndex(4);
|
|
|
|
|
|
// 直接加载源操作数到 T0,不依赖 slots 中是否存在
|
|
|
EmitValueToReg(conv.GetSrc(), PhysReg::T0, slots, block, function);
|
|
|
block.Append(Opcode::SIToFP, {Operand::Reg(PhysReg::FT0),
|
|
|
Operand::Reg(PhysReg::T0)});
|
|
|
StoreRegToSlot(PhysReg::FT0, dst_slot, block, true);
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
case ir::Opcode::FPToSI: {
|
|
|
auto& conv = static_cast<const ir::FPToSIInst&>(inst);
|
|
|
int dst_slot = function.CreateFrameIndex(4);
|
|
|
|
|
|
// 直接加载源操作数到 FT0,不依赖 slots
|
|
|
EmitValueToReg(conv.GetSrc(), PhysReg::FT0, slots, block, function);
|
|
|
block.Append(Opcode::FPToSI, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Reg(PhysReg::FT0)});
|
|
|
StoreRegToSlot(PhysReg::T0, dst_slot, block, false);
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
case ir::Opcode::Br: {
|
|
|
auto& br = static_cast<const ir::BrInst&>(inst);
|
|
|
auto* target = br.GetTarget();
|
|
|
MachineBasicBlock* target_block = GetOrCreateBlock(target, function);
|
|
|
block.Append(Opcode::Br, {Operand::Imm64(reinterpret_cast<intptr_t>(target_block))});
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
case ir::Opcode::CondBr: {
|
|
|
auto& condbr = static_cast<const ir::CondBrInst&>(inst);
|
|
|
auto* true_bb = condbr.GetTrueBB();
|
|
|
auto* false_bb = condbr.GetFalseBB();
|
|
|
|
|
|
EmitValueToReg(condbr.GetCond(), PhysReg::T0, slots, block, function);
|
|
|
|
|
|
MachineBasicBlock* true_block = GetOrCreateBlock(true_bb, function);
|
|
|
MachineBasicBlock* false_block = GetOrCreateBlock(false_bb, function);
|
|
|
|
|
|
block.Append(Opcode::CondBr, {Operand::Reg(PhysReg::T0),
|
|
|
Operand::Imm64(reinterpret_cast<intptr_t>(true_block)),
|
|
|
Operand::Imm64(reinterpret_cast<intptr_t>(false_block))});
|
|
|
return;
|
|
|
}
|
|
|
case ir::Opcode::Ret: {
|
|
|
auto& ret = static_cast<const ir::ReturnInst&>(inst);
|
|
|
if (ret.GetValue()) {
|
|
|
auto val = ret.GetValue();
|
|
|
if (val->GetType()->IsFloat32()) {
|
|
|
EmitValueToReg(val, PhysReg::FA0, slots, block, function);
|
|
|
} else {
|
|
|
EmitValueToReg(val, PhysReg::A0, slots, block, function);
|
|
|
}
|
|
|
} else {
|
|
|
block.Append(Opcode::MovImm,
|
|
|
{Operand::Reg(PhysReg::A0), Operand::Imm(0)});
|
|
|
}
|
|
|
block.Append(Opcode::Ret);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
default: {
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
} // namespace
|
|
|
|
|
|
std::unique_ptr<MachineFunction> LowerFunctionToMIR(const ir::Function& func) {
|
|
|
block_map.clear();
|
|
|
|
|
|
auto machine_func = std::make_unique<MachineFunction>(func.GetName());
|
|
|
ValueSlotMap slots;
|
|
|
int ireg = 0, freg = 0, stack_idx = 0;
|
|
|
for (size_t i = 0; i < func.GetNumArgs(); i++) {
|
|
|
ir::Argument* arg = func.GetArgument(i);
|
|
|
int size = (arg->GetType()->IsPtrInt32() || arg->GetType()->IsPtrFloat32()) ? 8 : 4;
|
|
|
int slot = machine_func->CreateFrameIndex(size);
|
|
|
MachineBasicBlock* entry = machine_func->GetEntry();
|
|
|
|
|
|
if (arg->GetType()->IsFloat32()) {
|
|
|
if (freg < 8) {
|
|
|
PhysReg argReg = static_cast<PhysReg>(static_cast<int>(PhysReg::FA0) + freg);
|
|
|
entry->Append(Opcode::StoreFloat, {Operand::Reg(argReg), Operand::FrameIndex(slot)});
|
|
|
freg++;
|
|
|
} else {
|
|
|
entry->Append(Opcode::LoadCallerStackArgFloat, {
|
|
|
Operand::Reg(PhysReg::FT0),
|
|
|
Operand::FrameIndex(slot),
|
|
|
Operand::Imm(stack_idx)
|
|
|
});
|
|
|
stack_idx++;
|
|
|
}
|
|
|
} else {
|
|
|
if (ireg < 8) {
|
|
|
PhysReg argReg = static_cast<PhysReg>(static_cast<int>(PhysReg::A0) + ireg);
|
|
|
entry->Append(Opcode::Store, {Operand::Reg(argReg), Operand::FrameIndex(slot)});
|
|
|
ireg++;
|
|
|
} else {
|
|
|
entry->Append(Opcode::LoadCallerStackArg, {
|
|
|
Operand::Reg(PhysReg::T0),
|
|
|
Operand::FrameIndex(slot),
|
|
|
Operand::Imm(stack_idx)
|
|
|
});
|
|
|
stack_idx++;
|
|
|
}
|
|
|
}
|
|
|
slots[arg] = slot;
|
|
|
}
|
|
|
|
|
|
// 第一遍:创建所有 IR 基本块对应的 MIR 基本块
|
|
|
for (const auto& ir_block : func.GetBlocks()) {
|
|
|
GetOrCreateBlock(ir_block.get(), *machine_func);
|
|
|
}
|
|
|
|
|
|
// 第二遍:遍历所有基本块,降低指令
|
|
|
for (const auto& ir_block : func.GetBlocks()) {
|
|
|
MachineBasicBlock* mbb = GetOrCreateBlock(ir_block.get(), *machine_func);
|
|
|
|
|
|
for (const auto& inst : ir_block->GetInstructions()) {
|
|
|
LowerInstructionToBlock(*inst, *machine_func, slots, *mbb);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return machine_func;
|
|
|
}
|
|
|
|
|
|
std::vector<std::unique_ptr<MachineFunction>> LowerToMIR(const ir::Module& module) {
|
|
|
DefaultContext();
|
|
|
|
|
|
// 收集全局变量
|
|
|
g_globalVars.clear();
|
|
|
for (const auto& global : module.GetGlobalVariables()) {
|
|
|
GlobalVarInfo info;
|
|
|
info.name = global->GetName();
|
|
|
info.isConst = global->IsConst();
|
|
|
info.isArray = global->IsArray();
|
|
|
info.arraySize = global->GetNumElements();
|
|
|
info.isFloat = global->IsFloat();
|
|
|
info.value = 0;
|
|
|
info.valueF = 0.0f;
|
|
|
|
|
|
if (info.isArray) {
|
|
|
if (info.isFloat) {
|
|
|
const auto& initVals = global->GetInitValsF();
|
|
|
for (float val : initVals) {
|
|
|
info.arrayValuesF.push_back(val);
|
|
|
}
|
|
|
} else {
|
|
|
if (global->HasInitVals()) {
|
|
|
const auto& initVals = global->GetInitVals();
|
|
|
for (int val : initVals) {
|
|
|
info.arrayValues.push_back(val);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
if (info.isFloat) {
|
|
|
info.valueF = global->GetInitValF();
|
|
|
} else {
|
|
|
info.value = global->GetInitVal();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
g_globalVars.push_back(info);
|
|
|
}
|
|
|
|
|
|
const auto& functions = module.GetFunctions();
|
|
|
if (functions.empty()) {
|
|
|
throw std::runtime_error(FormatError("mir", "模块中没有函数"));
|
|
|
}
|
|
|
|
|
|
std::vector<std::unique_ptr<MachineFunction>> result;
|
|
|
|
|
|
for (const auto& func : functions) {
|
|
|
auto machine_func = LowerFunctionToMIR(*func);
|
|
|
result.push_back(std::move(machine_func));
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
} // namespace mir
|