diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index e6251e20..80dcf320 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -1390,28 +1390,73 @@ namespace mir } } - int addr = EmitPtrValue(load.GetPtr(), function, value_vregs, - scalar_slots, array_slots, block); - if (is_ptr) - { - int vreg = function.CreateVReg(VRegClass::Ptr); - block.Append(Opcode::LoadMem, - {Operand::VReg(vreg, VRegClass::Ptr), Operand::VReg(addr, VRegClass::Ptr)}); - value_vregs[&load] = vreg; - } - else if (is_float) + // 缩放寻址:GEP + Load → ldr [base, idx, uxtw #2] + bool scaled_load = false; + if (auto *gep = dynamic_cast(load.GetPtr())) { - int vreg = function.CreateVReg(VRegClass::Float); - block.Append(Opcode::LoadMem, - {Operand::VReg(vreg, VRegClass::Float), Operand::VReg(addr, VRegClass::Ptr)}); - value_vregs[&load] = vreg; + int idx_imm = 0; + if (!TryGetConstantInt(gep->GetIndex(), idx_imm)) + { + scaled_load = true; + int base_addr = EmitPtrValue(gep->GetBasePtr(), function, value_vregs, + scalar_slots, array_slots, block); + int idx_vreg = EmitIntValue(gep->GetIndex(), function, value_vregs, + scalar_slots, array_slots, block); + if (is_ptr) + { + int vreg = function.CreateVReg(VRegClass::Ptr); + block.Append(Opcode::LoadMem, + {Operand::VReg(vreg, VRegClass::Ptr), + Operand::VReg(base_addr, VRegClass::Ptr), + Operand::VReg(idx_vreg, VRegClass::Int)}); + value_vregs[&load] = vreg; + } + else if (is_float) + { + int vreg = function.CreateVReg(VRegClass::Float); + block.Append(Opcode::LoadMem, + {Operand::VReg(vreg, VRegClass::Float), + Operand::VReg(base_addr, VRegClass::Ptr), + Operand::VReg(idx_vreg, VRegClass::Int)}); + value_vregs[&load] = vreg; + } + else + { + int vreg = function.CreateVReg(VRegClass::Int); + block.Append(Opcode::LoadMem, + {Operand::VReg(vreg, VRegClass::Int), + Operand::VReg(base_addr, VRegClass::Ptr), + Operand::VReg(idx_vreg, VRegClass::Int)}); + value_vregs[&load] = vreg; + } + } } - else + + if (!scaled_load) { - int vreg = function.CreateVReg(VRegClass::Int); - block.Append(Opcode::LoadMem, - {Operand::VReg(vreg, VRegClass::Int), Operand::VReg(addr, VRegClass::Ptr)}); - value_vregs[&load] = vreg; + int addr = EmitPtrValue(load.GetPtr(), function, value_vregs, + scalar_slots, array_slots, block); + if (is_ptr) + { + int vreg = function.CreateVReg(VRegClass::Ptr); + block.Append(Opcode::LoadMem, + {Operand::VReg(vreg, VRegClass::Ptr), Operand::VReg(addr, VRegClass::Ptr)}); + value_vregs[&load] = vreg; + } + else if (is_float) + { + int vreg = function.CreateVReg(VRegClass::Float); + block.Append(Opcode::LoadMem, + {Operand::VReg(vreg, VRegClass::Float), Operand::VReg(addr, VRegClass::Ptr)}); + value_vregs[&load] = vreg; + } + else + { + int vreg = function.CreateVReg(VRegClass::Int); + block.Append(Opcode::LoadMem, + {Operand::VReg(vreg, VRegClass::Int), Operand::VReg(addr, VRegClass::Ptr)}); + value_vregs[&load] = vreg; + } } return; }