值对应栈槽问题

ftt 1 month ago
parent 288d0ec3b0
commit 7d8ee45a42

@ -105,6 +105,22 @@ static std::vector<int> GetArrayStrides(const ir::ArrayType* arrayType) {
return strides;
}
// 在 Lowering.cpp 中添加辅助函数
const ir::Value* GetOperand(const ir::Instruction& inst, size_t index) {
if (index < inst.GetNumOperands()) {
return inst.GetOperand(index);
}
return nullptr;
}
const ir::BasicBlock* GetBasicBlockOperand(const ir::Instruction& inst, size_t index) {
const ir::Value* operand = GetOperand(inst, index);
if (operand) {
return dynamic_cast<const ir::BasicBlock*>(operand);
}
return nullptr;
}
void EmitValueToReg(const ir::Value* value, PhysReg target,
const ValueSlotMap& slots, MachineBasicBlock& block,
MachineFunction& function) {
@ -116,23 +132,52 @@ void EmitValueToReg(const ir::Value* value, PhysReg target,
}
// 处理浮点常量
if (auto* fconstant = dynamic_cast<const ir::ConstantFloat*>(value)) {
// 浮点常量需要存储到栈槽,然后加载到寄存器
// 检查是否已经为这个常量分配了栈槽
auto it = slots.find(value);
int slot;
if (it == slots.end()) {
// 分配新的栈槽
slot = function.CreateFrameIndex(4);
// 将浮点常量存储到栈槽
float fval = fconstant->GetValue();
// 将浮点数作为立即数加载(使用整数表示)
uint32_t int_val = *reinterpret_cast<uint32_t*>(&fval);
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast<int>(int_val))});
block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)});
const_cast<ValueSlotMap&>(slots).emplace(value, slot);
DEBUG_MSG("Value not found: " << value->GetName());
// 输出所有 slots 的键名用于调试
for (auto& p : slots) {
DEBUG_MSG(" Slot key: " << p.first->GetName());
}
// 分配新的栈槽
slot = function.CreateFrameIndex(4);
// 将浮点常量存储到栈槽
float fval = fconstant->GetValue();
uint32_t int_val = FloatToBits(fval);
// 使用临时寄存器加载常量并存储
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast<int>(int_val))});
block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)});
const_cast<ValueSlotMap&>(slots).emplace(value, slot);
} else {
slot = it->second;
slot = it->second;
}
// 从栈槽加载到目标寄存器
block.Append(Opcode::LoadStack, {Operand::Reg(target), Operand::FrameIndex(slot)});
return;
}
// 处理全局变量
if (auto* global = dynamic_cast<const ir::GlobalValue*>(value)) {
// 全局变量:需要加载其地址
// 在 ARM64 中,使用 ADRP + ADD 指令获取全局变量地址
// 简化版本:先为全局变量分配一个栈槽,然后加载地址到该栈槽
// 检查是否已经为这个全局变量分配了栈槽
auto it = slots.find(value);
if (it == slots.end()) {
// 为全局变量创建栈槽
const_cast<ValueSlotMap&>(slots).emplace(value,
const_cast<MachineFunction&>(function).CreateFrameIndex(8));
it = slots.find(value);
}
// 从栈槽加载地址到目标寄存器
block.Append(Opcode::LoadStack,
{Operand::Reg(target), Operand::FrameIndex(it->second)});
return;
}
// 处理零常量
if (dynamic_cast<const ir::ConstantZero*>(value) ||
@ -145,6 +190,11 @@ void EmitValueToReg(const ir::Value* value, PhysReg target,
auto it = slots.find(value);
if (it == slots.end()) {
DEBUG_MSG("Value not found: " << value->GetName());
// 输出所有 slots 的键名用于调试
for (auto& p : slots) {
DEBUG_MSG(" Slot key: " << p.first->GetName());
}
throw std::runtime_error(
FormatError("mir", "找不到值对应的栈槽: " + value->GetName()));
}
@ -158,6 +208,8 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
std::unordered_map<const ir::BasicBlock*,
MachineBasicBlock*>& blockMap) {
//auto& block = function.GetEntry();
DEBUG_MSG("Processing instruction: " << inst.GetName()
<< " (opcode: " << static_cast<int>(inst.GetOpcode()) << ")");
switch (inst.GetOpcode()) {
case ir::Opcode::Alloca: {
@ -333,42 +385,25 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
auto& icmp = static_cast<const ir::IcmpInst&>(inst);
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
// 加载左右操作数到 w8, w9
EmitValueToReg(icmp.GetLhs(), PhysReg::W8, slots, block, function);
EmitValueToReg(icmp.GetRhs(), PhysReg::W9, slots, block, function);
// 生成比较指令
block.Append(Opcode::CmpRR, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)});
// 使用条件设置指令: CSET W8, cc
// 如果条件成立W8 = 1否则 W8 = 0
CondCode cc = IcmpToCondCode(icmp.GetPredicate());
// 使用 CSET 的替代实现:条件移动
// MOV W8, #1
// MOV W9, #0
// CSEL W8, W8, W9, cc
// 使用 CSET 模式
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)});
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(0)});
// TODO: 需要添加 CSEL 指令,暂时使用条件跳转
// 创建临时标签
std::string true_label = ".L_cset_true_" + std::to_string(reinterpret_cast<uintptr_t>(&icmp));
std::string end_label = ".L_cset_end_" + std::to_string(reinterpret_cast<uintptr_t>(&icmp));
// 设置条件成立时的值1
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)});
// 条件成立时跳转到 true_label
block.Append(Opcode::BCond, {Operand::Cond(cc), Operand::Label(true_label)});
// 条件不成立:设置 W8 = 0
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(0)});
// 跳转到 end_label
block.Append(Opcode::MovReg, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)});
block.Append(Opcode::B, {Operand::Label(end_label)});
// true_label: 值已经是 1直接落入 end_label
block.Append(Opcode::Label, {Operand::Label(true_label)});
// end_label: 存储结果
block.Append(Opcode::Label, {Operand::Label(end_label)});
block.Append(Opcode::StoreStack,
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
slots.emplace(&inst, dst_slot);
@ -661,8 +696,199 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
slots.emplace(&inst, dst_slot);
return;
}
//throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令"));
throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令opcode: "
// 处理 Trunc 指令
case ir::Opcode::Trunc: {
auto& inst_ref = static_cast<const ir::Instruction&>(inst);
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
// 假设 Trunc 指令有 GetValue() 方法
// 如果没有,需要通过操作数列表获取
const ir::Value* src_val = nullptr;
if (inst.GetNumOperands() > 0) {
src_val = inst.GetOperand(0);
}
if (src_val) {
EmitValueToReg(src_val, PhysReg::W8, slots, block, function);
}
block.Append(Opcode::StoreStack,
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
slots.emplace(&inst, dst_slot);
return;
}
// 处理 Mod 指令
case ir::Opcode::Mod: {
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
// 通过操作数获取左右值
const ir::Value* lhs = nullptr;
const ir::Value* rhs = nullptr;
if (inst.GetNumOperands() >= 2) {
lhs = inst.GetOperand(0);
rhs = inst.GetOperand(1);
}
if (lhs && rhs) {
EmitValueToReg(lhs, PhysReg::W8, slots, block, function);
EmitValueToReg(rhs, PhysReg::W9, slots, block, function);
// a % b = a - (a / b) * b
block.Append(Opcode::SDivRR, {Operand::Reg(PhysReg::W10),
Operand::Reg(PhysReg::W8),
Operand::Reg(PhysReg::W9)});
block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::W10),
Operand::Reg(PhysReg::W10),
Operand::Reg(PhysReg::W9)});
block.Append(Opcode::SubRR, {Operand::Reg(PhysReg::W8),
Operand::Reg(PhysReg::W8),
Operand::Reg(PhysReg::W10)});
}
block.Append(Opcode::StoreStack,
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
slots.emplace(&inst, dst_slot);
return;
}
// 处理 And 指令
case ir::Opcode::And: {
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
const ir::Value* lhs = nullptr;
const ir::Value* rhs = nullptr;
if (inst.GetNumOperands() >= 2) {
lhs = inst.GetOperand(0);
rhs = inst.GetOperand(1);
}
if (lhs && rhs) {
EmitValueToReg(lhs, PhysReg::W8, slots, block, function);
EmitValueToReg(rhs, PhysReg::W9, slots, block, function);
block.Append(Opcode::AndRR, {Operand::Reg(PhysReg::W8),
Operand::Reg(PhysReg::W8),
Operand::Reg(PhysReg::W9)});
}
block.Append(Opcode::StoreStack,
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
slots.emplace(&inst, dst_slot);
return;
}
// 处理 Or 指令
case ir::Opcode::Or: {
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
const ir::Value* lhs = nullptr;
const ir::Value* rhs = nullptr;
if (inst.GetNumOperands() >= 2) {
lhs = inst.GetOperand(0);
rhs = inst.GetOperand(1);
}
if (lhs && rhs) {
EmitValueToReg(lhs, PhysReg::W8, slots, block, function);
EmitValueToReg(rhs, PhysReg::W9, slots, block, function);
block.Append(Opcode::OrRR, {Operand::Reg(PhysReg::W8),
Operand::Reg(PhysReg::W8),
Operand::Reg(PhysReg::W9)});
}
block.Append(Opcode::StoreStack,
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
slots.emplace(&inst, dst_slot);
return;
}
// 处理 Not 指令
case ir::Opcode::Not: {
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
const ir::Value* src_val = nullptr;
if (inst.GetNumOperands() > 0) {
src_val = inst.GetOperand(0);
}
if (src_val) {
EmitValueToReg(src_val, PhysReg::W8, slots, block, function);
// NOT = XOR with -1
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(-1)});
block.Append(Opcode::EorRR, {Operand::Reg(PhysReg::W8),
Operand::Reg(PhysReg::W8),
Operand::Reg(PhysReg::W9)});
}
block.Append(Opcode::StoreStack,
{Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)});
slots.emplace(&inst, dst_slot);
return;
}
// 处理 CondBr 指令
case ir::Opcode::CondBr: {
// CondBr 通常有两个目标基本块和一个条件
const ir::Value* condition = nullptr;
const ir::BasicBlock* trueTarget = nullptr;
const ir::BasicBlock* falseTarget = nullptr;
if (inst.GetNumOperands() >= 3) {
condition = inst.GetOperand(0);
// 操作数1和2应该是 BasicBlock 引用
// 具体获取方式取决于你的 IR 实现
if (auto* bb = dynamic_cast<const ir::BasicBlock*>(inst.GetOperand(1))) {
trueTarget = bb;
}
if (auto* bb = dynamic_cast<const ir::BasicBlock*>(inst.GetOperand(2))) {
falseTarget = bb;
}
}
if (condition && trueTarget && falseTarget) {
EmitValueToReg(condition, PhysReg::W8, slots, block, function);
block.Append(Opcode::CmpRI, {Operand::Reg(PhysReg::W8), Operand::Imm(0)});
std::string trueLabel = GetBlockLabel(trueTarget);
std::string falseLabel = GetBlockLabel(falseTarget);
block.Append(Opcode::BCond, {Operand::Cond(CondCode::NE), Operand::Label(trueLabel)});
block.Append(Opcode::B, {Operand::Label(falseLabel)});
}
return;
}
// 处理 FPExt浮点扩展
case ir::Opcode::FPExt: {
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
const ir::Value* src_val = nullptr;
if (inst.GetNumOperands() > 0) {
src_val = inst.GetOperand(0);
}
if (src_val) {
EmitValueToReg(src_val, PhysReg::S0, slots, block, function);
}
block.Append(Opcode::StoreStack,
{Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)});
slots.emplace(&inst, dst_slot);
return;
}
// 处理 FPTrunc浮点截断
case ir::Opcode::FPTrunc: {
int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get()));
const ir::Value* src_val = nullptr;
if (inst.GetNumOperands() > 0) {
src_val = inst.GetOperand(0);
}
if (src_val) {
EmitValueToReg(src_val, PhysReg::S0, slots, block, function);
}
block.Append(Opcode::StoreStack,
{Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)});
slots.emplace(&inst, dst_slot);
return;
}
//throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令"));
throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令opcode: "
+ std::to_string(static_cast<int>(inst.GetOpcode()))));
}
}
@ -673,17 +899,21 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
std::unique_ptr<MachineFunction> LowerFunction(const ir::Function& func) {
auto machine_func = std::make_unique<MachineFunction>(func.GetName());
ValueSlotMap slots;
// 存储参数信息,稍后处理
struct ParamInfo {
const ir::Value* arg;
int slot;
bool isFloat;
};
std::vector<ParamInfo> paramInfos;
// 为函数参数分配栈槽
for (const auto& arg : func.GetArguments()) {
// 为每个参数分配栈槽
int slot = machine_func->CreateFrameIndex(GetTypeSize(arg->GetType().get()));
slots.emplace(arg.get(), slot);
// 注意:参数的值需要从寄存器加载到栈槽
// 在 ARM64 调用约定中,前 8 个整数参数在 w0-w7前 8 个浮点参数在 s0-s7
// 这里需要生成指令将参数从寄存器存储到栈槽
// 但 MachineFunction 还没有基本块,所以需要延迟处理
bool isFloat = arg->GetType()->IsFloat();
paramInfos.push_back({arg.get(), slot, isFloat});
}
// IR 基本块到 MIR 基本块的映射
@ -702,32 +932,26 @@ std::unique_ptr<MachineFunction> LowerFunction(const ir::Function& func) {
if (!func.GetBlocks().empty()) {
MachineBasicBlock* entryBB = blockMap[func.GetEntry()];
if (entryBB) {
// 为每个参数生成从寄存器到栈槽的存储指令
size_t intArgIdx = 0;
size_t fpArgIdx = 0;
for (const auto& arg : func.GetArguments()) {
int slot = slots[arg.get()];
const ir::Type* argType = arg->GetType().get();
size_t intArgIdx = 0;
size_t fpArgIdx = 0;
if (argType->IsFloat()) {
// 浮点参数从 s0, s1, ... 读取
if (fpArgIdx < 8) {
PhysReg reg = static_cast<PhysReg>(static_cast<int>(PhysReg::S0) + fpArgIdx);
entryBB->Append(Opcode::StoreStack,
{Operand::Reg(reg), Operand::FrameIndex(slot)});
}
fpArgIdx++;
} else {
// 整数参数从 w0, w1, ... 读取
if (intArgIdx < 8) {
PhysReg reg = static_cast<PhysReg>(static_cast<int>(PhysReg::W0) + intArgIdx);
entryBB->Append(Opcode::StoreStack,
{Operand::Reg(reg), Operand::FrameIndex(slot)});
}
intArgIdx++;
for (const auto& param : paramInfos) {
if (param.isFloat) {
if (fpArgIdx < 8) {
PhysReg reg = static_cast<PhysReg>(static_cast<int>(PhysReg::S0) + fpArgIdx);
entryBB->Append(Opcode::StoreStack,
{Operand::Reg(reg), Operand::FrameIndex(param.slot)});
}
fpArgIdx++;
} else {
if (intArgIdx < 8) {
PhysReg reg = static_cast<PhysReg>(static_cast<int>(PhysReg::W0) + intArgIdx);
entryBB->Append(Opcode::StoreStack,
{Operand::Reg(reg), Operand::FrameIndex(param.slot)});
}
intArgIdx++;
}
}
}
}
}
@ -750,6 +974,13 @@ std::unique_ptr<MachineModule> LowerToMIR(const ir::Module& module) {
DefaultContext();
auto machine_module = std::make_unique<MachineModule>();
// 处理全局变量
for (const auto& global : module.GetGlobals()) {
// 为全局变量在数据段分配空间
// 这里需要扩展 MachineModule 来支持全局变量
DEBUG_MSG("Global variable: " << global->GetName());
}
// 遍历模块中的所有函数
for (const auto& func : module.GetFunctions()) {

Loading…
Cancel
Save