1558 lines · cpp
1//===-- SystemZFrameLowering.cpp - Frame lowering for SystemZ -------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "SystemZFrameLowering.h"10#include "SystemZCallingConv.h"11#include "SystemZInstrInfo.h"12#include "SystemZMachineFunctionInfo.h"13#include "SystemZRegisterInfo.h"14#include "SystemZSubtarget.h"15#include "llvm/CodeGen/LivePhysRegs.h"16#include "llvm/CodeGen/MachineInstrBuilder.h"17#include "llvm/CodeGen/MachineModuleInfo.h"18#include "llvm/CodeGen/MachineRegisterInfo.h"19#include "llvm/CodeGen/RegisterScavenging.h"20#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"21#include "llvm/IR/CallingConv.h"22#include "llvm/IR/Function.h"23#include "llvm/Target/TargetMachine.h"24 25using namespace llvm;26 27namespace {28// The ABI-defined register save slots, relative to the CFA (i.e.29// incoming stack pointer + SystemZMC::ELFCallFrameSize).30static const TargetFrameLowering::SpillSlot ELFSpillOffsetTable[] = {31 { SystemZ::R2D, 0x10 },32 { SystemZ::R3D, 0x18 },33 { SystemZ::R4D, 0x20 },34 { SystemZ::R5D, 0x28 },35 { SystemZ::R6D, 0x30 },36 { SystemZ::R7D, 0x38 },37 { SystemZ::R8D, 0x40 },38 { SystemZ::R9D, 0x48 },39 { SystemZ::R10D, 0x50 },40 { SystemZ::R11D, 0x58 },41 { SystemZ::R12D, 0x60 },42 { SystemZ::R13D, 0x68 },43 { SystemZ::R14D, 0x70 },44 { SystemZ::R15D, 0x78 },45 { SystemZ::F0D, 0x80 },46 { SystemZ::F2D, 0x88 },47 { SystemZ::F4D, 0x90 },48 { SystemZ::F6D, 0x98 }49};50 51static const TargetFrameLowering::SpillSlot XPLINKSpillOffsetTable[] = {52 {SystemZ::R4D, 0x00}, {SystemZ::R5D, 0x08}, {SystemZ::R6D, 0x10},53 {SystemZ::R7D, 0x18}, {SystemZ::R8D, 0x20}, {SystemZ::R9D, 0x28},54 {SystemZ::R10D, 0x30}, {SystemZ::R11D, 0x38}, {SystemZ::R12D, 0x40},55 {SystemZ::R13D, 0x48}, {SystemZ::R14D, 0x50}, {SystemZ::R15D, 0x58}};56} // end anonymous namespace57 58SystemZFrameLowering::SystemZFrameLowering(StackDirection D, Align StackAl,59 int LAO, Align TransAl,60 bool StackReal, unsigned PointerSize)61 : TargetFrameLowering(D, StackAl, LAO, TransAl, StackReal),62 PointerSize(PointerSize) {}63 64std::unique_ptr<SystemZFrameLowering>65SystemZFrameLowering::create(const SystemZSubtarget &STI) {66 unsigned PtrSz =67 STI.getTargetLowering()->getTargetMachine().getPointerSize(0);68 if (STI.isTargetXPLINK64())69 return std::make_unique<SystemZXPLINKFrameLowering>(PtrSz);70 return std::make_unique<SystemZELFFrameLowering>(PtrSz);71}72 73namespace {74struct SZFrameSortingObj {75 bool IsValid = false; // True if we care about this Object.76 uint32_t ObjectIndex = 0; // Index of Object into MFI list.77 uint64_t ObjectSize = 0; // Size of Object in bytes.78 uint32_t D12Count = 0; // 12-bit displacement only.79 uint32_t DPairCount = 0; // 12 or 20 bit displacement.80};81typedef std::vector<SZFrameSortingObj> SZFrameObjVec;82} // namespace83 84// TODO: Move to base class.85void SystemZELFFrameLowering::orderFrameObjects(86 const MachineFunction &MF, SmallVectorImpl<int> &ObjectsToAllocate) const {87 const MachineFrameInfo &MFI = MF.getFrameInfo();88 auto *TII = MF.getSubtarget<SystemZSubtarget>().getInstrInfo();89 90 // Make a vector of sorting objects to track all MFI objects and mark those91 // to be sorted as valid.92 if (ObjectsToAllocate.size() <= 1)93 return;94 SZFrameObjVec SortingObjects(MFI.getObjectIndexEnd());95 for (auto &Obj : ObjectsToAllocate) {96 SortingObjects[Obj].IsValid = true;97 SortingObjects[Obj].ObjectIndex = Obj;98 SortingObjects[Obj].ObjectSize = MFI.getObjectSize(Obj);99 }100 101 // Examine uses for each object and record short (12-bit) and "pair"102 // displacement types.103 for (auto &MBB : MF)104 for (auto &MI : MBB) {105 if (MI.isDebugInstr())106 continue;107 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {108 const MachineOperand &MO = MI.getOperand(I);109 if (!MO.isFI())110 continue;111 int Index = MO.getIndex();112 if (Index >= 0 && Index < MFI.getObjectIndexEnd() &&113 SortingObjects[Index].IsValid) {114 if (TII->hasDisplacementPairInsn(MI.getOpcode()))115 SortingObjects[Index].DPairCount++;116 else if (!(MI.getDesc().TSFlags & SystemZII::Has20BitOffset))117 SortingObjects[Index].D12Count++;118 }119 }120 }121 122 // Sort all objects for short/paired displacements, which should be123 // sufficient as it seems like all frame objects typically are within the124 // long displacement range. Sorting works by computing the "density" as125 // Count / ObjectSize. The comparisons of two such fractions are refactored126 // by multiplying both sides with A.ObjectSize * B.ObjectSize, in order to127 // eliminate the (fp) divisions. A higher density object needs to go after128 // in the list in order for it to end up lower on the stack.129 auto CmpD12 = [](const SZFrameSortingObj &A, const SZFrameSortingObj &B) {130 // Put all invalid and variable sized objects at the end.131 if (!A.IsValid || !B.IsValid)132 return A.IsValid;133 if (!A.ObjectSize || !B.ObjectSize)134 return A.ObjectSize > 0;135 uint64_t ADensityCmp = A.D12Count * B.ObjectSize;136 uint64_t BDensityCmp = B.D12Count * A.ObjectSize;137 if (ADensityCmp != BDensityCmp)138 return ADensityCmp < BDensityCmp;139 return A.DPairCount * B.ObjectSize < B.DPairCount * A.ObjectSize;140 };141 llvm::stable_sort(SortingObjects, CmpD12);142 143 // Now modify the original list to represent the final order that144 // we want.145 unsigned Idx = 0;146 for (auto &Obj : SortingObjects) {147 // All invalid items are sorted at the end, so it's safe to stop.148 if (!Obj.IsValid)149 break;150 ObjectsToAllocate[Idx++] = Obj.ObjectIndex;151 }152}153 154bool SystemZFrameLowering::hasReservedCallFrame(155 const MachineFunction &MF) const {156 // The ELF ABI requires us to allocate 160 bytes of stack space for the157 // callee, with any outgoing stack arguments being placed above that. It158 // seems better to make that area a permanent feature of the frame even if159 // we're using a frame pointer. Similarly, 64-bit XPLINK requires 96 bytes160 // of stack space for the register save area.161 return true;162}163 164bool SystemZELFFrameLowering::assignCalleeSavedSpillSlots(165 MachineFunction &MF, const TargetRegisterInfo *TRI,166 std::vector<CalleeSavedInfo> &CSI) const {167 SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();168 MachineFrameInfo &MFFrame = MF.getFrameInfo();169 bool IsVarArg = MF.getFunction().isVarArg();170 if (CSI.empty())171 return true; // Early exit if no callee saved registers are modified!172 173 unsigned LowGPR = 0;174 unsigned HighGPR = SystemZ::R15D;175 int StartSPOffset = SystemZMC::ELFCallFrameSize;176 for (auto &CS : CSI) {177 MCRegister Reg = CS.getReg();178 int Offset = getRegSpillOffset(MF, Reg);179 if (Offset) {180 if (SystemZ::GR64BitRegClass.contains(Reg) && StartSPOffset > Offset) {181 LowGPR = Reg;182 StartSPOffset = Offset;183 }184 Offset -= SystemZMC::ELFCallFrameSize;185 int FrameIdx =186 MFFrame.CreateFixedSpillStackObject(getPointerSize(), Offset);187 CS.setFrameIdx(FrameIdx);188 } else189 CS.setFrameIdx(INT32_MAX);190 }191 192 // Save the range of call-saved registers, for use by the193 // prologue/epilogue inserters.194 ZFI->setRestoreGPRRegs(LowGPR, HighGPR, StartSPOffset);195 if (IsVarArg) {196 // Also save the GPR varargs, if any. R6D is call-saved, so would197 // already be included, but we also need to handle the call-clobbered198 // argument registers.199 Register FirstGPR = ZFI->getVarArgsFirstGPR();200 if (FirstGPR < SystemZ::ELFNumArgGPRs) {201 unsigned Reg = SystemZ::ELFArgGPRs[FirstGPR];202 int Offset = getRegSpillOffset(MF, Reg);203 if (StartSPOffset > Offset) {204 LowGPR = Reg; StartSPOffset = Offset;205 }206 }207 }208 ZFI->setSpillGPRRegs(LowGPR, HighGPR, StartSPOffset);209 210 // Create fixed stack objects for the remaining registers.211 int CurrOffset = -SystemZMC::ELFCallFrameSize;212 if (usePackedStack(MF))213 CurrOffset += StartSPOffset;214 215 for (auto &CS : CSI) {216 if (CS.getFrameIdx() != INT32_MAX)217 continue;218 MCRegister Reg = CS.getReg();219 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);220 unsigned Size = TRI->getSpillSize(*RC);221 CurrOffset -= Size;222 assert(CurrOffset % 8 == 0 &&223 "8-byte alignment required for for all register save slots");224 int FrameIdx = MFFrame.CreateFixedSpillStackObject(Size, CurrOffset);225 CS.setFrameIdx(FrameIdx);226 }227 228 return true;229}230 231void SystemZELFFrameLowering::determineCalleeSaves(MachineFunction &MF,232 BitVector &SavedRegs,233 RegScavenger *RS) const {234 TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);235 236 MachineFrameInfo &MFFrame = MF.getFrameInfo();237 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();238 bool HasFP = hasFP(MF);239 SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();240 bool IsVarArg = MF.getFunction().isVarArg();241 242 // va_start stores incoming FPR varargs in the normal way, but delegates243 // the saving of incoming GPR varargs to spillCalleeSavedRegisters().244 // Record these pending uses, which typically include the call-saved245 // argument register R6D.246 if (IsVarArg)247 for (unsigned I = MFI->getVarArgsFirstGPR(); I < SystemZ::ELFNumArgGPRs; ++I)248 SavedRegs.set(SystemZ::ELFArgGPRs[I]);249 250 // If there are any landing pads, entering them will modify r6/r7.251 if (!MF.getLandingPads().empty()) {252 SavedRegs.set(SystemZ::R6D);253 SavedRegs.set(SystemZ::R7D);254 }255 256 // If the function requires a frame pointer, record that the hard257 // frame pointer will be clobbered.258 if (HasFP)259 SavedRegs.set(SystemZ::R11D);260 261 // If the function calls other functions, record that the return262 // address register will be clobbered.263 if (MFFrame.hasCalls())264 SavedRegs.set(SystemZ::R14D);265 266 // If we are saving GPRs other than the stack pointer, we might as well267 // save and restore the stack pointer at the same time, via STMG and LMG.268 // This allows the deallocation to be done by the LMG, rather than needing269 // a separate %r15 addition.270 const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF);271 for (unsigned I = 0; CSRegs[I]; ++I) {272 unsigned Reg = CSRegs[I];273 if (SystemZ::GR64BitRegClass.contains(Reg) && SavedRegs.test(Reg)) {274 SavedRegs.set(SystemZ::R15D);275 break;276 }277 }278}279 280SystemZELFFrameLowering::SystemZELFFrameLowering(unsigned PointerSize)281 : SystemZFrameLowering(TargetFrameLowering::StackGrowsDown, Align(8), 0,282 Align(8), /* StackRealignable */ false, PointerSize),283 RegSpillOffsets(0) {284 285 // Due to the SystemZ ABI, the DWARF CFA (Canonical Frame Address) is not286 // equal to the incoming stack pointer, but to incoming stack pointer plus287 // 160. Instead of using a Local Area Offset, the Register save area will288 // be occupied by fixed frame objects, and all offsets are actually289 // relative to CFA.290 291 // Create a mapping from register number to save slot offset.292 // These offsets are relative to the start of the register save area.293 RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);294 for (const auto &Entry : ELFSpillOffsetTable)295 RegSpillOffsets[Entry.Reg] = Entry.Offset;296}297 298// Add GPR64 to the save instruction being built by MIB, which is in basic299// block MBB. IsImplicit says whether this is an explicit operand to the300// instruction, or an implicit one that comes between the explicit start301// and end registers.302static void addSavedGPR(MachineBasicBlock &MBB, MachineInstrBuilder &MIB,303 unsigned GPR64, bool IsImplicit) {304 const TargetRegisterInfo *RI =305 MBB.getParent()->getSubtarget().getRegisterInfo();306 Register GPR32 = RI->getSubReg(GPR64, SystemZ::subreg_l32);307 bool IsLive = MBB.isLiveIn(GPR64) || MBB.isLiveIn(GPR32);308 if (!IsLive || !IsImplicit) {309 MIB.addReg(GPR64, getImplRegState(IsImplicit) | getKillRegState(!IsLive));310 if (!IsLive)311 MBB.addLiveIn(GPR64);312 }313}314 315bool SystemZELFFrameLowering::spillCalleeSavedRegisters(316 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,317 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {318 if (CSI.empty())319 return false;320 321 MachineFunction &MF = *MBB.getParent();322 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();323 SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();324 bool IsVarArg = MF.getFunction().isVarArg();325 DebugLoc DL;326 327 // Save GPRs328 SystemZ::GPRRegs SpillGPRs = ZFI->getSpillGPRRegs();329 if (SpillGPRs.LowGPR) {330 assert(SpillGPRs.LowGPR != SpillGPRs.HighGPR &&331 "Should be saving %r15 and something else");332 333 // Build an STMG instruction.334 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG));335 336 // Add the explicit register operands.337 addSavedGPR(MBB, MIB, SpillGPRs.LowGPR, false);338 addSavedGPR(MBB, MIB, SpillGPRs.HighGPR, false);339 340 // Add the address.341 MIB.addReg(SystemZ::R15D).addImm(SpillGPRs.GPROffset);342 343 // Make sure all call-saved GPRs are included as operands and are344 // marked as live on entry.345 for (const CalleeSavedInfo &I : CSI) {346 MCRegister Reg = I.getReg();347 if (SystemZ::GR64BitRegClass.contains(Reg))348 addSavedGPR(MBB, MIB, Reg, true);349 }350 351 // ...likewise GPR varargs.352 if (IsVarArg)353 for (unsigned I = ZFI->getVarArgsFirstGPR(); I < SystemZ::ELFNumArgGPRs; ++I)354 addSavedGPR(MBB, MIB, SystemZ::ELFArgGPRs[I], true);355 }356 357 // Save FPRs/VRs in the normal TargetInstrInfo way.358 for (const CalleeSavedInfo &I : CSI) {359 MCRegister Reg = I.getReg();360 if (SystemZ::FP64BitRegClass.contains(Reg)) {361 MBB.addLiveIn(Reg);362 TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),363 &SystemZ::FP64BitRegClass, Register());364 }365 if (SystemZ::VR128BitRegClass.contains(Reg)) {366 MBB.addLiveIn(Reg);367 TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),368 &SystemZ::VR128BitRegClass, Register());369 }370 }371 372 return true;373}374 375bool SystemZELFFrameLowering::restoreCalleeSavedRegisters(376 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,377 MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {378 if (CSI.empty())379 return false;380 381 MachineFunction &MF = *MBB.getParent();382 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();383 SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();384 bool HasFP = hasFP(MF);385 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();386 387 // Restore FPRs/VRs in the normal TargetInstrInfo way.388 for (const CalleeSavedInfo &I : CSI) {389 MCRegister Reg = I.getReg();390 if (SystemZ::FP64BitRegClass.contains(Reg))391 TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),392 &SystemZ::FP64BitRegClass, Register());393 if (SystemZ::VR128BitRegClass.contains(Reg))394 TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),395 &SystemZ::VR128BitRegClass, Register());396 }397 398 // Restore call-saved GPRs (but not call-clobbered varargs, which at399 // this point might hold return values).400 SystemZ::GPRRegs RestoreGPRs = ZFI->getRestoreGPRRegs();401 if (RestoreGPRs.LowGPR) {402 // If we saved any of %r2-%r5 as varargs, we should also be saving403 // and restoring %r6. If we're saving %r6 or above, we should be404 // restoring it too.405 assert(RestoreGPRs.LowGPR != RestoreGPRs.HighGPR &&406 "Should be loading %r15 and something else");407 408 // Build an LMG instruction.409 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG));410 411 // Add the explicit register operands.412 MIB.addReg(RestoreGPRs.LowGPR, RegState::Define);413 MIB.addReg(RestoreGPRs.HighGPR, RegState::Define);414 415 // Add the address.416 MIB.addReg(HasFP ? SystemZ::R11D : SystemZ::R15D);417 MIB.addImm(RestoreGPRs.GPROffset);418 419 // Do a second scan adding regs as being defined by instruction420 for (const CalleeSavedInfo &I : CSI) {421 MCRegister Reg = I.getReg();422 if (Reg != RestoreGPRs.LowGPR && Reg != RestoreGPRs.HighGPR &&423 SystemZ::GR64BitRegClass.contains(Reg))424 MIB.addReg(Reg, RegState::ImplicitDefine);425 }426 }427 428 return true;429}430 431void SystemZELFFrameLowering::processFunctionBeforeFrameFinalized(432 MachineFunction &MF, RegScavenger *RS) const {433 MachineFrameInfo &MFFrame = MF.getFrameInfo();434 SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();435 MachineRegisterInfo *MRI = &MF.getRegInfo();436 bool BackChain = MF.getSubtarget<SystemZSubtarget>().hasBackChain();437 438 if (!usePackedStack(MF) || BackChain)439 // Create the incoming register save area.440 getOrCreateFramePointerSaveIndex(MF);441 442 // Get the size of our stack frame to be allocated ...443 uint64_t StackSize = (MFFrame.estimateStackSize(MF) +444 SystemZMC::ELFCallFrameSize);445 // ... and the maximum offset we may need to reach into the446 // caller's frame to access the save area or stack arguments.447 int64_t MaxArgOffset = 0;448 for (int I = MFFrame.getObjectIndexBegin(); I != 0; ++I)449 if (MFFrame.getObjectOffset(I) >= 0) {450 int64_t ArgOffset = MFFrame.getObjectOffset(I) +451 MFFrame.getObjectSize(I);452 MaxArgOffset = std::max(MaxArgOffset, ArgOffset);453 }454 455 uint64_t MaxReach = StackSize + MaxArgOffset;456 if (!isUInt<12>(MaxReach)) {457 // We may need register scavenging slots if some parts of the frame458 // are outside the reach of an unsigned 12-bit displacement.459 // Create 2 for the case where both addresses in an MVC are460 // out of range.461 RS->addScavengingFrameIndex(462 MFFrame.CreateSpillStackObject(getPointerSize(), Align(8)));463 RS->addScavengingFrameIndex(464 MFFrame.CreateSpillStackObject(getPointerSize(), Align(8)));465 }466 467 // If R6 is used as an argument register it is still callee saved. If it in468 // this case is not clobbered (and restored) it should never be marked as469 // killed.470 if (MF.front().isLiveIn(SystemZ::R6D) &&471 ZFI->getRestoreGPRRegs().LowGPR != SystemZ::R6D)472 for (auto &MO : MRI->use_nodbg_operands(SystemZ::R6D))473 MO.setIsKill(false);474}475 476// Emit instructions before MBBI (in MBB) to add NumBytes to Reg.477static void emitIncrement(MachineBasicBlock &MBB,478 MachineBasicBlock::iterator &MBBI, const DebugLoc &DL,479 Register Reg, int64_t NumBytes,480 const TargetInstrInfo *TII) {481 while (NumBytes) {482 unsigned Opcode;483 int64_t ThisVal = NumBytes;484 if (isInt<16>(NumBytes))485 Opcode = SystemZ::AGHI;486 else {487 Opcode = SystemZ::AGFI;488 // Make sure we maintain 8-byte stack alignment.489 int64_t MinVal = -uint64_t(1) << 31;490 int64_t MaxVal = (int64_t(1) << 31) - 8;491 if (ThisVal < MinVal)492 ThisVal = MinVal;493 else if (ThisVal > MaxVal)494 ThisVal = MaxVal;495 }496 MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII->get(Opcode), Reg)497 .addReg(Reg).addImm(ThisVal);498 // The CC implicit def is dead.499 MI->getOperand(3).setIsDead();500 NumBytes -= ThisVal;501 }502}503 504// Add CFI for the new CFA offset.505static void buildCFAOffs(MachineBasicBlock &MBB,506 MachineBasicBlock::iterator MBBI,507 const DebugLoc &DL, int Offset,508 const SystemZInstrInfo *ZII) {509 unsigned CFIIndex = MBB.getParent()->addFrameInst(510 MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset));511 BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))512 .addCFIIndex(CFIIndex);513}514 515// Add CFI for the new frame location.516static void buildDefCFAReg(MachineBasicBlock &MBB,517 MachineBasicBlock::iterator MBBI,518 const DebugLoc &DL, unsigned Reg,519 const SystemZInstrInfo *ZII) {520 MachineFunction &MF = *MBB.getParent();521 const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();522 unsigned RegNum = MRI->getDwarfRegNum(Reg, true);523 unsigned CFIIndex = MF.addFrameInst(524 MCCFIInstruction::createDefCfaRegister(nullptr, RegNum));525 BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))526 .addCFIIndex(CFIIndex);527}528 529void SystemZELFFrameLowering::emitPrologue(MachineFunction &MF,530 MachineBasicBlock &MBB) const {531 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");532 const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>();533 const SystemZTargetLowering &TLI = *STI.getTargetLowering();534 MachineFrameInfo &MFFrame = MF.getFrameInfo();535 auto *ZII = STI.getInstrInfo();536 SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();537 MachineBasicBlock::iterator MBBI = MBB.begin();538 const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();539 const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();540 bool HasFP = hasFP(MF);541 542 // In GHC calling convention C stack space, including the ABI-defined543 // 160-byte base area, is (de)allocated by GHC itself. This stack space may544 // be used by LLVM as spill slots for the tail recursive GHC functions. Thus545 // do not allocate stack space here, too.546 if (MF.getFunction().getCallingConv() == CallingConv::GHC) {547 if (MFFrame.getStackSize() > 2048 * sizeof(long)) {548 report_fatal_error(549 "Pre allocated stack space for GHC function is too small");550 }551 if (HasFP) {552 report_fatal_error(553 "In GHC calling convention a frame pointer is not supported");554 }555 MFFrame.setStackSize(MFFrame.getStackSize() + SystemZMC::ELFCallFrameSize);556 return;557 }558 559 // Debug location must be unknown since the first debug location is used560 // to determine the end of the prologue.561 DebugLoc DL;562 // Add mcount instrumentation if necessary.563 if (MF.getFunction()564 .getFnAttribute("systemz-instrument-function-entry")565 .getValueAsString() == "mcount") {566 567 // Store return address 8 bytes above stack pointer.568 BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG))569 .addReg(SystemZ::R14D)570 .addReg(SystemZ::R15D)571 .addImm(8)572 .addReg(0);573 574 // Call mcount (Regmask from CC AnyReg since mcount preserves all normal575 // argument registers).576 const uint32_t *Mask = MF.getSubtarget<SystemZSubtarget>()577 .getSpecialRegisters()578 ->getCallPreservedMask(MF, CallingConv::AnyReg);579 BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::CallBRASL))580 .addExternalSymbol("mcount")581 .addRegMask(Mask);582 583 // Reload return address from 8 bytes above stack pointer.584 BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LG))585 .addReg(SystemZ::R14D, RegState::Define)586 .addReg(SystemZ::R15D)587 .addImm(8)588 .addReg(0);589 }590 591 // The current offset of the stack pointer from the CFA.592 int64_t SPOffsetFromCFA = -SystemZMC::ELFCFAOffsetFromInitialSP;593 594 if (ZFI->getSpillGPRRegs().LowGPR) {595 // Skip over the GPR saves.596 if (MBBI != MBB.end() && MBBI->getOpcode() == SystemZ::STMG)597 ++MBBI;598 else599 llvm_unreachable("Couldn't skip over GPR saves");600 601 // Add CFI for the GPR saves.602 for (auto &Save : CSI) {603 MCRegister Reg = Save.getReg();604 if (SystemZ::GR64BitRegClass.contains(Reg)) {605 int FI = Save.getFrameIdx();606 int64_t Offset = MFFrame.getObjectOffset(FI);607 unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(608 nullptr, MRI->getDwarfRegNum(Reg, true), Offset));609 BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))610 .addCFIIndex(CFIIndex);611 }612 }613 }614 615 uint64_t StackSize = MFFrame.getStackSize();616 // We need to allocate the ABI-defined 160-byte base area whenever617 // we allocate stack space for our own use and whenever we call another618 // function.619 bool HasStackObject = false;620 for (unsigned i = 0, e = MFFrame.getObjectIndexEnd(); i != e; ++i)621 if (!MFFrame.isDeadObjectIndex(i)) {622 HasStackObject = true;623 break;624 }625 if (HasStackObject || MFFrame.hasCalls())626 StackSize += SystemZMC::ELFCallFrameSize;627 // Don't allocate the incoming reg save area.628 StackSize = StackSize > SystemZMC::ELFCallFrameSize629 ? StackSize - SystemZMC::ELFCallFrameSize630 : 0;631 MFFrame.setStackSize(StackSize);632 633 if (StackSize) {634 // Allocate StackSize bytes.635 int64_t Delta = -int64_t(StackSize);636 const unsigned ProbeSize = TLI.getStackProbeSize(MF);637 bool FreeProbe = (ZFI->getSpillGPRRegs().GPROffset &&638 (ZFI->getSpillGPRRegs().GPROffset + StackSize) < ProbeSize);639 if (!FreeProbe &&640 MF.getSubtarget().getTargetLowering()->hasInlineStackProbe(MF)) {641 // Stack probing may involve looping, but splitting the prologue block642 // is not possible at this point since it would invalidate the643 // SaveBlocks / RestoreBlocks sets of PEI in the single block function644 // case. Build a pseudo to be handled later by inlineStackProbe().645 BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::PROBED_STACKALLOC))646 .addImm(StackSize);647 }648 else {649 bool StoreBackchain = MF.getSubtarget<SystemZSubtarget>().hasBackChain();650 // If we need backchain, save current stack pointer. R1 is free at651 // this point.652 if (StoreBackchain)653 BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR))654 .addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D);655 emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII);656 buildCFAOffs(MBB, MBBI, DL, SPOffsetFromCFA + Delta, ZII);657 if (StoreBackchain)658 BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG))659 .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D)660 .addImm(getBackchainOffset(MF)).addReg(0);661 }662 SPOffsetFromCFA += Delta;663 }664 665 if (HasFP) {666 // Copy the base of the frame to R11.667 BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R11D)668 .addReg(SystemZ::R15D);669 670 // Add CFI for the new frame location.671 buildDefCFAReg(MBB, MBBI, DL, SystemZ::R11D, ZII);672 673 // Mark the FramePtr as live at the beginning of every block except674 // the entry block. (We'll have marked R11 as live on entry when675 // saving the GPRs.)676 for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))677 MBBJ.addLiveIn(SystemZ::R11D);678 }679 680 // Skip over the FPR/VR saves.681 SmallVector<unsigned, 8> CFIIndexes;682 for (auto &Save : CSI) {683 MCRegister Reg = Save.getReg();684 if (SystemZ::FP64BitRegClass.contains(Reg)) {685 if (MBBI != MBB.end() &&686 (MBBI->getOpcode() == SystemZ::STD ||687 MBBI->getOpcode() == SystemZ::STDY))688 ++MBBI;689 else690 llvm_unreachable("Couldn't skip over FPR save");691 } else if (SystemZ::VR128BitRegClass.contains(Reg)) {692 if (MBBI != MBB.end() &&693 MBBI->getOpcode() == SystemZ::VST)694 ++MBBI;695 else696 llvm_unreachable("Couldn't skip over VR save");697 } else698 continue;699 700 // Add CFI for the this save.701 unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);702 Register IgnoredFrameReg;703 int64_t Offset =704 getFrameIndexReference(MF, Save.getFrameIdx(), IgnoredFrameReg)705 .getFixed();706 707 unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(708 nullptr, DwarfReg, SPOffsetFromCFA + Offset));709 CFIIndexes.push_back(CFIIndex);710 }711 // Complete the CFI for the FPR/VR saves, modelling them as taking effect712 // after the last save.713 for (auto CFIIndex : CFIIndexes) {714 BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))715 .addCFIIndex(CFIIndex);716 }717}718 719void SystemZELFFrameLowering::emitEpilogue(MachineFunction &MF,720 MachineBasicBlock &MBB) const {721 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();722 auto *ZII =723 static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());724 SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();725 MachineFrameInfo &MFFrame = MF.getFrameInfo();726 727 // See SystemZELFFrameLowering::emitPrologue728 if (MF.getFunction().getCallingConv() == CallingConv::GHC)729 return;730 731 // Skip the return instruction.732 assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks");733 734 uint64_t StackSize = MFFrame.getStackSize();735 if (ZFI->getRestoreGPRRegs().LowGPR) {736 --MBBI;737 unsigned Opcode = MBBI->getOpcode();738 if (Opcode != SystemZ::LMG)739 llvm_unreachable("Expected to see callee-save register restore code");740 741 unsigned AddrOpNo = 2;742 DebugLoc DL = MBBI->getDebugLoc();743 uint64_t Offset = StackSize + MBBI->getOperand(AddrOpNo + 1).getImm();744 unsigned NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);745 746 // If the offset is too large, use the largest stack-aligned offset747 // and add the rest to the base register (the stack or frame pointer).748 if (!NewOpcode) {749 uint64_t NumBytes = Offset - 0x7fff8;750 emitIncrement(MBB, MBBI, DL, MBBI->getOperand(AddrOpNo).getReg(),751 NumBytes, ZII);752 Offset -= NumBytes;753 NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);754 assert(NewOpcode && "No restore instruction available");755 }756 757 MBBI->setDesc(ZII->get(NewOpcode));758 MBBI->getOperand(AddrOpNo + 1).ChangeToImmediate(Offset);759 } else if (StackSize) {760 DebugLoc DL = MBBI->getDebugLoc();761 emitIncrement(MBB, MBBI, DL, SystemZ::R15D, StackSize, ZII);762 }763}764 765void SystemZELFFrameLowering::inlineStackProbe(766 MachineFunction &MF, MachineBasicBlock &PrologMBB) const {767 auto *ZII =768 static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());769 const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>();770 const SystemZTargetLowering &TLI = *STI.getTargetLowering();771 772 MachineInstr *StackAllocMI = nullptr;773 for (MachineInstr &MI : PrologMBB)774 if (MI.getOpcode() == SystemZ::PROBED_STACKALLOC) {775 StackAllocMI = &MI;776 break;777 }778 if (StackAllocMI == nullptr)779 return;780 uint64_t StackSize = StackAllocMI->getOperand(0).getImm();781 const unsigned ProbeSize = TLI.getStackProbeSize(MF);782 uint64_t NumFullBlocks = StackSize / ProbeSize;783 uint64_t Residual = StackSize % ProbeSize;784 int64_t SPOffsetFromCFA = -SystemZMC::ELFCFAOffsetFromInitialSP;785 MachineBasicBlock *MBB = &PrologMBB;786 MachineBasicBlock::iterator MBBI = StackAllocMI;787 const DebugLoc DL = StackAllocMI->getDebugLoc();788 789 // Allocate a block of Size bytes on the stack and probe it.790 auto allocateAndProbe = [&](MachineBasicBlock &InsMBB,791 MachineBasicBlock::iterator InsPt, unsigned Size,792 bool EmitCFI) -> void {793 emitIncrement(InsMBB, InsPt, DL, SystemZ::R15D, -int64_t(Size), ZII);794 if (EmitCFI) {795 SPOffsetFromCFA -= Size;796 buildCFAOffs(InsMBB, InsPt, DL, SPOffsetFromCFA, ZII);797 }798 // Probe by means of a volatile compare.799 MachineMemOperand *MMO = MF.getMachineMemOperand(MachinePointerInfo(),800 MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad, 8, Align(1));801 BuildMI(InsMBB, InsPt, DL, ZII->get(SystemZ::CG))802 .addReg(SystemZ::R0D, RegState::Undef)803 .addReg(SystemZ::R15D).addImm(Size - 8).addReg(0)804 .addMemOperand(MMO);805 };806 807 bool StoreBackchain = MF.getSubtarget<SystemZSubtarget>().hasBackChain();808 if (StoreBackchain)809 BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR))810 .addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D);811 812 MachineBasicBlock *DoneMBB = nullptr;813 MachineBasicBlock *LoopMBB = nullptr;814 if (NumFullBlocks < 3) {815 // Emit unrolled probe statements.816 for (unsigned int i = 0; i < NumFullBlocks; i++)817 allocateAndProbe(*MBB, MBBI, ProbeSize, true/*EmitCFI*/);818 } else {819 // Emit a loop probing the pages.820 uint64_t LoopAlloc = ProbeSize * NumFullBlocks;821 SPOffsetFromCFA -= LoopAlloc;822 823 // Use R0D to hold the exit value.824 BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R0D)825 .addReg(SystemZ::R15D);826 buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R0D, ZII);827 emitIncrement(*MBB, MBBI, DL, SystemZ::R0D, -int64_t(LoopAlloc), ZII);828 buildCFAOffs(*MBB, MBBI, DL, -int64_t(SystemZMC::ELFCallFrameSize + LoopAlloc),829 ZII);830 831 DoneMBB = SystemZ::splitBlockBefore(MBBI, MBB);832 LoopMBB = SystemZ::emitBlockAfter(MBB);833 MBB->addSuccessor(LoopMBB);834 LoopMBB->addSuccessor(LoopMBB);835 LoopMBB->addSuccessor(DoneMBB);836 837 MBB = LoopMBB;838 allocateAndProbe(*MBB, MBB->end(), ProbeSize, false/*EmitCFI*/);839 BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::CLGR))840 .addReg(SystemZ::R15D).addReg(SystemZ::R0D);841 BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::BRC))842 .addImm(SystemZ::CCMASK_ICMP).addImm(SystemZ::CCMASK_CMP_GT).addMBB(MBB);843 844 MBB = DoneMBB;845 MBBI = DoneMBB->begin();846 buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R15D, ZII);847 }848 849 if (Residual)850 allocateAndProbe(*MBB, MBBI, Residual, true/*EmitCFI*/);851 852 if (StoreBackchain)853 BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::STG))854 .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D)855 .addImm(getBackchainOffset(MF)).addReg(0);856 857 StackAllocMI->eraseFromParent();858 if (DoneMBB != nullptr) {859 // Compute the live-in lists for the new blocks.860 fullyRecomputeLiveIns({DoneMBB, LoopMBB});861 }862}863 864bool SystemZELFFrameLowering::hasFPImpl(const MachineFunction &MF) const {865 return (MF.getTarget().Options.DisableFramePointerElim(MF) ||866 MF.getFrameInfo().hasVarSizedObjects());867}868 869StackOffset SystemZELFFrameLowering::getFrameIndexReference(870 const MachineFunction &MF, int FI, Register &FrameReg) const {871 // Our incoming SP is actually SystemZMC::ELFCallFrameSize below the CFA, so872 // add that difference here.873 StackOffset Offset =874 TargetFrameLowering::getFrameIndexReference(MF, FI, FrameReg);875 return Offset + StackOffset::getFixed(SystemZMC::ELFCallFrameSize);876}877 878unsigned SystemZELFFrameLowering::getRegSpillOffset(MachineFunction &MF,879 Register Reg) const {880 bool IsVarArg = MF.getFunction().isVarArg();881 const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();882 bool BackChain = Subtarget.hasBackChain();883 bool SoftFloat = Subtarget.hasSoftFloat();884 unsigned Offset = RegSpillOffsets[Reg];885 if (usePackedStack(MF) && !(IsVarArg && !SoftFloat)) {886 if (SystemZ::GR64BitRegClass.contains(Reg))887 // Put all GPRs at the top of the Register save area with packed888 // stack. Make room for the backchain if needed.889 Offset += BackChain ? 24 : 32;890 else891 Offset = 0;892 }893 return Offset;894}895 896int SystemZELFFrameLowering::getOrCreateFramePointerSaveIndex(897 MachineFunction &MF) const {898 SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();899 int FI = ZFI->getFramePointerSaveIndex();900 if (!FI) {901 MachineFrameInfo &MFFrame = MF.getFrameInfo();902 int Offset = getBackchainOffset(MF) - SystemZMC::ELFCallFrameSize;903 FI = MFFrame.CreateFixedObject(getPointerSize(), Offset, false);904 ZFI->setFramePointerSaveIndex(FI);905 }906 return FI;907}908 909bool SystemZELFFrameLowering::usePackedStack(MachineFunction &MF) const {910 bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack");911 const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();912 bool BackChain = Subtarget.hasBackChain();913 bool SoftFloat = Subtarget.hasSoftFloat();914 if (HasPackedStackAttr && BackChain && !SoftFloat)915 report_fatal_error("packed-stack + backchain + hard-float is unsupported.");916 bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC;917 return HasPackedStackAttr && CallConv;918}919 920SystemZXPLINKFrameLowering::SystemZXPLINKFrameLowering(unsigned PointerSize)921 : SystemZFrameLowering(TargetFrameLowering::StackGrowsDown, Align(32), 0,922 Align(32), /* StackRealignable */ false,923 PointerSize),924 RegSpillOffsets(-1) {925 926 // Create a mapping from register number to save slot offset.927 // These offsets are relative to the start of the local are area.928 RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);929 for (const auto &Entry : XPLINKSpillOffsetTable)930 RegSpillOffsets[Entry.Reg] = Entry.Offset;931}932 933int SystemZXPLINKFrameLowering::getOrCreateFramePointerSaveIndex(934 MachineFunction &MF) const {935 SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();936 int FI = ZFI->getFramePointerSaveIndex();937 if (!FI) {938 MachineFrameInfo &MFFrame = MF.getFrameInfo();939 FI = MFFrame.CreateFixedObject(getPointerSize(), 0, false);940 MFFrame.setStackID(FI, TargetStackID::NoAlloc);941 ZFI->setFramePointerSaveIndex(FI);942 }943 return FI;944}945 946// Checks if the function is a potential candidate for being a XPLeaf routine.947static bool isXPLeafCandidate(const MachineFunction &MF) {948 const MachineFrameInfo &MFFrame = MF.getFrameInfo();949 const MachineRegisterInfo &MRI = MF.getRegInfo();950 const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();951 auto *Regs =952 static_cast<SystemZXPLINK64Registers *>(Subtarget.getSpecialRegisters());953 954 // If function calls other functions including alloca, then it is not a XPLeaf955 // routine.956 if (MFFrame.hasCalls())957 return false;958 959 // If the function has var Sized Objects, then it is not a XPLeaf routine.960 if (MFFrame.hasVarSizedObjects())961 return false;962 963 // If the function adjusts the stack, then it is not a XPLeaf routine.964 if (MFFrame.adjustsStack())965 return false;966 967 // If function modifies the stack pointer register, then it is not a XPLeaf968 // routine.969 if (MRI.isPhysRegModified(Regs->getStackPointerRegister()))970 return false;971 972 // If function modifies the ADA register, then it is not a XPLeaf routine.973 if (MRI.isPhysRegModified(Regs->getAddressOfCalleeRegister()))974 return false;975 976 // If function modifies the return address register, then it is not a XPLeaf977 // routine.978 if (MRI.isPhysRegModified(Regs->getReturnFunctionAddressRegister()))979 return false;980 981 // If the backchain pointer should be stored, then it is not a XPLeaf routine.982 if (MF.getSubtarget<SystemZSubtarget>().hasBackChain())983 return false;984 985 // If function acquires its own stack frame, then it is not a XPLeaf routine.986 // At the time this function is called, only slots for local variables are987 // allocated, so this is a very rough estimate.988 if (MFFrame.estimateStackSize(MF) > 0)989 return false;990 991 return true;992}993 994bool SystemZXPLINKFrameLowering::assignCalleeSavedSpillSlots(995 MachineFunction &MF, const TargetRegisterInfo *TRI,996 std::vector<CalleeSavedInfo> &CSI) const {997 MachineFrameInfo &MFFrame = MF.getFrameInfo();998 SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();999 const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();1000 auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();1001 auto &GRRegClass = SystemZ::GR64BitRegClass;1002 1003 // At this point, the result of isXPLeafCandidate() is not accurate because1004 // the size of the save area has not yet been determined. If1005 // isXPLeafCandidate() indicates a potential leaf function, and there are no1006 // callee-save registers, then it is indeed a leaf function, and we can early1007 // exit.1008 // TODO: It is possible for leaf functions to use callee-saved registers.1009 // It can use the 0-2k range between R4 and the caller's stack frame without1010 // acquiring its own stack frame.1011 bool IsLeaf = CSI.empty() && isXPLeafCandidate(MF);1012 if (IsLeaf)1013 return true;1014 1015 // For non-leaf functions:1016 // - the address of callee (entry point) register R6 must be saved1017 CSI.push_back(CalleeSavedInfo(Regs.getAddressOfCalleeRegister()));1018 CSI.back().setRestored(false);1019 1020 // The return address register R7 must be saved and restored.1021 CSI.push_back(CalleeSavedInfo(Regs.getReturnFunctionAddressRegister()));1022 1023 // If the function needs a frame pointer, or if the backchain pointer should1024 // be stored, then save the stack pointer register R4.1025 if (hasFP(MF) || Subtarget.hasBackChain())1026 CSI.push_back(CalleeSavedInfo(Regs.getStackPointerRegister()));1027 1028 // If this function has an associated personality function then the1029 // environment register R5 must be saved in the DSA.1030 if (!MF.getLandingPads().empty())1031 CSI.push_back(CalleeSavedInfo(Regs.getADARegister()));1032 1033 // Scan the call-saved GPRs and find the bounds of the register spill area.1034 Register LowRestoreGPR = 0;1035 int LowRestoreOffset = INT32_MAX;1036 Register LowSpillGPR = 0;1037 int LowSpillOffset = INT32_MAX;1038 Register HighGPR = 0;1039 int HighOffset = -1;1040 1041 // Query index of the saved frame pointer.1042 int FPSI = MFI->getFramePointerSaveIndex();1043 1044 for (auto &CS : CSI) {1045 MCRegister Reg = CS.getReg();1046 int Offset = RegSpillOffsets[Reg];1047 if (Offset >= 0) {1048 if (GRRegClass.contains(Reg)) {1049 if (LowSpillOffset > Offset) {1050 LowSpillOffset = Offset;1051 LowSpillGPR = Reg;1052 }1053 if (CS.isRestored() && LowRestoreOffset > Offset) {1054 LowRestoreOffset = Offset;1055 LowRestoreGPR = Reg;1056 }1057 1058 if (Offset > HighOffset) {1059 HighOffset = Offset;1060 HighGPR = Reg;1061 }1062 // Non-volatile GPRs are saved in the dedicated register save area at1063 // the bottom of the stack and are not truly part of the "normal" stack1064 // frame. Mark the frame index as NoAlloc to indicate it as such.1065 unsigned RegSize = getPointerSize();1066 int FrameIdx =1067 (FPSI && Offset == 0)1068 ? FPSI1069 : MFFrame.CreateFixedSpillStackObject(RegSize, Offset);1070 CS.setFrameIdx(FrameIdx);1071 MFFrame.setStackID(FrameIdx, TargetStackID::NoAlloc);1072 }1073 } else {1074 MCRegister Reg = CS.getReg();1075 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);1076 Align Alignment = TRI->getSpillAlign(*RC);1077 unsigned Size = TRI->getSpillSize(*RC);1078 Alignment = std::min(Alignment, getStackAlign());1079 int FrameIdx = MFFrame.CreateStackObject(Size, Alignment, true);1080 CS.setFrameIdx(FrameIdx);1081 }1082 }1083 1084 // Save the range of call-saved registers, for use by the1085 // prologue/epilogue inserters.1086 if (LowRestoreGPR)1087 MFI->setRestoreGPRRegs(LowRestoreGPR, HighGPR, LowRestoreOffset);1088 1089 // Save the range of call-saved registers, for use by the epilogue inserter.1090 assert(LowSpillGPR && "Expected registers to spill");1091 MFI->setSpillGPRRegs(LowSpillGPR, HighGPR, LowSpillOffset);1092 1093 return true;1094}1095 1096void SystemZXPLINKFrameLowering::determineCalleeSaves(MachineFunction &MF,1097 BitVector &SavedRegs,1098 RegScavenger *RS) const {1099 TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);1100 1101 bool HasFP = hasFP(MF);1102 const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();1103 auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();1104 1105 // If the function requires a frame pointer, record that the hard1106 // frame pointer will be clobbered.1107 if (HasFP)1108 SavedRegs.set(Regs.getFramePointerRegister());1109}1110 1111bool SystemZXPLINKFrameLowering::spillCalleeSavedRegisters(1112 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,1113 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {1114 if (CSI.empty())1115 return true;1116 1117 MachineFunction &MF = *MBB.getParent();1118 SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();1119 const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();1120 const TargetInstrInfo *TII = Subtarget.getInstrInfo();1121 auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();1122 SystemZ::GPRRegs SpillGPRs = ZFI->getSpillGPRRegs();1123 DebugLoc DL;1124 1125 // Save GPRs1126 if (SpillGPRs.LowGPR) {1127 assert(SpillGPRs.LowGPR != SpillGPRs.HighGPR &&1128 "Should be saving multiple registers");1129 1130 // Build an STM/STMG instruction.1131 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG));1132 1133 // Add the explicit register operands.1134 addSavedGPR(MBB, MIB, SpillGPRs.LowGPR, false);1135 addSavedGPR(MBB, MIB, SpillGPRs.HighGPR, false);1136 1137 // Add the address r41138 MIB.addReg(Regs.getStackPointerRegister());1139 1140 // Add the partial offset1141 // We cannot add the actual offset as, at the stack is not finalized1142 MIB.addImm(SpillGPRs.GPROffset);1143 1144 // Make sure all call-saved GPRs are included as operands and are1145 // marked as live on entry.1146 auto &GRRegClass = SystemZ::GR64BitRegClass;1147 for (const CalleeSavedInfo &I : CSI) {1148 MCRegister Reg = I.getReg();1149 if (GRRegClass.contains(Reg))1150 addSavedGPR(MBB, MIB, Reg, true);1151 }1152 }1153 1154 // Spill FPRs to the stack in the normal TargetInstrInfo way1155 for (const CalleeSavedInfo &I : CSI) {1156 MCRegister Reg = I.getReg();1157 if (SystemZ::FP64BitRegClass.contains(Reg)) {1158 MBB.addLiveIn(Reg);1159 TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),1160 &SystemZ::FP64BitRegClass, Register());1161 }1162 if (SystemZ::VR128BitRegClass.contains(Reg)) {1163 MBB.addLiveIn(Reg);1164 TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),1165 &SystemZ::VR128BitRegClass, Register());1166 }1167 }1168 1169 return true;1170}1171 1172bool SystemZXPLINKFrameLowering::restoreCalleeSavedRegisters(1173 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,1174 MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {1175 1176 if (CSI.empty())1177 return false;1178 1179 MachineFunction &MF = *MBB.getParent();1180 SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();1181 const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();1182 const TargetInstrInfo *TII = Subtarget.getInstrInfo();1183 auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();1184 1185 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();1186 1187 // Restore FPRs in the normal TargetInstrInfo way.1188 for (const CalleeSavedInfo &I : CSI) {1189 MCRegister Reg = I.getReg();1190 if (SystemZ::FP64BitRegClass.contains(Reg))1191 TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),1192 &SystemZ::FP64BitRegClass, Register());1193 if (SystemZ::VR128BitRegClass.contains(Reg))1194 TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),1195 &SystemZ::VR128BitRegClass, Register());1196 }1197 1198 // Restore call-saved GPRs (but not call-clobbered varargs, which at1199 // this point might hold return values).1200 SystemZ::GPRRegs RestoreGPRs = ZFI->getRestoreGPRRegs();1201 if (RestoreGPRs.LowGPR) {1202 assert(isInt<20>(Regs.getStackPointerBias() + RestoreGPRs.GPROffset));1203 if (RestoreGPRs.LowGPR == RestoreGPRs.HighGPR)1204 // Build an LG/L instruction.1205 BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LG), RestoreGPRs.LowGPR)1206 .addReg(Regs.getStackPointerRegister())1207 .addImm(Regs.getStackPointerBias() + RestoreGPRs.GPROffset)1208 .addReg(0);1209 else {1210 // Build an LMG/LM instruction.1211 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG));1212 1213 // Add the explicit register operands.1214 MIB.addReg(RestoreGPRs.LowGPR, RegState::Define);1215 MIB.addReg(RestoreGPRs.HighGPR, RegState::Define);1216 1217 // Add the address.1218 MIB.addReg(Regs.getStackPointerRegister());1219 MIB.addImm(Regs.getStackPointerBias() + RestoreGPRs.GPROffset);1220 1221 // Do a second scan adding regs as being defined by instruction1222 for (const CalleeSavedInfo &I : CSI) {1223 MCRegister Reg = I.getReg();1224 if (Reg > RestoreGPRs.LowGPR && Reg < RestoreGPRs.HighGPR)1225 MIB.addReg(Reg, RegState::ImplicitDefine);1226 }1227 }1228 }1229 1230 return true;1231}1232 1233void SystemZXPLINKFrameLowering::emitPrologue(MachineFunction &MF,1234 MachineBasicBlock &MBB) const {1235 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");1236 const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();1237 SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();1238 MachineBasicBlock::iterator MBBI = MBB.begin();1239 auto *ZII = Subtarget.getInstrInfo();1240 auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();1241 MachineFrameInfo &MFFrame = MF.getFrameInfo();1242 MachineInstr *StoreInstr = nullptr;1243 1244 determineFrameLayout(MF);1245 1246 bool HasFP = hasFP(MF);1247 // Debug location must be unknown since the first debug location is used1248 // to determine the end of the prologue.1249 DebugLoc DL;1250 uint64_t Offset = 0;1251 1252 const uint64_t StackSize = MFFrame.getStackSize();1253 1254 if (ZFI->getSpillGPRRegs().LowGPR) {1255 // Skip over the GPR saves.1256 if ((MBBI != MBB.end()) && ((MBBI->getOpcode() == SystemZ::STMG))) {1257 const int Operand = 3;1258 // Now we can set the offset for the operation, since now the Stack1259 // has been finalized.1260 Offset = Regs.getStackPointerBias() + MBBI->getOperand(Operand).getImm();1261 // Maximum displacement for STMG instruction.1262 if (isInt<20>(Offset - StackSize))1263 Offset -= StackSize;1264 else1265 StoreInstr = &*MBBI;1266 MBBI->getOperand(Operand).setImm(Offset);1267 ++MBBI;1268 } else1269 llvm_unreachable("Couldn't skip over GPR saves");1270 }1271 1272 if (StackSize) {1273 MachineBasicBlock::iterator InsertPt = StoreInstr ? StoreInstr : MBBI;1274 // Allocate StackSize bytes.1275 int64_t Delta = -int64_t(StackSize);1276 1277 // In case the STM(G) instruction also stores SP (R4), but the displacement1278 // is too large, the SP register is manipulated first before storing,1279 // resulting in the wrong value stored and retrieved later. In this case, we1280 // need to temporarily save the value of SP, and store it later to memory.1281 if (StoreInstr && HasFP) {1282 // Insert LR r0,r4 before STMG instruction.1283 BuildMI(MBB, InsertPt, DL, ZII->get(SystemZ::LGR))1284 .addReg(SystemZ::R0D, RegState::Define)1285 .addReg(SystemZ::R4D);1286 // Insert ST r0,xxx(,r4) after STMG instruction.1287 BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG))1288 .addReg(SystemZ::R0D, RegState::Kill)1289 .addReg(SystemZ::R4D)1290 .addImm(Offset)1291 .addReg(0);1292 }1293 1294 emitIncrement(MBB, InsertPt, DL, Regs.getStackPointerRegister(), Delta,1295 ZII);1296 1297 // If the requested stack size is larger than the guard page, then we need1298 // to check if we need to call the stack extender. This requires adding a1299 // conditional branch, but splitting the prologue block is not possible at1300 // this point since it would invalidate the SaveBlocks / RestoreBlocks sets1301 // of PEI in the single block function case. Build a pseudo to be handled1302 // later by inlineStackProbe().1303 const uint64_t GuardPageSize = 1024 * 1024;1304 if (StackSize > GuardPageSize) {1305 assert(StoreInstr && "Wrong insertion point");1306 BuildMI(MBB, InsertPt, DL, ZII->get(SystemZ::XPLINK_STACKALLOC));1307 }1308 }1309 1310 if (HasFP) {1311 // Copy the base of the frame to Frame Pointer Register.1312 BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR),1313 Regs.getFramePointerRegister())1314 .addReg(Regs.getStackPointerRegister());1315 1316 // Mark the FramePtr as live at the beginning of every block except1317 // the entry block. (We'll have marked R8 as live on entry when1318 // saving the GPRs.)1319 for (MachineBasicBlock &B : llvm::drop_begin(MF))1320 B.addLiveIn(Regs.getFramePointerRegister());1321 }1322 1323 // Save GPRs used for varargs, if any.1324 const TargetInstrInfo *TII = Subtarget.getInstrInfo();1325 bool IsVarArg = MF.getFunction().isVarArg();1326 1327 if (IsVarArg) {1328 // FixedRegs is the number of used registers, accounting for shadow1329 // registers.1330 unsigned FixedRegs = ZFI->getVarArgsFirstGPR() + ZFI->getVarArgsFirstFPR();1331 auto &GPRs = SystemZ::XPLINK64ArgGPRs;1332 for (unsigned I = FixedRegs; I < SystemZ::XPLINK64NumArgGPRs; I++) {1333 uint64_t StartOffset = MFFrame.getOffsetAdjustment() +1334 MFFrame.getStackSize() + Regs.getCallFrameSize() +1335 getOffsetOfLocalArea() + I * getPointerSize();1336 unsigned Reg = GPRs[I];1337 BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STG))1338 .addReg(Reg)1339 .addReg(Regs.getStackPointerRegister())1340 .addImm(StartOffset)1341 .addReg(0);1342 if (!MBB.isLiveIn(Reg))1343 MBB.addLiveIn(Reg);1344 }1345 }1346}1347 1348void SystemZXPLINKFrameLowering::emitEpilogue(MachineFunction &MF,1349 MachineBasicBlock &MBB) const {1350 const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();1351 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();1352 SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();1353 MachineFrameInfo &MFFrame = MF.getFrameInfo();1354 auto *ZII = Subtarget.getInstrInfo();1355 auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();1356 1357 // Skip the return instruction.1358 assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks");1359 1360 uint64_t StackSize = MFFrame.getStackSize();1361 if (StackSize) {1362 unsigned SPReg = Regs.getStackPointerRegister();1363 if (ZFI->getRestoreGPRRegs().LowGPR != SPReg) {1364 DebugLoc DL = MBBI->getDebugLoc();1365 emitIncrement(MBB, MBBI, DL, SPReg, StackSize, ZII);1366 }1367 }1368}1369 1370// Emit a compare of the stack pointer against the stack floor, and a call to1371// the LE stack extender if needed.1372void SystemZXPLINKFrameLowering::inlineStackProbe(1373 MachineFunction &MF, MachineBasicBlock &PrologMBB) const {1374 auto *ZII =1375 static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());1376 1377 MachineInstr *StackAllocMI = nullptr;1378 for (MachineInstr &MI : PrologMBB)1379 if (MI.getOpcode() == SystemZ::XPLINK_STACKALLOC) {1380 StackAllocMI = &MI;1381 break;1382 }1383 if (StackAllocMI == nullptr)1384 return;1385 1386 bool NeedSaveSP = hasFP(MF);1387 bool NeedSaveArg = PrologMBB.isLiveIn(SystemZ::R3D);1388 const int64_t SaveSlotR3 = 2192;1389 1390 MachineBasicBlock &MBB = PrologMBB;1391 const DebugLoc DL = StackAllocMI->getDebugLoc();1392 1393 // The 2nd half of block MBB after split.1394 MachineBasicBlock *NextMBB;1395 1396 // Add new basic block for the call to the stack overflow function.1397 MachineBasicBlock *StackExtMBB =1398 MF.CreateMachineBasicBlock(MBB.getBasicBlock());1399 MF.push_back(StackExtMBB);1400 1401 // LG r3,72(,r3)1402 BuildMI(StackExtMBB, DL, ZII->get(SystemZ::LG), SystemZ::R3D)1403 .addReg(SystemZ::R3D)1404 .addImm(72)1405 .addReg(0);1406 // BASR r3,r31407 BuildMI(StackExtMBB, DL, ZII->get(SystemZ::CallBASR_STACKEXT))1408 .addReg(SystemZ::R3D);1409 if (NeedSaveArg) {1410 if (!NeedSaveSP) {1411 // LGR r0,r31412 BuildMI(MBB, StackAllocMI, DL, ZII->get(SystemZ::LGR))1413 .addReg(SystemZ::R0D, RegState::Define)1414 .addReg(SystemZ::R3D);1415 } else {1416 // In this case, the incoming value of r4 is saved in r0 so the1417 // latter register is unavailable. Store r3 in its corresponding1418 // slot in the parameter list instead. Do this at the start of1419 // the prolog before r4 is manipulated by anything else.1420 // STG r3, 2192(r4)1421 BuildMI(MBB, MBB.begin(), DL, ZII->get(SystemZ::STG))1422 .addReg(SystemZ::R3D)1423 .addReg(SystemZ::R4D)1424 .addImm(SaveSlotR3)1425 .addReg(0);1426 }1427 }1428 // LLGT r3,12081429 BuildMI(MBB, StackAllocMI, DL, ZII->get(SystemZ::LLGT), SystemZ::R3D)1430 .addReg(0)1431 .addImm(1208)1432 .addReg(0);1433 // CG r4,64(,r3)1434 BuildMI(MBB, StackAllocMI, DL, ZII->get(SystemZ::CG))1435 .addReg(SystemZ::R4D)1436 .addReg(SystemZ::R3D)1437 .addImm(64)1438 .addReg(0);1439 // JLL b'0100',F'37'1440 BuildMI(MBB, StackAllocMI, DL, ZII->get(SystemZ::BRC))1441 .addImm(SystemZ::CCMASK_ICMP)1442 .addImm(SystemZ::CCMASK_CMP_LT)1443 .addMBB(StackExtMBB);1444 1445 NextMBB = SystemZ::splitBlockBefore(StackAllocMI, &MBB);1446 MBB.addSuccessor(NextMBB);1447 MBB.addSuccessor(StackExtMBB);1448 if (NeedSaveArg) {1449 if (!NeedSaveSP) {1450 // LGR r3, r01451 BuildMI(*NextMBB, StackAllocMI, DL, ZII->get(SystemZ::LGR))1452 .addReg(SystemZ::R3D, RegState::Define)1453 .addReg(SystemZ::R0D, RegState::Kill);1454 } else {1455 // In this case, the incoming value of r4 is saved in r0 so the1456 // latter register is unavailable. We stored r3 in its corresponding1457 // slot in the parameter list instead and we now restore it from there.1458 // LGR r3, r01459 BuildMI(*NextMBB, StackAllocMI, DL, ZII->get(SystemZ::LGR))1460 .addReg(SystemZ::R3D, RegState::Define)1461 .addReg(SystemZ::R0D);1462 // LG r3, 2192(r3)1463 BuildMI(*NextMBB, StackAllocMI, DL, ZII->get(SystemZ::LG))1464 .addReg(SystemZ::R3D, RegState::Define)1465 .addReg(SystemZ::R3D)1466 .addImm(SaveSlotR3)1467 .addReg(0);1468 }1469 }1470 1471 // Add jump back from stack extension BB.1472 BuildMI(StackExtMBB, DL, ZII->get(SystemZ::J)).addMBB(NextMBB);1473 StackExtMBB->addSuccessor(NextMBB);1474 1475 StackAllocMI->eraseFromParent();1476 1477 // Compute the live-in lists for the new blocks.1478 fullyRecomputeLiveIns({StackExtMBB, NextMBB});1479}1480 1481bool SystemZXPLINKFrameLowering::hasFPImpl(const MachineFunction &MF) const {1482 return (MF.getFrameInfo().hasVarSizedObjects());1483}1484 1485void SystemZXPLINKFrameLowering::processFunctionBeforeFrameFinalized(1486 MachineFunction &MF, RegScavenger *RS) const {1487 MachineFrameInfo &MFFrame = MF.getFrameInfo();1488 const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();1489 auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();1490 1491 // Setup stack frame offset1492 MFFrame.setOffsetAdjustment(Regs.getStackPointerBias());1493 1494 // Nothing to do for leaf functions.1495 uint64_t StackSize = MFFrame.estimateStackSize(MF);1496 if (StackSize == 0 && MFFrame.getCalleeSavedInfo().empty())1497 return;1498 1499 // Although the XPLINK specifications for AMODE64 state that minimum size1500 // of the param area is minimum 32 bytes and no rounding is otherwise1501 // specified, we round this area in 64 bytes increments to be compatible1502 // with existing compilers.1503 MFFrame.setMaxCallFrameSize(1504 std::max(64U, (unsigned)alignTo(MFFrame.getMaxCallFrameSize(), 64)));1505 1506 // Add frame values with positive object offsets. Since the displacement from1507 // the SP/FP is calculated by ObjectOffset + StackSize + Bias, object offsets1508 // with positive values are in the caller's stack frame. We need to include1509 // that since it is accessed by displacement to SP/FP.1510 int64_t LargestArgOffset = 0;1511 for (int I = MFFrame.getObjectIndexBegin(); I != 0; ++I) {1512 if (MFFrame.getObjectOffset(I) >= 0) {1513 int64_t ObjOffset = MFFrame.getObjectOffset(I) + MFFrame.getObjectSize(I);1514 LargestArgOffset = std::max(ObjOffset, LargestArgOffset);1515 }1516 }1517 1518 uint64_t MaxReach = (StackSize + Regs.getCallFrameSize() +1519 Regs.getStackPointerBias() + LargestArgOffset);1520 1521 if (!isUInt<12>(MaxReach)) {1522 // We may need register scavenging slots if some parts of the frame1523 // are outside the reach of an unsigned 12-bit displacement.1524 RS->addScavengingFrameIndex(MFFrame.CreateSpillStackObject(8, Align(8)));1525 RS->addScavengingFrameIndex(MFFrame.CreateSpillStackObject(8, Align(8)));1526 }1527}1528 1529// Determines the size of the frame, and creates the deferred spill objects.1530void SystemZXPLINKFrameLowering::determineFrameLayout(1531 MachineFunction &MF) const {1532 MachineFrameInfo &MFFrame = MF.getFrameInfo();1533 const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();1534 auto *Regs =1535 static_cast<SystemZXPLINK64Registers *>(Subtarget.getSpecialRegisters());1536 1537 uint64_t StackSize = MFFrame.getStackSize();1538 if (StackSize == 0)1539 return;1540 1541 // Add the size of the register save area and the reserved area to the size.1542 StackSize += Regs->getCallFrameSize();1543 MFFrame.setStackSize(StackSize);1544 1545 // We now know the stack size. Update the stack objects for the register save1546 // area now. This has no impact on the stack frame layout, as this is already1547 // computed. However, it makes sure that all callee saved registers have a1548 // valid offset assigned.1549 for (int FrameIdx = MFFrame.getObjectIndexBegin(); FrameIdx != 0;1550 ++FrameIdx) {1551 if (MFFrame.getStackID(FrameIdx) == TargetStackID::NoAlloc) {1552 int64_t SPOffset = MFFrame.getObjectOffset(FrameIdx);1553 SPOffset -= StackSize;1554 MFFrame.setObjectOffset(FrameIdx, SPOffset);1555 }1556 }1557}1558