You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

828 lines
33 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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)) {
// 通过栈槽加载以保证浮点寄存器符合 NaNboxing 要求
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