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.

641 lines
23 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 <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:
// 全局变量加载 - 使用 lw32位
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:
// 间接加载 - 使用 lw32位
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:
// 间接存储 - 使用 sw32位
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