|
|
#include "mir/MIR.h"
|
|
|
|
|
|
#include <ostream>
|
|
|
#include <stdexcept>
|
|
|
#include <iostream>
|
|
|
#include <vector>
|
|
|
#include <unordered_map>
|
|
|
#include "utils/Log.h"
|
|
|
|
|
|
|
|
|
|
|
|
// 引用全局变量(定义在 Lowering.cpp 中)
|
|
|
extern std::vector<mir::GlobalVarInfo> g_globalVars;
|
|
|
|
|
|
namespace mir {
|
|
|
namespace {
|
|
|
|
|
|
const FrameSlot& GetFrameSlot(const MachineFunction& function,
|
|
|
const Operand& operand) {
|
|
|
if (operand.GetKind() != Operand::Kind::FrameIndex) {
|
|
|
throw std::runtime_error(FormatError("mir", "期望 FrameIndex 操作数"));
|
|
|
}
|
|
|
return function.GetFrameSlot(operand.GetFrameIndex());
|
|
|
}
|
|
|
|
|
|
// 32位整数加载/存储
|
|
|
void EmitStackLoad(std::ostream& os, PhysReg dst, int offset, PhysReg base = PhysReg::S0) {
|
|
|
if (offset >= -2048 && offset <= 2047) {
|
|
|
os << " lw " << PhysRegName(dst) << ", " << offset << "(" << PhysRegName(base) << ")\n";
|
|
|
} else {
|
|
|
os << " li t4, " << offset << "\n";
|
|
|
os << " add t4, " << PhysRegName(base) << ", t4\n";
|
|
|
os << " lw " << PhysRegName(dst) << ", 0(t4)\n";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void EmitStackStore(std::ostream& os, PhysReg src, int offset, PhysReg base = PhysReg::S0) {
|
|
|
if (offset >= -2048 && offset <= 2047) {
|
|
|
os << " sw " << PhysRegName(src) << ", " << offset << "(" << PhysRegName(base) << ")\n";
|
|
|
} else {
|
|
|
os << " li t4, " << offset << "\n";
|
|
|
os << " add t4, " << PhysRegName(base) << ", t4\n";
|
|
|
os << " sw " << PhysRegName(src) << ", 0(t4)\n";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 64位指针加载/存储
|
|
|
void EmitStackLoad64(std::ostream& os, PhysReg dst, int offset, PhysReg base = PhysReg::S0) {
|
|
|
if (offset >= -2048 && offset <= 2047) {
|
|
|
os << " ld " << PhysRegName(dst) << ", " << offset << "(" << PhysRegName(base) << ")\n";
|
|
|
} else {
|
|
|
os << " li t4, " << offset << "\n";
|
|
|
os << " add t4, " << PhysRegName(base) << ", t4\n";
|
|
|
os << " ld " << PhysRegName(dst) << ", 0(t4)\n";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void EmitStackStore64(std::ostream& os, PhysReg src, int offset, PhysReg base = PhysReg::S0) {
|
|
|
if (offset >= -2048 && offset <= 2047) {
|
|
|
os << " sd " << PhysRegName(src) << ", " << offset << "(" << PhysRegName(base) << ")\n";
|
|
|
} else {
|
|
|
os << " li t4, " << offset << "\n";
|
|
|
os << " add t4, " << PhysRegName(base) << ", t4\n";
|
|
|
os << " sd " << PhysRegName(src) << ", 0(t4)\n";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 浮点加载/存储(保持32位)
|
|
|
void EmitStackLoadFloat(std::ostream& os, PhysReg dst, int offset, PhysReg base = PhysReg::S0) {
|
|
|
if (offset >= -2048 && offset <= 2047) {
|
|
|
os << " flw " << PhysRegName(dst) << ", " << offset << "(" << PhysRegName(base) << ")\n";
|
|
|
} else {
|
|
|
os << " li t4, " << offset << "\n";
|
|
|
os << " add t4, " << PhysRegName(base) << ", t4\n";
|
|
|
os << " flw " << PhysRegName(dst) << ", 0(t4)\n";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void EmitStackStoreFloat(std::ostream& os, PhysReg src, int offset, PhysReg base = PhysReg::S0) {
|
|
|
if (offset >= -2048 && offset <= 2047) {
|
|
|
os << " fsw " << PhysRegName(src) << ", " << offset << "(" << PhysRegName(base) << ")\n";
|
|
|
} else {
|
|
|
os << " li t4, " << offset << "\n";
|
|
|
os << " add t4, " << PhysRegName(base) << ", t4\n";
|
|
|
os << " fsw " << PhysRegName(src) << ", 0(t4)\n";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 输出单个函数的汇编
|
|
|
void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
|
|
|
// 收集所有基本块名称
|
|
|
std::unordered_map<const MachineBasicBlock*, std::string> block_names;
|
|
|
for (const auto& block_ptr : function.GetBlocks()) {
|
|
|
block_names[block_ptr.get()] = block_ptr->GetName();
|
|
|
}
|
|
|
|
|
|
int frame_size = function.GetFrameSize(); // 局部变量区大小(正数)
|
|
|
int local_vars = function.GetLocalVarsSize();
|
|
|
int total_frame = local_vars + 16 ;
|
|
|
bool prologue_done = false;
|
|
|
|
|
|
for (const auto& block_ptr : function.GetBlocks()) {
|
|
|
const auto& block = *block_ptr;
|
|
|
|
|
|
// 输出基本块标签(入口块不输出,因为函数名已经是标签)
|
|
|
if (block.GetName() != "entry") {
|
|
|
os << block.GetName() << ":\n";
|
|
|
}
|
|
|
|
|
|
for (const auto& inst : block.GetInstructions()) {
|
|
|
const auto& ops = inst.GetOperands();
|
|
|
|
|
|
// 在入口块的第一条指令前输出序言
|
|
|
if (!prologue_done && block.GetName() == "entry") {
|
|
|
// 分配栈帧:sp -= total_frame
|
|
|
if (total_frame <= 2047) {
|
|
|
os << " addi sp, sp, -" << total_frame << "\n";
|
|
|
} else {
|
|
|
os << " li t4, -" << total_frame << "\n";
|
|
|
os << " add sp, sp, t4\n";
|
|
|
}
|
|
|
|
|
|
// 保存 ra 和 s0(在局部变量区之后,即 sp + frame_size 处)
|
|
|
// ra 保存在 sp + frame_size
|
|
|
// s0 保存在 sp + frame_size + 8
|
|
|
int ra_offset = local_vars;
|
|
|
int s0_offset = local_vars + 8;
|
|
|
|
|
|
if (ra_offset <= 2047) {
|
|
|
os << " sd ra, " << ra_offset << "(sp)\n";
|
|
|
} else {
|
|
|
os << " li t4, " << ra_offset << "\n";
|
|
|
os << " add t4, sp, t4\n";
|
|
|
os << " sd ra, 0(t4)\n";
|
|
|
}
|
|
|
|
|
|
if (s0_offset <= 2047) {
|
|
|
os << " sd s0, " << s0_offset << "(sp)\n";
|
|
|
} else {
|
|
|
os << " li t4, " << s0_offset << "\n";
|
|
|
os << " add t4, sp, t4\n";
|
|
|
os << " sd s0, 0(t4)\n";
|
|
|
}
|
|
|
os << " mv s0, sp\n";
|
|
|
prologue_done = true;
|
|
|
}
|
|
|
|
|
|
switch (inst.GetOpcode()) {
|
|
|
case Opcode::Prologue:
|
|
|
case Opcode::Epilogue:
|
|
|
break;
|
|
|
|
|
|
case Opcode::MovImm:
|
|
|
os << " li " << PhysRegName(ops.at(0).GetReg()) << ", "
|
|
|
<< ops.at(1).GetImm() << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::Load: {
|
|
|
if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Reg) {
|
|
|
os << " ld " << PhysRegName(ops[0].GetReg()) << ", 0(" << PhysRegName(ops[1].GetReg()) << ")\n";
|
|
|
} /*else if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Imm) {
|
|
|
// 用于调用者 outgoing 存储的占位偏移(将在 Outgoing 中修正)
|
|
|
int offset = ops[1].GetImm(); // 实际偏移 = local_vars + 16 + offset
|
|
|
os << " ld " << PhysRegName(ops[0].GetReg()) << ", " << offset << "(sp)\n";*/
|
|
|
else {
|
|
|
int frame_idx = ops[1].GetFrameIndex();
|
|
|
const auto& slot = function.GetFrameSlot(frame_idx);
|
|
|
if (slot.size == 8) EmitStackLoad64(os, ops[0].GetReg(), slot.offset);
|
|
|
else EmitStackLoad(os, ops[0].GetReg(), slot.offset);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case Opcode::Store: {
|
|
|
if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Reg) {
|
|
|
os << " sd " << PhysRegName(ops[0].GetReg()) << ", 0(" << PhysRegName(ops[1].GetReg()) << ")\n";
|
|
|
} /*else if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Imm) {
|
|
|
int offset = ops[1].GetImm();
|
|
|
// 实际偏移需在 AsmPrinter 中加上 local_vars+16,这里简单先直接用 offset(动态修正稍复杂)
|
|
|
// 临时方案:直接生成 sw t0, offset(sp),但 offset 应为 local_vars+16=?
|
|
|
// 由于 AsmPrinter 中可访问 function.GetLocalVarsSize(),我们计算:
|
|
|
int actual_offset = function.GetLocalVarsSize() + 16 + offset;
|
|
|
if (actual_offset <= 2047) os << " sd " << PhysRegName(ops[0].GetReg()) << ", " << actual_offset << "(sp)\n";
|
|
|
else { }*/
|
|
|
else {
|
|
|
int frame_idx = ops[1].GetFrameIndex();
|
|
|
const auto& slot = function.GetFrameSlot(frame_idx);
|
|
|
if (slot.size == 8) EmitStackStore64(os, ops[0].GetReg(), slot.offset);
|
|
|
else EmitStackStore(os, ops[0].GetReg(), slot.offset);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case Opcode::LoadCallerStackArg: {
|
|
|
// ops: [0] dst (T0), [1] dstFrameIndex, [2] argvIndex (Imm)
|
|
|
int argv_index = ops[2].GetImm();
|
|
|
int dst_slot = ops[1].GetFrameIndex();
|
|
|
int total_frame = function.GetFrameSize();
|
|
|
// 调用者栈参数位于 sp + total_frame + argv_index*8
|
|
|
int caller_offset = total_frame + argv_index * 8;
|
|
|
// 加载到 T0
|
|
|
if (caller_offset <= 2047) {
|
|
|
os << " ld " << PhysRegName(ops[0].GetReg()) << ", " << caller_offset << "(s0)\n";
|
|
|
} else {
|
|
|
os << " li t4, " << caller_offset << "\n";
|
|
|
os << " add t4, s0, t4\n";
|
|
|
os << " ld " << PhysRegName(ops[0].GetReg()) << ", 0(t4)\n";
|
|
|
}
|
|
|
// 再存入本地槽
|
|
|
const auto& slot = function.GetFrameSlot(dst_slot);
|
|
|
if (slot.size == 8) {
|
|
|
EmitStackStore64(os, ops[0].GetReg(), slot.offset);
|
|
|
} else {
|
|
|
EmitStackStore(os, ops[0].GetReg(), slot.offset);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case Opcode::LoadCallerStackArgFloat: {
|
|
|
int argv_index = ops.at(2).GetImm();
|
|
|
int dst_slot = ops.at(1).GetFrameIndex();
|
|
|
int total_frame = function.GetFrameSize();
|
|
|
int caller_offset = total_frame + argv_index * 8;
|
|
|
// 使用 s0 保证稳定
|
|
|
if (caller_offset <= 2047) {
|
|
|
os << " flw " << PhysRegName(ops.at(0).GetReg()) << ", " << caller_offset << "(s0)\n";
|
|
|
} else {
|
|
|
os << " li t4, " << caller_offset << "\n";
|
|
|
os << " add t4, s0, t4\n";
|
|
|
os << " flw " << PhysRegName(ops.at(0).GetReg()) << ", 0(t4)\n";
|
|
|
}
|
|
|
const auto& slot = function.GetFrameSlot(dst_slot);
|
|
|
EmitStackStoreFloat(os, ops.at(0).GetReg(), slot.offset);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case Opcode::Add:
|
|
|
os << " add " << PhysRegName(ops.at(0).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(1).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(2).GetReg()) << "\n";
|
|
|
break;
|
|
|
case Opcode::Addi:
|
|
|
os << " addi " << PhysRegName(ops[0].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[1].GetReg()) << ", "
|
|
|
<< ops[2].GetImm() << "\n";
|
|
|
break;
|
|
|
case Opcode::Sub:
|
|
|
os << " sub " << PhysRegName(ops.at(0).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(1).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(2).GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::Mul: {
|
|
|
if (ops.size() > 2 && ops.at(2).GetKind() == Operand::Kind::Imm) {
|
|
|
os << " mul " << PhysRegName(ops.at(0).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(1).GetReg()) << ", "
|
|
|
<< ops.at(2).GetImm() << "\n";
|
|
|
} else {
|
|
|
os << " mul " << PhysRegName(ops.at(0).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(1).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(2).GetReg()) << "\n";
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case Opcode::Div:
|
|
|
os << " div " << PhysRegName(ops.at(0).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(1).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(2).GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::Rem:
|
|
|
os << " rem " << PhysRegName(ops.at(0).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(1).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(2).GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::Slt:
|
|
|
os << " slt " << PhysRegName(ops.at(0).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(1).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(2).GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::Slti:
|
|
|
os << " slti " << PhysRegName(ops.at(0).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(1).GetReg()) << ", "
|
|
|
<< ops.at(2).GetImm() << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::Sltu:
|
|
|
os << " sltu " << PhysRegName(ops.at(0).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(1).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(2).GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::Sltiu:
|
|
|
os << " sltiu " << PhysRegName(ops.at(0).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(1).GetReg()) << ", "
|
|
|
<< ops.at(2).GetImm() << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::Xori:
|
|
|
os << " xori " << PhysRegName(ops.at(0).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(1).GetReg()) << ", "
|
|
|
<< ops.at(2).GetImm() << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::LoadGlobalAddr: {
|
|
|
std::string global_name = ops.at(1).GetGlobalName();
|
|
|
os << " la " << PhysRegName(ops.at(0).GetReg()) << ", " << global_name << "\n";
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case Opcode::LoadGlobal:
|
|
|
// 全局变量加载 - 使用 lw(32位)
|
|
|
os << " lw " << PhysRegName(ops.at(0).GetReg()) << ", 0("
|
|
|
<< PhysRegName(ops.at(1).GetReg()) << ")\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::StoreGlobal: {
|
|
|
std::string global_name = ops.at(1).GetGlobalName();
|
|
|
os << " la t1, " << global_name << "\n";
|
|
|
os << " sw " << PhysRegName(ops.at(0).GetReg()) << ", 0(t1)\n";
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case Opcode::GEP:
|
|
|
break;
|
|
|
|
|
|
case Opcode::LoadIndirect:
|
|
|
// 间接加载 - 使用 lw(32位)
|
|
|
os << " lw " << PhysRegName(ops.at(0).GetReg()) << ", 0("
|
|
|
<< PhysRegName(ops.at(1).GetReg()) << ")\n";
|
|
|
break;
|
|
|
case Opcode::LoadIndirectFloat:
|
|
|
os << " flw " << PhysRegName(ops[0].GetReg()) << ", 0("
|
|
|
<< PhysRegName(ops[1].GetReg()) << ")\n";
|
|
|
break;
|
|
|
case Opcode::Call: {
|
|
|
std::string func_name = "memset"; // 默认值
|
|
|
if (!ops.empty() && ops[0].GetKind() == Operand::Kind::Func) {
|
|
|
func_name = ops[0].GetFuncName();
|
|
|
}
|
|
|
os << " call " << func_name << "\n";
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case Opcode::LoadAddr: {
|
|
|
int frame_idx = ops.at(1).GetFrameIndex();
|
|
|
const auto& slot = function.GetFrameSlot(frame_idx);
|
|
|
// 计算地址(64 位),offset 是正数
|
|
|
if (slot.offset <= 2047) {
|
|
|
os << " addi " << PhysRegName(ops.at(0).GetReg()) << ", s0, " << slot.offset << "\n";
|
|
|
} else {
|
|
|
os << " li " << PhysRegName(ops.at(0).GetReg()) << ", " << slot.offset << "\n";
|
|
|
os << " add " << PhysRegName(ops.at(0).GetReg()) << ", s0, "
|
|
|
<< PhysRegName(ops.at(0).GetReg()) << "\n";
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case Opcode::Slli:
|
|
|
os << " slli " << PhysRegName(ops.at(0).GetReg()) << ", "
|
|
|
<< PhysRegName(ops.at(1).GetReg()) << ", "
|
|
|
<< ops.at(2).GetImm() << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::StoreIndirect:
|
|
|
// 间接存储 - 使用 sw(32位)
|
|
|
os << " sw " << PhysRegName(ops.at(0).GetReg()) << ", 0("
|
|
|
<< PhysRegName(ops.at(1).GetReg()) << ")\n";
|
|
|
break;
|
|
|
case Opcode::StoreIndirectFloat:
|
|
|
os << " fsw " << PhysRegName(ops[0].GetReg()) << ", 0("
|
|
|
<< PhysRegName(ops[1].GetReg()) << ")\n";
|
|
|
break;
|
|
|
case Opcode::Ret:{
|
|
|
// 恢复 ra 和 s0
|
|
|
int ra_offset = local_vars;
|
|
|
int s0_offset = local_vars + 8;
|
|
|
|
|
|
if (ra_offset <= 2047) {
|
|
|
os << " ld ra, " << ra_offset << "(s0)\n";
|
|
|
} else {
|
|
|
os << " li t3, " << ra_offset << "\n";
|
|
|
os << " add t3, s0, t3\n";
|
|
|
os << " ld ra, 0(t3)\n";
|
|
|
}
|
|
|
|
|
|
// 恢复 sp
|
|
|
if (total_frame <= 2047) {
|
|
|
os << " addi sp, s0, " << total_frame << "\n";
|
|
|
} else {
|
|
|
os << " li t3, " << total_frame << "\n";
|
|
|
os << " add sp, s0, t3\n";
|
|
|
}
|
|
|
|
|
|
if (s0_offset <= 2047) {
|
|
|
os << " ld s0, " << s0_offset << "(s0)\n";
|
|
|
} else {
|
|
|
os << " li t3, " << s0_offset << "\n";
|
|
|
os << " add t3, s0, t3\n";
|
|
|
os << " ld s0, 0(t3)\n";
|
|
|
}
|
|
|
|
|
|
|
|
|
os << " ret\n";
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case Opcode::Br: {
|
|
|
auto* target = reinterpret_cast<MachineBasicBlock*>(ops[0].GetImm64());
|
|
|
os << " j " << target->GetName() << "\n";
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case Opcode::CondBr: {
|
|
|
auto* true_target = reinterpret_cast<MachineBasicBlock*>(ops[1].GetImm64());
|
|
|
auto* false_target = reinterpret_cast<MachineBasicBlock*>(ops[2].GetImm64());
|
|
|
auto true_it = block_names.find(true_target);
|
|
|
auto false_it = block_names.find(false_target);
|
|
|
if (true_it == block_names.end() || false_it == block_names.end()) {
|
|
|
throw std::runtime_error(FormatError("mir", "CondBr: 找不到基本块名称"));
|
|
|
}
|
|
|
os << " bnez " << PhysRegName(ops[0].GetReg()) << ", "
|
|
|
<< true_it->second << "\n";
|
|
|
os << " j " << false_it->second << "\n";
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
// 浮点运算
|
|
|
case Opcode::FAdd:
|
|
|
os << " fadd.s " << PhysRegName(ops[0].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[1].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[2].GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::FSub:
|
|
|
os << " fsub.s " << PhysRegName(ops[0].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[1].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[2].GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::FMul:
|
|
|
os << " fmul.s " << PhysRegName(ops[0].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[1].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[2].GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::FDiv:
|
|
|
os << " fdiv.s " << PhysRegName(ops[0].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[1].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[2].GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::FEq:
|
|
|
os << " feq.s " << PhysRegName(ops[0].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[1].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[2].GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::FLt:
|
|
|
os << " flt.s " << PhysRegName(ops[0].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[1].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[2].GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::FLe:
|
|
|
os << " fle.s " << PhysRegName(ops[0].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[1].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[2].GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::FMov:
|
|
|
os << " fmv.s " << PhysRegName(ops[0].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[1].GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::FMovWX:
|
|
|
os << " fmv.w.x " << PhysRegName(ops[0].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[1].GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::FMovXW:
|
|
|
os << " fmv.x.w " << PhysRegName(ops[0].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[1].GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::SIToFP:
|
|
|
os << " fcvt.s.w " << PhysRegName(ops[0].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[1].GetReg()) << "\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::FPToSI:
|
|
|
os << " fcvt.w.s " << PhysRegName(ops[0].GetReg()) << ", "
|
|
|
<< PhysRegName(ops[1].GetReg()) << ", rtz\n";
|
|
|
break;
|
|
|
|
|
|
case Opcode::LoadFloat:
|
|
|
if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Reg) {
|
|
|
os << " flw " << PhysRegName(ops[0].GetReg()) << ", 0("
|
|
|
<< PhysRegName(ops[1].GetReg()) << ")\n";
|
|
|
} else {
|
|
|
int frame_idx = ops[1].GetFrameIndex();
|
|
|
const auto& slot = function.GetFrameSlot(frame_idx);
|
|
|
EmitStackLoadFloat(os, ops[0].GetReg(), slot.offset);
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case Opcode::StoreFloat:
|
|
|
if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Reg) {
|
|
|
os << " fsw " << PhysRegName(ops[0].GetReg()) << ", 0("
|
|
|
<< PhysRegName(ops[1].GetReg()) << ")\n";
|
|
|
} else {
|
|
|
int frame_idx = ops[1].GetFrameIndex();
|
|
|
const auto& slot = function.GetFrameSlot(frame_idx);
|
|
|
EmitStackStoreFloat(os, ops[0].GetReg(), slot.offset);
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
os << ".size " << function.GetName() << ", .-" << function.GetName() << "\n";
|
|
|
}
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
// 输出多个函数的汇编
|
|
|
void PrintAsm(const std::vector<std::unique_ptr<MachineFunction>>& functions, std::ostream& os) {
|
|
|
// ========== 输出全局变量 ==========
|
|
|
|
|
|
// .data 段:非常量变量
|
|
|
bool hasData = false;
|
|
|
for (const auto& gv : g_globalVars) {
|
|
|
if (gv.isConst) continue; // 常量到 .rodata
|
|
|
if (!hasData) {
|
|
|
os << ".data\n";
|
|
|
hasData = true;
|
|
|
}
|
|
|
os << " .global " << gv.name << "\n";
|
|
|
os << " .type " << gv.name << ", @object\n";
|
|
|
|
|
|
if (gv.isArray && gv.arraySize > 1) {
|
|
|
int totalSize = gv.arraySize * 4;
|
|
|
os << " .size " << gv.name << ", " << totalSize << "\n";
|
|
|
os << gv.name << ":\n";
|
|
|
if (gv.isFloat) {
|
|
|
if (!gv.arrayValuesF.empty()) {
|
|
|
for (float val : gv.arrayValuesF) {
|
|
|
union { float f; uint32_t i; } u;
|
|
|
u.f = val;
|
|
|
os << " .word " << u.i << "\n";
|
|
|
}
|
|
|
} else {
|
|
|
for (int i = 0; i < gv.arraySize; i++) os << " .word 0\n";
|
|
|
}
|
|
|
} else {
|
|
|
if (!gv.arrayValues.empty()) {
|
|
|
for (int val : gv.arrayValues) os << " .word " << val << "\n";
|
|
|
} else {
|
|
|
for (int i = 0; i < gv.arraySize; i++) os << " .word 0\n";
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
os << " .size " << gv.name << ", 4\n";
|
|
|
os << gv.name << ":\n";
|
|
|
if (gv.isFloat) {
|
|
|
union { float f; uint32_t i; } u;
|
|
|
u.f = gv.valueF;
|
|
|
os << " .word " << u.i << "\n";
|
|
|
} else {
|
|
|
os << " .word " << gv.value << "\n";
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// .rodata 段:只读常量
|
|
|
bool hasRodata = false;
|
|
|
for (const auto& gv : g_globalVars) {
|
|
|
if (!gv.isConst) continue;
|
|
|
if (!hasRodata) {
|
|
|
os << ".section .rodata\n";
|
|
|
hasRodata = true;
|
|
|
}
|
|
|
os << " .global " << gv.name << "\n";
|
|
|
os << " .type " << gv.name << ", @object\n";
|
|
|
|
|
|
if (gv.isArray && gv.arraySize > 1) {
|
|
|
int totalSize = gv.arraySize * 4;
|
|
|
os << " .size " << gv.name << ", " << totalSize << "\n";
|
|
|
os << gv.name << ":\n";
|
|
|
if (gv.isFloat) {
|
|
|
if (!gv.arrayValuesF.empty()) {
|
|
|
for (float val : gv.arrayValuesF) {
|
|
|
union { float f; uint32_t i; } u;
|
|
|
u.f = val;
|
|
|
os << " .word " << u.i << "\n";
|
|
|
}
|
|
|
} else {
|
|
|
for (int i = 0; i < gv.arraySize; i++) os << " .word 0\n";
|
|
|
}
|
|
|
} else {
|
|
|
if (!gv.arrayValues.empty()) {
|
|
|
for (int val : gv.arrayValues) os << " .word " << val << "\n";
|
|
|
} else {
|
|
|
for (int i = 0; i < gv.arraySize; i++) os << " .word 0\n";
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
os << " .size " << gv.name << ", 4\n";
|
|
|
os << gv.name << ":\n";
|
|
|
if (gv.isFloat) {
|
|
|
union { float f; uint32_t i; } u;
|
|
|
u.f = gv.valueF;
|
|
|
os << " .word " << u.i << "\n";
|
|
|
} else {
|
|
|
os << " .word " << gv.value << "\n";
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// ========== 输出代码段 ==========
|
|
|
os << ".text\n";
|
|
|
|
|
|
// 输出每个函数
|
|
|
for (const auto& func_ptr : functions) {
|
|
|
os << ".global " << func_ptr->GetName() << "\n";
|
|
|
os << ".type " << func_ptr->GetName() << ", @function\n";
|
|
|
os << func_ptr->GetName() << ":\n";
|
|
|
|
|
|
PrintAsmFunction(*func_ptr, os);
|
|
|
|
|
|
os << "\n"; // 函数之间加空行
|
|
|
}
|
|
|
}
|
|
|
|
|
|
} // namespace mir
|