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();
455 MachineModuleInfo &MMI = MF.getMMI();
457
458 // Add callee saved registers to move list.
459 const auto &CSI = MFI.getCalleeSavedInfo();
460 if (CSI.empty())
461 return;
462
463 // Calculate offsets.
464 for (const auto &I : CSI) {
465 int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
466 Register Reg = I.getReg();
467
468 unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
469 BuildCFI(MBB, MBBI, DL,
470 MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
471 }
472}
473
475 MachineBasicBlock &MBB) const {
476 assert(&STI == &MF.getSubtarget<M68kSubtarget>() &&
477 "MF used frame lowering for wrong subtarget");
478
480 MachineFrameInfo &MFI = MF.getFrameInfo();
481 const auto &Fn = MF.getFunction();
482 MachineModuleInfo &MMI = MF.getMMI();
484 uint64_t MaxAlign = calculateMaxStackAlign(MF); // Desired stack alignment.
485 uint64_t StackSize = MFI.getStackSize(); // Number of bytes to allocate.
486 bool HasFP = hasFP(MF);
487 bool NeedsDwarfCFI = MMI.hasDebugInfo() || Fn.needsUnwindTableEntry();
489 const unsigned MachineFramePtr = FramePtr;
490 unsigned BasePtr = TRI->getBaseRegister();
491
492 // Debug location must be unknown since the first debug location is used
493 // to determine the end of the prologue.
494 DebugLoc DL;
495
496 // Add RETADDR move area to callee saved frame size.
497 int TailCallReturnAddrDelta = MMFI->getTCReturnAddrDelta();
498
499 if (TailCallReturnAddrDelta < 0) {
501 TailCallReturnAddrDelta);
502 }
503
504 // Insert stack pointer adjustment for later moving of return addr. Only
505 // applies to tail call optimized functions where the callee argument stack
506 // size is bigger than the callers.
507 if (TailCallReturnAddrDelta < 0) {
508 BuildStackAdjustment(MBB, MBBI, DL, TailCallReturnAddrDelta,
509 /*InEpilogue=*/false)
511 }
512
513 // Mapping for machine moves:
514 //
515 // DST: VirtualFP AND
516 // SRC: VirtualFP => DW_CFA_def_cfa_offset
517 // ELSE => DW_CFA_def_cfa
518 //
519 // SRC: VirtualFP AND
520 // DST: Register => DW_CFA_def_cfa_register
521 //
522 // ELSE
523 // OFFSET < 0 => DW_CFA_offset_extended_sf
524 // REG < 64 => DW_CFA_offset + Reg
525 // ELSE => DW_CFA_offset_extended
526
527 uint64_t NumBytes = 0;
528 int stackGrowth = -SlotSize;
529
530 if (HasFP) {
531 // Calculate required stack adjustment.
532 uint64_t FrameSize = StackSize - SlotSize;
533 // If required, include space for extra hidden slot for stashing base
534 // pointer.
535 if (MMFI->getRestoreBasePointer())
536 FrameSize += SlotSize;
537
538 NumBytes = FrameSize - MMFI->getCalleeSavedFrameSize();
539
540 // Callee-saved registers are pushed on stack before the stack is realigned.
541 if (TRI->hasStackRealignment(MF))
542 NumBytes = alignTo(NumBytes, MaxAlign);
543
544 // Get the offset of the stack slot for the FP register, which is
545 // guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
546 // Update the frame offset adjustment.
547 MFI.setOffsetAdjustment(-NumBytes);
548
549 BuildMI(MBB, MBBI, DL, TII.get(M68k::LINK16))
550 .addReg(M68k::WA6, RegState::Kill)
551 .addImm(-NumBytes)
553
554 if (NeedsDwarfCFI) {
555 // Mark the place where FP was saved.
556 // Define the current CFA rule to use the provided offset.
557 assert(StackSize);
558 BuildCFI(MBB, MBBI, DL,
559 MCCFIInstruction::cfiDefCfaOffset(nullptr, 2 * stackGrowth));
560
561 // Change the rule for the FramePtr to be an "offset" rule.
562 int DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true);
563 assert(DwarfFramePtr > 0);
564 BuildCFI(MBB, MBBI, DL,
565 MCCFIInstruction::createOffset(nullptr, DwarfFramePtr,
566 2 * stackGrowth));
567 }
568
569 if (NeedsDwarfCFI) {
570 // Mark effective beginning of when frame pointer becomes valid.
571 // Define the current CFA to use the FP register.
572 unsigned DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true);
573 BuildCFI(MBB, MBBI, DL,
574 MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr));
575 }
576
577 // Mark the FramePtr as live-in in every block. Don't do this again for
578 // funclet prologues.
579 for (MachineBasicBlock &EveryMBB : MF)
580 EveryMBB.addLiveIn(MachineFramePtr);
581 } else {
582 NumBytes = StackSize - MMFI->getCalleeSavedFrameSize();
583 }
584
585 // Skip the callee-saved push instructions.
586 bool PushedRegs = false;
587 int StackOffset = 2 * stackGrowth;
588
589 while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup) &&
590 MBBI->getOpcode() == M68k::PUSH32r) {
591 PushedRegs = true;
592 ++MBBI;
593
594 if (!HasFP && NeedsDwarfCFI) {
595 // Mark callee-saved push instruction.
596 // Define the current CFA rule to use the provided offset.
597 assert(StackSize);
598 BuildCFI(MBB, MBBI, DL,
600 StackOffset += stackGrowth;
601 }
602 }
603
604 // Realign stack after we pushed callee-saved registers (so that we'll be
605 // able to calculate their offsets from the frame pointer).
606 if (TRI->hasStackRealignment(MF)) {
607 assert(HasFP && "There should be a frame pointer if stack is realigned.");
608 BuildStackAlignAND(MBB, MBBI, DL, StackPtr, MaxAlign);
609 }
610
611 // If there is an SUB32ri of SP immediately before this instruction, merge
612 // the two. This can be the case when tail call elimination is enabled and
613 // the callee has more arguments then the caller.
614 NumBytes -= mergeSPUpdates(MBB, MBBI, true);
615
616 // Adjust stack pointer: ESP -= numbytes.
617 if (!HasFP)
618 emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, /*InEpilogue=*/false);
619
620 unsigned SPOrEstablisher = StackPtr;
621
622 // If we need a base pointer, set it up here. It's whatever the value
623 // of the stack pointer is at this point. Any variable size objects
624 // will be allocated after this, so we can still use the base pointer
625 // to reference locals.
626 if (TRI->hasBasePointer(MF)) {
627 // Update the base pointer with the current stack pointer.
628 BuildMI(MBB, MBBI, DL, TII.get(M68k::MOV32aa), BasePtr)
629 .addReg(SPOrEstablisher)
631 if (MMFI->getRestoreBasePointer()) {
632 // Stash value of base pointer. Saving SP instead of FP shortens
633 // dependence chain. Used by SjLj EH.
634 unsigned Opm = M68k::MOV32ja;
636 FramePtr, true,
638 .addReg(SPOrEstablisher)
640 }
641 }
642
643 if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) {
644 // Mark end of stack pointer adjustment.
645 if (!HasFP && NumBytes) {
646 // Define the current CFA rule to use the provided offset.
647 assert(StackSize);
648 BuildCFI(
649 MBB, MBBI, DL,
650 MCCFIInstruction::cfiDefCfaOffset(nullptr, -StackSize + stackGrowth));
651 }
652
653 // Emit DWARF info specifying the offsets of the callee-saved registers.
654 if (PushedRegs)
655 emitPrologueCalleeSavedFrameMoves(MBB, MBBI, DL);
656 }
657
658 // TODO Interrupt handlers
659 // M68k Interrupt handling function cannot assume anything about the
660 // direction flag (DF in CCR register). Clear this flag by creating "cld"
661 // instruction in each prologue of interrupt handler function. The "cld"
662 // instruction should only in these cases:
663 // 1. The interrupt handling function uses any of the "rep" instructions.
664 // 2. Interrupt handling function calls another function.
665}
666
667static bool isTailCallOpcode(unsigned Opc) {
668 return Opc == M68k::TCRETURNj || Opc == M68k::TCRETURNq;
669}
670
672 MachineBasicBlock &MBB) const {
673 const MachineFrameInfo &MFI = MF.getFrameInfo();
676 std::optional<unsigned> RetOpcode;
677 if (MBBI != MBB.end())
678 RetOpcode = MBBI->getOpcode();
679 DebugLoc DL;
680 if (MBBI != MBB.end())
681 DL = MBBI->getDebugLoc();
683 unsigned MachineFramePtr = FramePtr;
684
685 // Get the number of bytes to allocate from the FrameInfo.
686 uint64_t StackSize = MFI.getStackSize();
687 uint64_t MaxAlign = calculateMaxStackAlign(MF);
688 unsigned CSSize = MMFI->getCalleeSavedFrameSize();
689 uint64_t NumBytes = 0;
690
691 if (hasFP(MF)) {
692 // Calculate required stack adjustment.
693 uint64_t FrameSize = StackSize - SlotSize;
694 NumBytes = FrameSize - CSSize;
695
696 // Callee-saved registers were pushed on stack before the stack was
697 // realigned.
698 if (TRI->hasStackRealignment(MF))
699 NumBytes = alignTo(FrameSize, MaxAlign);
700
701 } else {
702 NumBytes = StackSize - CSSize;
703 }
704
705 // Skip the callee-saved pop instructions.
706 while (MBBI != MBB.begin()) {
707 MachineBasicBlock::iterator PI = std::prev(MBBI);
708 unsigned Opc = PI->getOpcode();
709
710 if ((Opc != M68k::POP32r || !PI->getFlag(MachineInstr::FrameDestroy)) &&
711 Opc != M68k::DBG_VALUE && !PI->isTerminator())
712 break;
713
714 --MBBI;
715 }
717
718 if (MBBI != MBB.end())
719 DL = MBBI->getDebugLoc();
720
721 // If there is an ADD32ri or SUB32ri of SP immediately before this
722 // instruction, merge the two instructions.
723 if (NumBytes || MFI.hasVarSizedObjects())
724 NumBytes += mergeSPUpdates(MBB, MBBI, true);
725
726 // If dynamic alloca is used, then reset SP to point to the last callee-saved
727 // slot before popping them off! Same applies for the case, when stack was
728 // realigned. Don't do this if this was a funclet epilogue, since the funclets
729 // will not do realignment or dynamic stack allocation.
730 if ((TRI->hasStackRealignment(MF) || MFI.hasVarSizedObjects())) {
731 if (TRI->hasStackRealignment(MF))
732 MBBI = FirstCSPop;
733 uint64_t LEAAmount = -CSSize;
734
735 // 'move %FramePtr, SP' will not be recognized as an epilogue sequence.
736 // However, we may use this sequence if we have a frame pointer because the
737 // effects of the prologue can safely be undone.
738 if (LEAAmount != 0) {
739 unsigned Opc = M68k::LEA32p;
741 BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr), FramePtr, false,
742 LEAAmount);
743 --MBBI;
744 } else {
745 BuildMI(MBB, MBBI, DL, TII.get(M68k::UNLK))
746 .addReg(MachineFramePtr, RegState::Kill)
748 --MBBI;
749 }
750 } else if (hasFP(MF)) {
751 BuildMI(MBB, MBBI, DL, TII.get(M68k::UNLK))
752 .addReg(MachineFramePtr, RegState::Kill)
754 } else if (NumBytes) {
755 // Adjust stack pointer back: SP += numbytes.
756 emitSPUpdate(MBB, MBBI, NumBytes, /*InEpilogue=*/true);
757 --MBBI;
758 }
759
760 if (!RetOpcode || !isTailCallOpcode(*RetOpcode)) {
761 // Add the return addr area delta back since we are not tail calling.
762 int Offset = -1 * MMFI->getTCReturnAddrDelta();
763 assert(Offset >= 0 && "TCDelta should never be positive");
764 if (Offset) {
766
767 // Check for possible merge with preceding ADD instruction.
768 Offset += mergeSPUpdates(MBB, MBBI, true);
769 emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true);
770 }
771 }
772}
773
775 BitVector &SavedRegs,
776 RegScavenger *RS) const {
778
779 MachineFrameInfo &MFI = MF.getFrameInfo();
780
782 int64_t TailCallReturnAddrDelta = M68kFI->getTCReturnAddrDelta();
783
784 if (TailCallReturnAddrDelta < 0) {
785 // create RETURNADDR area
786 // arg
787 // arg
788 // RETADDR
789 // { ...
790 // RETADDR area
791 // ...
792 // }
793 // [FP]
794 MFI.CreateFixedObject(-TailCallReturnAddrDelta,
795 TailCallReturnAddrDelta - SlotSize, true);
796 }
797
798 // Spill the BasePtr if it's used.
799 if (TRI->hasBasePointer(MF)) {
800 SavedRegs.set(TRI->getBaseRegister());
801 }
802}
803
806 std::vector<CalleeSavedInfo> &CSI) const {
807 MachineFrameInfo &MFI = MF.getFrameInfo();
809
810 int SpillSlotOffset = getOffsetOfLocalArea() + M68kFI->getTCReturnAddrDelta();
811
812 if (hasFP(MF)) {
813 // emitPrologue always spills frame register the first thing.
814 SpillSlotOffset -= SlotSize;
815 MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset);
816
817 // Since emitPrologue and emitEpilogue will handle spilling and restoring of
818 // the frame register, we can delete it from CSI list and not have to worry
819 // about avoiding it later.
820 Register FPReg = TRI->getFrameRegister(MF);
821 for (unsigned i = 0, e = CSI.size(); i < e; ++i) {
822 if (TRI->regsOverlap(CSI[i].getReg(), FPReg)) {
823 CSI.erase(CSI.begin() + i);
824 break;
825 }
826 }
827 }
828
829 // The rest is fine
830 return false;
831}
832
836 auto &MRI = *static_cast<const M68kRegisterInfo *>(TRI);
837 auto DL = MBB.findDebugLoc(MI);
838
839 int FI = 0;
840 unsigned Mask = 0;
841 for (const auto &Info : CSI) {
842 FI = std::max(FI, Info.getFrameIdx());
843 Register Reg = Info.getReg();
844 unsigned Shift = MRI.getSpillRegisterOrder(Reg);
845 Mask |= 1 << Shift;
846 }
847
848 auto I =
849 M68k::addFrameReference(BuildMI(MBB, MI, DL, TII.get(M68k::MOVM32pm)), FI)
850 .addImm(Mask)
852
853 // Append implicit registers and mem locations
854 const MachineFunction &MF = *MBB.getParent();
855 const MachineRegisterInfo &RI = MF.getRegInfo();
856 for (const auto &Info : CSI) {
857 Register Reg = Info.getReg();
858 bool IsLiveIn = RI.isLiveIn(Reg);
859 if (!IsLiveIn)
860 MBB.addLiveIn(Reg);
861 I.addReg(Reg, IsLiveIn ? RegState::Implicit : RegState::ImplicitKill);
862 M68k::addMemOperand(I, Info.getFrameIdx(), 0);
863 }
864
865 return true;
866}
867
871 auto &MRI = *static_cast<const M68kRegisterInfo *>(TRI);
872 auto DL = MBB.findDebugLoc(MI);
873
874 int FI = 0;
875 unsigned Mask = 0;
876 for (const auto &Info : CSI) {
877 FI = std::max(FI, Info.getFrameIdx());
878 Register Reg = Info.getReg();
879 unsigned Shift = MRI.getSpillRegisterOrder(Reg);
880 Mask |= 1 << Shift;
881 }
882
884 BuildMI(MBB, MI, DL, TII.get(M68k::MOVM32mp)).addImm(Mask), FI)
886
887 // Append implicit registers and mem locations
888 for (const auto &Info : CSI) {
889 I.addReg(Info.getReg(), RegState::ImplicitDefine);
890 M68k::addMemOperand(I, Info.getFrameIdx(), 0);
891 }
892
893 return true;
894}
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:675
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:548
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:583
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
Definition: MCDwarf.h:556
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:564
static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size, SMLoc Loc={})
A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE.
Definition: MCDwarf.h:653
const MCRegisterInfo * getRegisterInfo() const
Definition: MCContext.h:455
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.
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.
const MCContext & getContext() const
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:456
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.