[backend] supported if

This commit is contained in:
Lixuanwang
2025-06-23 06:16:19 +08:00
parent 10e1476ba1
commit af00612376
3 changed files with 238 additions and 142 deletions

View File

@@ -14,17 +14,35 @@ const std::vector<RISCv32CodeGen::PhysicalReg> RISCv32CodeGen::allocable_regs =
std::string RISCv32CodeGen::reg_to_string(PhysicalReg reg) {
switch (reg) {
case PhysicalReg::S0: return "s0";
case PhysicalReg::T0: return "t0"; case PhysicalReg::T1: return "t1";
case PhysicalReg::T2: return "t2"; case PhysicalReg::T3: return "t3";
case PhysicalReg::T4: return "t4"; case PhysicalReg::T5: return "t5";
case PhysicalReg::T6: return "t6"; case PhysicalReg::A0: return "a0";
case PhysicalReg::A1: return "a1"; case PhysicalReg::A2: return "a2";
case PhysicalReg::A3: return "a3"; case PhysicalReg::A4: return "a4";
case PhysicalReg::A5: return "a5"; case PhysicalReg::A6: return "a6";
case PhysicalReg::T0: return "t0";
case PhysicalReg::T1: return "t1";
case PhysicalReg::T2: return "t2";
case PhysicalReg::T3: return "t3";
case PhysicalReg::T4: return "t4";
case PhysicalReg::T5: return "t5";
case PhysicalReg::T6: return "t6";
case PhysicalReg::A0: return "a0";
case PhysicalReg::A1: return "a1";
case PhysicalReg::A2: return "a2";
case PhysicalReg::A3: return "a3";
case PhysicalReg::A4: return "a4";
case PhysicalReg::A5: return "a5";
case PhysicalReg::A6: return "a6";
case PhysicalReg::A7: return "a7";
default: return "";
}
}
// 简单的临时寄存器分配器
class TempRegAllocator {
std::vector<std::string> regs = {"t0", "t1", "t2", "t3", "t4", "t5", "t6"};
size_t current = 0;
public:
std::string get_next() {
if (current >= regs.size()) throw std::runtime_error("临时寄存器不足");
return regs[current++];
}
void reset() { current = 0; }
};
std::string RISCv32CodeGen::code_gen() {
std::stringstream ss;
@@ -34,7 +52,6 @@ std::string RISCv32CodeGen::code_gen() {
std::string RISCv32CodeGen::module_gen() {
std::stringstream ss;
// 生成全局变量(数据段)
bool has_globals = !module->getGlobals().empty();
if (has_globals) {
ss << ".data\n";
@@ -59,7 +76,6 @@ std::string RISCv32CodeGen::module_gen() {
}
}
}
// 生成函数(文本段)
if (!module->getFunctions().empty()) {
ss << ".text\n";
for (const auto& func : module->getFunctions()) {
@@ -71,25 +87,24 @@ std::string RISCv32CodeGen::module_gen() {
std::string RISCv32CodeGen::function_gen(Function* func) {
std::stringstream ss;
// 函数标签
ss << ".globl " << func->getName() << "\n";
ss << func->getName() << ":\n";
// 寄存器分配
auto alloc = register_allocation(func);
// 序言:分配堆栈,保存 ra 和 s0设置帧指针
int stack_size = alloc.stack_size;
ss << " addi sp, sp, -" << stack_size << "\n";
ss << " sw ra, " << (stack_size - 4) << "(sp)\n";
ss << " sw s0, " << (stack_size - 8) << "(sp)\n";
ss << " mv s0, sp\n";
// 生成基本块代码
if (stack_size > 0) {
ss << " addi sp, sp, -" << stack_size << "\n";
ss << " sw ra, " << (stack_size - 4) << "(sp)\n";
ss << " sw s0, " << (stack_size - 8) << "(sp)\n";
ss << " mv s0, sp\n";
}
for (const auto& bb : func->getBasicBlocks()) {
ss << basicBlock_gen(bb.get(), alloc);
}
// 结尾:恢复 ra 和 s0释放堆栈
ss << " lw ra, " << (stack_size - 4) << "(sp)\n";
ss << " lw s0, " << (stack_size - 8) << "(sp)\n";
ss << " addi sp, sp, " << stack_size << "\n";
if (stack_size > 0) {
ss << " lw ra, " << (stack_size - 4) << "(sp)\n";
ss << " lw s0, " << (stack_size - 8) << "(sp)\n";
ss << " addi sp, sp, " << stack_size << "\n";
}
ss << " ret\n";
return ss.str();
}
@@ -108,168 +123,249 @@ std::string RISCv32CodeGen::basicBlock_gen(BasicBlock* bb, const RegAllocResult&
std::vector<std::string> RISCv32CodeGen::instruction_gen(Instruction* inst, const RegAllocResult& alloc) {
std::vector<std::string> insts;
if (auto bin = dynamic_cast<BinaryInst*>(inst)) {
auto load_operand = [&](Value* val, const std::string& reg) {
if (auto constant = dynamic_cast<ConstantValue*>(val)) {
if (constant->isInt()) {
insts.push_back("li " + reg + ", " + std::to_string(constant->getInt()));
} else {
float f = constant->getFloat();
uint32_t float_bits = *(uint32_t*)&f;
insts.push_back("li " + reg + ", " + std::to_string(float_bits));
insts.push_back("fmv.w.x " + reg + ", " + reg);
}
} else if (alloc.stack_map.find(val) != alloc.stack_map.end()) {
insts.push_back("lw " + reg + ", " + std::to_string(alloc.stack_map.at(val)) + "(s0)");
} else if (auto global = dynamic_cast<GlobalValue*>(val)) {
insts.push_back("la " + reg + ", " + global->getName());
}
};
if (auto alloca = dynamic_cast<AllocaInst*>(inst)) {
// 栈空间已在 register_allocation 中分配
}
else if (auto store = dynamic_cast<StoreInst*>(inst)) {
std::string val_reg = "t0";
load_operand(store->getValue(), val_reg);
auto ptr = store->getPointer();
if (auto alloca = dynamic_cast<AllocaInst*>(ptr)) {
int offset = alloc.stack_map.at(alloca);
insts.push_back("sw " + val_reg + ", " + std::to_string(offset) + "(s0)");
} else if (auto global = dynamic_cast<GlobalValue*>(ptr)) {
std::string ptr_reg = "t1";
insts.push_back("la " + ptr_reg + ", " + global->getName());
insts.push_back("sw " + val_reg + ", 0(" + ptr_reg + ")");
}
}
else if (auto load = dynamic_cast<LoadInst*>(inst)) {
std::string dst_reg = "t0";
auto ptr = load->getPointer();
if (auto alloca = dynamic_cast<AllocaInst*>(ptr)) {
int offset = alloc.stack_map.at(alloca);
insts.push_back("lw " + dst_reg + ", " + std::to_string(offset) + "(s0)");
} else if (auto global = dynamic_cast<GlobalValue*>(ptr)) {
std::string ptr_reg = "t1";
insts.push_back("la " + ptr_reg + ", " + global->getName());
insts.push_back("lw " + dst_reg + ", 0(" + ptr_reg + ")");
}
if (alloc.stack_map.find(load) != alloc.stack_map.end()) {
insts.push_back("sw " + dst_reg + ", " + std::to_string(alloc.stack_map.at(load)) + "(s0)");
}
}
else if (auto bin = dynamic_cast<BinaryInst*>(inst)) {
std::string lhs_reg = "t0";
std::string rhs_reg = "t1";
std::string dst_reg = "t2";
// 加载 LHS
if (auto lhs_const = dynamic_cast<ConstantValue*>(bin->getLhs())) {
if (lhs_const->isInt()) {
insts.push_back("li " + lhs_reg + ", " + std::to_string(lhs_const->getInt()));
}
} else if (auto lhs_load = dynamic_cast<LoadInst*>(bin->getLhs())) {
auto ptr_it = alloc.stack_map.find(lhs_load->getPointer());
if (ptr_it != alloc.stack_map.end()) {
insts.push_back("lw " + lhs_reg + ", " + std::to_string(ptr_it->second) + "(s0)");
}
} else {
auto lhs_it = alloc.stack_map.find(bin->getLhs());
if (lhs_it != alloc.stack_map.end()) {
insts.push_back("lw " + lhs_reg + ", " + std::to_string(lhs_it->second) + "(s0)");
}
}
// 加载 RHS
if (auto rhs_const = dynamic_cast<ConstantValue*>(bin->getRhs())) {
if (rhs_const->isInt()) {
insts.push_back("li " + rhs_reg + ", " + std::to_string(rhs_const->getInt()));
}
} else if (auto rhs_load = dynamic_cast<LoadInst*>(bin->getRhs())) {
auto ptr_it = alloc.stack_map.find(rhs_load->getPointer());
if (ptr_it != alloc.stack_map.end()) {
insts.push_back("lw " + rhs_reg + ", " + std::to_string(ptr_it->second) + "(s0)");
}
} else {
auto rhs_it = alloc.stack_map.find(bin->getRhs());
if (rhs_it != alloc.stack_map.end()) {
insts.push_back("lw " + rhs_reg + ", " + std::to_string(rhs_it->second) + "(s0)");
}
}
// 执行二元操作
load_operand(bin->getLhs(), lhs_reg);
load_operand(bin->getRhs(), rhs_reg);
std::string opcode;
if (bin->getKind() == BinaryInst::kAdd) opcode = "add";
else if (bin->getKind() == BinaryInst::kSub) opcode = "sub";
else if (bin->getKind() == BinaryInst::kMul) opcode = "mul";
else return insts; // 未支持的操作
insts.push_back(opcode + " " + dst_reg + ", " + lhs_reg + ", " + rhs_reg);
// 存储结果
auto dst_it = alloc.stack_map.find(bin);
if (dst_it != alloc.stack_map.end()) {
insts.push_back("sw " + dst_reg + ", " + std::to_string(dst_it->second) + "(s0)");
switch (bin->getKind()) {
case BinaryInst::kAdd: opcode = "add"; break;
case BinaryInst::kSub: opcode = "sub"; break;
case BinaryInst::kMul: opcode = "mul"; break;
case BinaryInst::kDiv: opcode = "div"; break;
case BinaryInst::kRem: opcode = "rem"; break;
case BinaryInst::kFAdd: opcode = "fadd.s"; break;
case BinaryInst::kFSub: opcode = "fsub.s"; break;
case BinaryInst::kFMul: opcode = "fmul.s"; break;
case BinaryInst::kFDiv: opcode = "fdiv.s"; break;
case BinaryInst::kICmpEQ: insts.push_back("seqz " + dst_reg + ", " + lhs_reg); break;
case BinaryInst::kICmpNE: insts.push_back("snez " + dst_reg + ", " + lhs_reg); break;
case BinaryInst::kICmpLT: insts.push_back("slt " + dst_reg + ", " + lhs_reg + ", " + rhs_reg); break;
case BinaryInst::kICmpGT: insts.push_back("sgt " + dst_reg + ", " + lhs_reg + ", " + rhs_reg); break;
case BinaryInst::kICmpLE: insts.push_back("sle " + dst_reg + ", " + lhs_reg + ", " + rhs_reg); break;
case BinaryInst::kICmpGE: insts.push_back("sge " + dst_reg + ", " + lhs_reg + ", " + rhs_reg); break;
case BinaryInst::kAnd: opcode = "and"; break;
case BinaryInst::kOr: opcode = "or"; break;
default: return insts;
}
} else if (auto load = dynamic_cast<LoadInst*>(inst)) {
if (!opcode.empty()) {
insts.push_back(opcode + " " + dst_reg + ", " + lhs_reg + ", " + rhs_reg);
}
if (alloc.stack_map.find(bin) != alloc.stack_map.end()) {
insts.push_back("sw " + dst_reg + ", " + std::to_string(alloc.stack_map.at(bin)) + "(s0)");
}
}
else if (auto uny = dynamic_cast<UnaryInst*>(inst)) {
std::string src_reg = "t0";
std::string dst_reg = "t1";
// 检查是否为局部变量
auto ptr_it = alloc.stack_map.find(load->getPointer());
if (ptr_it != alloc.stack_map.end()) {
// 局部变量:直接从栈加载
insts.push_back("lw " + dst_reg + ", " + std::to_string(ptr_it->second) + "(s0)");
} else {
// 全局变量:加载地址并读取
std::string ptr_reg = "t0";
insts.push_back("la " + ptr_reg + ", " + load->getPointer()->getName());
insts.push_back("lw " + dst_reg + ", 0(" + ptr_reg + ")");
load_operand(uny->getOperand(), src_reg);
switch (uny->getKind()) {
case UnaryInst::kNeg: insts.push_back("sub " + dst_reg + ", x0, " + src_reg); break;
case UnaryInst::kNot: insts.push_back("xori " + dst_reg + ", " + src_reg + ", -1"); break;
case UnaryInst::kFNeg: insts.push_back("fneg.s " + dst_reg + ", " + src_reg); break;
case UnaryInst::kFtoI: insts.push_back("fcvt.w.s " + dst_reg + ", " + src_reg); break;
case UnaryInst::kItoF: insts.push_back("fcvt.s.w " + dst_reg + ", " + src_reg); break;
case UnaryInst::kBitFtoI: insts.push_back("fmv.x.w " + dst_reg + ", " + src_reg); break;
case UnaryInst::kBitItoF: insts.push_back("fmv.w.x " + dst_reg + ", " + src_reg); break;
default: return insts;
}
// 仅在需要时存储
auto dst_it = alloc.stack_map.find(load);
if (dst_it != alloc.stack_map.end()) {
insts.push_back("sw " + dst_reg + ", " + std::to_string(dst_it->second) + "(s0)");
if (alloc.stack_map.find(uny) != alloc.stack_map.end()) {
insts.push_back("sw " + dst_reg + ", " + std::to_string(alloc.stack_map.at(uny)) + "(s0)");
}
} else if (auto store = dynamic_cast<StoreInst*>(inst)) {
std::string val_reg = "t0";
// 加载值
if (auto val_const = dynamic_cast<ConstantValue*>(store->getValue())) {
if (val_const->isInt()) {
insts.push_back("li " + val_reg + ", " + std::to_string(val_const->getInt()));
}
} else {
auto val_it = alloc.stack_map.find(store->getValue());
if (val_it != alloc.stack_map.end()) {
insts.push_back("lw " + val_reg + ", " + std::to_string(val_it->second) + "(s0)");
}
}
else if (auto call = dynamic_cast<CallInst*>(inst)) {
auto args = call->getArguments();
size_t i = 0;
for (auto it = args.begin(); it != args.end() && i < 8; ++it, ++i) {
load_operand((*it)->getValue(), "a" + std::to_string(i));
}
// 检查是否为局部变量
auto ptr_it = alloc.stack_map.find(store->getPointer());
if (ptr_it != alloc.stack_map.end()) {
// 局部变量:直接存储到栈
insts.push_back("sw " + val_reg + ", " + std::to_string(ptr_it->second) + "(s0)");
} else {
// 全局变量:加载地址并存储
std::string ptr_reg = "t1";
insts.push_back("la " + ptr_reg + ", " + store->getPointer()->getName());
insts.push_back("sw " + val_reg + ", 0(" + ptr_reg + ")");
insts.push_back("jal " + call->getCallee()->getName());
if (alloc.stack_map.find(call) != alloc.stack_map.end()) {
insts.push_back("sw a0, " + std::to_string(alloc.stack_map.at(call)) + "(s0)");
}
} else if (auto ret = dynamic_cast<ReturnInst*>(inst)) {
}
else if (auto condBr = dynamic_cast<CondBrInst*>(inst)) {
std::string cond_reg = "t0";
load_operand(condBr->getCondition(), cond_reg);
insts.push_back("bnez " + cond_reg + ", " + condBr->getThenBlock()->getName());
insts.push_back("j " + condBr->getElseBlock()->getName());
}
else if (auto br = dynamic_cast<UncondBrInst*>(inst)) {
insts.push_back("j " + br->getBlock()->getName());
}
else if (auto ret = dynamic_cast<ReturnInst*>(inst)) {
if (ret->hasReturnValue()) {
if (auto ret_const = dynamic_cast<ConstantValue*>(ret->getReturnValue())) {
if (ret_const->isInt()) {
insts.push_back("li a0, " + std::to_string(ret_const->getInt()));
}
} else {
auto ret_it = alloc.stack_map.find(ret->getReturnValue());
if (ret_it != alloc.stack_map.end()) {
insts.push_back("lw a0, " + std::to_string(ret_it->second) + "(s0)");
}
}
load_operand(ret->getReturnValue(), "a0");
}
// 栈恢复在 function_gen 中处理
}
else if (auto la = dynamic_cast<LaInst*>(inst)) {
std::string dst_reg = "t0";
load_operand(la->getPointer(), dst_reg);
for (size_t i = 0; i < la->getNumIndices(); ++i) {
std::string idx_reg = "t1";
load_operand(la->getIndex(i), idx_reg);
insts.push_back("slli " + idx_reg + ", " + idx_reg + ", 2");
insts.push_back("add " + dst_reg + ", " + dst_reg + ", " + idx_reg);
}
if (alloc.stack_map.find(la) != alloc.stack_map.end()) {
insts.push_back("sw " + dst_reg + ", " + std::to_string(alloc.stack_map.at(la)) + "(s0)");
}
}
else if (auto memset = dynamic_cast<MemsetInst*>(inst)) {
std::string ptr_reg = "t0";
std::string val_reg = "t1";
std::string size_reg = "t2";
load_operand(memset->getPointer(), ptr_reg);
load_operand(memset->getValue(), val_reg);
load_operand(memset->getSize(), size_reg);
insts.push_back("mv t3, " + ptr_reg);
insts.push_back("add t4, " + ptr_reg + ", " + size_reg);
insts.push_back("1: sw " + val_reg + ", 0(" + ptr_reg + ")");
insts.push_back("addi " + ptr_reg + ", " + ptr_reg + ", 4");
insts.push_back("blt " + ptr_reg + ", t4, 1b");
}
else if (auto phi = dynamic_cast<PhiInst*>(inst)) {
// Phi 指令由 eliminate_phi 处理
}
return insts;
}
RISCv32CodeGen::RegAllocResult RISCv32CodeGen::register_allocation(Function* func) {
RegAllocResult result;
int stack_offset = 0; // 从 0 开始,每槽增 4
std::set<Value*> allocated; // 跟踪已分配的变量
int stack_offset = 0;
std::set<Value*> allocated;
// 分配局部变量栈空间
for (const auto& bb : func->getBasicBlocks()) {
for (const auto& inst : bb->getInstructions()) {
// 为局部变量分配栈空间
if (auto store = dynamic_cast<StoreInst*>(inst.get())) {
auto ptr = store->getPointer();
if (result.stack_map.find(ptr) == result.stack_map.end() && allocated.find(ptr) == allocated.end()) {
result.stack_map[ptr] = stack_offset;
if (auto alloca = dynamic_cast<AllocaInst*>(inst.get())) {
if (result.stack_map.find(alloca) == result.stack_map.end()) {
result.stack_map[alloca] = stack_offset;
stack_offset += 4;
allocated.insert(ptr);
}
} else if (auto load = dynamic_cast<LoadInst*>(inst.get())) {
// 为 load 结果分配栈空间(如果后续使用)
if (result.stack_map.find(load) == result.stack_map.end() && allocated.find(load) == allocated.end()) {
result.stack_map[load] = stack_offset;
stack_offset += 4;
allocated.insert(load);
}
} else if (auto bin = dynamic_cast<BinaryInst*>(inst.get())) {
// 为二元操作结果分配栈空间
}
}
}
// 分配函数参数栈空间(入口块的 arguments
auto entry_block = func->getEntryBlock();
auto args = entry_block->getArguments();
for (size_t i = 0; i < args.size(); ++i) {
if (i >= 8) { // 超过 8 个参数需要栈空间
if (result.stack_map.find(args[i]) == result.stack_map.end()) {
result.stack_map[args[i]] = stack_offset;
stack_offset += 4;
}
}
}
// 分配中间结果栈空间(如 BinaryInst 和 CallInst
for (const auto& bb : func->getBasicBlocks()) {
for (const auto& inst : bb->getInstructions()) {
if (auto bin = dynamic_cast<BinaryInst*>(inst.get())) {
if (result.stack_map.find(bin) == result.stack_map.end() && allocated.find(bin) == allocated.end()) {
result.stack_map[bin] = stack_offset;
stack_offset += 4;
allocated.insert(bin);
}
} else if (auto call = dynamic_cast<CallInst*>(inst.get())) {
if (result.stack_map.find(call) == result.stack_map.end() && allocated.find(call) == allocated.end()) {
result.stack_map[call] = stack_offset;
stack_offset += 4;
allocated.insert(call);
}
}
}
}
// 为 ra 和 s0 预留空间
result.stack_size = stack_offset + 8; // ra (4) + s0 (4)
// 按 16 字节对齐
// 检查是否需要保存 ra 和 s0
bool needs_caller_saved = false;
for (const auto& bb : func->getBasicBlocks()) {
for (const auto& inst : bb->getInstructions()) {
if (dynamic_cast<CallInst*>(inst.get())) {
needs_caller_saved = true;
break;
}
}
if (needs_caller_saved) break;
}
if (needs_caller_saved || stack_offset > 0) {
stack_offset += 8; // 保存 ra 和 s0
}
result.stack_size = stack_offset;
if (result.stack_size % 16 != 0) {
result.stack_size += (16 - (result.stack_size % 16));
result.stack_size += (16 - result.stack_size % 16);
}
return result;
}
void RISCv32CodeGen::eliminate_phi(Function* func) {
// 占位符:未实现 Phi 消除
// Placeholder: Phi elimination requires inserting moves at predecessor blocks
}
std::map<Instruction*, std::set<Value*>> RISCv32CodeGen::liveness_analysis(Function* func) {
std::map<Instruction*, std::set<Value*>> live_sets;
// 占位符:未实现活跃性分析
// Placeholder: Implement liveness analysis
return live_sets;
}
std::map<Value*, std::set<Value*>> RISCv32CodeGen::build_interference_graph(
const std::map<Instruction*, std::set<Value*>>& live_sets) {
std::map<Value*, std::set<Value*>> graph;
// 占位符:未实现干扰图构建
// Placeholder: Implement interference graph
return graph;
}

View File

@@ -6,9 +6,9 @@ int main() {
int c;
if (a == b)
c = a + b;
c = b - a + 20; // 21 <- this
else
c = a * b + b;
c = a * b + b + b + 10; // 16
return c;
}

View File

@@ -7,7 +7,7 @@ int mul(int x, int y) {
int main(){
int a, b;
a = 10;
b = 0;
a = mul(a, b);
return a + b;
b = 3;
a = mul(a, b); //60
return a + b; //66
}