LLVM 19.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 MachineModuleInfo &MMI = MF.getMMI();
250 const auto &Fn = MF.getFunction();
251 bool DwarfCFI = MMI.hasDebugInfo() || Fn.needsUnwindTableEntry();
252
253 // If we have any exception handlers in this function, and we adjust
254 // the SP before calls, we may need to indicate this to the unwinder
255 // using GNU_ARGS_SIZE. Note that this may be necessary even when
256 // Amount == 0, because the preceding function may have set a non-0
257 // GNU_ARGS_SIZE.
258 // TODO: We don't need to reset this between subsequent functions,
259 // if it didn't change.
260 bool HasDwarfEHHandlers = !MF.getLandingPads().empty();
261
262 if (HasDwarfEHHandlers && !IsDestroy &&
264 BuildCFI(MBB, I, DL,
265 MCCFIInstruction::createGnuArgsSize(nullptr, Amount));
266 }
267
268 if (Amount == 0)
269 return I;
270
271 // Factor out the amount that gets handled inside the sequence
272 // (Pushes of argument for frame setup, callee pops for frame destroy)
273 Amount -= InternalAmt;
274
275 // TODO: This is needed only if we require precise CFA.
276 // If this is a callee-pop calling convention, emit a CFA adjust for
277 // the amount the callee popped.
278 if (IsDestroy && InternalAmt && DwarfCFI && !hasFP(MF))
279 BuildCFI(MBB, I, DL,
280 MCCFIInstruction::createAdjustCfaOffset(nullptr, -InternalAmt));
281
282 // Add Amount to SP to destroy a frame, or subtract to setup.
283 int64_t StackAdjustment = IsDestroy ? Amount : -Amount;
284 int64_t CfaAdjustment = -StackAdjustment;
285
286 if (StackAdjustment) {
287 // Merge with any previous or following adjustment instruction. Note: the
288 // instructions merged with here do not have CFI, so their stack
289 // adjustments do not feed into CfaAdjustment.
290 StackAdjustment += mergeSPUpdates(MBB, I, true);
291 StackAdjustment += mergeSPUpdates(MBB, I, false);
292
293 if (StackAdjustment) {
294 BuildStackAdjustment(MBB, I, DL, StackAdjustment, false);
295 }
296 }
297
298 if (DwarfCFI && !hasFP(MF)) {
299 // If we don't have FP, but need to generate unwind information,
300 // we need to set the correct CFA offset after the stack adjustment.
301 // How much we adjust the CFA offset depends on whether we're emitting
302 // CFI only for EH purposes or for debugging. EH only requires the CFA
303 // offset to be correct at each call site, while for debugging we want
304 // it to be more precise.
305
306 // TODO: When not using precise CFA, we also need to adjust for the
307 // InternalAmt here.
308 if (CfaAdjustment) {
309 BuildCFI(
310 MBB, I, DL,
311 MCCFIInstruction::createAdjustCfaOffset(nullptr, CfaAdjustment));
312 }
313 }
314
315 return I;
316 }
317
318 if (IsDestroy && InternalAmt) {
319 // If we are performing frame pointer elimination and if the callee pops
320 // something off the stack pointer, add it back. We do this until we have
321 // more advanced stack pointer tracking ability.
322 // We are not tracking the stack pointer adjustment by the callee, so make
323 // sure we restore the stack pointer immediately after the call, there may
324 // be spill code inserted between the CALL and ADJCALLSTACKUP instructions.
327 while (CI != B && !std::prev(CI)->isCall())
328 --CI;
329 BuildStackAdjustment(MBB, CI, DL, -InternalAmt, /*InEpilogue=*/false);
330 }
331
332 return I;
333}
334
335/// Emit a series of instructions to increment / decrement the stack pointer by
336/// a constant value.
339 int64_t NumBytes, bool InEpilogue) const {
340 bool IsSub = NumBytes < 0;
341 uint64_t Offset = IsSub ? -NumBytes : NumBytes;
342
343 uint64_t Chunk = (1LL << 31) - 1;
345
346 while (Offset) {
347 if (Offset > Chunk) {
348 // Rather than emit a long series of instructions for large offsets,
349 // load the offset into a register and do one sub/add
350 Register Reg;
351
352 if (IsSub && !isRegLiveIn(MBB, M68k::D0))
353 Reg = M68k::D0;
354 else
355 Reg = findDeadCallerSavedReg(MBB, MBBI, TRI);
356
357 if (Reg) {
358 unsigned Opc = M68k::MOV32ri;
359 BuildMI(MBB, MBBI, DL, TII.get(Opc), Reg).addImm(Offset);
360 Opc = IsSub ? M68k::SUB32ar : M68k::ADD32ar;
361 MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr)
362 .addReg(StackPtr)
363 .addReg(Reg);
364 // ??? still no CCR
365 MI->getOperand(3).setIsDead(); // The CCR implicit def is dead.
366 Offset = 0;
367 continue;
368 }
369 }
370
371 uint64_t ThisVal = std::min(Offset, Chunk);
372
373 MachineInstrBuilder MI = BuildStackAdjustment(
374 MBB, MBBI, DL, IsSub ? -ThisVal : ThisVal, InEpilogue);
375 if (IsSub)
376 MI.setMIFlag(MachineInstr::FrameSetup);
377 else
379
380 Offset -= ThisVal;
381 }
382}
383
386 bool MergeWithPrevious) const {
387 if ((MergeWithPrevious && MBBI == MBB.begin()) ||
388 (!MergeWithPrevious && MBBI == MBB.end()))
389 return 0;
390
391 MachineBasicBlock::iterator PI = MergeWithPrevious ? std::prev(MBBI) : MBBI;
393 MergeWithPrevious ? nullptr : std::next(MBBI);
394 unsigned Opc = PI->getOpcode();
395 int Offset = 0;
396
397 if (!MergeWithPrevious && NI != MBB.end() &&
398 NI->getOpcode() == TargetOpcode::CFI_INSTRUCTION) {
399 // Don't merge with the next instruction if it has CFI.
400 return Offset;
401 }
402
403 if (Opc == M68k::ADD32ai && PI->getOperand(0).getReg() == StackPtr) {
404 assert(PI->getOperand(1).getReg() == StackPtr);
405 Offset += PI->getOperand(2).getImm();
406 MBB.erase(PI);
407 if (!MergeWithPrevious)
408 MBBI = NI;
409 } else if (Opc == M68k::SUB32ai && PI->getOperand(0).getReg() == StackPtr) {
410 assert(PI->getOperand(1).getReg() == StackPtr);
411 Offset -= PI->getOperand(2).getImm();
412 MBB.erase(PI);
413 if (!MergeWithPrevious)
414 MBBI = NI;
415 }
416
417 return Offset;
418}
419
420MachineInstrBuilder M68kFrameLowering::BuildStackAdjustment(
422 const DebugLoc &DL, int64_t Offset, bool InEpilogue) const {
423 assert(Offset != 0 && "zero offset stack adjustment requested");
424
425 // TODO can `lea` be used to adjust stack?
426
427 bool IsSub = Offset < 0;
428 uint64_t AbsOffset = IsSub ? -Offset : Offset;
429 unsigned Opc = IsSub ? M68k::SUB32ai : M68k::ADD32ai;
430
431 MachineInstrBuilder MI = BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr)
432 .addReg(StackPtr)
433 .addImm(AbsOffset);
434 // FIXME Update CCR as well. For now we just
435 // conservatively say CCR implicit def is dead
436 MI->getOperand(3).setIsDead();
437 return MI;
438}
439
440void M68kFrameLowering::BuildCFI(MachineBasicBlock &MBB,
442 const DebugLoc &DL,
443 const MCCFIInstruction &CFIInst) const {
445 unsigned CFIIndex = MF.addFrameInst(CFIInst);
446 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
447 .addCFIIndex(CFIIndex);
448}
449
450void M68kFrameLowering::emitPrologueCalleeSavedFrameMoves(
452 const DebugLoc &DL) const {
454 MachineFrameInfo &MFI = MF.getFrameInfo();
456
457 // Add callee saved registers to move list.
458 const auto &CSI = MFI.getCalleeSavedInfo();
459 if (CSI.empty())
460 return;
461
462 // Calculate offsets.
463 for (const auto &I : CSI) {
464 int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
465 Register Reg = I.getReg();
466
467 unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
468 BuildCFI(MBB, MBBI, DL,
469 MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
470 }
471}
472
474 MachineBasicBlock &MBB) const {
475 assert(&STI == &MF.getSubtarget<M68kSubtarget>() &&
476 "MF used frame lowering for wrong subtarget");
477
479 MachineFrameInfo &MFI = MF.getFrameInfo();
480 const auto &Fn = MF.getFunction();
481 MachineModuleInfo &MMI = MF.getMMI();
483 uint64_t MaxAlign = calculateMaxStackAlign(MF); // Desired stack alignment.
484 uint64_t StackSize = MFI.getStackSize(); // Number of bytes to allocate.
485 bool HasFP = hasFP(MF);
486 bool NeedsDwarfCFI = MMI.hasDebugInfo() || Fn.needsUnwindTableEntry();
488 const unsigned MachineFramePtr = FramePtr;
489 unsigned BasePtr = TRI->getBaseRegister();
490
491 // Debug location must be unknown since the first debug location is used
492 // to determine the end of the prologue.
493 DebugLoc DL;
494
495 // Add RETADDR move area to callee saved frame size.
496 int TailCallReturnAddrDelta = MMFI->getTCReturnAddrDelta();
497
498 if (TailCallReturnAddrDelta < 0) {
500 TailCallReturnAddrDelta);
501 }
502
503 // Insert stack pointer adjustment for later moving of return addr. Only
504 // applies to tail call optimized functions where the callee argument stack
505 // size is bigger than the callers.
506 if (TailCallReturnAddrDelta < 0) {
507 BuildStackAdjustment(MBB, MBBI, DL, TailCallReturnAddrDelta,
508 /*InEpilogue=*/false)
510 }
511
512 // Mapping for machine moves:
513 //
514 // DST: VirtualFP AND
515 // SRC: VirtualFP => DW_CFA_def_cfa_offset
516 // ELSE => DW_CFA_def_cfa
517 //
518 // SRC: VirtualFP AND
519 // DST: Register => DW_CFA_def_cfa_register
520 //
521 // ELSE
522 // OFFSET < 0 => DW_CFA_offset_extended_sf
523 // REG < 64 => DW_CFA_offset + Reg
524 // ELSE => DW_CFA_offset_extended
525
526 uint64_t NumBytes = 0;
527 int stackGrowth = -SlotSize;
528
529 if (HasFP) {
530 // Calculate required stack adjustment.
531 uint64_t FrameSize = StackSize - SlotSize;
532 // If required, include space for extra hidden slot for stashing base
533 // pointer.
534 if (MMFI->getRestoreBasePointer())
535 FrameSize += SlotSize;
536
537 NumBytes = FrameSize - MMFI->getCalleeSavedFrameSize();
538
539 // Callee-saved registers are pushed on stack before the stack is realigned.
540 if (TRI->hasStackRealignment(MF))
541 NumBytes = alignTo(NumBytes, MaxAlign);
542
543 // Get the offset of the stack slot for the FP register, which is
544 // guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
545 // Update the frame offset adjustment.
546 MFI.setOffsetAdjustment(-NumBytes);
547
548 BuildMI(MBB, MBBI, DL, TII.get(M68k::LINK16))
549 .addReg(M68k::WA6, RegState::Kill)
550 .addImm(-NumBytes)
552
553 if (NeedsDwarfCFI) {
554 // Mark the place where FP was saved.
555 // Define the current CFA rule to use the provided offset.
556 assert(StackSize);
557 BuildCFI(MBB, MBBI, DL,
558 MCCFIInstruction::cfiDefCfaOffset(nullptr, 2 * stackGrowth));
559
560 // Change the rule for the FramePtr to be an "offset" rule.
561 int DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true);
562 assert(DwarfFramePtr > 0);
563 BuildCFI(MBB, MBBI, DL,
564 MCCFIInstruction::createOffset(nullptr, DwarfFramePtr,
565 2 * stackGrowth));
566 }
567
568 if (NeedsDwarfCFI) {
569 // Mark effective beginning of when frame pointer becomes valid.
570 // Define the current CFA to use the FP register.
571 unsigned DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true);
572 BuildCFI(MBB, MBBI, DL,
573 MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr));
574 }
575
576 // Mark the FramePtr as live-in in every block. Don't do this again for
577 // funclet prologues.
578 for (MachineBasicBlock &EveryMBB : MF)
579 EveryMBB.addLiveIn(MachineFramePtr);
580 } else {
581 NumBytes = StackSize - MMFI->getCalleeSavedFrameSize();
582 }
583
584 // Skip the callee-saved push instructions.
585 bool PushedRegs = false;
586 int StackOffset = 2 * stackGrowth;
587
588 while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup) &&
589 MBBI->getOpcode() == M68k::PUSH32r) {
590 PushedRegs = true;
591 ++MBBI;
592
593 if (!HasFP && NeedsDwarfCFI) {
594 // Mark callee-saved push instruction.
595 // Define the current CFA rule to use the provided offset.
596 assert(StackSize);
597 BuildCFI(MBB, MBBI, DL,
599 StackOffset += stackGrowth;
600 }
601 }
602
603 // Realign stack after we pushed callee-saved registers (so that we'll be
604 // able to calculate their offsets from the frame pointer).
605 if (TRI->hasStackRealignment(MF)) {
606 assert(HasFP && "There should be a frame pointer if stack is realigned.");
607 BuildStackAlignAND(MBB, MBBI, DL, StackPtr, MaxAlign);
608 }
609
610 // If there is an SUB32ri of SP immediately before this instruction, merge
611 // the two. This can be the case when tail call elimination is enabled and
612 // the callee has more arguments then the caller.
613 NumBytes -= mergeSPUpdates(MBB, MBBI, true);
614
615 // Adjust stack pointer: ESP -= numbytes.
616 if (!HasFP)
617 emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, /*InEpilogue=*/false);
618
619 unsigned SPOrEstablisher = StackPtr;
620
621 // If we need a base pointer, set it up here. It's whatever the value
622 // of the stack pointer is at this point. Any variable size objects
623 // will be allocated after this, so we can still use the base pointer
624 // to reference locals.
625 if (TRI->hasBasePointer(MF)) {
626 // Update the base pointer with the current stack pointer.
627 BuildMI(MBB, MBBI, DL, TII.get(M68k::MOV32aa), BasePtr)
628 .addReg(SPOrEstablisher)
630 if (MMFI->getRestoreBasePointer()) {
631 // Stash value of base pointer. Saving SP instead of FP shortens
632 // dependence chain. Used by SjLj EH.
633 unsigned Opm = M68k::MOV32ja;
635 FramePtr, true,
637 .addReg(SPOrEstablisher)
639 }
640 }
641
642 if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) {
643 // Mark end of stack pointer adjustment.
644 if (!HasFP && NumBytes) {
645 // Define the current CFA rule to use the provided offset.
646 assert(StackSize);
647 BuildCFI(
648 MBB, MBBI, DL,
649 MCCFIInstruction::cfiDefCfaOffset(nullptr, -StackSize + stackGrowth));
650 }
651
652 // Emit DWARF info specifying the offsets of the callee-saved registers.
653 if (PushedRegs)
654 emitPrologueCalleeSavedFrameMoves(MBB, MBBI, DL);
655 }
656
657 // TODO Interrupt handlers
658 // M68k Interrupt handling function cannot assume anything about the
659 // direction flag (DF in CCR register). Clear this flag by creating "cld"
660 // instruction in each prologue of interrupt handler function. The "cld"
661 // instruction should only in these cases:
662 // 1. The interrupt handling function uses any of the "rep" instructions.
663 // 2. Interrupt handling function calls another function.
664}
665
666static bool isTailCallOpcode(unsigned Opc) {
667 return Opc == M68k::TCRETURNj || Opc == M68k::TCRETURNq;
668}
669
671 MachineBasicBlock &MBB) const {
672 const MachineFrameInfo &MFI = MF.getFrameInfo();
675 std::optional<unsigned> RetOpcode;
676 if (MBBI != MBB.end())
677 RetOpcode = MBBI->getOpcode();
678 DebugLoc DL;
679 if (MBBI != MBB.end())
680 DL = MBBI->getDebugLoc();
682 unsigned MachineFramePtr = FramePtr;
683
684 // Get the number of bytes to allocate from the FrameInfo.
685 uint64_t StackSize = MFI.getStackSize();
686 uint64_t MaxAlign = calculateMaxStackAlign(MF);
687 unsigned CSSize = MMFI->getCalleeSavedFrameSize();
688 uint64_t NumBytes = 0;
689
690 if (hasFP(MF)) {
691 // Calculate required stack adjustment.
692 uint64_t FrameSize = StackSize - SlotSize;
693 NumBytes = FrameSize - CSSize;
694
695 // Callee-saved registers were pushed on stack before the stack was
696 // realigned.
697 if (TRI->hasStackRealignment(MF))
698 NumBytes = alignTo(FrameSize, MaxAlign);
699
700 } else {
701 NumBytes = StackSize - CSSize;
702 }
703
704 // Skip the callee-saved pop instructions.
705 while (MBBI != MBB.begin()) {
706 MachineBasicBlock::iterator PI = std::prev(MBBI);
707 unsigned Opc = PI->getOpcode();
708
709 if ((Opc != M68k::POP32r || !PI->getFlag(MachineInstr::FrameDestroy)) &&
710 Opc != M68k::DBG_VALUE && !PI->isTerminator())
711 break;
712
713 --MBBI;
714 }
716
717 if (MBBI != MBB.end())
718 DL = MBBI->getDebugLoc();
719
720 // If there is an ADD32ri or SUB32ri of SP immediately before this
721 // instruction, merge the two instructions.
722 if (NumBytes || MFI.hasVarSizedObjects())
723 NumBytes += mergeSPUpdates(MBB, MBBI, true);
724
725 // If dynamic alloca is used, then reset SP to point to the last callee-saved
726 // slot before popping them off! Same applies for the case, when stack was
727 // realigned. Don't do this if this was a funclet epilogue, since the funclets
728 // will not do realignment or dynamic stack allocation.
729 if ((TRI->hasStackRealignment(MF) || MFI.hasVarSizedObjects())) {
730 if (TRI->hasStackRealignment(MF))
731 MBBI = FirstCSPop;
732 uint64_t LEAAmount = -CSSize;
733
734 // 'move %FramePtr, SP' will not be recognized as an epilogue sequence.
735 // However, we may use this sequence if we have a frame pointer because the
736 // effects of the prologue can safely be undone.
737 if (LEAAmount != 0) {
738 unsigned Opc = M68k::LEA32p;
740 BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr), FramePtr, false,
741 LEAAmount);
742 --MBBI;
743 } else {
744 BuildMI(MBB, MBBI, DL, TII.get(M68k::UNLK))
745 .addReg(MachineFramePtr, RegState::Kill)
747 --MBBI;
748 }
749 } else if (hasFP(MF)) {
750 BuildMI(MBB, MBBI, DL, TII.get(M68k::UNLK))
751 .addReg(MachineFramePtr, RegState::Kill)
753 } else if (NumBytes) {
754 // Adjust stack pointer back: SP += numbytes.
755 emitSPUpdate(MBB, MBBI, NumBytes, /*InEpilogue=*/true);
756 --MBBI;
757 }
758
759 if (!RetOpcode || !isTailCallOpcode(*RetOpcode)) {
760 // Add the return addr area delta back since we are not tail calling.
761 int Offset = -1 * MMFI->getTCReturnAddrDelta();
762 assert(Offset >= 0 && "TCDelta should never be positive");
763 if (Offset) {
765
766 // Check for possible merge with preceding ADD instruction.
767 Offset += mergeSPUpdates(MBB, MBBI, true);
768 emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true);
769 }
770 }
771}
772
774 BitVector &SavedRegs,
775 RegScavenger *RS) const {
777
778 MachineFrameInfo &MFI = MF.getFrameInfo();
779
781 int64_t TailCallReturnAddrDelta = M68kFI->getTCReturnAddrDelta();
782
783 if (TailCallReturnAddrDelta < 0) {
784 // create RETURNADDR area
785 // arg
786 // arg
787 // RETADDR
788 // { ...
789 // RETADDR area
790 // ...
791 // }
792 // [FP]
793 MFI.CreateFixedObject(-TailCallReturnAddrDelta,
794 TailCallReturnAddrDelta - SlotSize, true);
795 }
796
797 // Spill the BasePtr if it's used.
798 if (TRI->hasBasePointer(MF)) {
799 SavedRegs.set(TRI->getBaseRegister());
800 }
801}
802
805 std::vector<CalleeSavedInfo> &CSI) const {
806 MachineFrameInfo &MFI = MF.getFrameInfo();
808
809 int SpillSlotOffset = getOffsetOfLocalArea() + M68kFI->getTCReturnAddrDelta();
810
811 if (hasFP(MF)) {
812 // emitPrologue always spills frame register the first thing.
813 SpillSlotOffset -= SlotSize;
814 MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset);
815
816 // Since emitPrologue and emitEpilogue will handle spilling and restoring of
817 // the frame register, we can delete it from CSI list and not have to worry
818 // about avoiding it later.
819 Register FPReg = TRI->getFrameRegister(MF);
820 for (unsigned i = 0, e = CSI.size(); i < e; ++i) {
821 if (TRI->regsOverlap(CSI[i].getReg(), FPReg)) {
822 CSI.erase(CSI.begin() + i);
823 break;
824 }
825 }
826 }
827
828 // The rest is fine
829 return false;
830}
831
835 auto &MRI = *static_cast<const M68kRegisterInfo *>(TRI);
836 auto DL = MBB.findDebugLoc(MI);
837
838 int FI = 0;
839 unsigned Mask = 0;
840 for (const auto &Info : CSI) {
841 FI = std::max(FI, Info.getFrameIdx());
842 Register Reg = Info.getReg();
843 unsigned Shift = MRI.getSpillRegisterOrder(Reg);
844 Mask |= 1 << Shift;
845 }
846
847 auto I =
848 M68k::addFrameReference(BuildMI(MBB, MI, DL, TII.get(M68k::MOVM32pm)), FI)
849 .addImm(Mask)
851
852 // Append implicit registers and mem locations
853 const MachineFunction &MF = *MBB.getParent();
854 const MachineRegisterInfo &RI = MF.getRegInfo();
855 for (const auto &Info : CSI) {
856 Register Reg = Info.getReg();
857 bool IsLiveIn = RI.isLiveIn(Reg);
858 if (!IsLiveIn)
859 MBB.addLiveIn(Reg);
860 I.addReg(Reg, IsLiveIn ? RegState::Implicit : RegState::ImplicitKill);
861 M68k::addMemOperand(I, Info.getFrameIdx(), 0);
862 }
863
864 return true;
865}
866
870 auto &MRI = *static_cast<const M68kRegisterInfo *>(TRI);
871 auto DL = MBB.findDebugLoc(MI);
872
873 int FI = 0;
874 unsigned Mask = 0;
875 for (const auto &Info : CSI) {
876 FI = std::max(FI, Info.getFrameIdx());
877 Register Reg = Info.getReg();
878 unsigned Shift = MRI.getSpillRegisterOrder(Reg);
879 Mask |= 1 << Shift;
880 }
881
883 BuildMI(MBB, MI, DL, TII.get(M68k::MOVM32mp)).addImm(Mask), FI)
885
886 // Append implicit registers and mem locations
887 for (const auto &Info : CSI) {
888 I.addReg(Info.getReg(), RegState::ImplicitDefine);
889 M68k::addMemOperand(I, Info.getFrameIdx(), 0);
890 }
891
892 return true;
893}
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:719
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 createOffset(MCSymbol *L, unsigned Register, int 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, int Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
Definition: MCDwarf.h:573
static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int 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
static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size, SMLoc Loc={})
A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE.
Definition: MCDwarf.h:670
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.
void setOffsetAdjustment(int Adj)
Set the correction for frame offsets.
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.
unsigned addFrameInst(const MCCFIInstruction &Inst)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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.
MachineModuleInfo & getMMI() const
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
This class contains meta information specific to a module.
bool hasDebugInfo() const
Returns true if valid debug info is present.
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.