Files
mysysy/src/backend/RISCv64/RISCv64ISel.cpp
2025-08-05 19:04:04 +08:00

1673 lines
86 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "RISCv64ISel.h"
#include "IR.h" // For GlobalValue
#include <stdexcept>
#include <set>
#include <functional>
#include <cmath>
#include <limits>
#include <iostream>
namespace sysy {
// DAG节点定义 (内部实现)
struct RISCv64ISel::DAGNode {
enum NodeKind {
ARGUMENT,
CONSTANT, // 整数或地址常量
LOAD,
STORE,
BINARY, // 整数二元运算
CALL,
RETURN,
BRANCH,
ALLOCA_ADDR,
UNARY, // 整数一元运算
MEMSET,
GET_ELEMENT_PTR,
FP_CONSTANT, // 浮点常量
FBINARY, // 浮点二元运算 (如 FADD, FSUB, FCMP)
FUNARY, // 浮点一元运算 (如 FCVT, FNEG)
};
NodeKind kind;
Value* value = nullptr;
std::vector<DAGNode*> operands;
std::vector<DAGNode*> users;
DAGNode(NodeKind k) : kind(k) {}
};
RISCv64ISel::RISCv64ISel() : vreg_counter(0), local_label_counter(0) {}
// 为一个IR Value获取或分配一个新的虚拟寄存器
unsigned RISCv64ISel::getVReg(Value* val) {
if (!val) {
throw std::runtime_error("Cannot get vreg for a null Value.");
}
if (vreg_map.find(val) == vreg_map.end()) {
if (vreg_counter == 0) {
vreg_counter = 1; // vreg 0 保留
}
unsigned new_vreg = vreg_counter++;
vreg_map[val] = new_vreg;
vreg_to_value_map[new_vreg] = val;
vreg_type_map[new_vreg] = val->getType();
}
return vreg_map.at(val);
}
unsigned RISCv64ISel::getNewVReg(Type* type) {
unsigned new_vreg = vreg_counter++;
vreg_type_map[new_vreg] = type; // 记录这个新vreg的类型
return new_vreg;
}
// 主入口函数
std::unique_ptr<MachineFunction> RISCv64ISel::runOnFunction(Function* func) {
F = func;
if (!F) return nullptr;
MFunc = std::make_unique<MachineFunction>(F, this);
vreg_map.clear();
bb_map.clear();
vreg_counter = 0;
local_label_counter = 0;
select();
return std::move(MFunc);
}
// 指令选择主流程
void RISCv64ISel::select() {
// 遍历基本块为它们创建对应的MachineBasicBlock
bool is_first_block = true;
for (const auto& bb_ptr : F->getBasicBlocks()) {
std::string mbb_name;
if (is_first_block) {
// 对于函数的第一个基本块,其标签必须与函数名完全相同
mbb_name = F->getName();
is_first_block = false;
} else {
// 对于后续的基本块继续使用它们在IR中的原始名称
mbb_name = bb_ptr->getName();
}
auto mbb = std::make_unique<MachineBasicBlock>(mbb_name, MFunc.get());
bb_map[bb_ptr.get()] = mbb.get();
MFunc->addBlock(std::move(mbb));
}
// 遍历Argument对象为它们分配虚拟寄存器。
if (F) {
for (Argument* arg : F->getArguments()) {
// getVReg会为每个代表参数的Argument对象在vreg_map中创建一个条目。
// 这样当后续的store指令使用这个参数时就能找到对应的vreg。
getVReg(arg);
}
}
// 遍历基本块,进行指令选择
for (const auto& bb_ptr : F->getBasicBlocks()) {
selectBasicBlock(bb_ptr.get());
}
// 链接MachineBasicBlock的前驱和后继
for (const auto& bb_ptr : F->getBasicBlocks()) {
CurMBB = bb_map.at(bb_ptr.get());
for (auto succ : bb_ptr->getSuccessors()) {
CurMBB->successors.push_back(bb_map.at(succ));
}
for (auto pred : bb_ptr->getPredecessors()) {
CurMBB->predecessors.push_back(bb_map.at(pred));
}
}
}
// 处理单个基本块
void RISCv64ISel::selectBasicBlock(BasicBlock* bb) {
CurMBB = bb_map.at(bb);
auto dag = build_dag(bb);
if (DEBUG) { // 使用 DEBUG 宏或变量来控制是否打印
print_dag(dag, bb->getName());
}
std::map<Value*, DAGNode*> value_to_node;
for(const auto& node : dag) {
if (node->value) {
value_to_node[node->value] = node.get();
}
}
std::set<DAGNode*> selected_nodes;
std::function<void(DAGNode*)> select_recursive =
[&](DAGNode* node) {
if (DEEPDEBUG) {
std::cout << "[DEEPDEBUG] select_recursive: Visiting node with kind: " << node->kind
<< " (Value: " << (node->value ? node->value->getName() : "null") << ")" << std::endl;
}
if (!node || selected_nodes.count(node)) return;
for (auto operand : node->operands) {
select_recursive(operand);
}
selectNode(node);
selected_nodes.insert(node);
};
for (const auto& inst_ptr : bb->getInstructions()) {
DAGNode* node_to_select = nullptr;
auto it = value_to_node.find(inst_ptr.get());
if (it != value_to_node.end()) {
node_to_select = it->second;
} else {
for(const auto& node : dag) {
if(node->value == inst_ptr.get()) {
node_to_select = node.get();
break;
}
}
}
if(node_to_select) {
select_recursive(node_to_select);
}
}
}
// 核心函数为DAG节点选择并生成MachineInstr (已修复和增强的完整版本)
void RISCv64ISel::selectNode(DAGNode* node) {
// 调用者select_recursive已经保证了操作数节点会先于当前节点被选择。
// 因此,这里我们只处理当前节点。
switch (node->kind) {
// “延迟物化”Late Materialization思想。
// 这三种节点仅作为标记不直接生成指令。它们的目的是在DAG中保留类型信息。
// 加载其值的责任被转移给了使用它们的父节点如STORE, BINARY等
case DAGNode::ARGUMENT:
case DAGNode::CONSTANT:
case DAGNode::ALLOCA_ADDR: {
if (node->value) {
// GlobalValue objects (global variables) should not get virtual registers
// since they represent memory addresses, not register-allocated values
if (dynamic_cast<GlobalValue*>(node->value) == nullptr) {
// 确保它有一个关联的虚拟寄存器即可,不生成代码。
getVReg(node->value);
}
}
if (auto const_val1 = dynamic_cast<ConstantValue*>(node->value)) {
if (const_val1->getInt() == 128875) {
foo3 = 1;
std::cerr << "Found constant 128875 in selectNode!" << std::endl;
}
}
break;
}
case DAGNode::FP_CONSTANT: {
// RISC-V没有直接加载浮点立即数的指令
// 标准做法是1. 将浮点数的32位二进制表示加载到一个整数寄存器
// 2. 使用 fmv.w.x 指令将位模式从整数寄存器移动到浮点寄存器
auto const_val = dynamic_cast<ConstantValue*>(node->value);
auto float_vreg = getVReg(const_val);
auto temp_int_vreg = getNewVReg(Type::getIntType()); // 临时整数虚拟寄存器
float f_val = const_val->getFloat();
// 使用 reinterpret_cast 获取浮点数的32位二进制表示
uint32_t float_bits = *reinterpret_cast<uint32_t*>(&f_val);
// 1. li temp_int_vreg, float_bits
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(temp_int_vreg));
li->addOperand(std::make_unique<ImmOperand>(float_bits));
CurMBB->addInstruction(std::move(li));
// 2. fmv.w.x float_vreg, temp_int_vreg
auto fmv = std::make_unique<MachineInstr>(RVOpcodes::FMV_W_X);
fmv->addOperand(std::make_unique<RegOperand>(float_vreg));
fmv->addOperand(std::make_unique<RegOperand>(temp_int_vreg));
CurMBB->addInstruction(std::move(fmv));
break;
}
case DAGNode::LOAD: {
auto dest_vreg = getVReg(node->value);
Value* ptr_val = node->operands[0]->value;
// 1. 获取加载结果的类型 (即这个LOAD指令自身的类型)
Type* loaded_type = node->value->getType();
// 2. 根据类型选择正确的伪指令或真实指令操作码
RVOpcodes frame_opcode;
RVOpcodes real_opcode;
if (loaded_type->isPointer()) {
frame_opcode = RVOpcodes::FRAME_LOAD_D;
real_opcode = RVOpcodes::LD;
} else if (loaded_type->isFloat()) {
frame_opcode = RVOpcodes::FRAME_LOAD_F;
real_opcode = RVOpcodes::FLW;
} else { // 默认为整数
frame_opcode = RVOpcodes::FRAME_LOAD_W;
real_opcode = RVOpcodes::LW;
}
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
// 3. 创建使用新的、区分宽度的伪指令
auto instr = std::make_unique<MachineInstr>(frame_opcode);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca)));
CurMBB->addInstruction(std::move(instr));
} else if (auto global = dynamic_cast<GlobalValue*>(ptr_val)) {
// 对于全局变量,先用 la 加载其地址
auto addr_vreg = getNewVReg(Type::getPointerType(global->getType()));
auto la = std::make_unique<MachineInstr>(RVOpcodes::LA);
la->addOperand(std::make_unique<RegOperand>(addr_vreg));
la->addOperand(std::make_unique<LabelOperand>(global->getName()));
CurMBB->addInstruction(std::move(la));
// 然后根据类型使用 ld 或 lw 加载其值
auto load_instr = std::make_unique<MachineInstr>(real_opcode);
load_instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
load_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(load_instr));
} else {
// 对于已经在虚拟寄存器中的指针地址,直接通过该地址加载
auto ptr_vreg = getVReg(ptr_val);
// 根据类型使用 ld 或 lw
auto load_instr = std::make_unique<MachineInstr>(real_opcode);
load_instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
load_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(ptr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(load_instr));
}
break;
}
case DAGNode::STORE: {
Value* val_to_store = node->operands[0]->value;
Value* ptr_val = node->operands[1]->value;
// 如果要存储的值是一个常量,就在这里生成 `li` 指令加载它
if (auto val_const = dynamic_cast<ConstantValue*>(val_to_store)) {
// 区分整数常量和浮点常量
if (val_const->isInt()) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(val_const)));
li->addOperand(std::make_unique<ImmOperand>(val_const->getInt()));
CurMBB->addInstruction(std::move(li));
} else if (val_const->isFloat()) {
// 先将浮点数的位模式加载到整数vreg再用fmv.w.x移到浮点vreg
auto temp_int_vreg = getNewVReg(Type::getIntType());
auto float_vreg = getVReg(val_const);
float f_val = val_const->getFloat();
uint32_t float_bits = *reinterpret_cast<uint32_t*>(&f_val);
// 1. li temp_int_vreg, float_bits
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(temp_int_vreg));
li->addOperand(std::make_unique<ImmOperand>(float_bits));
CurMBB->addInstruction(std::move(li));
// 2. fmv.w.x float_vreg, temp_int_vreg
auto fmv = std::make_unique<MachineInstr>(RVOpcodes::FMV_W_X);
fmv->addOperand(std::make_unique<RegOperand>(float_vreg));
fmv->addOperand(std::make_unique<RegOperand>(temp_int_vreg));
CurMBB->addInstruction(std::move(fmv));
}
}
auto val_vreg = getVReg(val_to_store);
// 1. 获取被存储的值的类型
Type* stored_type = val_to_store->getType();
// 2. 根据类型选择正确的伪指令或真实指令操作码
RVOpcodes frame_opcode;
RVOpcodes real_opcode;
if (stored_type->isPointer()) {
frame_opcode = RVOpcodes::FRAME_STORE_D;
real_opcode = RVOpcodes::SD;
} else if (stored_type->isFloat()) {
frame_opcode = RVOpcodes::FRAME_STORE_F;
real_opcode = RVOpcodes::FSW;
} else { // 默认为整数
frame_opcode = RVOpcodes::FRAME_STORE_W;
real_opcode = RVOpcodes::SW;
}
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
// 3. 创建使用新的、区分宽度的伪指令
auto instr = std::make_unique<MachineInstr>(frame_opcode);
instr->addOperand(std::make_unique<RegOperand>(val_vreg));
instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca)));
CurMBB->addInstruction(std::move(instr));
} else if (auto global = dynamic_cast<GlobalValue*>(ptr_val)) {
// 向全局变量存储
auto addr_vreg = getNewVReg(Type::getIntType());
auto la = std::make_unique<MachineInstr>(RVOpcodes::LA);
la->addOperand(std::make_unique<RegOperand>(addr_vreg));
la->addOperand(std::make_unique<LabelOperand>(global->getName()));
CurMBB->addInstruction(std::move(la));
// 根据类型使用 sd 或 sw
auto store_instr = std::make_unique<MachineInstr>(real_opcode);
store_instr->addOperand(std::make_unique<RegOperand>(val_vreg));
store_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(store_instr));
} else {
// 向一个指针(存储在虚拟寄存器中)指向的地址存储
auto ptr_vreg = getVReg(ptr_val);
// 根据类型使用 sd 或 sw
auto store_instr = std::make_unique<MachineInstr>(real_opcode);
store_instr->addOperand(std::make_unique<RegOperand>(val_vreg));
store_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(ptr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(store_instr));
}
break;
}
case DAGNode::BINARY: {
auto bin = dynamic_cast<BinaryInst*>(node->value);
Value* lhs = bin->getLhs();
Value* rhs = bin->getRhs();
if (bin->getKind() == BinaryInst::kAdd) {
Value* base = nullptr;
Value* offset = nullptr;
// 扩展基地址的判断,使其可以识别 AllocaInst 或 GlobalValue
if (dynamic_cast<AllocaInst*>(lhs) || dynamic_cast<GlobalValue*>(lhs)) {
base = lhs;
offset = rhs;
} else if (dynamic_cast<AllocaInst*>(rhs) || dynamic_cast<GlobalValue*>(rhs)) {
base = rhs;
offset = lhs;
}
// 如果成功匹配到地址计算模式
if (base) {
// 1. 先为偏移量加载常量(如果它是常量的话)
if (auto const_offset = dynamic_cast<ConstantValue*>(offset)) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(const_offset)));
li->addOperand(std::make_unique<ImmOperand>(const_offset->getInt()));
CurMBB->addInstruction(std::move(li));
}
// 2. 根据基地址的类型,生成不同的指令来获取基地址
auto base_addr_vreg = getNewVReg(Type::getIntType()); // 创建一个新的临时vreg来存放基地址
// 情况一:基地址是局部栈变量
if (auto alloca_base = dynamic_cast<AllocaInst*>(base)) {
auto frame_addr_instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_ADDR);
frame_addr_instr->addOperand(std::make_unique<RegOperand>(base_addr_vreg));
frame_addr_instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca_base)));
CurMBB->addInstruction(std::move(frame_addr_instr));
}
// 情况二:基地址是全局变量
else if (auto global_base = dynamic_cast<GlobalValue*>(base)) {
auto la_instr = std::make_unique<MachineInstr>(RVOpcodes::LA);
la_instr->addOperand(std::make_unique<RegOperand>(base_addr_vreg));
la_instr->addOperand(std::make_unique<LabelOperand>(global_base->getName()));
CurMBB->addInstruction(std::move(la_instr));
}
// 3. 生成真正的add指令计算最终地址这部分逻辑保持不变
auto final_addr_vreg = getVReg(bin); // 这是整个二元运算的结果vreg
auto offset_vreg = getVReg(offset);
auto add_instr = std::make_unique<MachineInstr>(RVOpcodes::ADD); // 指针运算是64位
add_instr->addOperand(std::make_unique<RegOperand>(final_addr_vreg));
add_instr->addOperand(std::make_unique<RegOperand>(base_addr_vreg));
add_instr->addOperand(std::make_unique<RegOperand>(offset_vreg));
CurMBB->addInstruction(std::move(add_instr));
return; // 地址计算处理完毕,直接返回
}
}
// 在BINARY节点内部按需加载常量操作数。
auto load_val_if_const = [&](Value* val) {
if (auto c = dynamic_cast<ConstantValue*>(val)) {
if (DEBUG) {
std::cout << "[DEBUG] selectNode-BINARY: Found constant operand with value " << c->getInt()
<< ". Generating LI instruction." << std::endl;
}
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(c)));
li->addOperand(std::make_unique<ImmOperand>(c->getInt()));
CurMBB->addInstruction(std::move(li));
}
};
// 检查是否能应用立即数优化。
bool rhs_is_imm_opt = false;
if (auto rhs_const = dynamic_cast<ConstantValue*>(rhs)) {
if (bin->getKind() == BinaryInst::kAdd && rhs_const->getInt() >= -2048 && rhs_const->getInt() < 2048) {
rhs_is_imm_opt = true;
}
}
// 仅在不能作为立即数操作数时才需要提前加载。
load_val_if_const(lhs);
if (!rhs_is_imm_opt) {
load_val_if_const(rhs);
}
auto dest_vreg = getVReg(bin);
auto lhs_vreg = getVReg(lhs);
// 融合 ADDIW 优化。
if (rhs_is_imm_opt) {
auto rhs_const = dynamic_cast<ConstantValue*>(rhs);
auto instr = std::make_unique<MachineInstr>(RVOpcodes::ADDIW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<ImmOperand>(rhs_const->getInt()));
CurMBB->addInstruction(std::move(instr));
return; // 指令已生成,直接返回。
}
auto rhs_vreg = getVReg(rhs);
switch (bin->getKind()) {
case BinaryInst::kAdd: {
// 区分指针运算64位和整数运算32位
RVOpcodes opcode = (lhs->getType()->isPointer() || rhs->getType()->isPointer()) ? RVOpcodes::ADD : RVOpcodes::ADDW;
auto instr = std::make_unique<MachineInstr>(opcode);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case BinaryInst::kSub: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case BinaryInst::kMul: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::MULW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kDiv: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::DIVW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kRem: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::REMW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kSRA: {
auto rhs_const = dynamic_cast<ConstantInteger*>(rhs);
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SRAIW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<ImmOperand>(rhs_const->getInt()));
CurMBB->addInstruction(std::move(instr));
break;
}
case BinaryInst::kICmpEQ: { // 等于 (a == b) -> (subw; seqz)
auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
sub->addOperand(std::make_unique<RegOperand>(dest_vreg));
sub->addOperand(std::make_unique<RegOperand>(lhs_vreg));
sub->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(sub));
auto seqz = std::make_unique<MachineInstr>(RVOpcodes::SEQZ);
seqz->addOperand(std::make_unique<RegOperand>(dest_vreg));
seqz->addOperand(std::make_unique<RegOperand>(dest_vreg));
CurMBB->addInstruction(std::move(seqz));
break;
}
case BinaryInst::kICmpNE: { // 不等于 (a != b) -> (subw; snez)
auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
sub->addOperand(std::make_unique<RegOperand>(dest_vreg));
sub->addOperand(std::make_unique<RegOperand>(lhs_vreg));
sub->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(sub));
auto snez = std::make_unique<MachineInstr>(RVOpcodes::SNEZ);
snez->addOperand(std::make_unique<RegOperand>(dest_vreg));
snez->addOperand(std::make_unique<RegOperand>(dest_vreg));
CurMBB->addInstruction(std::move(snez));
break;
}
case BinaryInst::kICmpLT: { // 小于 (a < b) -> slt
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SLT);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case BinaryInst::kICmpGT: { // 大于 (a > b) -> (b < a) -> slt
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SLT);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case BinaryInst::kICmpLE: { // 小于等于 (a <= b) -> !(b < a) -> (slt; xori)
auto slt = std::make_unique<MachineInstr>(RVOpcodes::SLT);
slt->addOperand(std::make_unique<RegOperand>(dest_vreg));
slt->addOperand(std::make_unique<RegOperand>(rhs_vreg));
slt->addOperand(std::make_unique<RegOperand>(lhs_vreg));
CurMBB->addInstruction(std::move(slt));
auto xori = std::make_unique<MachineInstr>(RVOpcodes::XORI);
xori->addOperand(std::make_unique<RegOperand>(dest_vreg));
xori->addOperand(std::make_unique<RegOperand>(dest_vreg));
xori->addOperand(std::make_unique<ImmOperand>(1));
CurMBB->addInstruction(std::move(xori));
break;
}
case BinaryInst::kICmpGE: { // 大于等于 (a >= b) -> !(a < b) -> (slt; xori)
auto slt = std::make_unique<MachineInstr>(RVOpcodes::SLT);
slt->addOperand(std::make_unique<RegOperand>(dest_vreg));
slt->addOperand(std::make_unique<RegOperand>(lhs_vreg));
slt->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(slt));
auto xori = std::make_unique<MachineInstr>(RVOpcodes::XORI);
xori->addOperand(std::make_unique<RegOperand>(dest_vreg));
xori->addOperand(std::make_unique<RegOperand>(dest_vreg));
xori->addOperand(std::make_unique<ImmOperand>(1));
CurMBB->addInstruction(std::move(xori));
break;
}
default:
throw std::runtime_error("Unsupported binary instruction in ISel");
}
break;
}
case DAGNode::FBINARY: {
auto bin = dynamic_cast<BinaryInst*>(node->value);
auto dest_vreg = getVReg(bin);
auto lhs_vreg = getVReg(bin->getLhs());
auto rhs_vreg = getVReg(bin->getRhs());
switch (bin->getKind()) {
case Instruction::kFAdd: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FADD_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFSub: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FSUB_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFMul: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FMUL_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFDiv: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FDIV_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
// --- 浮点比较指令 ---
// 注意:比较结果(0或1)写入的是一个通用整数寄存器(dest_vreg)
case Instruction::kFCmpEQ: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FEQ_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFCmpLT: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FLT_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFCmpLE: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FLE_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
// --- 通过交换操作数或组合指令实现其余比较 ---
case Instruction::kFCmpGT: { // a > b 等价于 b < a
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FLT_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg)); // 操作数交换
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFCmpGE: { // a >= b 等价于 b <= a
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FLE_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg)); // 操作数交换
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFCmpNE: { // a != b 等价于 !(a == b)
// 1. 先用 feq.s 比较,结果存入 dest_vreg
auto feq = std::make_unique<MachineInstr>(RVOpcodes::FEQ_S);
feq->addOperand(std::make_unique<RegOperand>(dest_vreg));
feq->addOperand(std::make_unique<RegOperand>(lhs_vreg));
feq->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(feq));
// 2. 再用 seqz 对结果取反 (如果相等(1)则变0如果不等(0)则变1)
auto seqz = std::make_unique<MachineInstr>(RVOpcodes::SEQZ);
seqz->addOperand(std::make_unique<RegOperand>(dest_vreg));
seqz->addOperand(std::make_unique<RegOperand>(dest_vreg));
CurMBB->addInstruction(std::move(seqz));
break;
}
default:
throw std::runtime_error("Unsupported float binary instruction in ISel");
}
break;
}
case DAGNode::UNARY: {
auto unary = dynamic_cast<UnaryInst*>(node->value);
auto dest_vreg = getVReg(unary);
auto src_vreg = getVReg(unary->getOperand());
switch (unary->getKind()) {
case UnaryInst::kNeg: { // 取负: 0 - src
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
instr->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case UnaryInst::kNot: { // 逻辑非: src == 0 ? 1 : 0
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SEQZ);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
default:
throw std::runtime_error("Unsupported unary instruction in ISel");
}
break;
}
case DAGNode::FUNARY: {
auto unary = dynamic_cast<UnaryInst*>(node->value);
auto dest_vreg = getVReg(unary);
auto src_vreg = getVReg(unary->getOperand());
switch (unary->getKind()) {
case Instruction::kItoF: { // 整数 to 浮点
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FCVT_S_W);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); // 目标是浮点vreg
instr->addOperand(std::make_unique<RegOperand>(src_vreg)); // 源是整数vreg
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFtoI: { // 浮点 to 整数 (C/C++: 截断)
// C/C++ 标准要求向零截断 (truncate), 对应的RISC-V舍入模式是 RTZ (Round Towards Zero).
// fcvt.w.s 指令使用 fcsr 中的 frm 字段来决定舍入模式。
// 我们需要手动设置 frm=1 (RTZ), 执行转换, 然后恢复 frm=0 (RNE, 默认).
// 1. fsrmi x0, 1 (set rounding mode to RTZ)
auto fsrmi1 = std::make_unique<MachineInstr>(RVOpcodes::FSRMI);
fsrmi1->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
fsrmi1->addOperand(std::make_unique<ImmOperand>(1));
CurMBB->addInstruction(std::move(fsrmi1));
// 2. fcvt.w.s dest_vreg, src_vreg
auto fcvt = std::make_unique<MachineInstr>(RVOpcodes::FCVT_W_S);
fcvt->addOperand(std::make_unique<RegOperand>(dest_vreg));
fcvt->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(fcvt));
// 3. fsrmi x0, 0 (restore rounding mode to RNE)
auto fsrmi0 = std::make_unique<MachineInstr>(RVOpcodes::FSRMI);
fsrmi0->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
fsrmi0->addOperand(std::make_unique<ImmOperand>(0));
CurMBB->addInstruction(std::move(fsrmi0));
break;
}
case Instruction::kFNeg: { // 浮点取负
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FNEG_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
// --- 处理位传送指令 ---
case Instruction::kBitItoF: { // 整数位模式 -> 浮点寄存器
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FMV_W_X);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); // 目标是浮点vreg
instr->addOperand(std::make_unique<RegOperand>(src_vreg)); // 源是整数vreg
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kBitFtoI: { // 浮点位模式 -> 整数寄存器
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FMV_X_W);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); // 目标是整数vreg
instr->addOperand(std::make_unique<RegOperand>(src_vreg)); // 源是浮点vreg
CurMBB->addInstruction(std::move(instr));
break;
}
default:
throw std::runtime_error("Unsupported float unary instruction in ISel");
}
break;
}
case DAGNode::CALL: {
auto call = dynamic_cast<CallInst*>(node->value);
size_t num_operands = node->operands.size();
// --- 步骤 1: 分配寄存器参数和栈参数 ---
// 根据RISC-V调用约定前8个整数/指针参数通过a0-a7传递
// 前8个浮点参数通过fa0-fa7传递 (物理寄存器 f10-f17)。其余参数通过栈传递。
int int_reg_idx = 0; // a0-a7 的索引
int fp_reg_idx = 0; // fa0-fa7 的索引
// 用于存储需要通过栈传递的参数
std::vector<DAGNode*> stack_args;
for (size_t i = 0; i < num_operands; ++i) {
DAGNode* arg_node = node->operands[i];
Value* arg_val = arg_node->value;
Type* arg_type = arg_val->getType();
// 判断参数是浮点类型还是整型/指针类型
if (arg_type->isFloat()) {
if (fp_reg_idx < 8) {
// --- 处理浮点寄存器参数 (fa0-fa7, 对应物理寄存器 F10-F17) ---
auto arg_preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::F10) + fp_reg_idx);
fp_reg_idx++;
if (auto const_val = dynamic_cast<ConstantValue*>(arg_val)) {
// 如果是浮点常量,需要先物化
// 1. 获取其32位二进制表示
float f_val = const_val->getFloat();
uint32_t float_bits = *reinterpret_cast<uint32_t*>(&f_val);
// 2. 将位模式加载到一个临时整数寄存器 (使用t0)
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(PhysicalReg::T0));
li->addOperand(std::make_unique<ImmOperand>(float_bits));
CurMBB->addInstruction(std::move(li));
// 3. 使用fmv.w.x将位模式从整数寄存器移动到目标浮点参数寄存器
auto fmv_wx = std::make_unique<MachineInstr>(RVOpcodes::FMV_W_X);
fmv_wx->addOperand(std::make_unique<RegOperand>(arg_preg));
fmv_wx->addOperand(std::make_unique<RegOperand>(PhysicalReg::T0));
CurMBB->addInstruction(std::move(fmv_wx));
} else {
// 如果已经是虚拟寄存器,直接用 fmv.s 移动
auto src_vreg = getVReg(arg_val);
auto fmv_s = std::make_unique<MachineInstr>(RVOpcodes::FMV_S);
fmv_s->addOperand(std::make_unique<RegOperand>(arg_preg));
fmv_s->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(fmv_s));
}
} else {
// 浮点寄存器已用完,放到栈上传递
stack_args.push_back(arg_node);
}
} else { // 整数或指针参数
if (int_reg_idx < 8) {
// --- 处理整数/指针寄存器参数 (a0-a7) ---
auto arg_preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + int_reg_idx);
int_reg_idx++;
if (arg_node->kind == DAGNode::CONSTANT) {
if (auto const_val = dynamic_cast<ConstantValue*>(arg_val)) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(arg_preg));
li->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li));
}
} else {
auto src_vreg = getVReg(arg_val);
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(arg_preg));
mv->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(mv));
}
} else {
// 整数寄存器已用完,放到栈上传递
stack_args.push_back(arg_node);
}
}
}
// --- 步骤 2: 处理所有栈参数 ---
int stack_space = 0;
if (!stack_args.empty()) {
// 计算栈参数所需的总空间RV64中每个槽位为8字节
stack_space = stack_args.size() * 8;
// 根据ABI为call分配的栈空间需要16字节对齐
if (stack_space % 16 != 0) {
stack_space += 16 - (stack_space % 16);
}
// 在栈上分配空间
if (stack_space > 0) {
auto alloc_instr = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
alloc_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
alloc_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
alloc_instr->addOperand(std::make_unique<ImmOperand>(-stack_space));
CurMBB->addInstruction(std::move(alloc_instr));
}
// 将每个参数存储到栈上对应的位置
for (size_t i = 0; i < stack_args.size(); ++i) {
DAGNode* arg_node = stack_args[i];
Value* arg_val = arg_node->value;
Type* arg_type = arg_val->getType();
int offset = i * 8;
unsigned src_vreg;
// 如果是常量先加载到临时vreg
if (auto const_val = dynamic_cast<ConstantValue*>(arg_val)) {
src_vreg = getNewVReg(arg_type);
if(arg_type->isFloat()) {
auto temp_int_vreg = getNewVReg(Type::getIntType());
float f_val = const_val->getFloat();
uint32_t float_bits = *reinterpret_cast<uint32_t*>(&f_val);
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(temp_int_vreg));
li->addOperand(std::make_unique<ImmOperand>(float_bits));
CurMBB->addInstruction(std::move(li));
auto fmv_wx = std::make_unique<MachineInstr>(RVOpcodes::FMV_W_X);
fmv_wx->addOperand(std::make_unique<RegOperand>(src_vreg));
fmv_wx->addOperand(std::make_unique<RegOperand>(temp_int_vreg));
CurMBB->addInstruction(std::move(fmv_wx));
} else {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(src_vreg));
li->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li));
}
} else {
src_vreg = getVReg(arg_val);
}
// 根据类型选择 fsw (浮点) 或 sd (整型/指针) 存储指令
std::unique_ptr<MachineInstr> store_instr;
if (arg_type->isFloat()) {
store_instr = std::make_unique<MachineInstr>(RVOpcodes::FSW);
} else {
store_instr = std::make_unique<MachineInstr>(RVOpcodes::SD);
}
store_instr->addOperand(std::make_unique<RegOperand>(src_vreg));
store_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>(offset)
));
CurMBB->addInstruction(std::move(store_instr));
}
}
// --- 步骤 3: 生成CALL指令 ---
auto call_instr = std::make_unique<MachineInstr>(RVOpcodes::CALL);
// 如果函数有返回值,将它的目标虚拟寄存器作为第一个操作数
if (!call->getType()->isVoid()) {
unsigned dest_vreg = getVReg(call);
call_instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
}
// 将函数名标签作为后续操作数
call_instr->addOperand(std::make_unique<LabelOperand>(call->getCallee()->getName()));
// 将所有参数的虚拟寄存器也作为后续操作数供getInstrUseDef分析
for (size_t i = 0; i < num_operands; ++i) {
if (node->operands[i]->kind != DAGNode::CONSTANT && node->operands[i]->kind != DAGNode::FP_CONSTANT) {
call_instr->addOperand(std::make_unique<RegOperand>(getVReg(node->operands[i]->value)));
}
}
CurMBB->addInstruction(std::move(call_instr));
// --- 步骤 4: 处理返回值 ---
if (!call->getType()->isVoid()) {
unsigned dest_vreg = getVReg(call);
if (call->getType()->isFloat()) {
// 浮点返回值在 fa0 (物理寄存器 F10)
auto fmv_s = std::make_unique<MachineInstr>(RVOpcodes::FMV_S);
fmv_s->addOperand(std::make_unique<RegOperand>(dest_vreg));
fmv_s->addOperand(std::make_unique<RegOperand>(PhysicalReg::F10)); // fa0
CurMBB->addInstruction(std::move(fmv_s));
} else {
// 整数/指针返回值在 a0
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(dest_vreg));
mv->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
CurMBB->addInstruction(std::move(mv));
}
}
// --- 步骤 5: 回收为栈参数分配的空间 ---
if (stack_space > 0) {
auto dealloc_instr = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
dealloc_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
dealloc_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
dealloc_instr->addOperand(std::make_unique<ImmOperand>(stack_space));
CurMBB->addInstruction(std::move(dealloc_instr));
}
break;
}
case DAGNode::RETURN: {
auto ret_inst_ir = dynamic_cast<ReturnInst*>(node->value);
if (ret_inst_ir && ret_inst_ir->hasReturnValue()) {
Value* ret_val = ret_inst_ir->getReturnValue();
Type* ret_type = ret_val->getType();
if (ret_type->isFloat()) {
// --- 处理浮点返回值 ---
// 返回值需要被放入 fa0 (物理寄存器 F10)
if (auto const_val = dynamic_cast<ConstantValue*>(ret_val)) {
// 如果是浮点常量需要先物化到fa0
float f_val = const_val->getFloat();
uint32_t float_bits = *reinterpret_cast<uint32_t*>(&f_val);
// 1. 加载位模式到临时整数寄存器 (t0)
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(PhysicalReg::T0));
li->addOperand(std::make_unique<ImmOperand>(float_bits));
CurMBB->addInstruction(std::move(li));
// 2. 将位模式从 t0 移动到 fa0
auto fmv_wx = std::make_unique<MachineInstr>(RVOpcodes::FMV_W_X);
fmv_wx->addOperand(std::make_unique<RegOperand>(PhysicalReg::F10)); // fa0
fmv_wx->addOperand(std::make_unique<RegOperand>(PhysicalReg::T0));
CurMBB->addInstruction(std::move(fmv_wx));
} else {
// 如果是vreg直接用 fmv.s 移动到 fa0
auto fmv_s = std::make_unique<MachineInstr>(RVOpcodes::FMV_S);
fmv_s->addOperand(std::make_unique<RegOperand>(PhysicalReg::F10)); // fa0
fmv_s->addOperand(std::make_unique<RegOperand>(getVReg(ret_val)));
CurMBB->addInstruction(std::move(fmv_s));
}
} else {
// --- 处理整数/指针返回值 ---
// 返回值需要被放入 a0
// 在RETURN节点内加载常量返回值
if (auto const_val = dynamic_cast<ConstantValue*>(ret_val)) {
auto li_instr = std::make_unique<MachineInstr>(RVOpcodes::LI);
li_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
li_instr->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li_instr));
} else {
auto mv_instr = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
mv_instr->addOperand(std::make_unique<RegOperand>(getVReg(ret_val)));
CurMBB->addInstruction(std::move(mv_instr));
}
}
}
// 函数尾声epilogue不由RETURN节点生成
// 而是由后续的AsmPrinter或其它Pass统一处理这是一种常见且有效的模块化设计。
auto ret_mi = std::make_unique<MachineInstr>(RVOpcodes::RET);
CurMBB->addInstruction(std::move(ret_mi));
break;
}
case DAGNode::BRANCH: {
// 处理条件分支
if (auto cond_br = dynamic_cast<CondBrInst*>(node->value)) {
Value* condition = cond_br->getCondition();
auto then_bb_name = cond_br->getThenBlock()->getName();
auto else_bb_name = cond_br->getElseBlock()->getName();
// 检查分支条件是否为编译期常量
if (auto const_cond = dynamic_cast<ConstantValue*>(condition)) {
// 如果条件是常量直接生成一个无条件跳转J而不是BNE
if (const_cond->getInt() != 0) { // 条件为 true
auto j_instr = std::make_unique<MachineInstr>(RVOpcodes::J);
j_instr->addOperand(std::make_unique<LabelOperand>(then_bb_name));
CurMBB->addInstruction(std::move(j_instr));
} else { // 条件为 false
auto j_instr = std::make_unique<MachineInstr>(RVOpcodes::J);
j_instr->addOperand(std::make_unique<LabelOperand>(else_bb_name));
CurMBB->addInstruction(std::move(j_instr));
}
}
// 如果条件不是常量,则执行标准流程
else {
// 为条件变量生成加载指令(如果它是常量的话,尽管上面已经处理了)
// 这一步是为了逻辑完整,以防有其他类型的常量没有被捕获
if (auto const_val = dynamic_cast<ConstantValue*>(condition)) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(const_val)));
li->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li));
}
auto cond_vreg = getVReg(condition);
// 生成 bne cond, zero, then_label (如果cond不为0则跳转到then)
auto br_instr = std::make_unique<MachineInstr>(RVOpcodes::BNE);
br_instr->addOperand(std::make_unique<RegOperand>(cond_vreg));
br_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
br_instr->addOperand(std::make_unique<LabelOperand>(then_bb_name));
CurMBB->addInstruction(std::move(br_instr));
// 为else分支生成无条件跳转 (后续Pass可以优化掉不必要的跳转)
auto j_instr = std::make_unique<MachineInstr>(RVOpcodes::J);
j_instr->addOperand(std::make_unique<LabelOperand>(else_bb_name));
CurMBB->addInstruction(std::move(j_instr));
}
}
// 处理无条件分支
else if (auto uncond_br = dynamic_cast<UncondBrInst*>(node->value)) {
auto j_instr = std::make_unique<MachineInstr>(RVOpcodes::J);
j_instr->addOperand(std::make_unique<LabelOperand>(uncond_br->getBlock()->getName()));
CurMBB->addInstruction(std::move(j_instr));
}
break;
}
case DAGNode::MEMSET: {
// Memset的核心展开逻辑在虚拟寄存器层面是正确的无需修改。
// 之前的bug是由于其输入地址、值、大小的虚拟寄存器未被正确初始化。
// 在修复了CONSTANT/ALLOCA_ADDR的加载问题后此处的逻辑现在可以正常工作。
if (DEBUG) {
std::cout << "[DEBUG] selectNode-MEMSET: Processing MEMSET node." << std::endl;
}
auto memset = dynamic_cast<MemsetInst*>(node->value);
Value* val_to_set = memset->getValue();
Value* size_to_set = memset->getSize();
Value* ptr_val = memset->getPointer();
auto dest_addr_vreg = getVReg(ptr_val);
if (auto const_val = dynamic_cast<ConstantValue*>(val_to_set)) {
if (DEBUG) {
std::cout << "[DEBUG] selectNode-MEMSET: Found constant 'value' operand (" << const_val->getInt() << "). Generating LI." << std::endl;
}
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(const_val)));
li->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li));
}
if (auto const_size = dynamic_cast<ConstantValue*>(size_to_set)) {
if (DEBUG) {
std::cout << "[DEBUG] selectNode-MEMSET: Found constant 'size' operand (" << const_size->getInt() << "). Generating LI." << std::endl;
}
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(const_size)));
li->addOperand(std::make_unique<ImmOperand>(const_size->getInt()));
CurMBB->addInstruction(std::move(li));
}
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
if (DEBUG) {
std::cout << "[DEBUG] selectNode-MEMSET: Found 'pointer' operand is an AllocaInst. Generating FRAME_ADDR." << std::endl;
}
// 生成新的伪指令来获取栈地址
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_ADDR);
instr->addOperand(std::make_unique<RegOperand>(dest_addr_vreg)); // 目标虚拟寄存器
instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca))); // 源AllocaInst
CurMBB->addInstruction(std::move(instr));
}
auto r_dest_addr = getVReg(memset->getPointer());
auto r_num_bytes = getVReg(memset->getSize());
auto r_value_byte = getVReg(memset->getValue());
// 为memset内部逻辑创建新的临时虚拟寄存器
Type* ptr_type = Type::getPointerType(Type::getIntType());
auto r_counter = getNewVReg(ptr_type);
auto r_end_addr = getNewVReg(ptr_type);
auto r_current_addr = getNewVReg(ptr_type);
auto r_temp_val = getNewVReg(Type::getIntType());
// 定义一系列lambda表达式来简化指令创建
auto add_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, unsigned rs2) {
auto i = std::make_unique<MachineInstr>(op);
i->addOperand(std::make_unique<RegOperand>(rd));
i->addOperand(std::make_unique<RegOperand>(rs1));
i->addOperand(std::make_unique<RegOperand>(rs2));
CurMBB->addInstruction(std::move(i));
};
auto addi_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, int64_t imm) {
auto i = std::make_unique<MachineInstr>(op);
i->addOperand(std::make_unique<RegOperand>(rd));
i->addOperand(std::make_unique<RegOperand>(rs1));
i->addOperand(std::make_unique<ImmOperand>(imm));
CurMBB->addInstruction(std::move(i));
};
auto store_instr = [&](RVOpcodes op, unsigned src, unsigned base, int64_t off) {
auto i = std::make_unique<MachineInstr>(op);
i->addOperand(std::make_unique<RegOperand>(src));
i->addOperand(std::make_unique<MemOperand>(std::make_unique<RegOperand>(base), std::make_unique<ImmOperand>(off)));
CurMBB->addInstruction(std::move(i));
};
auto branch_instr = [&](RVOpcodes op, unsigned rs1, unsigned rs2, const std::string& label) {
auto i = std::make_unique<MachineInstr>(op);
i->addOperand(std::make_unique<RegOperand>(rs1));
i->addOperand(std::make_unique<RegOperand>(rs2));
i->addOperand(std::make_unique<LabelOperand>(label));
CurMBB->addInstruction(std::move(i));
};
auto jump_instr = [&](const std::string& label) {
auto i = std::make_unique<MachineInstr>(RVOpcodes::J);
i->addOperand(std::make_unique<LabelOperand>(label));
CurMBB->addInstruction(std::move(i));
};
auto label_instr = [&](const std::string& name) {
auto i = std::make_unique<MachineInstr>(RVOpcodes::LABEL);
i->addOperand(std::make_unique<LabelOperand>(name));
CurMBB->addInstruction(std::move(i));
};
// 生成唯一的循环标签
int unique_id = this->local_label_counter++;
std::string loop_start_label = MFunc->getName() + "_memset_loop_start_" + std::to_string(unique_id);
std::string loop_end_label = MFunc->getName() + "_memset_loop_end_" + std::to_string(unique_id);
std::string remainder_label = MFunc->getName() + "_memset_remainder_" + std::to_string(unique_id);
std::string done_label = MFunc->getName() + "_memset_done_" + std::to_string(unique_id);
// 构造64位的填充值
addi_instr(RVOpcodes::ANDI, r_temp_val, r_value_byte, 255);
addi_instr(RVOpcodes::SLLI, r_value_byte, r_temp_val, 8);
add_instr(RVOpcodes::OR, r_temp_val, r_temp_val, r_value_byte);
addi_instr(RVOpcodes::SLLI, r_value_byte, r_temp_val, 16);
add_instr(RVOpcodes::OR, r_temp_val, r_temp_val, r_value_byte);
addi_instr(RVOpcodes::SLLI, r_value_byte, r_temp_val, 32);
add_instr(RVOpcodes::OR, r_temp_val, r_temp_val, r_value_byte);
// 计算循环边界
add_instr(RVOpcodes::ADD, r_end_addr, r_dest_addr, r_num_bytes);
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(r_current_addr));
mv->addOperand(std::make_unique<RegOperand>(r_dest_addr));
CurMBB->addInstruction(std::move(mv));
addi_instr(RVOpcodes::ANDI, r_counter, r_num_bytes, -8);
add_instr(RVOpcodes::ADD, r_counter, r_dest_addr, r_counter);
// 8字节主循环
label_instr(loop_start_label);
branch_instr(RVOpcodes::BGEU, r_current_addr, r_counter, loop_end_label);
store_instr(RVOpcodes::SD, r_temp_val, r_current_addr, 0);
addi_instr(RVOpcodes::ADDI, r_current_addr, r_current_addr, 8);
jump_instr(loop_start_label);
// 1字节收尾循环
label_instr(loop_end_label);
label_instr(remainder_label);
branch_instr(RVOpcodes::BGEU, r_current_addr, r_end_addr, done_label);
store_instr(RVOpcodes::SB, r_temp_val, r_current_addr, 0);
addi_instr(RVOpcodes::ADDI, r_current_addr, r_current_addr, 1);
jump_instr(remainder_label);
label_instr(done_label);
break;
}
case DAGNode::GET_ELEMENT_PTR: {
auto gep = dynamic_cast<GetElementPtrInst*>(node->value);
auto result_vreg = getVReg(gep);
// --- Step 1: 获取基地址 (此部分逻辑正确,保持不变) ---
auto base_ptr_node = node->operands[0];
auto current_addr_vreg = getNewVReg(gep->getType());
if (auto alloca_base = dynamic_cast<AllocaInst*>(base_ptr_node->value)) {
auto frame_addr_instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_ADDR);
frame_addr_instr->addOperand(std::make_unique<RegOperand>(current_addr_vreg));
frame_addr_instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca_base)));
CurMBB->addInstruction(std::move(frame_addr_instr));
} else if (auto global_base = dynamic_cast<GlobalValue*>(base_ptr_node->value)) {
auto la_instr = std::make_unique<MachineInstr>(RVOpcodes::LA);
la_instr->addOperand(std::make_unique<RegOperand>(current_addr_vreg));
la_instr->addOperand(std::make_unique<LabelOperand>(global_base->getName()));
CurMBB->addInstruction(std::move(la_instr));
} else if (auto const_global_base = dynamic_cast<ConstantVariable*>(base_ptr_node->value)) {
auto la_instr = std::make_unique<MachineInstr>(RVOpcodes::LA);
la_instr->addOperand(std::make_unique<RegOperand>(current_addr_vreg));
la_instr->addOperand(std::make_unique<LabelOperand>(const_global_base->getName()));
CurMBB->addInstruction(std::move(la_instr));
} else {
auto base_vreg = getVReg(base_ptr_node->value);
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(current_addr_vreg));
mv->addOperand(std::make_unique<RegOperand>(base_vreg));
CurMBB->addInstruction(std::move(mv));
}
// --- Step 2: 遵循LLVM GEP语义迭代计算地址 ---
// 初始被索引的类型,是基指针指向的那个类型 (例如, [2 x i32])
Type* current_type = gep->getBasePointer()->getType()->as<PointerType>()->getBaseType();
// 迭代处理 GEP 的每一个索引
for (size_t i = 0; i < gep->getNumIndices(); ++i) {
Value* indexValue = gep->getIndex(i);
// GEP的第一个索引以整个 `current_type` 的大小为步长。
// 后续的索引则以 `current_type` 的元素大小为步长。
// 这一步是计算地址偏移的关键。
unsigned stride = getTypeSizeInBytes(current_type);
// 如果步长为0例如对一个void类型或空结构体索引则不产生任何偏移
if (stride != 0) {
// --- 为当前索引和步长生成偏移计算指令 ---
auto offset_vreg = getNewVReg(Type::getIntType());
// 处理索引 - 区分常量与动态值
unsigned index_vreg;
if (auto const_index = dynamic_cast<ConstantValue*>(indexValue)) {
// 对于常量索引,直接创建新的虚拟寄存器
index_vreg = getNewVReg(Type::getIntType());
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(index_vreg));
li->addOperand(std::make_unique<ImmOperand>(const_index->getInt()));
CurMBB->addInstruction(std::move(li));
} else {
// 对于动态索引,使用已存在的虚拟寄存器
index_vreg = getVReg(indexValue);
}
// 优化如果步长是1可以直接移动(MV)作为偏移量,无需乘法
if (stride == 1) {
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(offset_vreg));
mv->addOperand(std::make_unique<RegOperand>(index_vreg));
CurMBB->addInstruction(std::move(mv));
} else {
// 步长不为1需要生成乘法指令
auto size_vreg = getNewVReg(Type::getIntType());
auto li_size = std::make_unique<MachineInstr>(RVOpcodes::LI);
li_size->addOperand(std::make_unique<RegOperand>(size_vreg));
li_size->addOperand(std::make_unique<ImmOperand>(stride));
CurMBB->addInstruction(std::move(li_size));
auto mul = std::make_unique<MachineInstr>(RVOpcodes::MULW);
mul->addOperand(std::make_unique<RegOperand>(offset_vreg));
mul->addOperand(std::make_unique<RegOperand>(index_vreg));
mul->addOperand(std::make_unique<RegOperand>(size_vreg));
CurMBB->addInstruction(std::move(mul));
}
// 将计算出的偏移量累加到当前地址上
auto add = std::make_unique<MachineInstr>(RVOpcodes::ADD);
add->addOperand(std::make_unique<RegOperand>(current_addr_vreg));
add->addOperand(std::make_unique<RegOperand>(current_addr_vreg));
add->addOperand(std::make_unique<RegOperand>(offset_vreg));
CurMBB->addInstruction(std::move(add));
}
// --- 为下一次迭代更新类型:深入一层 ---
if (auto array_type = current_type->as<ArrayType>()) {
current_type = array_type->getElementType();
} else if (auto ptr_type = current_type->as<PointerType>()) {
// 这种情况不应该在第二次迭代后发生,但为了逻辑健壮性保留
current_type = ptr_type->getBaseType();
}
// 如果`current_type`已经是i32等基本类型它会保持不变
// 但下一次循环如果还有索引,`getTypeSizeInBytes(i32)`仍然能正确计算步长。
}
// --- Step 3: 将最终计算出的地址存入GEP的目标虚拟寄存器 (保持不变) ---
auto final_mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
final_mv->addOperand(std::make_unique<RegOperand>(result_vreg));
final_mv->addOperand(std::make_unique<RegOperand>(current_addr_vreg));
CurMBB->addInstruction(std::move(final_mv));
break;
}
default:
throw std::runtime_error("Unsupported DAGNode kind in ISel");
}
}
// 以下是忠实移植的DAG构建函数
RISCv64ISel::DAGNode* RISCv64ISel::create_node(int kind_int, Value* val, std::map<Value*, DAGNode*>& value_to_node, std::vector<std::unique_ptr<DAGNode>>& nodes_storage) {
auto kind = static_cast<DAGNode::NodeKind>(kind_int);
if (val && value_to_node.count(val) && kind != DAGNode::STORE && kind != DAGNode::RETURN && kind != DAGNode::BRANCH && kind != DAGNode::MEMSET) {
return value_to_node[val];
}
auto node = std::make_unique<DAGNode>(kind);
node->value = val;
DAGNode* raw_node_ptr = node.get();
nodes_storage.push_back(std::move(node));
if (val && !val->getType()->isVoid() && (dynamic_cast<Instruction*>(val) || dynamic_cast<GlobalValue*>(val))) {
value_to_node[val] = raw_node_ptr;
}
return raw_node_ptr;
}
RISCv64ISel::DAGNode* RISCv64ISel::get_operand_node(
Value* val_ir,
std::map<Value*, DAGNode*>& value_to_node,
std::vector<std::unique_ptr<DAGNode>>& nodes_storage
) {
// 空指针错误处理
if (val_ir == nullptr) {
throw std::runtime_error("get_operand_node received a null Value.");
}
// 规则1如果这个Value已经有对应的节点直接返回
if (value_to_node.count(val_ir)) {
return value_to_node[val_ir];
}
if (auto const_val = dynamic_cast<ConstantValue*>(val_ir)) {
if (const_val->isInt()) {
return create_node(DAGNode::CONSTANT, val_ir, value_to_node, nodes_storage);
} else {
// 为浮点常量创建新的FP_CONSTANT节点
return create_node(DAGNode::FP_CONSTANT, val_ir, value_to_node, nodes_storage);
}
}
if (dynamic_cast<GlobalValue*>(val_ir)) {
return create_node(DAGNode::CONSTANT, val_ir, value_to_node, nodes_storage);
}
if (dynamic_cast<AllocaInst*>(val_ir)) {
return create_node(DAGNode::ALLOCA_ADDR, val_ir, value_to_node, nodes_storage);
}
if (dynamic_cast<Argument*>(val_ir)) {
return create_node(DAGNode::ARGUMENT, val_ir, value_to_node, nodes_storage);
}
if (dynamic_cast<ConstantVariable*>(val_ir)) {
// 全局常量数组和全局变量类似,在指令选择层面都表现为一个常量地址
// 因此也为它创建一个 CONSTANT 类型的节点
return create_node(DAGNode::CONSTANT, val_ir, value_to_node, nodes_storage);
}
// 如果代码执行到这里意味着val_ir不是上述任何一种叶子节点
// 且它也不是在当前基本块中定义的否则它会在value_to_node中被找到
// 这说明它是一个来自前驱块的Live-In值。
// 我们将其视为一个与函数参数(Argument)类似的“块输入值”并为它创建一个ARGUMENT节点。
// 这样,后续的指令选择逻辑就知道这个值是直接可用的,无需在当前块内计算。
if (dynamic_cast<Instruction*>(val_ir)) {
return create_node(DAGNode::ARGUMENT, val_ir, value_to_node, nodes_storage);
}
// 如果一个Value不是任何已知类型也不是指令那说明出现了未处理的情况抛出异常。
throw std::runtime_error("Unhandled Value type in get_operand_node for value named: " + val_ir->getName());
}
std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicBlock* bb) {
std::vector<std::unique_ptr<DAGNode>> nodes_storage;
std::map<Value*, DAGNode*> value_to_node;
for (const auto& inst_ptr : bb->getInstructions()) {
Instruction* inst = inst_ptr.get();
if (auto alloca = dynamic_cast<AllocaInst*>(inst)) {
create_node(DAGNode::ALLOCA_ADDR, alloca, value_to_node, nodes_storage);
} else if (auto store = dynamic_cast<StoreInst*>(inst)) {
auto store_node = create_node(DAGNode::STORE, store, value_to_node, nodes_storage);
store_node->operands.push_back(get_operand_node(store->getValue(), value_to_node, nodes_storage));
store_node->operands.push_back(get_operand_node(store->getPointer(), value_to_node, nodes_storage));
} else if (auto memset = dynamic_cast<MemsetInst*>(inst)) {
auto memset_node = create_node(DAGNode::MEMSET, memset, value_to_node, nodes_storage);
memset_node->operands.push_back(get_operand_node(memset->getPointer(), value_to_node, nodes_storage));
memset_node->operands.push_back(get_operand_node(memset->getBegin(), value_to_node, nodes_storage));
memset_node->operands.push_back(get_operand_node(memset->getSize(), value_to_node, nodes_storage));
memset_node->operands.push_back(get_operand_node(memset->getValue(), value_to_node, nodes_storage));
if (DEBUG) {
std::cout << "[DEBUG] build_dag: Created MEMSET node for: " << memset->getName() << std::endl;
for (size_t i = 0; i < memset_node->operands.size(); ++i) {
std::cout << " -> Operand " << i << " has kind: " << memset_node->operands[i]->kind << std::endl;
}
}
} else if (auto gep = dynamic_cast<GetElementPtrInst*>(inst)) {
// 如果这个GEP指令已经创建过节点则跳过
if(value_to_node.count(gep)) continue;
// 创建一个新的 GET_ELEMENT_PTR 类型的节点
auto gep_node = create_node(DAGNode::GET_ELEMENT_PTR, gep, value_to_node, nodes_storage);
// 第一个操作数是基指针(即数组本身)
gep_node->operands.push_back(get_operand_node(gep->getBasePointer(), value_to_node, nodes_storage));
// 依次添加所有索引作为后续的操作数
for (auto index : gep->getIndices()) {
// 从 Use 对象中获取真正的 Value*
gep_node->operands.push_back(get_operand_node(index->getValue(), value_to_node, nodes_storage));
}
} else if (auto load = dynamic_cast<LoadInst*>(inst)) {
auto load_node = create_node(DAGNode::LOAD, load, value_to_node, nodes_storage);
load_node->operands.push_back(get_operand_node(load->getPointer(), value_to_node, nodes_storage));
} else if (auto bin = dynamic_cast<BinaryInst*>(inst)) {
if(value_to_node.count(bin)) continue;
if (bin->getKind() == Instruction::kFSub) {
if (auto const_lhs = dynamic_cast<ConstantValue*>(bin->getLhs())) {
// 使用isZero()来判断浮点数0.0,比直接比较更健壮
if (const_lhs->isZero()) {
// 这是一个浮点取负操作,创建 FUNARY 节点
auto funary_node = create_node(DAGNode::FUNARY, bin, value_to_node, nodes_storage);
funary_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
continue; // 处理完毕,跳到下一条指令
}
}
}
if (bin->getKind() == BinaryInst::kSub) {
if (auto const_lhs = dynamic_cast<ConstantValue*>(bin->getLhs())) {
if (const_lhs->getInt() == 0) {
auto unary_node = create_node(DAGNode::UNARY, bin, value_to_node, nodes_storage);
unary_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
continue;
}
}
}
if (bin->isFPBinary()) { // 假设浮点指令枚举值更大
auto fbin_node = create_node(DAGNode::FBINARY, bin, value_to_node, nodes_storage);
fbin_node->operands.push_back(get_operand_node(bin->getLhs(), value_to_node, nodes_storage));
fbin_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
} else {
auto bin_node = create_node(DAGNode::BINARY, bin, value_to_node, nodes_storage);
bin_node->operands.push_back(get_operand_node(bin->getLhs(), value_to_node, nodes_storage));
bin_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
}
} else if (auto un = dynamic_cast<UnaryInst*>(inst)) {
if(value_to_node.count(un)) continue;
if (un->getKind() >= Instruction::kFNeg) {
auto funary_node = create_node(DAGNode::FUNARY, un, value_to_node, nodes_storage);
funary_node->operands.push_back(get_operand_node(un->getOperand(), value_to_node, nodes_storage));
} else {
auto unary_node = create_node(DAGNode::UNARY, un, value_to_node, nodes_storage);
unary_node->operands.push_back(get_operand_node(un->getOperand(), value_to_node, nodes_storage));
}
} else if (auto call = dynamic_cast<CallInst*>(inst)) {
if(value_to_node.count(call)) continue;
auto call_node = create_node(DAGNode::CALL, call, value_to_node, nodes_storage);
for (auto arg : call->getArguments()) {
call_node->operands.push_back(get_operand_node(arg->getValue(), value_to_node, nodes_storage));
}
} else if (auto ret = dynamic_cast<ReturnInst*>(inst)) {
auto ret_node = create_node(DAGNode::RETURN, ret, value_to_node, nodes_storage);
if (ret->hasReturnValue()) {
ret_node->operands.push_back(get_operand_node(ret->getReturnValue(), value_to_node, nodes_storage));
}
} else if (auto cond_br = dynamic_cast<CondBrInst*>(inst)) {
auto br_node = create_node(DAGNode::BRANCH, cond_br, value_to_node, nodes_storage);
br_node->operands.push_back(get_operand_node(cond_br->getCondition(), value_to_node, nodes_storage));
} else if (auto uncond_br = dynamic_cast<UncondBrInst*>(inst)) {
create_node(DAGNode::BRANCH, uncond_br, value_to_node, nodes_storage);
}
}
return nodes_storage;
}
/**
* @brief 计算一个类型在内存中占用的字节数。
* @param type 需要计算大小的IR类型。
* @return 该类型占用的字节数。
*/
unsigned RISCv64ISel::getTypeSizeInBytes(Type* type) {
if (!type) {
assert(false && "Cannot get size of a null type.");
return 0;
}
switch (type->getKind()) {
// 对于SysY语言基本类型int和float都占用4字节
case Type::kInt:
case Type::kFloat:
return 4;
// 指针类型在RISC-V 64位架构下占用8字节
// 虽然SysY没有'int*'语法但数组变量在IR层面本身就是指针类型
case Type::kPointer:
return 8;
// 数组类型的总大小 = 元素数量 * 单个元素的大小
case Type::kArray: {
auto arrayType = type->as<ArrayType>();
// 递归调用以计算元素大小
return arrayType->getNumElements() * getTypeSizeInBytes(arrayType->getElementType());
}
// 其他类型如Void, Label等不占用栈空间或者不应该出现在这里
default:
// 如果遇到未处理的类型,触发断言,方便调试
assert(false && "Unsupported type for size calculation.");
return 0;
}
}
// 打印DAG图以供调试的辅助函数
void RISCv64ISel::print_dag(const std::vector<std::unique_ptr<DAGNode>>& dag, const std::string& bb_name) {
// 检查是否有DEBUG宏或者全局变量避免在非调试模式下打印
// if (!DEBUG) return;
std::cerr << "=== DAG for Basic Block: " << bb_name << " ===\n";
std::set<DAGNode*> visited;
// 为节点分配临时ID方便阅读
std::map<DAGNode*, int> node_to_id;
int current_id = 0;
for (const auto& node_ptr : dag) {
node_to_id[node_ptr.get()] = current_id++;
}
// 将NodeKind枚举转换为字符串的辅助函数
auto get_kind_string = [](DAGNode::NodeKind kind) {
switch (kind) {
case DAGNode::ARGUMENT: return "ARGUMENT";
case DAGNode::CONSTANT: return "CONSTANT";
case DAGNode::LOAD: return "LOAD";
case DAGNode::STORE: return "STORE";
case DAGNode::BINARY: return "BINARY";
case DAGNode::CALL: return "CALL";
case DAGNode::RETURN: return "RETURN";
case DAGNode::BRANCH: return "BRANCH";
case DAGNode::ALLOCA_ADDR: return "ALLOCA_ADDR";
case DAGNode::UNARY: return "UNARY";
case DAGNode::MEMSET: return "MEMSET";
case DAGNode::GET_ELEMENT_PTR: return "GET_ELEMENT_PTR";
default: return "UNKNOWN";
}
};
// 递归打印节点的lambda表达式
std::function<void(DAGNode*, int)> print_node =
[&](DAGNode* node, int indent) {
if (!node) return;
std::string current_indent(indent, ' ');
int node_id = node_to_id.count(node) ? node_to_id[node] : -1;
std::cerr << current_indent << "Node#" << node_id << ": " << get_kind_string(node->kind);
// 尝试打印关联的虚拟寄存器
if (node->value && vreg_map.count(node->value)) {
std::cerr << " (vreg: %vreg" << vreg_map.at(node->value) << ")";
}
// 打印关联的IR Value信息
if (node->value) {
std::cerr << " [";
if (auto inst = dynamic_cast<Instruction*>(node->value)) {
std::cerr << inst->getKindString();
if (!inst->getName().empty()) {
std::cerr << "(" << inst->getName() << ")";
}
} else if (auto constant = dynamic_cast<ConstantValue*>(node->value)) {
std::cerr << "Const(" << constant->getInt() << ")";
} else if (auto global = dynamic_cast<GlobalValue*>(node->value)) {
std::cerr << "Global(" << global->getName() << ")";
} else if (auto alloca = dynamic_cast<AllocaInst*>(node->value)) {
std::cerr << "Alloca(" << alloca->getName() << ")";
}
std::cerr << "]";
}
std::cerr << "\n";
if (visited.count(node)) {
std::cerr << current_indent << " (已打印过子节点)\n";
return;
}
visited.insert(node);
if (!node->operands.empty()) {
std::cerr << current_indent << " Operands:\n";
for (auto operand : node->operands) {
print_node(operand, indent + 4);
}
}
};
// 从根节点(没有用户的节点,或有副作用的节点)开始打印
for (const auto& node_ptr : dag) {
if (node_ptr->users.empty() ||
node_ptr->kind == DAGNode::STORE ||
node_ptr->kind == DAGNode::RETURN ||
node_ptr->kind == DAGNode::BRANCH ||
node_ptr->kind == DAGNode::MEMSET)
{
print_node(node_ptr.get(), 0);
}
}
std::cerr << "======================================\n\n";
}
unsigned int RISCv64ISel::getVRegCounter() const {
return vreg_counter;
}
} // namespace sysy