LLVM 20.0.0git
M68kFrameLowering.cpp
Go to the documentation of this file.
1//===-- M68kFrameLowering.cpp - M68k Frame Information ----------*- C++ -*-===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file contains the M68k implementation of TargetFrameLowering class.
11///
12//===----------------------------------------------------------------------===//
13
14#include "M68kFrameLowering.h"
15
16#include "M68kInstrBuilder.h"
17#include "M68kInstrInfo.h"
18#include "M68kMachineFunction.h"
19#include "M68kSubtarget.h"
20
21#include "llvm/ADT/SmallSet.h"
27#include "llvm/IR/DataLayout.h"
28#include "llvm/IR/Function.h"
33
34using namespace llvm;
35
37 : TargetFrameLowering(StackGrowsDown, Alignment, -4), STI(STI),
38 TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {
39 SlotSize = STI.getSlotSize();
40 StackPtr = TRI->getStackRegister();
41}
42
44 const MachineFrameInfo &MFI = MF.getFrameInfo();
45 const TargetRegisterInfo *TRI = STI.getRegisterInfo();
46
49 TRI->hasStackRealignment(MF);
50}
51
52// FIXME Make sure no other factors prevent us from reserving call frame
54 return !MF.getFrameInfo().hasVarSizedObjects() &&
55 !MF.getInfo<M68kMachineFunctionInfo>()->getHasPushSequences();
56}
57
59 const MachineFunction &MF) const {
60 return hasReservedCallFrame(MF) ||
61 (hasFP(MF) && !TRI->hasStackRealignment(MF)) ||
62 TRI->hasBasePointer(MF);
63}
64
66 const MachineFunction &MF) const {
67 return MF.getFrameInfo().hasStackObjects() ||
68 MF.getInfo<M68kMachineFunctionInfo>()->getHasPushSequences();
69}
70
71// NOTE: this only has a subset of the full frame index logic. In
72// particular, the FI < 0 and AfterFPPop logic is handled in
73// M68kRegisterInfo::eliminateFrameIndex, but not here. Possibly
74// (probably?) it should be moved into here.
77 Register &FrameReg) const {
78 const MachineFrameInfo &MFI = MF.getFrameInfo();
79
80 // We can't calculate offset from frame pointer if the stack is realigned,
81 // so enforce usage of stack/base pointer. The base pointer is used when we
82 // have dynamic allocas in addition to dynamic realignment.
83 if (TRI->hasBasePointer(MF))
84 FrameReg = TRI->getBaseRegister();
85 else if (TRI->hasStackRealignment(MF))
86 FrameReg = TRI->getStackRegister();
87 else
88 FrameReg = TRI->getFrameRegister(MF);
89
90 // Offset will hold the offset from the stack pointer at function entry to the
91 // object.
92 // We need to factor in additional offsets applied during the prologue to the
93 // frame, base, and stack pointer depending on which is used.
96 uint64_t StackSize = MFI.getStackSize();
97 bool HasFP = hasFP(MF);
98
99 // TODO: Support tail calls
100 if (TRI->hasBasePointer(MF)) {
101 assert(HasFP && "VLAs and dynamic stack realign, but no FP?!");
102 if (FI < 0) {
103 // Skip the saved FP.
104 return StackOffset::getFixed(Offset + SlotSize);
105 }
106
107 assert((-(Offset + StackSize)) % MFI.getObjectAlign(FI).value() == 0);
108 return StackOffset::getFixed(Offset + StackSize);
109 }
110 if (TRI->hasStackRealignment(MF)) {
111 if (FI < 0) {
112 // Skip the saved FP.
113 return StackOffset::getFixed(Offset + SlotSize);
114 }
115
116 assert((-(Offset + StackSize)) % MFI.getObjectAlign(FI).value() == 0);
117 return StackOffset::getFixed(Offset + StackSize);
118 }
119
120 if (!HasFP)
121 return StackOffset::getFixed(Offset + StackSize);
122
123 // Skip the saved FP.
124 Offset += SlotSize;
125
126 // Skip the RETADDR move area
127 int TailCallReturnAddrDelta = MMFI->getTCReturnAddrDelta();
128 if (TailCallReturnAddrDelta < 0)
129 Offset -= TailCallReturnAddrDelta;
130
132}
133
134/// Return a caller-saved register that isn't live
135/// when it reaches the "return" instruction. We can then pop a stack object
136/// to this register without worry about clobbering it.
139 const M68kRegisterInfo *TRI) {
140 const MachineFunction *MF = MBB.getParent();
141 if (MF->callsEHReturn())
142 return 0;
143
144 const TargetRegisterClass &AvailableRegs = *TRI->getRegsForTailCall(*MF);
145
146 if (MBBI == MBB.end())
147 return 0;
148
149 switch (MBBI->getOpcode()) {
150 default:
151 return 0;
152 case TargetOpcode::PATCHABLE_RET:
153 case M68k::RET: {
155
156 for (unsigned i = 0, e = MBBI->getNumOperands(); i != e; ++i) {
157 MachineOperand &MO = MBBI->getOperand(i);
158 if (!MO.isReg() || MO.isDef())
159 continue;
160 Register Reg = MO.getReg();
161 if (!Reg)
162 continue;
163 for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
164 Uses.insert(*AI);
165 }
166
167 for (auto CS : AvailableRegs)
168 if (!Uses.count(CS))
169 return CS;
170 }
171 }
172
173 return 0;
174}
175
176static bool isRegLiveIn(MachineBasicBlock &MBB, unsigned Reg) {
177 return llvm::any_of(MBB.liveins(),
179 return RegMask.PhysReg == Reg;
180 });
181}
182
184M68kFrameLowering::calculateMaxStackAlign(const MachineFunction &MF) const {
185 const MachineFrameInfo &MFI = MF.getFrameInfo();
186 uint64_t MaxAlign = MFI.getMaxAlign().value(); // Desired stack alignment.
187 unsigned StackAlign = getStackAlignment(); // ABI alignment
188 if (MF.getFunction().hasFnAttribute("stackrealign")) {
189 if (MFI.hasCalls())
190 MaxAlign = (StackAlign > MaxAlign) ? StackAlign : MaxAlign;
191 else if (MaxAlign < SlotSize)
192 MaxAlign = SlotSize;
193 }
194 return MaxAlign;
195}
196
197void M68kFrameLowering::BuildStackAlignAND(MachineBasicBlock &MBB,
199 const DebugLoc &DL, unsigned Reg,
200 uint64_t MaxAlign) const {
201 uint64_t Val = -MaxAlign;
202 unsigned AndOp = M68k::AND32di;
203 unsigned MovOp = M68k::MOV32rr;
204
205 // This function is normally used with SP which is Address Register, but AND,
206 // or any other logical instructions in M68k do not support ARs so we need
207 // to use a temp Data Register to perform the op.
208 unsigned Tmp = M68k::D0;
209
210 BuildMI(MBB, MBBI, DL, TII.get(MovOp), Tmp)
211 .addReg(Reg)
213
214 MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(AndOp), Tmp)
215 .addReg(Tmp)
216 .addImm(Val)
218
219 // The CCR implicit def is dead.
220 MI->getOperand(3).setIsDead();
221
222 BuildMI(MBB, MBBI, DL, TII.get(MovOp), Reg)
223 .addReg(Tmp)
225}
226
230 bool ReserveCallFrame = hasReservedCallFrame(MF);
231 unsigned Opcode = I->getOpcode();
232 bool IsDestroy = Opcode == TII.getCallFrameDestroyOpcode();
233 DebugLoc DL = I->getDebugLoc();
234 uint64_t Amount = !ReserveCallFrame ? I->getOperand(0).getImm() : 0;
235 uint64_t InternalAmt = (IsDestroy && Amount) ? I->getOperand(1).getImm() : 0;
236 I = MBB.erase(I);
237
238 if (!ReserveCallFrame) {
239 // If the stack pointer can be changed after prologue, turn the
240 // adjcallstackup instruction into a 'sub %SP, <amt>' and the
241 // adjcallstackdown instruction into 'add %SP, <amt>'
242
243 // We need to keep the stack aligned properly. To do this, we round the
244 // amount of space needed for the outgoing arguments up to the next
245 // alignment boundary.
246 unsigned StackAlign = getStackAlignment();
247 Amount = alignTo(Amount, StackAlign);
248
249 bool DwarfCFI = MF.needsFrameMoves();
250
251 // If we have any exception handlers in this function, and we adjust
252 // the SP before calls, we may need to indicate this to the unwinder
253 // using GNU_ARGS_SIZE. Note that this may be necessary even when
254 // Amount == 0, because the preceding function may have set a non-0
255 // GNU_ARGS_SIZE.
256 // TODO: We don't need to reset this between subsequent functions,
257 // if it didn't change.
258 bool HasDwarfEHHandlers = !MF.getLandingPads().empty();
259
260 if (HasDwarfEHHandlers && !IsDestroy &&
262 BuildCFI(MBB, I, DL,
263 MCCFIInstruction::createGnuArgsSize(nullptr, Amount));
264 }
265
266 if (Amount == 0)
267 return I;
268
269 // Factor out the amount that gets handled inside the sequence
270 // (Pushes of argument for frame setup, callee pops for frame destroy)
271 Amount -= InternalAmt;
272
273 // TODO: This is needed only if we require precise CFA.
274 // If this is a callee-pop calling convention, emit a CFA adjust for
275 // the amount the callee popped.
276 if (IsDestroy && InternalAmt && DwarfCFI && !hasFP(MF))
277 BuildCFI(MBB, I, DL,
278 MCCFIInstruction::createAdjustCfaOffset(nullptr, -InternalAmt));
279
280 // Add Amount to SP to destroy a frame, or subtract to setup.
281 int64_t StackAdjustment = IsDestroy ? Amount : -Amount;
282 int64_t CfaAdjustment = -StackAdjustment;
283
284 if (StackAdjustment) {
285 // Merge with any previous or following adjustment instruction. Note: the
286 // instructions merged with here do not have CFI, so their stack
287 // adjustments do not feed into CfaAdjustment.
288 StackAdjustment += mergeSPUpdates(MBB, I, true);
289 StackAdjustment += mergeSPUpdates(MBB, I, false);
290
291 if (StackAdjustment) {
292 BuildStackAdjustment(MBB, I, DL, StackAdjustment, false);
293 }
294 }
295
296 if (DwarfCFI && !hasFP(MF)) {
297 // If we don't have FP, but need to generate unwind information,
298 // we need to set the correct CFA offset after the stack adjustment.
299 // How much we adjust the CFA offset depends on whether we're emitting
300 // CFI only for EH purposes or for debugging. EH only requires the CFA
301 // offset to be correct at each call site, while for debugging we want
302 // it to be more precise.
303
304 // TODO: When not using precise CFA, we also need to adjust for the
305 // InternalAmt here.
306 if (CfaAdjustment) {
307 BuildCFI(
308 MBB, I, DL,
309 MCCFIInstruction::createAdjustCfaOffset(nullptr, CfaAdjustment));
310 }
311 }
312
313 return I;
314 }
315
316 if (IsDestroy && InternalAmt) {
317 // If we are performing frame pointer elimination and if the callee pops
318 // something off the stack pointer, add it back. We do this until we have
319 // more advanced stack pointer tracking ability.
320 // We are not tracking the stack pointer adjustment by the callee, so make
321 // sure we restore the stack pointer immediately after the call, there may
322 // be spill code inserted between the CALL and ADJCALLSTACKUP instructions.
325 while (CI != B && !std::prev(CI)->isCall())
326 --CI;
327 BuildStackAdjustment(MBB, CI, DL, -InternalAmt, /*InEpilogue=*/false);
328 }
329
330 return I;
331}
332
333/// Emit a series of instructions to increment / decrement the stack pointer by
334/// a constant value.
337 int64_t NumBytes, bool InEpilogue) const {
338 bool IsSub = NumBytes < 0;
339 uint64_t Offset = IsSub ? -NumBytes : NumBytes;
340
341 uint64_t Chunk = (1LL << 31) - 1;
343
344 while (Offset) {
345 if (Offset > Chunk) {
346 // Rather than emit a long series of instructions for large offsets,
347 // load the offset into a register and do one sub/add
348 Register Reg;
349
350 if (IsSub && !isRegLiveIn(MBB, M68k::D0))
351 Reg = M68k::D0;
352 else
353 Reg = findDeadCallerSavedReg(MBB, MBBI, TRI);
354
355 if (Reg) {
356 unsigned Opc = M68k::MOV32ri;
357 BuildMI(MBB, MBBI, DL, TII.get(Opc), Reg).addImm(Offset);
358 Opc = IsSub ? M68k::SUB32ar : M68k::ADD32ar;
359 MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr)
360 .addReg(StackPtr)
361 .addReg(Reg);
362 // ??? still no CCR
363 MI->getOperand(3).setIsDead(); // The CCR implicit def is dead.
364 Offset = 0;
365 continue;
366 }
367 }
368
369 uint64_t ThisVal = std::min(Offset, Chunk);
370
371 MachineInstrBuilder MI = BuildStackAdjustment(
372 MBB, MBBI, DL, IsSub ? -ThisVal : ThisVal, InEpilogue);
373 if (IsSub)
374 MI.setMIFlag(MachineInstr::FrameSetup);
375 else
377
378 Offset -= ThisVal;
379 }
380}
381
384 bool MergeWithPrevious) const {
385 if ((MergeWithPrevious && MBBI == MBB.begin()) ||
386 (!MergeWithPrevious && MBBI == MBB.end()))
387 return 0;
388
389 MachineBasicBlock::iterator PI = MergeWithPrevious ? std::prev(MBBI) : MBBI;
391 MergeWithPrevious ? nullptr : std::next(MBBI);
392 unsigned Opc = PI->getOpcode();
393 int Offset = 0;
394
395 if (!MergeWithPrevious && NI != MBB.end() &&
396 NI->getOpcode() == TargetOpcode::CFI_INSTRUCTION) {
397 // Don't merge with the next instruction if it has CFI.
398 return Offset;
399 }
400
401 if (Opc == M68k::ADD32ai && PI->getOperand(0).getReg() == StackPtr) {
402 assert(PI->getOperand(1).getReg() == StackPtr);
403 Offset += PI->getOperand(2).getImm();
404 MBB.erase(PI);
405 if (!MergeWithPrevious)
406 MBBI = NI;
407 } else if (Opc == M68k::SUB32ai && PI->getOperand(0).getReg() == StackPtr) {
408 assert(PI->getOperand(1).getReg() == StackPtr);
409 Offset -= PI->getOperand(2).getImm();
410 MBB.erase(PI);
411 if (!MergeWithPrevious)
412 MBBI = NI;
413 }
414
415 return Offset;
416}
417
418MachineInstrBuilder M68kFrameLowering::BuildStackAdjustment(
420 const DebugLoc &DL, int64_t Offset, bool InEpilogue) const {
421 assert(Offset != 0 && "zero offset stack adjustment requested");
422
423 // TODO can `lea` be used to adjust stack?
424
425 bool IsSub = Offset < 0;
426 uint64_t AbsOffset = IsSub ? -Offset : Offset;
427 unsigned Opc = IsSub ? M68k::SUB32ai : M68k::ADD32ai;
428
429 MachineInstrBuilder MI = BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr)
430 .addReg(StackPtr)
431 .addImm(AbsOffset);
432 // FIXME Update CCR as well. For now we just
433 // conservatively say CCR implicit def is dead
434 MI->getOperand(3).setIsDead();
435 return MI;
436}
437
438void M68kFrameLowering::BuildCFI(MachineBasicBlock &MBB,
440 const DebugLoc &DL,
441 const MCCFIInstruction &CFIInst) const {
443 unsigned CFIIndex = MF.addFrameInst(CFIInst);
444 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
445 .addCFIIndex(CFIIndex);
446}
447
448void M68kFrameLowering::emitPrologueCalleeSavedFrameMoves(
450 const DebugLoc &DL) const {
452 MachineFrameInfo &MFI = MF.getFrameInfo();
454
455 // Add callee saved registers to move list.
456 const auto &CSI = MFI.getCalleeSavedInfo();
457 if (CSI.empty())
458 return;
459
460 // Calculate offsets.
461 for (const auto &I : CSI) {
462 int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
463 Register Reg = I.getReg();
464
465 unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
466 BuildCFI(MBB, MBBI, DL,
467 MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
468 }
469}
470
472 MachineBasicBlock &MBB) const {
473 assert(&STI == &MF.getSubtarget<M68kSubtarget>() &&
474 "MF used frame lowering for wrong subtarget");
475
477 MachineFrameInfo &MFI = MF.getFrameInfo();
479 uint64_t MaxAlign = calculateMaxStackAlign(MF); // Desired stack alignment.
480 uint64_t StackSize = MFI.getStackSize(); // Number of bytes to allocate.
481 bool HasFP = hasFP(MF);
482 bool NeedsDwarfCFI = MF.needsFrameMoves();
484 const unsigned MachineFramePtr = FramePtr;
485 unsigned BasePtr = TRI->getBaseRegister();
486
487 // Debug location must be unknown since the first debug location is used
488 // to determine the end of the prologue.
489 DebugLoc DL;
490
491 // Add RETADDR move area to callee saved frame size.
492 int TailCallReturnAddrDelta = MMFI->getTCReturnAddrDelta();
493
494 if (TailCallReturnAddrDelta < 0) {
496 TailCallReturnAddrDelta);
497 }
498
499 // Insert stack pointer adjustment for later moving of return addr. Only
500 // applies to tail call optimized functions where the callee argument stack
501 // size is bigger than the callers.
502 if (TailCallReturnAddrDelta < 0) {
503 BuildStackAdjustment(MBB, MBBI, DL, TailCallReturnAddrDelta,
504 /*InEpilogue=*/false)
506 }
507
508 // Mapping for machine moves:
509 //
510 // DST: VirtualFP AND
511 // SRC: VirtualFP => DW_CFA_def_cfa_offset
512 // ELSE => DW_CFA_def_cfa
513 //
514 // SRC: VirtualFP AND
515 // DST: Register => DW_CFA_def_cfa_register
516 //
517 // ELSE
518 // OFFSET < 0 => DW_CFA_offset_extended_sf
519 // REG < 64 => DW_CFA_offset + Reg
520 // ELSE => DW_CFA_offset_extended
521
522 uint64_t NumBytes = 0;
523 int stackGrowth = -SlotSize;
524
525 if (HasFP) {
526 // Calculate required stack adjustment.
527 uint64_t FrameSize = StackSize - SlotSize;
528 // If required, include space for extra hidden slot for stashing base
529 // pointer.
530 if (MMFI->getRestoreBasePointer())
531 FrameSize += SlotSize;
532
533 NumBytes = FrameSize - MMFI->getCalleeSavedFrameSize();
534
535 // Callee-saved registers are pushed on stack before the stack is realigned.
536 if (TRI->hasStackRealignment(MF))
537 NumBytes = alignTo(NumBytes, MaxAlign);
538
539 // Get the offset of the stack slot for the FP register, which is
540 // guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
541 // Update the frame offset adjustment.
542 MFI.setOffsetAdjustment(-NumBytes);
543
544 BuildMI(MBB, MBBI, DL, TII.get(M68k::LINK16))
545 .addReg(M68k::WA6, RegState::Kill)
546 .addImm(-NumBytes)
548
549 if (NeedsDwarfCFI) {
550 // Mark the place where FP was saved.
551 // Define the current CFA rule to use the provided offset.
552 assert(StackSize);
553 BuildCFI(MBB, MBBI, DL,
554 MCCFIInstruction::cfiDefCfaOffset(nullptr, 2 * stackGrowth));
555
556 // Change the rule for the FramePtr to be an "offset" rule.
557 int DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true);
558 assert(DwarfFramePtr > 0);
559 BuildCFI(MBB, MBBI, DL,
560 MCCFIInstruction::createOffset(nullptr, DwarfFramePtr,
561 2 * stackGrowth));
562 }
563
564 if (NeedsDwarfCFI) {
565 // Mark effective beginning of when frame pointer becomes valid.
566 // Define the current CFA to use the FP register.
567 unsigned DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true);
568 BuildCFI(MBB, MBBI, DL,
569 MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr));
570 }
571
572 // Mark the FramePtr as live-in in every block. Don't do this again for
573 // funclet prologues.
574 for (MachineBasicBlock &EveryMBB : MF)
575 EveryMBB.addLiveIn(MachineFramePtr);
576 } else {
577 NumBytes = StackSize - MMFI->getCalleeSavedFrameSize();
578 }
579
580 // Skip the callee-saved push instructions.
581 bool PushedRegs = false;
582 int StackOffset = 2 * stackGrowth;
583
584 while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup) &&
585 MBBI->getOpcode() == M68k::PUSH32r) {
586 PushedRegs = true;
587 ++MBBI;
588
589 if (!HasFP && NeedsDwarfCFI) {
590 // Mark callee-saved push instruction.
591 // Define the current CFA rule to use the provided offset.
592 assert(StackSize);
593 BuildCFI(MBB, MBBI, DL,
595 StackOffset += stackGrowth;
596 }
597 }
598
599 // Realign stack after we pushed callee-saved registers (so that we'll be
600 // able to calculate their offsets from the frame pointer).
601 if (TRI->hasStackRealignment(MF)) {
602 assert(HasFP && "There should be a frame pointer if stack is realigned.");
603 BuildStackAlignAND(MBB, MBBI, DL, StackPtr, MaxAlign);
604 }
605
606 // If there is an SUB32ri of SP immediately before this instruction, merge
607 // the two. This can be the case when tail call elimination is enabled and
608 // the callee has more arguments then the caller.
609 NumBytes -= mergeSPUpdates(MBB, MBBI, true);
610
611 // Adjust stack pointer: ESP -= numbytes.
612 if (!HasFP)
613 emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, /*InEpilogue=*/false);
614
615 unsigned SPOrEstablisher = StackPtr;
616
617 // If we need a base pointer, set it up here. It's whatever the value
618 // of the stack pointer is at this point. Any variable size objects
619 // will be allocated after this, so we can still use the base pointer
620 // to reference locals.
621 if (TRI->hasBasePointer(MF)) {
622 // Update the base pointer with the current stack pointer.
623 BuildMI(MBB, MBBI, DL, TII.get(M68k::MOV32aa), BasePtr)
624 .addReg(SPOrEstablisher)
626 if (MMFI->getRestoreBasePointer()) {
627 // Stash value of base pointer. Saving SP instead of FP shortens
628 // dependence chain. Used by SjLj EH.
629 unsigned Opm = M68k::MOV32ja;
631 FramePtr, true,
633 .addReg(SPOrEstablisher)
635 }
636 }
637
638 if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) {
639 // Mark end of stack pointer adjustment.
640 if (!HasFP && NumBytes) {
641 // Define the current CFA rule to use the provided offset.
642 assert(StackSize);
643 BuildCFI(
644 MBB, MBBI, DL,
645 MCCFIInstruction::cfiDefCfaOffset(nullptr, -StackSize + stackGrowth));
646 }
647
648 // Emit DWARF info specifying the offsets of the callee-saved registers.
649 if (PushedRegs)
650 emitPrologueCalleeSavedFrameMoves(MBB, MBBI, DL);
651 }
652
653 // TODO Interrupt handlers
654 // M68k Interrupt handling function cannot assume anything about the
655 // direction flag (DF in CCR register). Clear this flag by creating "cld"
656 // instruction in each prologue of interrupt handler function. The "cld"
657 // instruction should only in these cases:
658 // 1. The interrupt handling function uses any of the "rep" instructions.
659 // 2. Interrupt handling function calls another function.
660}
661
662static bool isTailCallOpcode(unsigned Opc) {
663 return Opc == M68k::TCRETURNj || Opc == M68k::TCRETURNq;
664}
665
667 MachineBasicBlock &MBB) const {
668 const MachineFrameInfo &MFI = MF.getFrameInfo();
671 std::optional<unsigned> RetOpcode;
672 if (MBBI != MBB.end())
673 RetOpcode = MBBI->getOpcode();
674 DebugLoc DL;
675 if (MBBI != MBB.end())
676 DL = MBBI->getDebugLoc();
678 unsigned MachineFramePtr = FramePtr;
679
680 // Get the number of bytes to allocate from the FrameInfo.
681 uint64_t StackSize = MFI.getStackSize();
682 uint64_t MaxAlign = calculateMaxStackAlign(MF);
683 unsigned CSSize = MMFI->getCalleeSavedFrameSize();
684 uint64_t NumBytes = 0;
685
686 if (hasFP(MF)) {
687 // Calculate required stack adjustment.
688 uint64_t FrameSize = StackSize - SlotSize;
689 NumBytes = FrameSize - CSSize;
690
691 // Callee-saved registers were pushed on stack before the stack was
692 // realigned.
693 if (TRI->hasStackRealignment(MF))
694 NumBytes = alignTo(FrameSize, MaxAlign);
695
696 } else {
697 NumBytes = StackSize - CSSize;
698 }
699
700 // Skip the callee-saved pop instructions.
701 while (MBBI != MBB.begin()) {
702 MachineBasicBlock::iterator PI = std::prev(MBBI);
703 unsigned Opc = PI->getOpcode();
704
705 if ((Opc != M68k::POP32r || !PI->getFlag(MachineInstr::FrameDestroy)) &&
706 Opc != M68k::DBG_VALUE && !PI->isTerminator())
707 break;
708
709 --MBBI;
710 }
712
713 if (MBBI != MBB.end())
714 DL = MBBI->getDebugLoc();
715
716 // If there is an ADD32ri or SUB32ri of SP immediately before this
717 // instruction, merge the two instructions.
718 if (NumBytes || MFI.hasVarSizedObjects())
719 NumBytes += mergeSPUpdates(MBB, MBBI, true);
720
721 // If dynamic alloca is used, then reset SP to point to the last callee-saved
722 // slot before popping them off! Same applies for the case, when stack was
723 // realigned. Don't do this if this was a funclet epilogue, since the funclets
724 // will not do realignment or dynamic stack allocation.
725 if ((TRI->hasStackRealignment(MF) || MFI.hasVarSizedObjects())) {
726 if (TRI->hasStackRealignment(MF))
727 MBBI = FirstCSPop;
728 uint64_t LEAAmount = -CSSize;
729
730 // 'move %FramePtr, SP' will not be recognized as an epilogue sequence.
731 // However, we may use this sequence if we have a frame pointer because the
732 // effects of the prologue can safely be undone.
733 if (LEAAmount != 0) {
734 unsigned Opc = M68k::LEA32p;
736 BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr), FramePtr, false,
737 LEAAmount);
738 --MBBI;
739 } else {
740 BuildMI(MBB, MBBI, DL, TII.get(M68k::UNLK))
741 .addReg(MachineFramePtr, RegState::Kill)
743 --MBBI;
744 }
745 } else if (hasFP(MF)) {
746 BuildMI(MBB, MBBI, DL, TII.get(M68k::UNLK))
747 .addReg(MachineFramePtr, RegState::Kill)
749 } else if (NumBytes) {
750 // Adjust stack pointer back: SP += numbytes.
751 emitSPUpdate(MBB, MBBI, NumBytes, /*InEpilogue=*/true);
752 --MBBI;
753 }
754
755 if (!RetOpcode || !isTailCallOpcode(*RetOpcode)) {
756 // Add the return addr area delta back since we are not tail calling.
757 int Offset = -1 * MMFI->getTCReturnAddrDelta();
758 assert(Offset >= 0 && "TCDelta should never be positive");
759 if (Offset) {
761
762 // Check for possible merge with preceding ADD instruction.
763 Offset += mergeSPUpdates(MBB, MBBI, true);
764 emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true);
765 }
766 }
767}
768
770 BitVector &SavedRegs,
771 RegScavenger *RS) const {
773
774 MachineFrameInfo &MFI = MF.getFrameInfo();
775
777 int64_t TailCallReturnAddrDelta = M68kFI->getTCReturnAddrDelta();
778
779 if (TailCallReturnAddrDelta < 0) {
780 // create RETURNADDR area
781 // arg
782 // arg
783 // RETADDR
784 // { ...
785 // RETADDR area
786 // ...
787 // }
788 // [FP]
789 MFI.CreateFixedObject(-TailCallReturnAddrDelta,
790 TailCallReturnAddrDelta - SlotSize, true);
791 }
792
793 // Spill the BasePtr if it's used.
794 if (TRI->hasBasePointer(MF)) {
795 SavedRegs.set(TRI->getBaseRegister());
796 }
797}
798
801 std::vector<CalleeSavedInfo> &CSI) const {
802 MachineFrameInfo &MFI = MF.getFrameInfo();
804
805 int SpillSlotOffset = getOffsetOfLocalArea() + M68kFI->getTCReturnAddrDelta();
806
807 if (hasFP(MF)) {
808 // emitPrologue always spills frame register the first thing.
809 SpillSlotOffset -= SlotSize;
810 MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset);
811
812 // Since emitPrologue and emitEpilogue will handle spilling and restoring of
813 // the frame register, we can delete it from CSI list and not have to worry
814 // about avoiding it later.
815 Register FPReg = TRI->getFrameRegister(MF);
816 for (unsigned i = 0, e = CSI.size(); i < e; ++i) {
817 if (TRI->regsOverlap(CSI[i].getReg(), FPReg)) {
818 CSI.erase(CSI.begin() + i);
819 break;
820 }
821 }
822 }
823
824 // The rest is fine
825 return false;
826}
827
831 auto &MRI = *static_cast<const M68kRegisterInfo *>(TRI);
832 auto DL = MBB.findDebugLoc(MI);
833
834 int FI = 0;
835 unsigned Mask = 0;
836 for (const auto &Info : CSI) {
837 FI = std::max(FI, Info.getFrameIdx());
838 Register Reg = Info.getReg();
839 unsigned Shift = MRI.getSpillRegisterOrder(Reg);
840 Mask |= 1 << Shift;
841 }
842
843 auto I =
844 M68k::addFrameReference(BuildMI(MBB, MI, DL, TII.get(M68k::MOVM32pm)), FI)
845 .addImm(Mask)
847
848 // Append implicit registers and mem locations
849 const MachineFunction &MF = *MBB.getParent();
850 const MachineRegisterInfo &RI = MF.getRegInfo();
851 for (const auto &Info : CSI) {
852 Register Reg = Info.getReg();
853 bool IsLiveIn = RI.isLiveIn(Reg);
854 if (!IsLiveIn)
855 MBB.addLiveIn(Reg);
856 I.addReg(Reg, IsLiveIn ? RegState::Implicit : RegState::ImplicitKill);
857 M68k::addMemOperand(I, Info.getFrameIdx(), 0);
858 }
859
860 return true;
861}
862
866 auto &MRI = *static_cast<const M68kRegisterInfo *>(TRI);
867 auto DL = MBB.findDebugLoc(MI);
868
869 int FI = 0;
870 unsigned Mask = 0;
871 for (const auto &Info : CSI) {
872 FI = std::max(FI, Info.getFrameIdx());
873 Register Reg = Info.getReg();
874 unsigned Shift = MRI.getSpillRegisterOrder(Reg);
875 Mask |= 1 << Shift;
876 }
877
879 BuildMI(MBB, MI, DL, TII.get(M68k::MOVM32mp)).addImm(Mask), FI)
881
882 // Append implicit registers and mem locations
883 for (const auto &Info : CSI) {
884 I.addReg(Info.getReg(), RegState::ImplicitDefine);
885 M68k::addMemOperand(I, Info.getFrameIdx(), 0);
886 }
887
888 return true;
889}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
Rewrite Partial Register Uses
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
static bool isRegLiveIn(MachineBasicBlock &MBB, unsigned Reg)
static bool isTailCallOpcode(unsigned Opc)
static unsigned findDeadCallerSavedReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const M68kRegisterInfo *TRI)
Return a caller-saved register that isn't live when it reaches the "return" instruction.
This file contains the M68k declaration of TargetFrameLowering class.
This file exposes functions that may be used with BuildMI from the MachineInstrBuilder....
This file contains the M68k implementation of the TargetInstrInfo class.
This file declares the M68k specific subclass of MachineFunctionInfo.
This file declares the M68k specific subclass of TargetSubtargetInfo.
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallSet class.
static const unsigned FramePtr
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
BitVector & set()
Definition: BitVector.h:351
A debug info location.
Definition: DebugLoc.h:33
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.cpp:743
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
Insert epilog code into the function.
void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, int64_t NumBytes, bool InEpilogue) const
Emit a series of instructions to increment / decrement the stack pointer by a constant value.
bool assignCalleeSavedSpillSlots(MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector< CalleeSavedInfo > &CSI) const override
Allows target to override spill slot assignment logic.
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
Issues instruction(s) to spill all callee saved registers and returns true if it isn't possible / pro...
bool hasReservedCallFrame(const MachineFunction &MF) const override
Under normal circumstances, when a frame pointer is not required, we reserve argument space for call ...
M68kFrameLowering(const M68kSubtarget &sti, Align Alignment)
int mergeSPUpdates(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, bool doMergeWithPrevious) const
Check the instruction before/after the passed instruction.
StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const override
This method should return the base register and offset used to reference a frame index location.
MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
Insert prolog code into the function.
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
Issues instruction(s) to restore all callee saved registers and returns true if it isn't possible / p...
bool hasFP(const MachineFunction &MF) const override
Return true if the specified function should have a dedicated frame pointer register.
bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override
If there is a reserved call frame, the call frame pseudos can be simplified.
bool needsFrameIndexResolution(const MachineFunction &MF) const override
unsigned getCalleeSavedFrameSize() const
void setCalleeSavedFrameSize(unsigned bytes)
Register getFrameRegister(const MachineFunction &MF) const override
unsigned getBaseRegister() const
bool hasBasePointer(const MachineFunction &MF) const
unsigned getStackRegister() const
unsigned getSlotSize() const
getSlotSize - Stack slot size in bytes.
const M68kRegisterInfo * getRegisterInfo() const override
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_def_cfa_register modifies a rule for computing CFA.
Definition: MCDwarf.h:565
static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int64_t Size, SMLoc Loc={})
A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE.
Definition: MCDwarf.h:670
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
Definition: MCDwarf.h:600
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
Definition: MCDwarf.h:573
static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int64_t Adjustment, SMLoc Loc={})
.cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but Offset is a relative value that is added/subt...
Definition: MCDwarf.h:581
const MCRegisterInfo * getRegisterInfo() const
Definition: MCContext.h:414
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:63
MCRegAliasIterator enumerates all registers aliasing Reg.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
iterator_range< livein_iterator > liveins() const
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool hasCalls() const
Return true if the current function has any function calls.
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
bool hasStackObjects() const
Return true if there are any stack objects in this function.
int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, bool IsImmutable=false)
Create a spill slot at a fixed location on the stack.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
void setOffsetAdjustment(int64_t Adj)
Set the correction for frame offsets.
unsigned addFrameInst(const MCCFIInstruction &Inst)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
bool needsFrameMoves() const
True if this function needs frame moves for debug or exceptions.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const std::vector< LandingPadInfo > & getLandingPads() const
Return a reference to the landing pad info for the current function.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
Definition: MachineInstr.h:69
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool isLiveIn(Register Reg) const
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:307
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:135
StackOffset holds a fixed and a scalable offset in bytes.
Definition: TypeSize.h:33
int64_t getFixed() const
Returns the fixed component of the stack.
Definition: TypeSize.h:49
Information about stack frame layout on the target.
unsigned getStackAlignment() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
int getOffsetOfLocalArea() const
getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...
unsigned getCallFrameDestroyOpcode() const
TargetOptions Options
bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
static const MachineInstrBuilder & addMemOperand(const MachineInstrBuilder &MIB, int FI, int Offset=0)
static const MachineInstrBuilder & addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset=0)
addFrameReference - This function is used to add a reference to the base of an abstract object on the...
static const MachineInstrBuilder & addRegIndirectWithDisp(const MachineInstrBuilder &MIB, Register Reg, bool IsKill, int Offset)
addRegIndirectWithDisp - This function is used to add a memory reference of the form (Offset,...
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ DwarfCFI
DWARF-like instruction based exceptions.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1729
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition: Alignment.h:85
Pair of physical register and lane mask.