修改多维数组索引

ftt 4 weeks ago
parent d5a8affe83
commit 966b5b9c7f

@ -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: {

Loading…
Cancel
Save