|
|
|
|
@ -7,13 +7,13 @@
|
|
|
|
|
#include "ir/IR.h"
|
|
|
|
|
#include "utils/Log.h"
|
|
|
|
|
|
|
|
|
|
//#define DEBUG_Lower
|
|
|
|
|
#define DEBUG_Lower
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_Lower
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#define DEBUG_MSG(msg) std::cerr << "[Lower Debug] " << msg << std::endl
|
|
|
|
|
#else
|
|
|
|
|
#define DEBUG_MSG(msg)
|
|
|
|
|
#define DEBUG_MSG(msg) ((void)0)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace mir {
|
|
|
|
|
@ -655,132 +655,166 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// ========== GEP 指令(计算数组元素地址)==========
|
|
|
|
|
case ir::Opcode::GEP: {
|
|
|
|
|
auto& gep = static_cast<const ir::GEPInst&>(inst);
|
|
|
|
|
|
|
|
|
|
// GEP 返回指针类型,在 ARM64 上指针是 8 字节
|
|
|
|
|
int dst_slot = function.CreateFrameIndex(8);
|
|
|
|
|
|
|
|
|
|
// 获取基地址(数组的起始地址)
|
|
|
|
|
ir::Value* base = gep.GetBase();
|
|
|
|
|
const auto& indices = gep.GetIndices();
|
|
|
|
|
|
|
|
|
|
// 加载基地址到 x8(使用 64 位寄存器存储地址)
|
|
|
|
|
EmitValueToReg(base, PhysReg::X8, slots, block, function);
|
|
|
|
|
|
|
|
|
|
if (indices.empty()) {
|
|
|
|
|
// 没有索引,直接返回基地址
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取数组类型信息,计算每个维度的步长
|
|
|
|
|
const ir::Type* baseType = base->GetType().get();
|
|
|
|
|
|
|
|
|
|
// 如果基地址是指针类型,需要解引用获取元素类型
|
|
|
|
|
if (baseType->IsPtrInt32() || baseType->IsPtrFloat() || baseType->IsPtrInt1()) {
|
|
|
|
|
// 对于指针类型,第一个索引是偏移量(以元素为单位)
|
|
|
|
|
// 例如:int* p; p[1] 的 GEP 中 indices[0] = 1
|
|
|
|
|
if (indices.size() >= 1) {
|
|
|
|
|
// 加载索引到 x9
|
|
|
|
|
EmitValueToReg(indices[0], PhysReg::X9, slots, block, function);
|
|
|
|
|
|
|
|
|
|
// 乘以元素大小(int/float 是 4 字节)
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X10), Operand::Imm(4)});
|
|
|
|
|
block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
|
|
|
|
|
// 地址 = base + index * 4
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X9)});
|
|
|
|
|
}
|
|
|
|
|
auto& gep = static_cast<const ir::GEPInst&>(inst);
|
|
|
|
|
|
|
|
|
|
// 存储计算出的地址
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果基地址是数组类型,需要处理多维数组
|
|
|
|
|
if (baseType->IsArray()) {
|
|
|
|
|
const ir::ArrayType* arrayType = static_cast<const ir::ArrayType*>(baseType);
|
|
|
|
|
const std::vector<int>& dims = arrayType->GetDimensions();
|
|
|
|
|
DEBUG_MSG("Processing GEP instruction: " << inst.GetName());
|
|
|
|
|
|
|
|
|
|
// 计算每个维度的步长
|
|
|
|
|
std::vector<int> strides(dims.size());
|
|
|
|
|
int stride = 4; // 元素大小(int/float 是 4 字节)
|
|
|
|
|
for (int i = dims.size() - 1; i >= 0; --i) {
|
|
|
|
|
strides[i] = stride;
|
|
|
|
|
stride *= dims[i];
|
|
|
|
|
// GEP 返回指针类型,在 ARM64 上指针是 8 字节
|
|
|
|
|
int dst_slot = function.CreateFrameIndex(8);
|
|
|
|
|
|
|
|
|
|
// 获取基地址(数组的起始地址)
|
|
|
|
|
ir::Value* base = gep.GetBase();
|
|
|
|
|
const auto& indices = gep.GetIndices();
|
|
|
|
|
|
|
|
|
|
std::string baseName = base->GetName().empty() ? "unnamed" : base->GetName();
|
|
|
|
|
DEBUG_MSG("Base value: " << baseName);
|
|
|
|
|
DEBUG_MSG("Number of indices: " << indices.size());
|
|
|
|
|
|
|
|
|
|
// 打印索引值
|
|
|
|
|
for (size_t idx_i = 0; idx_i < indices.size(); ++idx_i) {
|
|
|
|
|
if (auto* const_int = dynamic_cast<const ir::ConstantInt*>(indices[idx_i])) {
|
|
|
|
|
DEBUG_MSG(" Index[" << idx_i << "] = " << const_int->GetValue() << " (constant)");
|
|
|
|
|
} else {
|
|
|
|
|
DEBUG_MSG(" Index[" << idx_i << "] = variable");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 计算总偏移量
|
|
|
|
|
// 地址 = base + index0 * stride0 + index1 * stride1 + ...
|
|
|
|
|
size_t numIndices = indices.size();
|
|
|
|
|
// 加载基地址到 x8
|
|
|
|
|
EmitValueToReg(base, PhysReg::X8, slots, block, function);
|
|
|
|
|
|
|
|
|
|
// 限制索引数量(不能超过维度数)
|
|
|
|
|
if (numIndices > dims.size()) {
|
|
|
|
|
numIndices = dims.size();
|
|
|
|
|
if (indices.empty()) {
|
|
|
|
|
DEBUG_MSG("No indices, storing base address directly");
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 加载当前地址到 x9 作为偏移量累加器
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X9), Operand::Imm(0)});
|
|
|
|
|
// 获取基地址类型
|
|
|
|
|
const ir::Type* baseType = base->GetType().get();
|
|
|
|
|
DEBUG_MSG("Base type kind: " << static_cast<int>(baseType->GetKind()));
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < numIndices; ++i) {
|
|
|
|
|
// 加载当前索引到 x10
|
|
|
|
|
EmitValueToReg(indices[i], PhysReg::X10, slots, block, function);
|
|
|
|
|
|
|
|
|
|
// 乘以步长
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X11), Operand::Imm(strides[i])});
|
|
|
|
|
block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X10),
|
|
|
|
|
Operand::Reg(PhysReg::X10),
|
|
|
|
|
Operand::Reg(PhysReg::X11)});
|
|
|
|
|
|
|
|
|
|
// 累加到偏移量
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
// 关键修改:对于数组指针类型,第一个索引是多余的,应该跳过
|
|
|
|
|
size_t start_index = 0;
|
|
|
|
|
if (baseType->IsPtrInt32() || baseType->IsPtrFloat() || baseType->IsPtrInt1()) {
|
|
|
|
|
// 对于指针类型,第一个索引是偏移量,不能跳过
|
|
|
|
|
DEBUG_MSG("Base is pointer type, using all indices for pointer arithmetic");
|
|
|
|
|
start_index = 0;
|
|
|
|
|
} else if (baseType->IsArray()) {
|
|
|
|
|
// 对于数组类型(非指针),第一个索引是多余的
|
|
|
|
|
// 因为 base 已经是数组本身,不需要再解引用
|
|
|
|
|
DEBUG_MSG("Base is array type, skipping first index (array decay)");
|
|
|
|
|
start_index = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 最终地址 = base + offset
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X9)});
|
|
|
|
|
// 如果基地址是数组类型,需要处理多维数组
|
|
|
|
|
if (baseType->IsArray()) {
|
|
|
|
|
DEBUG_MSG("Base is array type, processing multi-dimensional array");
|
|
|
|
|
const ir::ArrayType* arrayType = static_cast<const ir::ArrayType*>(baseType);
|
|
|
|
|
const std::vector<int>& dims = arrayType->GetDimensions();
|
|
|
|
|
|
|
|
|
|
DEBUG_MSG("Array dimensions: ");
|
|
|
|
|
for (size_t i = 0; i < dims.size(); ++i) {
|
|
|
|
|
DEBUG_MSG(" dim[" << i << "] = " << dims[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 正确计算每个维度的步长
|
|
|
|
|
std::vector<int> strides(dims.size());
|
|
|
|
|
int element_size = 4; // 元素大小(int/float 是 4 字节)
|
|
|
|
|
for (int i = dims.size() - 1; i >= 0; --i) {
|
|
|
|
|
if (i == static_cast<int>(dims.size()) - 1) {
|
|
|
|
|
strides[i] = element_size;
|
|
|
|
|
DEBUG_MSG("strides[" << i << "] = " << strides[i] << " (element size)");
|
|
|
|
|
} else {
|
|
|
|
|
strides[i] = strides[i + 1] * dims[i + 1];
|
|
|
|
|
DEBUG_MSG("strides[" << i << "] = " << strides[i+1] << " * " << dims[i+1]
|
|
|
|
|
<< " = " << strides[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 计算总偏移,跳过第一个索引
|
|
|
|
|
size_t numIndices = indices.size();
|
|
|
|
|
size_t effective_indices = numIndices - start_index;
|
|
|
|
|
if (effective_indices > dims.size()) {
|
|
|
|
|
DEBUG_MSG("Warning: effective indices (" << effective_indices << ") > dims.size() ("
|
|
|
|
|
<< dims.size() << "), truncating");
|
|
|
|
|
effective_indices = dims.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEBUG_MSG("Using " << effective_indices << " effective indices (starting from " << start_index << ")");
|
|
|
|
|
|
|
|
|
|
// 加载当前地址到 x9 作为偏移量累加器
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X9), Operand::Imm(0)});
|
|
|
|
|
|
|
|
|
|
// 用于调试的静态偏移计算
|
|
|
|
|
int debug_offset = 0;
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < effective_indices; ++i) {
|
|
|
|
|
size_t idx_pos = start_index + i;
|
|
|
|
|
int index_value = 0;
|
|
|
|
|
if (auto* const_int = dynamic_cast<const ir::ConstantInt*>(indices[idx_pos])) {
|
|
|
|
|
index_value = const_int->GetValue();
|
|
|
|
|
DEBUG_MSG("Index[" << idx_pos << "] = " << index_value << " (constant)");
|
|
|
|
|
debug_offset += index_value * strides[i];
|
|
|
|
|
DEBUG_MSG(" Contribution = " << index_value << " * " << strides[i]
|
|
|
|
|
<< " = " << (index_value * strides[i]));
|
|
|
|
|
DEBUG_MSG(" Running offset = " << debug_offset);
|
|
|
|
|
} else {
|
|
|
|
|
DEBUG_MSG("Index[" << idx_pos << "] = variable");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 加载当前索引到 x10
|
|
|
|
|
EmitValueToReg(indices[idx_pos], PhysReg::X10, slots, block, function);
|
|
|
|
|
|
|
|
|
|
// 乘以步长
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X11), Operand::Imm(strides[i])});
|
|
|
|
|
block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X10),
|
|
|
|
|
Operand::Reg(PhysReg::X10),
|
|
|
|
|
Operand::Reg(PhysReg::X11)});
|
|
|
|
|
|
|
|
|
|
// 累加到偏移量
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEBUG_MSG("Total computed offset = " << debug_offset);
|
|
|
|
|
|
|
|
|
|
// 最终地址 = base + offset
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X9)});
|
|
|
|
|
|
|
|
|
|
// 存储计算出的地址
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
DEBUG_MSG("Array GEP completed, result stored in slot " << dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 其他情况的处理...
|
|
|
|
|
DEBUG_MSG("Base is other type, using simple handling");
|
|
|
|
|
if (indices.size() >= 1) {
|
|
|
|
|
EmitValueToReg(indices[0], PhysReg::X9, slots, block, function);
|
|
|
|
|
|
|
|
|
|
// 乘以元素大小(默认 4 字节)
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X10), Operand::Imm(4)});
|
|
|
|
|
block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X9)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 存储计算出的地址
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
DEBUG_MSG("Simple GEP completed");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 其他情况:简单处理
|
|
|
|
|
// 只处理第一个索引
|
|
|
|
|
if (indices.size() >= 1) {
|
|
|
|
|
EmitValueToReg(indices[0], PhysReg::X9, slots, block, function);
|
|
|
|
|
|
|
|
|
|
// 乘以元素大小(默认 4 字节)
|
|
|
|
|
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X10), Operand::Imm(4)});
|
|
|
|
|
block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X9),
|
|
|
|
|
Operand::Reg(PhysReg::X10)});
|
|
|
|
|
|
|
|
|
|
block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X8),
|
|
|
|
|
Operand::Reg(PhysReg::X9)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 存储计算出的地址
|
|
|
|
|
block.Append(Opcode::StoreStack,
|
|
|
|
|
{Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)});
|
|
|
|
|
slots.emplace(&inst, dst_slot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 处理 Trunc 指令
|
|
|
|
|
case ir::Opcode::Trunc: {
|
|
|
|
|
|