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
36#define DEBUG_TYPE "m68k-frame"
37
39 : TargetFrameLowering(StackGrowsDown, Alignment, -4), STI(STI),
40 TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {
41 SlotSize = STI.getSlotSize();
42 StackPtr = TRI->getStackRegister();
43}
44
46 const MachineFrameInfo &MFI = MF.getFrameInfo();
47 const TargetRegisterInfo *TRI = STI.getRegisterInfo();
48
51 TRI->hasStackRealignment(MF);
52}
53
54// FIXME Make sure no other factors prevent us from reserving call frame
56 return !MF.getFrameInfo().hasVarSizedObjects() &&
57 !MF.getInfo<M68kMachineFunctionInfo>()->getHasPushSequences();
58}
59
61 const MachineFunction &MF) const {
62 return hasReservedCallFrame(MF) ||
63 (hasFP(MF) && !TRI->hasStackRealignment(MF)) ||
64 TRI->hasBasePointer(MF);
65}
66
68 const MachineFunction &MF) const {
69 return MF.getFrameInfo().hasStackObjects() ||
70 MF.getInfo<M68kMachineFunctionInfo>()->getHasPushSequences();
71}
72
73// NOTE: this only has a subset of the full frame index logic. In
74// particular, the FI < 0 and AfterFPPop logic is handled in
75// M68kRegisterInfo::eliminateFrameIndex, but not here. Possibly
76// (probably?) it should be moved into here.
79 Register &FrameReg) const {
80 const MachineFrameInfo &MFI = MF.getFrameInfo();
81
82 // We can't calculate offset from frame pointer if the stack is realigned,
83 // so enforce usage of stack/base pointer. The base pointer is used when we
84 // have dynamic allocas in addition to dynamic realignment.
85 if (TRI->hasBasePointer(MF))
86 FrameReg = TRI->getBaseRegister();
87 else if (TRI->hasStackRealignment(MF))
88 FrameReg = TRI->getStackRegister();
89 else
90 FrameReg = TRI->getFrameRegister(MF);
91
92 // Offset will hold the offset from the stack pointer at function entry to the
93 // object.
94 // We need to factor in additional offsets applied during the prologue to the
95 // frame, base, and stack pointer depending on which is used.
98 uint64_t StackSize = MFI.getStackSize();
99 bool HasFP = hasFP(MF);
100
101 // TODO: Support tail calls
102 if (TRI->hasBasePointer(MF)) {
103 assert(HasFP && "VLAs and dynamic stack realign, but no FP?!");
104 if (FI < 0) {
105 // Skip the saved FP.
106 return StackOffset::getFixed(Offset + SlotSize);
107 }
108
109 assert((-(Offset + StackSize)) % MFI.getObjectAlign(FI).value() == 0);
110 return StackOffset::getFixed(Offset + StackSize);
111 }
112 if (TRI->hasStackRealignment(MF)) {
113 if (FI < 0) {
114 // Skip the saved FP.
115 return StackOffset::getFixed(Offset + SlotSize);
116 }
117
118 assert((-(Offset + StackSize)) % MFI.getObjectAlign(FI).value() == 0);
119 return StackOffset::getFixed(Offset + StackSize);
120 }
121
122 if (!HasFP)
123 return StackOffset::getFixed(Offset + StackSize);
124
125 // Skip the saved FP.
126 Offset += SlotSize;
127
128 // Skip the RETADDR move area
129 int TailCallReturnAddrDelta = MMFI->getTCReturnAddrDelta();
130 if (TailCallReturnAddrDelta < 0)
131 Offset -= TailCallReturnAddrDelta;
132
134}
135
136/// Return a caller-saved register that isn't live
137/// when it reaches the "return" instruction. We can then pop a stack object
138/// to this register without worry about clobbering it.
141 const M68kRegisterInfo *TRI) {
142 const MachineFunction *MF = MBB.getParent();
143 if (MF->callsEHReturn())
144 return 0;
145
146 const TargetRegisterClass &AvailableRegs = *TRI->getRegsForTailCall(*MF);
147
148 if (MBBI == MBB.end())
149 return 0;
150
151 switch (MBBI->getOpcode()) {
152 default:
153 return 0;
154 case TargetOpcode::PATCHABLE_RET:
155 case M68k::RET: {
157
158 for (unsigned i = 0, e = MBBI->getNumOperands(); i != e; ++i) {
159 MachineOperand &MO = MBBI->getOperand(i);
160 if (!MO.isReg() || MO.isDef())
161 continue;
162 Register Reg = MO.getReg();
163 if (!Reg)
164 continue;
165 for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
166 Uses.insert(*AI);
167 }
168
169 for (auto CS : AvailableRegs)
170 if (!Uses.count(CS))
171 return CS;
172 }
173 }
174
175 return 0;
176}
177
178static bool isRegLiveIn(MachineBasicBlock &MBB, unsigned Reg) {
179 return llvm::any_of(MBB.liveins(),
181 return RegMask.PhysReg == Reg;
182 });
183}
184
186M68kFrameLowering::calculateMaxStackAlign(const MachineFunction &MF) const {
187 const MachineFrameInfo &MFI = MF.getFrameInfo();
188 uint64_t MaxAlign = MFI.getMaxAlign().value(); // Desired stack alignment.
189 unsigned StackAlign = getStackAlignment(); // ABI alignment
190 if (MF.getFunction().hasFnAttribute("stackrealign")) {
191 if (MFI.hasCalls())
192 MaxAlign = (StackAlign > MaxAlign) ? StackAlign : MaxAlign;
193 else if (MaxAlign < SlotSize)
194 MaxAlign = SlotSize;
195 }
196 return MaxAlign;
197}
198
199void M68kFrameLowering::BuildStackAlignAND(MachineBasicBlock &MBB,
201 const DebugLoc &DL, unsigned Reg,
202 uint64_t MaxAlign) const {
203 uint64_t Val = -MaxAlign;
204 unsigned AndOp = M68k::AND32di;
205 unsigned MovOp = M68k::MOV32rr;
206
207 // This function is normally used with SP which is Address Register, but AND,
208 // or any other logical instructions in M68k do not support ARs so we need
209 // to use a temp Data Register to perform the op.
210 unsigned Tmp = M68k::D0;
211
212 BuildMI(MBB, MBBI, DL, TII.get(MovOp), Tmp)
213 .addReg(Reg)
215
216 MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(AndOp), Tmp)
217 .addReg(Tmp)
218 .addImm(Val)
220
221 // The CCR implicit def is dead.
222 MI->getOperand(3).setIsDead();
223
224 BuildMI(MBB, MBBI, DL, TII.get(MovOp), Reg)
225 .addReg(Tmp)
227}
228
232 bool ReserveCallFrame = hasReservedCallFrame(MF);
233 unsigned Opcode = I->getOpcode();
234 bool IsDestroy = Opcode == TII.getCallFrameDestroyOpcode();
235 DebugLoc DL = I->getDebugLoc();
236 uint64_t Amount = I->getOperand(0).getImm();
237 uint64_t InternalAmt = (IsDestroy || Amount) ? I->getOperand(1).getImm() : 0;
238 I = MBB.erase(I);
239
240 if (!ReserveCallFrame) {
241 // If the stack pointer can be changed after prologue, turn the
242 // adjcallstackup instruction into a 'sub %SP, <amt>' and the
243 // adjcallstackdown instruction into 'add %SP, <amt>'
244
245 // We need to keep the stack aligned properly. To do this, we round the
246 // amount of space needed for the outgoing arguments up to the next
247 // alignment boundary.
248 unsigned StackAlign = getStackAlignment();
249 Amount = alignTo(Amount, StackAlign);
250
251 bool DwarfCFI = MF.needsFrameMoves();
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();
481 uint64_t MaxAlign = calculateMaxStackAlign(MF); // Desired stack alignment.
482 uint64_t StackSize = MFI.getStackSize(); // Number of bytes to allocate.
483 bool HasFP = hasFP(MF);
484 bool NeedsDwarfCFI = MF.needsFrameMoves();
486 const unsigned MachineFramePtr = FramePtr;
487 unsigned BasePtr = TRI->getBaseRegister();
488
489 // Debug location must be unknown since the first debug location is used
490 // to determine the end of the prologue.
491 DebugLoc DL;
492
493 // Add RETADDR move area to callee saved frame size.
494 int TailCallReturnAddrDelta = MMFI->getTCReturnAddrDelta();
495
496 if (TailCallReturnAddrDelta < 0) {
498 TailCallReturnAddrDelta);
499 }
500
501 // Insert stack pointer adjustment for later moving of return addr. Only
502 // applies to tail call optimized functions where the callee argument stack
503 // size is bigger than the callers.
504 if (TailCallReturnAddrDelta < 0) {
505 BuildStackAdjustment(MBB, MBBI, DL, TailCallReturnAddrDelta,
506 /*InEpilogue=*/false)
508 }
509
510 // Mapping for machine moves:
511 //
512 // DST: VirtualFP AND
513 // SRC: VirtualFP => DW_CFA_def_cfa_offset
514 // ELSE => DW_CFA_def_cfa
515 //
516 // SRC: VirtualFP AND
517 // DST: Register => DW_CFA_def_cfa_register
518 //
519 // ELSE
520 // OFFSET < 0 => DW_CFA_offset_extended_sf
521 // REG < 64 => DW_CFA_offset + Reg
522 // ELSE => DW_CFA_offset_extended
523
524 uint64_t NumBytes = 0;
525 int stackGrowth = -SlotSize;
526
527 if (HasFP) {
528 // Calculate required stack adjustment.
529 uint64_t FrameSize = StackSize - SlotSize;
530 // If required, include space for extra hidden slot for stashing base
531 // pointer.
532 if (MMFI->getRestoreBasePointer())
533 FrameSize += SlotSize;
534
535 NumBytes = FrameSize - MMFI->getCalleeSavedFrameSize();
536
537 // Callee-saved registers are pushed on stack before the stack is realigned.
538 if (TRI->hasStackRealignment(MF))
539 NumBytes = alignTo(NumBytes, MaxAlign);
540
541 // Get the offset of the stack slot for the FP register, which is
542 // guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
543 // Update the frame offset adjustment.
544 MFI.setOffsetAdjustment(-NumBytes);
545
546 BuildMI(MBB, MBBI, DL, TII.get(M68k::LINK16))
547 .addReg(M68k::WA6, RegState::Kill)
548 .addImm(-NumBytes)
550
551 if (NeedsDwarfCFI) {
552 // Mark the place where FP was saved.
553 // Define the current CFA rule to use the provided offset.
554 assert(StackSize);
555 BuildCFI(MBB, MBBI, DL,
556 MCCFIInstruction::cfiDefCfaOffset(nullptr, 2 * stackGrowth));
557
558 // Change the rule for the FramePtr to be an "offset" rule.
559 int DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true);
560 assert(DwarfFramePtr > 0);
561 BuildCFI(MBB, MBBI, DL,
562 MCCFIInstruction::createOffset(nullptr, DwarfFramePtr,
563 2 * stackGrowth));
564 }
565
566 if (NeedsDwarfCFI) {
567 // Mark effective beginning of when frame pointer becomes valid.
568 // Define the current CFA to use the FP register.
569 unsigned DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true);
570 BuildCFI(MBB, MBBI, DL,
571 MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr));
572 }
573
574 // Mark the FramePtr as live-in in every block. Don't do this again for
575 // funclet prologues.
576 for (MachineBasicBlock &EveryMBB : MF)
577 EveryMBB.addLiveIn(MachineFramePtr);
578 } else {
579 NumBytes = StackSize - MMFI->getCalleeSavedFrameSize();
580 }
581
582 // Skip the callee-saved push instructions.
583 bool PushedRegs = false;
584 int StackOffset = 2 * stackGrowth;
585
586 while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup) &&
587 MBBI->getOpcode() == M68k::PUSH32r) {
588 PushedRegs = true;
589 ++MBBI;
590
591 if (!HasFP && NeedsDwarfCFI) {
592 // Mark callee-saved push instruction.
593 // Define the current CFA rule to use the provided offset.
594 assert(StackSize);
595 BuildCFI(MBB, MBBI, DL,
597 StackOffset += stackGrowth;
598 }
599 }
600
601 // Realign stack after we pushed callee-saved registers (so that we'll be
602 // able to calculate their offsets from the frame pointer).
603 if (TRI->hasStackRealignment(MF)) {
604 assert(HasFP && "There should be a frame pointer if stack is realigned.");
605 BuildStackAlignAND(MBB, MBBI, DL, StackPtr, MaxAlign);
606 }
607
608 // If there is an SUB32ri of SP immediately before this instruction, merge
609 // the two. This can be the case when tail call elimination is enabled and
610 // the callee has more arguments then the caller.
611 NumBytes -= mergeSPUpdates(MBB, MBBI, true);
612
613 // Adjust stack pointer: ESP -= numbytes.
614 if (!HasFP)
615 emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, /*InEpilogue=*/false);
616
617 unsigned SPOrEstablisher = StackPtr;
618
619 // If we need a base pointer, set it up here. It's whatever the value
620 // of the stack pointer is at this point. Any variable size objects
621 // will be allocated after this, so we can still use the base pointer
622 // to reference locals.
623 if (TRI->hasBasePointer(MF)) {
624 // Update the base pointer with the current stack pointer.
625 BuildMI(MBB, MBBI, DL, TII.get(M68k::MOV32aa), BasePtr)
626 .addReg(SPOrEstablisher)
628 if (MMFI->getRestoreBasePointer()) {
629 // Stash value of base pointer. Saving SP instead of FP shortens
630 // dependence chain. Used by SjLj EH.
631 unsigned Opm = M68k::MOV32ja;
633 FramePtr, true,
635 .addReg(SPOrEstablisher)
637 }
638 }
639
640 if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) {
641 // Mark end of stack pointer adjustment.
642 if (!HasFP && NumBytes) {
643 // Define the current CFA rule to use the provided offset.
644 assert(StackSize);
645 BuildCFI(
646 MBB, MBBI, DL,
647 MCCFIInstruction::cfiDefCfaOffset(nullptr, -StackSize + stackGrowth));
648 }
649
650 // Emit DWARF info specifying the offsets of the callee-saved registers.
651 if (PushedRegs)
652 emitPrologueCalleeSavedFrameMoves(MBB, MBBI, DL);
653 }
654
655 // TODO Interrupt handlers
656 // M68k Interrupt handling function cannot assume anything about the
657 // direction flag (DF in CCR register). Clear this flag by creating "cld"
658 // instruction in each prologue of interrupt handler function. The "cld"
659 // instruction should only in these cases:
660 // 1. The interrupt handling function uses any of the "rep" instructions.
661 // 2. Interrupt handling function calls another function.
662}
663
664static bool isTailCallOpcode(unsigned Opc) {
665 return Opc == M68k::TCRETURNj || Opc == M68k::TCRETURNq;
666}
667
669 MachineBasicBlock &MBB) const {
670 const MachineFrameInfo &MFI = MF.getFrameInfo();
673 std::optional<unsigned> RetOpcode;
674 if (MBBI != MBB.end())
675 RetOpcode = MBBI->getOpcode();
676 DebugLoc DL;
677 if (MBBI != MBB.end())
678 DL = MBBI->getDebugLoc();
680 unsigned MachineFramePtr = FramePtr;
681
682 // Get the number of bytes to allocate from the FrameInfo.
683 uint64_t StackSize = MFI.getStackSize();
684 uint64_t MaxAlign = calculateMaxStackAlign(MF);
685 unsigned CSSize = MMFI->getCalleeSavedFrameSize();
686 uint64_t NumBytes = 0;
687
688 if (hasFP(MF)) {
689 // Calculate required stack adjustment.
690 uint64_t FrameSize = StackSize - SlotSize;
691 NumBytes = FrameSize - CSSize;
692
693 // Callee-saved registers were pushed on stack before the stack was
694 // realigned.
695 if (TRI->hasStackRealignment(MF))
696 NumBytes = alignTo(FrameSize, MaxAlign);
697
698 } else {
699 NumBytes = StackSize - CSSize;
700 }
701
702 // Skip the callee-saved pop instructions.
703 while (MBBI != MBB.begin()) {
704 MachineBasicBlock::iterator PI = std::prev(MBBI);
705 unsigned Opc = PI->getOpcode();
706
707 if ((Opc != M68k::POP32r || !PI->getFlag(MachineInstr::FrameDestroy)) &&
708 Opc != M68k::DBG_VALUE && !PI->isTerminator())
709 break;
710
711 --MBBI;
712 }
714
715 if (MBBI != MBB.end())
716 DL = MBBI->getDebugLoc();
717
718 // If there is an ADD32ri or SUB32ri of SP immediately before this
719 // instruction, merge the two instructions.
720 if (NumBytes || MFI.hasVarSizedObjects())
721 NumBytes += mergeSPUpdates(MBB, MBBI, true);
722
723 // If dynamic alloca is used, then reset SP to point to the last callee-saved
724 // slot before popping them off! Same applies for the case, when stack was
725 // realigned. Don't do this if this was a funclet epilogue, since the funclets
726 // will not do realignment or dynamic stack allocation.
727 if ((TRI->hasStackRealignment(MF) || MFI.hasVarSizedObjects())) {
728 if (TRI->hasStackRealignment(MF))
729 MBBI = FirstCSPop;
730 uint64_t LEAAmount = -CSSize;
731
732 // 'move %FramePtr, SP' will not be recognized as an epilogue sequence.
733 // However, we may use this sequence if we have a frame pointer because the
734 // effects of the prologue can safely be undone.
735 if (LEAAmount != 0) {
736 unsigned Opc = M68k::LEA32p;
738 BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr), FramePtr, false,
739 LEAAmount);
740 --MBBI;
741 } else {
742 BuildMI(MBB, MBBI, DL, TII.get(M68k::UNLK))
743 .addReg(MachineFramePtr, RegState::Kill)
745 --MBBI;
746 }
747 } else if (hasFP(MF)) {
748 BuildMI(MBB, MBBI, DL, TII.get(M68k::UNLK))
749 .addReg(MachineFramePtr, RegState::Kill)
751 } else if (NumBytes) {
752 // Adjust stack pointer back: SP += numbytes.
753 emitSPUpdate(MBB, MBBI, NumBytes, /*InEpilogue=*/true);
754 --MBBI;
755 }
756
757 if (!RetOpcode || !isTailCallOpcode(*RetOpcode)) {
758 // Add the return addr area delta back since we are not tail calling.
759 int Offset = -1 * MMFI->getTCReturnAddrDelta();
760 assert(Offset >= 0 && "TCDelta should never be positive");
761 if (Offset) {
763
764 // Check for possible merge with preceding ADD instruction.
765 Offset += mergeSPUpdates(MBB, MBBI, true);
766 emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true);
767 }
768 }
769}
770
772 BitVector &SavedRegs,
773 RegScavenger *RS) const {
775
776 MachineFrameInfo &MFI = MF.getFrameInfo();
777
779 int64_t TailCallReturnAddrDelta = M68kFI->getTCReturnAddrDelta();
780
781 if (TailCallReturnAddrDelta < 0) {
782 // create RETURNADDR area
783 // arg
784 // arg
785 // RETADDR
786 // { ...
787 // RETADDR area
788 // ...
789 // }
790 // [FP]
791 MFI.CreateFixedObject(-TailCallReturnAddrDelta,
792 TailCallReturnAddrDelta - SlotSize, true);
793 }
794
795 // Spill the BasePtr if it's used.
796 if (TRI->hasBasePointer(MF)) {
797 SavedRegs.set(TRI->getBaseRegister());
798 }
799}
800
803 std::vector<CalleeSavedInfo> &CSI) const {
804 MachineFrameInfo &MFI = MF.getFrameInfo();
806
807 int SpillSlotOffset = getOffsetOfLocalArea() + M68kFI->getTCReturnAddrDelta();
808
809 if (hasFP(MF)) {
810 // emitPrologue always spills frame register the first thing.
811 SpillSlotOffset -= SlotSize;
812 MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset);
813
814 // Since emitPrologue and emitEpilogue will handle spilling and restoring of
815 // the frame register, we can delete it from CSI list and not have to worry
816 // about avoiding it later.
817 Register FPReg = TRI->getFrameRegister(MF);
818 for (unsigned i = 0, e = CSI.size(); i < e; ++i) {
819 if (TRI->regsOverlap(CSI[i].getReg(), FPReg)) {
820 CSI.erase(CSI.begin() + i);
821 break;
822 }
823 }
824 }
825
826 // The rest is fine
827 return false;
828}
829
833 auto &MRI = *static_cast<const M68kRegisterInfo *>(TRI);
834 auto DL = MBB.findDebugLoc(MI);
835
836 int FI = 0;
837 unsigned Mask = 0;
838 for (const auto &Info : CSI) {
839 FI = std::max(FI, Info.getFrameIdx());
840 Register Reg = Info.getReg();
841 unsigned Shift = MRI.getSpillRegisterOrder(Reg);
842 Mask |= 1 << Shift;
843 }
844
845 auto I =
846 M68k::addFrameReference(BuildMI(MBB, MI, DL, TII.get(M68k::MOVM32pm)), FI)
847 .addImm(Mask)
849
850 // Append implicit registers and mem locations
851 const MachineFunction &MF = *MBB.getParent();
852 const MachineRegisterInfo &RI = MF.getRegInfo();
853 for (const auto &Info : CSI) {
854 Register Reg = Info.getReg();
855 bool IsLiveIn = RI.isLiveIn(Reg);
856 if (!IsLiveIn)
857 MBB.addLiveIn(Reg);
858 I.addReg(Reg, IsLiveIn ? RegState::Implicit : RegState::ImplicitKill);
859 M68k::addMemOperand(I, Info.getFrameIdx(), 0);
860 }
861
862 return true;
863}
864
868 auto &MRI = *static_cast<const M68kRegisterInfo *>(TRI);
869 auto DL = MBB.findDebugLoc(MI);
870
871 int FI = 0;
872 unsigned Mask = 0;
873 for (const auto &Info : CSI) {
874 FI = std::max(FI, Info.getFrameIdx());
875 Register Reg = Info.getReg();
876 unsigned Shift = MRI.getSpillRegisterOrder(Reg);
877 Mask |= 1 << Shift;
878 }
879
881 BuildMI(MBB, MI, DL, TII.get(M68k::MOVM32mp)).addImm(Mask), FI)
883
884 // Append implicit registers and mem locations
885 for (const auto &Info : CSI) {
886 I.addReg(Info.getReg(), RegState::ImplicitDefine);
887 M68k::addMemOperand(I, Info.getFrameIdx(), 0);
888 }
889
890 return true;
891}
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
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
static constexpr Register FPReg
Remove Loads Into Fake Uses
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:731
bool hasFPImpl(const MachineFunction &MF) const override
Return true if the specified function should have a dedicated frame pointer register.
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 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:582
static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int64_t Size, SMLoc Loc={})
A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE.
Definition: MCDwarf.h:693
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:617
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
Definition: MCDwarf.h:590
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:598
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 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 TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
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:310
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:132
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...
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
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:1746
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.