Thanks to visit codestin.com
Credit goes to llvm.org

LLVM 22.0.0git
AArch64PrologueEpilogue.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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
12#include "AArch64Subtarget.h"
14#include "llvm/ADT/Statistic.h"
17#include "llvm/MC/MCContext.h"
18
19#define DEBUG_TYPE "frame-info"
20
21STATISTIC(NumRedZoneFunctions, "Number of functions using red zone");
22
23namespace llvm {
24
25static bool matchLibcall(const TargetLowering &TLI, const MachineOperand &MO,
26 RTLIB::Libcall LC) {
27 return MO.isSymbol() &&
28 StringRef(TLI.getLibcallName(LC)) == MO.getSymbolName();
29}
30
32 return AFI->hasStreamingModeChanges() &&
33 !MF.getSubtarget<AArch64Subtarget>().hasSVE();
34}
35
38 unsigned Opc = MBBI->getOpcode();
39 if (Opc == AArch64::CNTD_XPiI)
40 return true;
41
42 if (!requiresGetVGCall())
43 return false;
44
45 if (Opc == AArch64::BL)
46 return matchLibcall(TLI, MBBI->getOperand(0), RTLIB::SMEABI_GET_CURRENT_VG);
47
48 return Opc == TargetOpcode::COPY;
49}
50
51// Convenience function to determine whether I is an SVE callee save.
53 switch (I->getOpcode()) {
54 default:
55 return false;
56 case AArch64::PTRUE_C_B:
57 case AArch64::LD1B_2Z_IMM:
58 case AArch64::ST1B_2Z_IMM:
59 case AArch64::STR_ZXI:
60 case AArch64::STR_PXI:
61 case AArch64::LDR_ZXI:
62 case AArch64::LDR_PXI:
63 case AArch64::PTRUE_B:
64 case AArch64::CPY_ZPzI_B:
65 case AArch64::CMPNE_PPzZI_B:
66 return I->getFlag(MachineInstr::FrameSetup) ||
68 case AArch64::SEH_SavePReg:
69 case AArch64::SEH_SaveZReg:
70 return true;
71 }
72}
73
77 : MF(MF), MBB(MBB), MFI(MF.getFrameInfo()),
78 Subtarget(MF.getSubtarget<AArch64Subtarget>()), AFL(AFL),
79 RegInfo(*Subtarget.getRegisterInfo()) {
80 TII = Subtarget.getInstrInfo();
81 AFI = MF.getInfo<AArch64FunctionInfo>();
82
83 HasFP = AFL.hasFP(MF);
84 NeedsWinCFI = AFL.needsWinCFI(MF);
85}
86
89 MachineBasicBlock::iterator MBBI, const DebugLoc &DL, int CSStackSizeInc,
90 bool EmitCFI, MachineInstr::MIFlag FrameFlag, int CFAOffset) const {
91 unsigned NewOpc;
92
93 // If the function contains streaming mode changes, we expect instructions
94 // to calculate the value of VG before spilling. Move past these instructions
95 // if necessary.
96 if (AFL.requiresSaveVG(MF)) {
97 auto &TLI = *Subtarget.getTargetLowering();
98 while (isVGInstruction(MBBI, TLI))
99 ++MBBI;
100 }
101
102 switch (MBBI->getOpcode()) {
103 default:
104 llvm_unreachable("Unexpected callee-save save/restore opcode!");
105 case AArch64::STPXi:
106 NewOpc = AArch64::STPXpre;
107 break;
108 case AArch64::STPDi:
109 NewOpc = AArch64::STPDpre;
110 break;
111 case AArch64::STPQi:
112 NewOpc = AArch64::STPQpre;
113 break;
114 case AArch64::STRXui:
115 NewOpc = AArch64::STRXpre;
116 break;
117 case AArch64::STRDui:
118 NewOpc = AArch64::STRDpre;
119 break;
120 case AArch64::STRQui:
121 NewOpc = AArch64::STRQpre;
122 break;
123 case AArch64::LDPXi:
124 NewOpc = AArch64::LDPXpost;
125 break;
126 case AArch64::LDPDi:
127 NewOpc = AArch64::LDPDpost;
128 break;
129 case AArch64::LDPQi:
130 NewOpc = AArch64::LDPQpost;
131 break;
132 case AArch64::LDRXui:
133 NewOpc = AArch64::LDRXpost;
134 break;
135 case AArch64::LDRDui:
136 NewOpc = AArch64::LDRDpost;
137 break;
138 case AArch64::LDRQui:
139 NewOpc = AArch64::LDRQpost;
140 break;
141 }
142 TypeSize Scale = TypeSize::getFixed(1), Width = TypeSize::getFixed(0);
143 int64_t MinOffset, MaxOffset;
144 bool Success = static_cast<const AArch64InstrInfo *>(TII)->getMemOpInfo(
145 NewOpc, Scale, Width, MinOffset, MaxOffset);
146 (void)Success;
147 assert(Success && "unknown load/store opcode");
148
149 // If the first store isn't right where we want SP then we can't fold the
150 // update in so create a normal arithmetic instruction instead.
151 if (MBBI->getOperand(MBBI->getNumOperands() - 1).getImm() != 0 ||
152 CSStackSizeInc < MinOffset * (int64_t)Scale.getFixedValue() ||
153 CSStackSizeInc > MaxOffset * (int64_t)Scale.getFixedValue()) {
154 // If we are destroying the frame, make sure we add the increment after the
155 // last frame operation.
156 if (FrameFlag == MachineInstr::FrameDestroy) {
157 ++MBBI;
158 // Also skip the SEH instruction, if needed
159 if (NeedsWinCFI && AArch64InstrInfo::isSEHInstruction(*MBBI))
160 ++MBBI;
161 }
162 emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP,
163 StackOffset::getFixed(CSStackSizeInc), TII, FrameFlag,
164 false, NeedsWinCFI, &HasWinCFI, EmitCFI,
165 StackOffset::getFixed(CFAOffset));
166
167 return std::prev(MBBI);
168 }
169
170 // Get rid of the SEH code associated with the old instruction.
171 if (NeedsWinCFI) {
172 auto SEH = std::next(MBBI);
173 if (AArch64InstrInfo::isSEHInstruction(*SEH))
174 SEH->eraseFromParent();
175 }
176
177 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(NewOpc));
178 MIB.addReg(AArch64::SP, RegState::Define);
179
180 // Copy all operands other than the immediate offset.
181 unsigned OpndIdx = 0;
182 for (unsigned OpndEnd = MBBI->getNumOperands() - 1; OpndIdx < OpndEnd;
183 ++OpndIdx)
184 MIB.add(MBBI->getOperand(OpndIdx));
185
186 assert(MBBI->getOperand(OpndIdx).getImm() == 0 &&
187 "Unexpected immediate offset in first/last callee-save save/restore "
188 "instruction!");
189 assert(MBBI->getOperand(OpndIdx - 1).getReg() == AArch64::SP &&
190 "Unexpected base register in callee-save save/restore instruction!");
191 assert(CSStackSizeInc % Scale == 0);
192 MIB.addImm(CSStackSizeInc / (int)Scale);
193
194 MIB.setMIFlags(MBBI->getFlags());
195 MIB.setMemRefs(MBBI->memoperands());
196
197 // Generate a new SEH code that corresponds to the new instruction.
198 if (NeedsWinCFI) {
199 HasWinCFI = true;
200 AFL.insertSEH(*MIB, *TII, FrameFlag);
201 }
202
203 if (EmitCFI)
204 CFIInstBuilder(MBB, MBBI, FrameFlag)
205 .buildDefCFAOffset(CFAOffset - CSStackSizeInc);
206
207 return std::prev(MBB.erase(MBBI));
208}
209
210// Fix up the SEH opcode associated with the save/restore instruction.
212 unsigned LocalStackSize) {
213 MachineOperand *ImmOpnd = nullptr;
214 unsigned ImmIdx = MBBI->getNumOperands() - 1;
215 switch (MBBI->getOpcode()) {
216 default:
217 llvm_unreachable("Fix the offset in the SEH instruction");
218 case AArch64::SEH_SaveFPLR:
219 case AArch64::SEH_SaveRegP:
220 case AArch64::SEH_SaveReg:
221 case AArch64::SEH_SaveFRegP:
222 case AArch64::SEH_SaveFReg:
223 case AArch64::SEH_SaveAnyRegQP:
224 case AArch64::SEH_SaveAnyRegQPX:
225 ImmOpnd = &MBBI->getOperand(ImmIdx);
226 break;
227 }
228 if (ImmOpnd)
229 ImmOpnd->setImm(ImmOpnd->getImm() + LocalStackSize);
230}
231
233 MachineInstr &MI, uint64_t LocalStackSize) const {
234 if (AArch64InstrInfo::isSEHInstruction(MI))
235 return;
236
237 unsigned Opc = MI.getOpcode();
238 unsigned Scale;
239 switch (Opc) {
240 case AArch64::STPXi:
241 case AArch64::STRXui:
242 case AArch64::STPDi:
243 case AArch64::STRDui:
244 case AArch64::LDPXi:
245 case AArch64::LDRXui:
246 case AArch64::LDPDi:
247 case AArch64::LDRDui:
248 Scale = 8;
249 break;
250 case AArch64::STPQi:
251 case AArch64::STRQui:
252 case AArch64::LDPQi:
253 case AArch64::LDRQui:
254 Scale = 16;
255 break;
256 default:
257 llvm_unreachable("Unexpected callee-save save/restore opcode!");
258 }
259
260 unsigned OffsetIdx = MI.getNumExplicitOperands() - 1;
261 assert(MI.getOperand(OffsetIdx - 1).getReg() == AArch64::SP &&
262 "Unexpected base register in callee-save save/restore instruction!");
263 // Last operand is immediate offset that needs fixing.
264 MachineOperand &OffsetOpnd = MI.getOperand(OffsetIdx);
265 // All generated opcodes have scaled offsets.
266 assert(LocalStackSize % Scale == 0);
267 OffsetOpnd.setImm(OffsetOpnd.getImm() + LocalStackSize / Scale);
268
269 if (NeedsWinCFI) {
270 HasWinCFI = true;
271 auto MBBI = std::next(MachineBasicBlock::iterator(MI));
272 assert(MBBI != MI.getParent()->end() && "Expecting a valid instruction");
273 assert(AArch64InstrInfo::isSEHInstruction(*MBBI) &&
274 "Expecting a SEH instruction");
275 fixupSEHOpcode(MBBI, LocalStackSize);
276 }
277}
278
280 uint64_t StackBumpBytes) const {
281 if (AFL.homogeneousPrologEpilog(MF))
282 return false;
283
284 if (AFI->getLocalStackSize() == 0)
285 return false;
286
287 // For WinCFI, if optimizing for size, prefer to not combine the stack bump
288 // (to force a stp with predecrement) to match the packed unwind format,
289 // provided that there actually are any callee saved registers to merge the
290 // decrement with.
291 // This is potentially marginally slower, but allows using the packed
292 // unwind format for functions that both have a local area and callee saved
293 // registers. Using the packed unwind format notably reduces the size of
294 // the unwind info.
295 if (AFL.needsWinCFI(MF) && AFI->getCalleeSavedStackSize() > 0 &&
296 MF.getFunction().hasOptSize())
297 return false;
298
299 // 512 is the maximum immediate for stp/ldp that will be used for
300 // callee-save save/restores
301 if (StackBumpBytes >= 512 ||
302 AFL.windowsRequiresStackProbe(MF, StackBumpBytes))
303 return false;
304
305 if (MFI.hasVarSizedObjects())
306 return false;
307
308 if (RegInfo.hasStackRealignment(MF))
309 return false;
310
311 // This isn't strictly necessary, but it simplifies things a bit since the
312 // current RedZone handling code assumes the SP is adjusted by the
313 // callee-save save/restore code.
314 if (AFL.canUseRedZone(MF))
315 return false;
316
317 // When there is an SVE area on the stack, always allocate the
318 // callee-saves and spills/locals separately.
319 if (AFL.getSVEStackSize(MF))
320 return false;
321
322 return true;
323}
324
329 EmitCFI = AFI->needsDwarfUnwindInfo(MF);
330 EmitAsyncCFI = AFI->needsAsyncDwarfUnwindInfo(MF);
331 IsFunclet = MBB.isEHFuncletEntry();
332 HomPrologEpilog = AFL.homogeneousPrologEpilog(MF);
333
334#ifndef NDEBUG
335 collectBlockLiveins();
336#endif
337}
338
339#ifndef NDEBUG
340/// Collect live registers from the end of \p MI's parent up to (including) \p
341/// MI in \p LiveRegs.
344
345 MachineBasicBlock &MBB = *MI.getParent();
346 LiveRegs.addLiveOuts(MBB);
347 for (const MachineInstr &MI :
348 reverse(make_range(MI.getIterator(), MBB.instr_end())))
349 LiveRegs.stepBackward(MI);
350}
351
352void AArch64PrologueEmitter::collectBlockLiveins() {
353 // Collect live register from the end of MBB up to the start of the existing
354 // frame setup instructions.
355 PrologueEndI = MBB.begin();
356 while (PrologueEndI != MBB.end() &&
357 PrologueEndI->getFlag(MachineInstr::FrameSetup))
358 ++PrologueEndI;
359
360 if (PrologueEndI != MBB.end()) {
361 getLivePhysRegsUpTo(*PrologueEndI, RegInfo, LiveRegs);
362 // Ignore registers used for stack management for now.
363 LiveRegs.removeReg(AArch64::SP);
364 LiveRegs.removeReg(AArch64::X19);
365 LiveRegs.removeReg(AArch64::FP);
366 LiveRegs.removeReg(AArch64::LR);
367
368 // X0 will be clobbered by a call to __arm_get_current_vg in the prologue.
369 // This is necessary to spill VG if required where SVE is unavailable, but
370 // X0 is preserved around this call.
371 if (requiresGetVGCall())
372 LiveRegs.removeReg(AArch64::X0);
373 }
374}
375
376void AArch64PrologueEmitter::verifyPrologueClobbers() const {
377 if (PrologueEndI == MBB.end())
378 return;
379 // Check if any of the newly instructions clobber any of the live registers.
380 for (MachineInstr &MI :
381 make_range(MBB.instr_begin(), PrologueEndI->getIterator())) {
382 for (auto &Op : MI.operands())
383 if (Op.isReg() && Op.isDef())
384 assert(!LiveRegs.contains(Op.getReg()) &&
385 "live register clobbered by inserted prologue instructions");
386 }
387}
388#endif
389
390void AArch64PrologueEmitter::determineLocalsStackSize(
391 uint64_t StackSize, uint64_t PrologueSaveSize) {
392 AFI->setLocalStackSize(StackSize - PrologueSaveSize);
393 CombineSPBump = shouldCombineCSRLocalStackBump(StackSize);
394}
395
396// Return the maximum possible number of bytes for `Size` due to the
397// architectural limit on the size of a SVE register.
398static int64_t upperBound(StackOffset Size) {
399 static const int64_t MAX_BYTES_PER_SCALABLE_BYTE = 16;
400 return Size.getScalable() * MAX_BYTES_PER_SCALABLE_BYTE + Size.getFixed();
401}
402
403void AArch64PrologueEmitter::allocateStackSpace(
404 MachineBasicBlock::iterator MBBI, int64_t RealignmentPadding,
405 StackOffset AllocSize, bool EmitCFI, StackOffset InitialOffset,
406 bool FollowupAllocs) {
407
408 if (!AllocSize)
409 return;
410
411 DebugLoc DL;
412 const int64_t MaxAlign = MFI.getMaxAlign().value();
413 const uint64_t AndMask = ~(MaxAlign - 1);
414
416 Register TargetReg = RealignmentPadding
417 ? AFL.findScratchNonCalleeSaveRegister(&MBB)
418 : AArch64::SP;
419 // SUB Xd/SP, SP, AllocSize
420 emitFrameOffset(MBB, MBBI, DL, TargetReg, AArch64::SP, -AllocSize, TII,
422 EmitCFI, InitialOffset);
423
424 if (RealignmentPadding) {
425 // AND SP, X9, 0b11111...0000
426 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), AArch64::SP)
427 .addReg(TargetReg, RegState::Kill)
430 AFI->setStackRealigned(true);
431
432 // No need for SEH instructions here; if we're realigning the stack,
433 // we've set a frame pointer and already finished the SEH prologue.
435 }
436 return;
437 }
438
439 //
440 // Stack probing allocation.
441 //
442
443 // Fixed length allocation. If we don't need to re-align the stack and don't
444 // have SVE objects, we can use a more efficient sequence for stack probing.
445 if (AllocSize.getScalable() == 0 && RealignmentPadding == 0) {
446 Register ScratchReg = AFL.findScratchNonCalleeSaveRegister(&MBB);
447 assert(ScratchReg != AArch64::NoRegister);
448 BuildMI(MBB, MBBI, DL, TII->get(AArch64::PROBED_STACKALLOC))
449 .addDef(ScratchReg)
450 .addImm(AllocSize.getFixed())
451 .addImm(InitialOffset.getFixed())
452 .addImm(InitialOffset.getScalable());
453 // The fixed allocation may leave unprobed bytes at the top of the
454 // stack. If we have subsequent allocation (e.g. if we have variable-sized
455 // objects), we need to issue an extra probe, so these allocations start in
456 // a known state.
457 if (FollowupAllocs) {
458 // STR XZR, [SP]
459 BuildMI(MBB, MBBI, DL, TII->get(AArch64::STRXui))
460 .addReg(AArch64::XZR)
461 .addReg(AArch64::SP)
462 .addImm(0)
464 }
465
466 return;
467 }
468
469 // Variable length allocation.
470
471 // If the (unknown) allocation size cannot exceed the probe size, decrement
472 // the stack pointer right away.
473 int64_t ProbeSize = AFI->getStackProbeSize();
474 if (upperBound(AllocSize) + RealignmentPadding <= ProbeSize) {
475 Register ScratchReg = RealignmentPadding
476 ? AFL.findScratchNonCalleeSaveRegister(&MBB)
477 : AArch64::SP;
478 assert(ScratchReg != AArch64::NoRegister);
479 // SUB Xd, SP, AllocSize
480 emitFrameOffset(MBB, MBBI, DL, ScratchReg, AArch64::SP, -AllocSize, TII,
482 EmitCFI, InitialOffset);
483 if (RealignmentPadding) {
484 // AND SP, Xn, 0b11111...0000
485 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), AArch64::SP)
486 .addReg(ScratchReg, RegState::Kill)
489 AFI->setStackRealigned(true);
490 }
491 if (FollowupAllocs || upperBound(AllocSize) + RealignmentPadding >
493 // STR XZR, [SP]
494 BuildMI(MBB, MBBI, DL, TII->get(AArch64::STRXui))
495 .addReg(AArch64::XZR)
496 .addReg(AArch64::SP)
497 .addImm(0)
499 }
500 return;
501 }
502
503 // Emit a variable-length allocation probing loop.
504 // TODO: As an optimisation, the loop can be "unrolled" into a few parts,
505 // each of them guaranteed to adjust the stack by less than the probe size.
506 Register TargetReg = AFL.findScratchNonCalleeSaveRegister(&MBB);
507 assert(TargetReg != AArch64::NoRegister);
508 // SUB Xd, SP, AllocSize
509 emitFrameOffset(MBB, MBBI, DL, TargetReg, AArch64::SP, -AllocSize, TII,
511 EmitCFI, InitialOffset);
512 if (RealignmentPadding) {
513 // AND Xn, Xn, 0b11111...0000
514 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), TargetReg)
515 .addReg(TargetReg, RegState::Kill)
518 }
519
520 BuildMI(MBB, MBBI, DL, TII->get(AArch64::PROBED_STACKALLOC_VAR))
521 .addReg(TargetReg);
522 if (EmitCFI) {
523 // Set the CFA register back to SP.
524 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
525 .buildDefCFARegister(AArch64::SP);
526 }
527 if (RealignmentPadding)
528 AFI->setStackRealigned(true);
529}
530
532 const MachineBasicBlock::iterator PrologueBeginI = MBB.begin();
533 const MachineBasicBlock::iterator EndI = MBB.end();
534
535 // At this point, we're going to decide whether or not the function uses a
536 // redzone. In most cases, the function doesn't have a redzone so let's
537 // assume that's false and set it to true in the case that there's a redzone.
538 AFI->setHasRedZone(false);
539
540 // Debug location must be unknown since the first debug location is used
541 // to determine the end of the prologue.
542 DebugLoc DL;
543
544 // In some cases, particularly with CallingConv::SwiftTail, it is possible to
545 // have a tail-call where the caller only needs to adjust the stack pointer in
546 // the epilogue. In this case, we still need to emit a SEH prologue sequence.
547 // See `seh-minimal-prologue-epilogue.ll` test cases.
548 if (AFI->getArgumentStackToRestore())
549 HasWinCFI = true;
550
551 if (AFI->shouldSignReturnAddress(MF)) {
552 // If pac-ret+leaf is in effect, PAUTH_PROLOGUE pseudo instructions
553 // are inserted by emitPacRetPlusLeafHardening().
554 if (!AFL.shouldSignReturnAddressEverywhere(MF)) {
555 BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::PAUTH_PROLOGUE))
557 }
558 // AArch64PointerAuth pass will insert SEH_PACSignLR
560 }
561
562 if (AFI->needsShadowCallStackPrologueEpilogue(MF)) {
563 emitShadowCallStackPrologue(PrologueBeginI, DL);
565 }
566
567 if (EmitCFI && AFI->isMTETagged())
568 BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::EMITMTETAGGED))
570
571 // We signal the presence of a Swift extended frame to external tools by
572 // storing FP with 0b0001 in bits 63:60. In normal userland operation a simple
573 // ORR is sufficient, it is assumed a Swift kernel would initialize the TBI
574 // bits so that is still true.
575 if (HasFP && AFI->hasSwiftAsyncContext())
576 emitSwiftAsyncContextFramePointer(PrologueBeginI, DL);
577
578 // All calls are tail calls in GHC calling conv, and functions have no
579 // prologue/epilogue.
580 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
581 return;
582
583 // Set tagged base pointer to the requested stack slot. Ideally it should
584 // match SP value after prologue.
585 if (std::optional<int> TBPI = AFI->getTaggedBasePointerIndex())
586 AFI->setTaggedBasePointerOffset(-MFI.getObjectOffset(*TBPI));
587 else
588 AFI->setTaggedBasePointerOffset(MFI.getStackSize());
589
590 // getStackSize() includes all the locals in its size calculation. We don't
591 // include these locals when computing the stack size of a funclet, as they
592 // are allocated in the parent's stack frame and accessed via the frame
593 // pointer from the funclet. We only save the callee saved registers in the
594 // funclet, which are really the callee saved registers of the parent
595 // function, including the funclet.
596 int64_t NumBytes =
597 IsFunclet ? AFL.getWinEHFuncletFrameSize(MF) : MFI.getStackSize();
598 if (!AFI->hasStackFrame() && !AFL.windowsRequiresStackProbe(MF, NumBytes))
599 return emitEmptyStackFramePrologue(NumBytes, PrologueBeginI, DL);
600
601 bool IsWin64 = Subtarget.isCallingConvWin64(F.getCallingConv(), F.isVarArg());
602 unsigned FixedObject = AFL.getFixedObjectSize(MF, AFI, IsWin64, IsFunclet);
603
604 // Windows unwind can't represent the required stack adjustments if we have
605 // both SVE callee-saves and dynamic stack allocations, and the frame
606 // pointer is before the SVE spills. The allocation of the frame pointer
607 // must be the last instruction in the prologue so the unwinder can restore
608 // the stack pointer correctly. (And there isn't any unwind opcode for
609 // `addvl sp, x29, -17`.)
610 //
611 // Because of this, we do spills in the opposite order on Windows: first SVE,
612 // then GPRs. The main side-effect of this is that it makes accessing
613 // parameters passed on the stack more expensive.
614 //
615 // We could consider rearranging the spills for simpler cases.
616 bool FPAfterSVECalleeSaves =
617 Subtarget.isTargetWindows() && AFI->getSVECalleeSavedStackSize();
618
619 if (FPAfterSVECalleeSaves && AFI->hasStackHazardSlotIndex())
620 reportFatalUsageError("SME hazard padding is not supported on Windows");
621
622 auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
623 // All of the remaining stack allocations are for locals.
624 determineLocalsStackSize(NumBytes, PrologueSaveSize);
625
626 MachineBasicBlock::iterator FirstGPRSaveI = PrologueBeginI;
627 if (FPAfterSVECalleeSaves) {
628 // If we're doing SVE saves first, we need to immediately allocate space
629 // for fixed objects, then space for the SVE callee saves.
630 //
631 // Windows unwind requires that the scalable size is a multiple of 16;
632 // that's handled when the callee-saved size is computed.
633 auto SaveSize =
634 StackOffset::getScalable(AFI->getSVECalleeSavedStackSize()) +
635 StackOffset::getFixed(FixedObject);
636 allocateStackSpace(PrologueBeginI, 0, SaveSize, false, StackOffset{},
637 /*FollowupAllocs=*/true);
638 NumBytes -= FixedObject;
639
640 // Now allocate space for the GPR callee saves.
641 MachineBasicBlock::iterator MBBI = PrologueBeginI;
642 while (MBBI != EndI && isSVECalleeSave(MBBI))
643 ++MBBI;
645 MBBI, DL, -AFI->getCalleeSavedStackSize(), EmitAsyncCFI);
646 NumBytes -= AFI->getCalleeSavedStackSize();
647 } else if (CombineSPBump) {
648 assert(!AFL.getSVEStackSize(MF) && "Cannot combine SP bump with SVE");
649 emitFrameOffset(MBB, PrologueBeginI, DL, AArch64::SP, AArch64::SP,
650 StackOffset::getFixed(-NumBytes), TII,
652 EmitAsyncCFI);
653 NumBytes = 0;
654 } else if (HomPrologEpilog) {
655 // Stack has been already adjusted.
656 NumBytes -= PrologueSaveSize;
657 } else if (PrologueSaveSize != 0) {
659 PrologueBeginI, DL, -PrologueSaveSize, EmitAsyncCFI);
660 NumBytes -= PrologueSaveSize;
661 }
662 assert(NumBytes >= 0 && "Negative stack allocation size!?");
663
664 // Move past the saves of the callee-saved registers, fixing up the offsets
665 // and pre-inc if we decided to combine the callee-save and local stack
666 // pointer bump above.
667 auto &TLI = *Subtarget.getTargetLowering();
668
669 MachineBasicBlock::iterator AfterGPRSavesI = FirstGPRSaveI;
670 while (AfterGPRSavesI != EndI &&
671 AfterGPRSavesI->getFlag(MachineInstr::FrameSetup) &&
672 !isSVECalleeSave(AfterGPRSavesI)) {
673 if (CombineSPBump &&
674 // Only fix-up frame-setup load/store instructions.
675 (!AFL.requiresSaveVG(MF) || !isVGInstruction(AfterGPRSavesI, TLI)))
676 fixupCalleeSaveRestoreStackOffset(*AfterGPRSavesI,
677 AFI->getLocalStackSize());
678 ++AfterGPRSavesI;
679 }
680
681 // For funclets the FP belongs to the containing function. Only set up FP if
682 // we actually need to.
683 if (!IsFunclet && HasFP)
684 emitFramePointerSetup(AfterGPRSavesI, DL, FixedObject);
685
686 // Now emit the moves for whatever callee saved regs we have (including FP,
687 // LR if those are saved). Frame instructions for SVE register are emitted
688 // later, after the instruction which actually save SVE regs.
689 if (EmitAsyncCFI)
690 emitCalleeSavedGPRLocations(AfterGPRSavesI);
691
692 // Alignment is required for the parent frame, not the funclet
693 const bool NeedsRealignment =
694 NumBytes && !IsFunclet && RegInfo.hasStackRealignment(MF);
695 const int64_t RealignmentPadding =
696 (NeedsRealignment && MFI.getMaxAlign() > Align(16))
697 ? MFI.getMaxAlign().value() - 16
698 : 0;
699
700 if (AFL.windowsRequiresStackProbe(MF, NumBytes + RealignmentPadding))
701 emitWindowsStackProbe(AfterGPRSavesI, DL, NumBytes, RealignmentPadding);
702
703 StackOffset SVEStackSize = AFL.getSVEStackSize(MF);
704 StackOffset SVECalleeSavesSize = {}, SVELocalsSize = SVEStackSize;
705 MachineBasicBlock::iterator CalleeSavesEnd = AfterGPRSavesI;
706
707 StackOffset CFAOffset =
708 StackOffset::getFixed((int64_t)MFI.getStackSize() - NumBytes);
709
710 // Process the SVE callee-saves to determine what space needs to be
711 // allocated.
712 MachineBasicBlock::iterator AfterSVESavesI = AfterGPRSavesI;
713 if (int64_t CalleeSavedSize = AFI->getSVECalleeSavedStackSize()) {
714 LLVM_DEBUG(dbgs() << "SVECalleeSavedStackSize = " << CalleeSavedSize
715 << "\n");
716 SVECalleeSavesSize = StackOffset::getScalable(CalleeSavedSize);
717 SVELocalsSize = SVEStackSize - SVECalleeSavesSize;
718 // Find callee save instructions in frame.
719 // Note: With FPAfterSVECalleeSaves the callee saves have already been
720 // allocated.
721 if (!FPAfterSVECalleeSaves) {
722 MachineBasicBlock::iterator CalleeSavesBegin = AfterGPRSavesI;
723 assert(isSVECalleeSave(CalleeSavesBegin) && "Unexpected instruction");
724 while (isSVECalleeSave(AfterSVESavesI) &&
725 AfterSVESavesI != MBB.getFirstTerminator())
726 ++AfterSVESavesI;
727 CalleeSavesEnd = AfterSVESavesI;
728
729 StackOffset LocalsSize = SVELocalsSize + StackOffset::getFixed(NumBytes);
730 // Allocate space for the callee saves (if any).
731 allocateStackSpace(CalleeSavesBegin, 0, SVECalleeSavesSize,
732 EmitAsyncCFI && !HasFP, CFAOffset,
733 MFI.hasVarSizedObjects() || LocalsSize);
734 }
735 }
736 CFAOffset += SVECalleeSavesSize;
737
738 if (EmitAsyncCFI)
739 emitCalleeSavedSVELocations(CalleeSavesEnd);
740
741 // Allocate space for the rest of the frame including SVE locals. Align the
742 // stack as necessary.
743 assert(!(AFL.canUseRedZone(MF) && NeedsRealignment) &&
744 "Cannot use redzone with stack realignment");
745 if (!AFL.canUseRedZone(MF)) {
746 // FIXME: in the case of dynamic re-alignment, NumBytes doesn't have
747 // the correct value here, as NumBytes also includes padding bytes,
748 // which shouldn't be counted here.
749 allocateStackSpace(CalleeSavesEnd, RealignmentPadding,
750 SVELocalsSize + StackOffset::getFixed(NumBytes),
751 EmitAsyncCFI && !HasFP, CFAOffset,
752 MFI.hasVarSizedObjects());
753 }
754
755 // If we need a base pointer, set it up here. It's whatever the value of the
756 // stack pointer is at this point. Any variable size objects will be allocated
757 // after this, so we can still use the base pointer to reference locals.
758 //
759 // FIXME: Clarify FrameSetup flags here.
760 // Note: Use emitFrameOffset() like above for FP if the FrameSetup flag is
761 // needed.
762 // For funclets the BP belongs to the containing function.
763 if (!IsFunclet && RegInfo.hasBasePointer(MF)) {
764 TII->copyPhysReg(MBB, AfterSVESavesI, DL, RegInfo.getBaseRegister(),
765 AArch64::SP, false);
766 if (NeedsWinCFI) {
767 HasWinCFI = true;
768 BuildMI(MBB, AfterSVESavesI, DL, TII->get(AArch64::SEH_Nop))
770 }
771 }
772
773 // The very last FrameSetup instruction indicates the end of prologue. Emit a
774 // SEH opcode indicating the prologue end.
775 if (NeedsWinCFI && HasWinCFI) {
776 BuildMI(MBB, AfterSVESavesI, DL, TII->get(AArch64::SEH_PrologEnd))
778 }
779
780 // SEH funclets are passed the frame pointer in X1. If the parent
781 // function uses the base register, then the base register is used
782 // directly, and is not retrieved from X1.
783 if (IsFunclet && F.hasPersonalityFn()) {
784 EHPersonality Per = classifyEHPersonality(F.getPersonalityFn());
786 BuildMI(MBB, AfterSVESavesI, DL, TII->get(TargetOpcode::COPY),
787 AArch64::FP)
788 .addReg(AArch64::X1)
790 MBB.addLiveIn(AArch64::X1);
791 }
792 }
793
794 if (EmitCFI && !EmitAsyncCFI) {
795 if (HasFP) {
796 emitDefineCFAWithFP(AfterSVESavesI, FixedObject);
797 } else {
798 StackOffset TotalSize =
799 SVEStackSize + StackOffset::getFixed((int64_t)MFI.getStackSize());
800 CFIInstBuilder CFIBuilder(MBB, AfterSVESavesI, MachineInstr::FrameSetup);
801 CFIBuilder.insertCFIInst(
802 createDefCFA(RegInfo, /*FrameReg=*/AArch64::SP, /*Reg=*/AArch64::SP,
803 TotalSize, /*LastAdjustmentWasScalable=*/false));
804 }
805 emitCalleeSavedGPRLocations(AfterSVESavesI);
806 emitCalleeSavedSVELocations(AfterSVESavesI);
807 }
808}
809
810void AArch64PrologueEmitter::emitShadowCallStackPrologue(
812 // Shadow call stack prolog: str x30, [x18], #8
813 BuildMI(MBB, MBBI, DL, TII->get(AArch64::STRXpost))
814 .addReg(AArch64::X18, RegState::Define)
815 .addReg(AArch64::LR)
816 .addReg(AArch64::X18)
817 .addImm(8)
819
820 // This instruction also makes x18 live-in to the entry block.
821 MBB.addLiveIn(AArch64::X18);
822
823 if (NeedsWinCFI)
824 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
826
827 if (EmitCFI) {
828 // Emit a CFI instruction that causes 8 to be subtracted from the value of
829 // x18 when unwinding past this frame.
830 static const char CFIInst[] = {
831 dwarf::DW_CFA_val_expression,
832 18, // register
833 2, // length
834 static_cast<char>(unsigned(dwarf::DW_OP_breg18)),
835 static_cast<char>(-8) & 0x7f, // addend (sleb128)
836 };
837 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
838 .buildEscape(StringRef(CFIInst, sizeof(CFIInst)));
839 }
840}
841
842void AArch64PrologueEmitter::emitSwiftAsyncContextFramePointer(
844 switch (MF.getTarget().Options.SwiftAsyncFramePointer) {
846 if (Subtarget.swiftAsyncContextIsDynamicallySet()) {
847 // The special symbol below is absolute and has a *value* that can be
848 // combined with the frame pointer to signal an extended frame.
849 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LOADgot), AArch64::X16)
850 .addExternalSymbol("swift_async_extendedFramePointerFlags",
852 if (NeedsWinCFI) {
853 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
855 HasWinCFI = true;
856 }
857 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::FP)
858 .addUse(AArch64::FP)
859 .addUse(AArch64::X16)
860 .addImm(Subtarget.isTargetILP32() ? 32 : 0);
861 if (NeedsWinCFI) {
862 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
864 HasWinCFI = true;
865 }
866 break;
867 }
868 [[fallthrough]];
869
871 // ORR x29, x29, #0x1000_0000_0000_0000
872 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXri), AArch64::FP)
873 .addUse(AArch64::FP)
874 .addImm(0x1100)
876 if (NeedsWinCFI) {
877 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
879 HasWinCFI = true;
880 }
881 break;
882
884 break;
885 }
886}
887
888void AArch64PrologueEmitter::emitEmptyStackFramePrologue(
889 int64_t NumBytes, MachineBasicBlock::iterator MBBI,
890 const DebugLoc &DL) const {
891 assert(!HasFP && "unexpected function without stack frame but with FP");
892 assert(!AFL.getSVEStackSize(MF) &&
893 "unexpected function without stack frame but with SVE objects");
894 // All of the stack allocation is for locals.
895 AFI->setLocalStackSize(NumBytes);
896 if (!NumBytes) {
897 if (NeedsWinCFI && HasWinCFI) {
898 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
900 }
901 return;
902 }
903 // REDZONE: If the stack size is less than 128 bytes, we don't need
904 // to actually allocate.
905 if (AFL.canUseRedZone(MF)) {
906 AFI->setHasRedZone(true);
907 ++NumRedZoneFunctions;
908 } else {
909 emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP,
910 StackOffset::getFixed(-NumBytes), TII,
912 if (EmitCFI) {
913 // Label used to tie together the PROLOG_LABEL and the MachineMoves.
914 MCSymbol *FrameLabel = MF.getContext().createTempSymbol();
915 // Encode the stack size of the leaf function.
916 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
917 .buildDefCFAOffset(NumBytes, FrameLabel);
918 }
919 }
920
921 if (NeedsWinCFI) {
922 HasWinCFI = true;
923 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
925 }
926}
927
928void AArch64PrologueEmitter::emitFramePointerSetup(
930 unsigned FixedObject) {
931 int64_t FPOffset = AFI->getCalleeSaveBaseToFrameRecordOffset();
932 if (CombineSPBump)
933 FPOffset += AFI->getLocalStackSize();
934
935 if (AFI->hasSwiftAsyncContext()) {
936 // Before we update the live FP we have to ensure there's a valid (or
937 // null) asynchronous context in its slot just before FP in the frame
938 // record, so store it now.
939 const auto &Attrs = MF.getFunction().getAttributes();
940 bool HaveInitialContext = Attrs.hasAttrSomewhere(Attribute::SwiftAsync);
941 if (HaveInitialContext)
942 MBB.addLiveIn(AArch64::X22);
943 Register Reg = HaveInitialContext ? AArch64::X22 : AArch64::XZR;
944 BuildMI(MBB, MBBI, DL, TII->get(AArch64::StoreSwiftAsyncContext))
945 .addUse(Reg)
946 .addUse(AArch64::SP)
947 .addImm(FPOffset - 8)
949 if (NeedsWinCFI) {
950 // WinCFI and arm64e, where StoreSwiftAsyncContext is expanded
951 // to multiple instructions, should be mutually-exclusive.
952 assert(Subtarget.getTargetTriple().getArchName() != "arm64e");
953 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
955 HasWinCFI = true;
956 }
957 }
958
959 if (HomPrologEpilog) {
960 auto Prolog = MBBI;
961 --Prolog;
962 assert(Prolog->getOpcode() == AArch64::HOM_Prolog);
963 Prolog->addOperand(MachineOperand::CreateImm(FPOffset));
964 } else {
965 // Issue sub fp, sp, FPOffset or
966 // mov fp,sp when FPOffset is zero.
967 // Note: All stores of callee-saved registers are marked as "FrameSetup".
968 // This code marks the instruction(s) that set the FP also.
969 emitFrameOffset(MBB, MBBI, DL, AArch64::FP, AArch64::SP,
970 StackOffset::getFixed(FPOffset), TII,
972 if (NeedsWinCFI && HasWinCFI) {
973 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
975 // After setting up the FP, the rest of the prolog doesn't need to be
976 // included in the SEH unwind info.
977 NeedsWinCFI = false;
978 }
979 }
980 if (EmitAsyncCFI)
981 emitDefineCFAWithFP(MBBI, FixedObject);
982}
983
984// Define the current CFA rule to use the provided FP.
985void AArch64PrologueEmitter::emitDefineCFAWithFP(
986 MachineBasicBlock::iterator MBBI, unsigned FixedObject) const {
987 const int OffsetToFirstCalleeSaveFromFP =
988 AFI->getCalleeSaveBaseToFrameRecordOffset() -
989 AFI->getCalleeSavedStackSize();
990 Register FramePtr = RegInfo.getFrameRegister(MF);
991 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
992 .buildDefCFA(FramePtr, FixedObject - OffsetToFirstCalleeSaveFromFP);
993}
994
995void AArch64PrologueEmitter::emitWindowsStackProbe(
996 MachineBasicBlock::iterator MBBI, const DebugLoc &DL, int64_t &NumBytes,
997 int64_t RealignmentPadding) const {
998 if (AFI->getSVECalleeSavedStackSize())
999 report_fatal_error("SVE callee saves not yet supported with stack probing");
1000
1001 // Find an available register to spill the value of X15 to, if X15 is being
1002 // used already for nest.
1003 unsigned X15Scratch = AArch64::NoRegister;
1004 if (llvm::any_of(MBB.liveins(),
1005 [this](const MachineBasicBlock::RegisterMaskPair &LiveIn) {
1006 return RegInfo.isSuperOrSubRegisterEq(AArch64::X15,
1007 LiveIn.PhysReg);
1008 })) {
1009 X15Scratch = AFL.findScratchNonCalleeSaveRegister(&MBB, /*HasCall=*/true);
1010 assert(X15Scratch != AArch64::NoRegister &&
1011 (X15Scratch < AArch64::X15 || X15Scratch > AArch64::X17));
1012#ifndef NDEBUG
1013 LiveRegs.removeReg(AArch64::X15); // ignore X15 since we restore it
1014#endif
1015 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrr), X15Scratch)
1016 .addReg(AArch64::XZR)
1017 .addReg(AArch64::X15, RegState::Undef)
1018 .addReg(AArch64::X15, RegState::Implicit)
1020 }
1021
1022 uint64_t NumWords = (NumBytes + RealignmentPadding) >> 4;
1023 if (NeedsWinCFI) {
1024 HasWinCFI = true;
1025 // alloc_l can hold at most 256MB, so assume that NumBytes doesn't
1026 // exceed this amount. We need to move at most 2^24 - 1 into x15.
1027 // This is at most two instructions, MOVZ followed by MOVK.
1028 // TODO: Fix to use multiple stack alloc unwind codes for stacks
1029 // exceeding 256MB in size.
1030 if (NumBytes >= (1 << 28))
1031 report_fatal_error("Stack size cannot exceed 256MB for stack "
1032 "unwinding purposes");
1033
1034 uint32_t LowNumWords = NumWords & 0xFFFF;
1035 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVZXi), AArch64::X15)
1036 .addImm(LowNumWords)
1039 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1041 if ((NumWords & 0xFFFF0000) != 0) {
1042 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVKXi), AArch64::X15)
1043 .addReg(AArch64::X15)
1044 .addImm((NumWords & 0xFFFF0000) >> 16) // High half
1047 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1049 }
1050 } else {
1051 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVi64imm), AArch64::X15)
1052 .addImm(NumWords)
1054 }
1055
1056 const char *ChkStk = Subtarget.getChkStkName();
1057 switch (MF.getTarget().getCodeModel()) {
1058 case CodeModel::Tiny:
1059 case CodeModel::Small:
1060 case CodeModel::Medium:
1061 case CodeModel::Kernel:
1062 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
1063 .addExternalSymbol(ChkStk)
1064 .addReg(AArch64::X15, RegState::Implicit)
1065 .addReg(AArch64::X16,
1067 .addReg(AArch64::X17,
1069 .addReg(AArch64::NZCV,
1072 if (NeedsWinCFI) {
1073 HasWinCFI = true;
1074 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1076 }
1077 break;
1078 case CodeModel::Large:
1079 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVaddrEXT))
1080 .addReg(AArch64::X16, RegState::Define)
1081 .addExternalSymbol(ChkStk)
1082 .addExternalSymbol(ChkStk)
1084 if (NeedsWinCFI) {
1085 HasWinCFI = true;
1086 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1088 }
1089
1091 .addReg(AArch64::X16, RegState::Kill)
1093 .addReg(AArch64::X16,
1095 .addReg(AArch64::X17,
1097 .addReg(AArch64::NZCV,
1100 if (NeedsWinCFI) {
1101 HasWinCFI = true;
1102 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1104 }
1105 break;
1106 }
1107
1108 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SUBXrx64), AArch64::SP)
1109 .addReg(AArch64::SP, RegState::Kill)
1110 .addReg(AArch64::X15, RegState::Kill)
1113 if (NeedsWinCFI) {
1114 HasWinCFI = true;
1115 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
1116 .addImm(NumBytes)
1118 }
1119 NumBytes = 0;
1120
1121 if (RealignmentPadding > 0) {
1122 if (RealignmentPadding >= 4096) {
1123 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVi64imm))
1124 .addReg(AArch64::X16, RegState::Define)
1125 .addImm(RealignmentPadding)
1127 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXrx64), AArch64::X15)
1128 .addReg(AArch64::SP)
1129 .addReg(AArch64::X16, RegState::Kill)
1132 } else {
1133 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXri), AArch64::X15)
1134 .addReg(AArch64::SP)
1135 .addImm(RealignmentPadding)
1136 .addImm(0)
1138 }
1139
1140 uint64_t AndMask = ~(MFI.getMaxAlign().value() - 1);
1141 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), AArch64::SP)
1142 .addReg(AArch64::X15, RegState::Kill)
1144 AFI->setStackRealigned(true);
1145
1146 // No need for SEH instructions here; if we're realigning the stack,
1147 // we've set a frame pointer and already finished the SEH prologue.
1149 }
1150 if (X15Scratch != AArch64::NoRegister) {
1151 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrr), AArch64::X15)
1152 .addReg(AArch64::XZR)
1153 .addReg(X15Scratch, RegState::Undef)
1154 .addReg(X15Scratch, RegState::Implicit)
1156 }
1157}
1158
1159void AArch64PrologueEmitter::emitCalleeSavedGPRLocations(
1161 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
1162 if (CSI.empty())
1163 return;
1164
1165 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameSetup);
1166 for (const auto &Info : CSI) {
1167 unsigned FrameIdx = Info.getFrameIdx();
1168 if (MFI.getStackID(FrameIdx) == TargetStackID::ScalableVector)
1169 continue;
1170
1171 assert(!Info.isSpilledToReg() && "Spilling to registers not implemented");
1172 int64_t Offset = MFI.getObjectOffset(FrameIdx) - AFL.getOffsetOfLocalArea();
1173 CFIBuilder.buildOffset(Info.getReg(), Offset);
1174 }
1175}
1176
1177void AArch64PrologueEmitter::emitCalleeSavedSVELocations(
1179 // Add callee saved registers to move list.
1180 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
1181 if (CSI.empty())
1182 return;
1183
1184 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameSetup);
1185
1186 std::optional<int64_t> IncomingVGOffsetFromDefCFA;
1187 if (AFL.requiresSaveVG(MF)) {
1188 auto IncomingVG = *find_if(
1189 reverse(CSI), [](auto &Info) { return Info.getReg() == AArch64::VG; });
1190 IncomingVGOffsetFromDefCFA = MFI.getObjectOffset(IncomingVG.getFrameIdx()) -
1191 AFL.getOffsetOfLocalArea();
1192 }
1193
1194 for (const auto &Info : CSI) {
1195 if (MFI.getStackID(Info.getFrameIdx()) != TargetStackID::ScalableVector)
1196 continue;
1197
1198 // Not all unwinders may know about SVE registers, so assume the lowest
1199 // common denominator.
1200 assert(!Info.isSpilledToReg() && "Spilling to registers not implemented");
1201 MCRegister Reg = Info.getReg();
1202 if (!RegInfo.regNeedsCFI(Reg, Reg))
1203 continue;
1204
1205 StackOffset Offset =
1206 StackOffset::getScalable(MFI.getObjectOffset(Info.getFrameIdx())) -
1207 StackOffset::getFixed(AFI->getCalleeSavedStackSize(MFI));
1208
1209 CFIBuilder.insertCFIInst(
1210 createCFAOffset(RegInfo, Reg, Offset, IncomingVGOffsetFromDefCFA));
1211 }
1212}
1213
1215 switch (MI.getOpcode()) {
1216 default:
1217 return false;
1218 case AArch64::CATCHRET:
1219 case AArch64::CLEANUPRET:
1220 return true;
1221 }
1222}
1223
1228 EmitCFI = AFI->needsAsyncDwarfUnwindInfo(MF);
1229 HomPrologEpilog = AFL.homogeneousPrologEpilog(MF, &MBB);
1230 SEHEpilogueStartI = MBB.end();
1231}
1232
1234 MachineBasicBlock::iterator EpilogueEndI = MBB.getLastNonDebugInstr();
1235 if (MBB.end() != EpilogueEndI) {
1236 DL = EpilogueEndI->getDebugLoc();
1237 IsFunclet = isFuncletReturnInstr(*EpilogueEndI);
1238 }
1239
1240 int64_t NumBytes =
1241 IsFunclet ? AFL.getWinEHFuncletFrameSize(MF) : MFI.getStackSize();
1242
1243 // All calls are tail calls in GHC calling conv, and functions have no
1244 // prologue/epilogue.
1245 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
1246 return;
1247
1248 // How much of the stack used by incoming arguments this function is expected
1249 // to restore in this particular epilogue.
1250 int64_t ArgumentStackToRestore = AFL.getArgumentStackToRestore(MF, MBB);
1251 bool IsWin64 = Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv(),
1252 MF.getFunction().isVarArg());
1253 unsigned FixedObject = AFL.getFixedObjectSize(MF, AFI, IsWin64, IsFunclet);
1254
1255 int64_t AfterCSRPopSize = ArgumentStackToRestore;
1256 auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
1257 // We cannot rely on the local stack size set in emitPrologue if the function
1258 // has funclets, as funclets have different local stack size requirements, and
1259 // the current value set in emitPrologue may be that of the containing
1260 // function.
1261 if (MF.hasEHFunclets())
1262 AFI->setLocalStackSize(NumBytes - PrologueSaveSize);
1263
1264 if (HomPrologEpilog) {
1266 auto FirstHomogenousEpilogI = MBB.getFirstTerminator();
1267 if (FirstHomogenousEpilogI != MBB.begin()) {
1268 auto HomogeneousEpilog = std::prev(FirstHomogenousEpilogI);
1269 if (HomogeneousEpilog->getOpcode() == AArch64::HOM_Epilog)
1270 FirstHomogenousEpilogI = HomogeneousEpilog;
1271 }
1272
1273 // Adjust local stack
1274 emitFrameOffset(MBB, FirstHomogenousEpilogI, DL, AArch64::SP, AArch64::SP,
1275 StackOffset::getFixed(AFI->getLocalStackSize()), TII,
1277
1278 // SP has been already adjusted while restoring callee save regs.
1279 // We've bailed-out the case with adjusting SP for arguments.
1280 assert(AfterCSRPopSize == 0);
1281 return;
1282 }
1283
1284 bool FPAfterSVECalleeSaves =
1285 Subtarget.isTargetWindows() && AFI->getSVECalleeSavedStackSize();
1286
1287 bool CombineSPBump = shouldCombineCSRLocalStackBump(NumBytes);
1288 // Assume we can't combine the last pop with the sp restore.
1289 bool CombineAfterCSRBump = false;
1290 if (FPAfterSVECalleeSaves) {
1291 AfterCSRPopSize += FixedObject;
1292 } else if (!CombineSPBump && PrologueSaveSize != 0) {
1293 MachineBasicBlock::iterator Pop = std::prev(MBB.getFirstTerminator());
1294 while (Pop->getOpcode() == TargetOpcode::CFI_INSTRUCTION ||
1295 AArch64InstrInfo::isSEHInstruction(*Pop))
1296 Pop = std::prev(Pop);
1297 // Converting the last ldp to a post-index ldp is valid only if the last
1298 // ldp's offset is 0.
1299 const MachineOperand &OffsetOp = Pop->getOperand(Pop->getNumOperands() - 1);
1300 // If the offset is 0 and the AfterCSR pop is not actually trying to
1301 // allocate more stack for arguments (in space that an untimely interrupt
1302 // may clobber), convert it to a post-index ldp.
1303 if (OffsetOp.getImm() == 0 && AfterCSRPopSize >= 0) {
1305 Pop, DL, PrologueSaveSize, EmitCFI, MachineInstr::FrameDestroy,
1306 PrologueSaveSize);
1307 } else {
1308 // If not, make sure to emit an add after the last ldp.
1309 // We're doing this by transferring the size to be restored from the
1310 // adjustment *before* the CSR pops to the adjustment *after* the CSR
1311 // pops.
1312 AfterCSRPopSize += PrologueSaveSize;
1313 CombineAfterCSRBump = true;
1314 }
1315 }
1316
1317 // Move past the restores of the callee-saved registers.
1318 // If we plan on combining the sp bump of the local stack size and the callee
1319 // save stack size, we might need to adjust the CSR save and restore offsets.
1320 MachineBasicBlock::iterator FirstGPRRestoreI = MBB.getFirstTerminator();
1321 MachineBasicBlock::iterator Begin = MBB.begin();
1322 while (FirstGPRRestoreI != Begin) {
1323 --FirstGPRRestoreI;
1324 if (!FirstGPRRestoreI->getFlag(MachineInstr::FrameDestroy) ||
1325 (!FPAfterSVECalleeSaves && isSVECalleeSave(FirstGPRRestoreI))) {
1326 ++FirstGPRRestoreI;
1327 break;
1328 } else if (CombineSPBump)
1329 fixupCalleeSaveRestoreStackOffset(*FirstGPRRestoreI,
1330 AFI->getLocalStackSize());
1331 }
1332
1333 if (NeedsWinCFI) {
1334 // Note that there are cases where we insert SEH opcodes in the
1335 // epilogue when we had no SEH opcodes in the prologue. For
1336 // example, when there is no stack frame but there are stack
1337 // arguments. Insert the SEH_EpilogStart and remove it later if it
1338 // we didn't emit any SEH opcodes to avoid generating WinCFI for
1339 // functions that don't need it.
1340 BuildMI(MBB, FirstGPRRestoreI, DL, TII->get(AArch64::SEH_EpilogStart))
1342 SEHEpilogueStartI = FirstGPRRestoreI;
1343 --SEHEpilogueStartI;
1344 }
1345
1346 if (HasFP && AFI->hasSwiftAsyncContext())
1347 emitSwiftAsyncContextFramePointer(EpilogueEndI, DL);
1348
1349 const StackOffset &SVEStackSize = AFL.getSVEStackSize(MF);
1350
1351 // If there is a single SP update, insert it before the ret and we're done.
1352 if (CombineSPBump) {
1353 assert(!SVEStackSize && "Cannot combine SP bump with SVE");
1354
1355 // When we are about to restore the CSRs, the CFA register is SP again.
1356 if (EmitCFI && HasFP)
1358 .buildDefCFA(AArch64::SP, NumBytes);
1359
1360 emitFrameOffset(MBB, MBB.getFirstTerminator(), DL, AArch64::SP, AArch64::SP,
1361 StackOffset::getFixed(NumBytes + AfterCSRPopSize), TII,
1363 EmitCFI, StackOffset::getFixed(NumBytes));
1364 return;
1365 }
1366
1367 NumBytes -= PrologueSaveSize;
1368 assert(NumBytes >= 0 && "Negative stack allocation size!?");
1369
1370 // Process the SVE callee-saves to determine what space needs to be
1371 // deallocated.
1372 StackOffset DeallocateBefore = {}, DeallocateAfter = SVEStackSize;
1373 MachineBasicBlock::iterator RestoreBegin = FirstGPRRestoreI,
1374 RestoreEnd = FirstGPRRestoreI;
1375 if (int64_t CalleeSavedSize = AFI->getSVECalleeSavedStackSize()) {
1376 if (FPAfterSVECalleeSaves)
1377 RestoreEnd = MBB.getFirstTerminator();
1378
1379 RestoreBegin = std::prev(RestoreEnd);
1380 while (RestoreBegin != MBB.begin() &&
1381 isSVECalleeSave(std::prev(RestoreBegin)))
1382 --RestoreBegin;
1383
1384 assert(isSVECalleeSave(RestoreBegin) &&
1385 isSVECalleeSave(std::prev(RestoreEnd)) && "Unexpected instruction");
1386
1387 StackOffset CalleeSavedSizeAsOffset =
1388 StackOffset::getScalable(CalleeSavedSize);
1389 DeallocateBefore = SVEStackSize - CalleeSavedSizeAsOffset;
1390 DeallocateAfter = CalleeSavedSizeAsOffset;
1391 }
1392
1393 // Deallocate the SVE area.
1394 if (FPAfterSVECalleeSaves) {
1395 // If the callee-save area is before FP, restoring the FP implicitly
1396 // deallocates non-callee-save SVE allocations. Otherwise, deallocate
1397 // them explicitly.
1398 if (!AFI->isStackRealigned() && !MFI.hasVarSizedObjects()) {
1399 emitFrameOffset(MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::SP,
1400 DeallocateBefore, TII, MachineInstr::FrameDestroy, false,
1402 }
1403
1404 // Deallocate callee-save non-SVE registers.
1405 emitFrameOffset(MBB, RestoreBegin, DL, AArch64::SP, AArch64::SP,
1406 StackOffset::getFixed(AFI->getCalleeSavedStackSize()), TII,
1408
1409 // Deallocate fixed objects.
1410 emitFrameOffset(MBB, RestoreEnd, DL, AArch64::SP, AArch64::SP,
1411 StackOffset::getFixed(FixedObject), TII,
1413
1414 // Deallocate callee-save SVE registers.
1415 emitFrameOffset(MBB, RestoreEnd, DL, AArch64::SP, AArch64::SP,
1416 DeallocateAfter, TII, MachineInstr::FrameDestroy, false,
1418 } else if (SVEStackSize) {
1419 int64_t SVECalleeSavedSize = AFI->getSVECalleeSavedStackSize();
1420 // If we have stack realignment or variable-sized objects we must use the
1421 // FP to restore SVE callee saves (as there is an unknown amount of
1422 // data/padding between the SP and SVE CS area).
1423 Register BaseForSVEDealloc =
1424 (AFI->isStackRealigned() || MFI.hasVarSizedObjects()) ? AArch64::FP
1425 : AArch64::SP;
1426 if (SVECalleeSavedSize && BaseForSVEDealloc == AArch64::FP) {
1427 Register CalleeSaveBase = AArch64::FP;
1428 if (int64_t CalleeSaveBaseOffset =
1429 AFI->getCalleeSaveBaseToFrameRecordOffset()) {
1430 // If we have have an non-zero offset to the non-SVE CS base we need to
1431 // compute the base address by subtracting the offest in a temporary
1432 // register first (to avoid briefly deallocating the SVE CS).
1433 CalleeSaveBase =
1434 MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
1435 emitFrameOffset(MBB, RestoreBegin, DL, CalleeSaveBase, AArch64::FP,
1436 StackOffset::getFixed(-CalleeSaveBaseOffset), TII,
1438 }
1439 // The code below will deallocate the stack space space by moving the
1440 // SP to the start of the SVE callee-save area.
1441 emitFrameOffset(MBB, RestoreBegin, DL, AArch64::SP, CalleeSaveBase,
1442 StackOffset::getScalable(-SVECalleeSavedSize), TII,
1444 } else if (BaseForSVEDealloc == AArch64::SP) {
1445 if (SVECalleeSavedSize) {
1446 // Deallocate the non-SVE locals first before we can deallocate (and
1447 // restore callee saves) from the SVE area.
1449 MBB, RestoreBegin, DL, AArch64::SP, AArch64::SP,
1451 false, NeedsWinCFI, &HasWinCFI, EmitCFI && !HasFP,
1452 SVEStackSize + StackOffset::getFixed(NumBytes + PrologueSaveSize));
1453 NumBytes = 0;
1454 }
1455
1456 emitFrameOffset(MBB, RestoreBegin, DL, AArch64::SP, AArch64::SP,
1457 DeallocateBefore, TII, MachineInstr::FrameDestroy, false,
1459 SVEStackSize +
1460 StackOffset::getFixed(NumBytes + PrologueSaveSize));
1461
1462 emitFrameOffset(MBB, RestoreEnd, DL, AArch64::SP, AArch64::SP,
1463 DeallocateAfter, TII, MachineInstr::FrameDestroy, false,
1465 DeallocateAfter +
1466 StackOffset::getFixed(NumBytes + PrologueSaveSize));
1467 }
1468 if (EmitCFI)
1469 emitCalleeSavedSVERestores(RestoreEnd);
1470 }
1471
1472 if (!HasFP) {
1473 bool RedZone = AFL.canUseRedZone(MF);
1474 // If this was a redzone leaf function, we don't need to restore the
1475 // stack pointer (but we may need to pop stack args for fastcc).
1476 if (RedZone && AfterCSRPopSize == 0)
1477 return;
1478
1479 // Pop the local variables off the stack. If there are no callee-saved
1480 // registers, it means we are actually positioned at the terminator and can
1481 // combine stack increment for the locals and the stack increment for
1482 // callee-popped arguments into (possibly) a single instruction and be done.
1483 bool NoCalleeSaveRestore = PrologueSaveSize == 0;
1484 int64_t StackRestoreBytes = RedZone ? 0 : NumBytes;
1485 if (NoCalleeSaveRestore)
1486 StackRestoreBytes += AfterCSRPopSize;
1487
1489 MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::SP,
1490 StackOffset::getFixed(StackRestoreBytes), TII,
1492 StackOffset::getFixed((RedZone ? 0 : NumBytes) + PrologueSaveSize));
1493
1494 // If we were able to combine the local stack pop with the argument pop,
1495 // then we're done.
1496 if (NoCalleeSaveRestore || AfterCSRPopSize == 0)
1497 return;
1498
1499 NumBytes = 0;
1500 }
1501
1502 // Restore the original stack pointer.
1503 // FIXME: Rather than doing the math here, we should instead just use
1504 // non-post-indexed loads for the restores if we aren't actually going to
1505 // be able to save any instructions.
1506 if (!IsFunclet && (MFI.hasVarSizedObjects() || AFI->isStackRealigned())) {
1508 MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::FP,
1509 StackOffset::getFixed(-AFI->getCalleeSaveBaseToFrameRecordOffset()),
1511 } else if (NumBytes)
1512 emitFrameOffset(MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::SP,
1513 StackOffset::getFixed(NumBytes), TII,
1515
1516 // When we are about to restore the CSRs, the CFA register is SP again.
1517 if (EmitCFI && HasFP)
1519 .buildDefCFA(AArch64::SP, PrologueSaveSize);
1520
1521 // This must be placed after the callee-save restore code because that code
1522 // assumes the SP is at the same location as it was after the callee-save save
1523 // code in the prologue.
1524 if (AfterCSRPopSize) {
1525 assert(AfterCSRPopSize > 0 && "attempting to reallocate arg stack that an "
1526 "interrupt may have clobbered");
1527
1529 MBB, MBB.getFirstTerminator(), DL, AArch64::SP, AArch64::SP,
1531 false, NeedsWinCFI, &HasWinCFI, EmitCFI,
1532 StackOffset::getFixed(CombineAfterCSRBump ? PrologueSaveSize : 0));
1533 }
1534}
1535
1536bool AArch64EpilogueEmitter::shouldCombineCSRLocalStackBump(
1537 uint64_t StackBumpBytes) const {
1539 StackBumpBytes))
1540 return false;
1541 if (MBB.empty())
1542 return true;
1543
1544 // Disable combined SP bump if the last instruction is an MTE tag store. It
1545 // is almost always better to merge SP adjustment into those instructions.
1546 MachineBasicBlock::iterator LastI = MBB.getFirstTerminator();
1547 MachineBasicBlock::iterator Begin = MBB.begin();
1548 while (LastI != Begin) {
1549 --LastI;
1550 if (LastI->isTransient())
1551 continue;
1552 if (!LastI->getFlag(MachineInstr::FrameDestroy))
1553 break;
1554 }
1555 switch (LastI->getOpcode()) {
1556 case AArch64::STGloop:
1557 case AArch64::STZGloop:
1558 case AArch64::STGi:
1559 case AArch64::STZGi:
1560 case AArch64::ST2Gi:
1561 case AArch64::STZ2Gi:
1562 return false;
1563 default:
1564 return true;
1565 }
1566 llvm_unreachable("unreachable");
1567}
1568
1569void AArch64EpilogueEmitter::emitSwiftAsyncContextFramePointer(
1571 switch (MF.getTarget().Options.SwiftAsyncFramePointer) {
1573 // Avoid the reload as it is GOT relative, and instead fall back to the
1574 // hardcoded value below. This allows a mismatch between the OS and
1575 // application without immediately terminating on the difference.
1576 [[fallthrough]];
1578 // We need to reset FP to its untagged state on return. Bit 60 is
1579 // currently used to show the presence of an extended frame.
1580
1581 // BIC x29, x29, #0x1000_0000_0000_0000
1582 BuildMI(MBB, MBB.getFirstTerminator(), DL, TII->get(AArch64::ANDXri),
1583 AArch64::FP)
1584 .addUse(AArch64::FP)
1585 .addImm(0x10fe)
1587 if (NeedsWinCFI) {
1588 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1590 HasWinCFI = true;
1591 }
1592 break;
1593
1595 break;
1596 }
1597}
1598
1599void AArch64EpilogueEmitter::emitShadowCallStackEpilogue(
1601 // Shadow call stack epilog: ldr x30, [x18, #-8]!
1602 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXpre))
1603 .addReg(AArch64::X18, RegState::Define)
1604 .addReg(AArch64::LR, RegState::Define)
1605 .addReg(AArch64::X18)
1606 .addImm(-8)
1608
1609 if (NeedsWinCFI)
1610 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1612
1613 if (AFI->needsAsyncDwarfUnwindInfo(MF))
1614 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameDestroy)
1615 .buildRestore(AArch64::X18);
1616}
1617
1618void AArch64EpilogueEmitter::emitCalleeSavedRestores(
1619 MachineBasicBlock::iterator MBBI, bool SVE) const {
1620 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
1621 if (CSI.empty())
1622 return;
1623
1624 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameDestroy);
1625
1626 for (const auto &Info : CSI) {
1627 if (SVE !=
1628 (MFI.getStackID(Info.getFrameIdx()) == TargetStackID::ScalableVector))
1629 continue;
1630
1631 MCRegister Reg = Info.getReg();
1632 if (SVE && !RegInfo.regNeedsCFI(Reg, Reg))
1633 continue;
1634
1635 CFIBuilder.buildRestore(Info.getReg());
1636 }
1637}
1638
1639void AArch64EpilogueEmitter::finalizeEpilogue() const {
1640 if (AFI->needsShadowCallStackPrologueEpilogue(MF)) {
1641 emitShadowCallStackEpilogue(MBB.getFirstTerminator(), DL);
1643 }
1644 if (EmitCFI)
1645 emitCalleeSavedGPRRestores(MBB.getFirstTerminator());
1646 if (AFI->shouldSignReturnAddress(MF)) {
1647 // If pac-ret+leaf is in effect, PAUTH_EPILOGUE pseudo instructions
1648 // are inserted by emitPacRetPlusLeafHardening().
1649 if (!AFL.shouldSignReturnAddressEverywhere(MF)) {
1650 BuildMI(MBB, MBB.getFirstTerminator(), DL,
1651 TII->get(AArch64::PAUTH_EPILOGUE))
1653 }
1654 // AArch64PointerAuth pass will insert SEH_PACSignLR
1656 }
1657 if (HasWinCFI) {
1658 BuildMI(MBB, MBB.getFirstTerminator(), DL, TII->get(AArch64::SEH_EpilogEnd))
1660 if (!MF.hasWinCFI())
1661 MF.setHasWinCFI(true);
1662 }
1663 if (NeedsWinCFI) {
1664 assert(SEHEpilogueStartI != MBB.end());
1665 if (!HasWinCFI)
1666 MBB.erase(SEHEpilogueStartI);
1667 }
1668}
1669
1670} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file contains the declaration of the AArch64PrologueEmitter and AArch64EpilogueEmitter classes,...
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
Analysis containing CSE Info
Definition CSEInfo.cpp:27
This file contains constants used for implementing Dwarf debug support.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
#define I(x, y, z)
Definition MD5.cpp:58
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:114
static Function * getFunction(FunctionType *Ty, const Twine &Name, Module *M)
static const unsigned FramePtr
AArch64EpilogueEmitter(MachineFunction &MF, MachineBasicBlock &MBB, const AArch64FrameLowering &AFL)
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
AArch64PrologueEmitter(MachineFunction &MF, MachineBasicBlock &MBB, const AArch64FrameLowering &AFL)
MachineBasicBlock::iterator convertCalleeSaveRestoreToSPPrePostIncDec(MachineBasicBlock::iterator MBBI, const DebugLoc &DL, int CSStackSizeInc, bool EmitCFI, MachineInstr::MIFlag FrameFlag=MachineInstr::FrameSetup, int CFAOffset=0) const
bool isVGInstruction(MachineBasicBlock::iterator MBBI, const TargetLowering &TLI) const
AArch64PrologueEpilogueCommon(MachineFunction &MF, MachineBasicBlock &MBB, const AArch64FrameLowering &AFL)
void fixupCalleeSaveRestoreStackOffset(MachineInstr &MI, uint64_t LocalStackSize) const
bool shouldCombineCSRLocalStackBump(uint64_t StackBumpBytes) const
const AArch64TargetLowering * getTargetLowering() const override
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this functions.
Helper class for creating CFI instructions and inserting them into MIR.
void buildDefCFAOffset(int64_t Offset, MCSymbol *Label=nullptr) const
void insertCFIInst(const MCCFIInstruction &CFIInst) const
void buildDefCFA(MCRegister Reg, int64_t Offset) const
A debug info location.
Definition DebugLoc.h:124
A set of physical registers with utility functions to track liveness when walking backward/forward th...
MachineInstrBundleIterator< MachineInstr > iterator
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
void setImm(int64_t immVal)
int64_t getImm() const
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
static MachineOperand CreateImm(int64_t Val)
const char * getSymbolName() const
Wrapper class representing virtual and physical registers.
Definition Register.h:19
StackOffset holds a fixed and a scalable offset in bytes.
Definition TypeSize.h:31
int64_t getFixed() const
Returns the fixed component of the stack.
Definition TypeSize.h:47
int64_t getScalable() const
Returns the scalable component of the stack.
Definition TypeSize.h:50
static StackOffset getScalable(int64_t Scalable)
Definition TypeSize.h:41
static StackOffset getFixed(int64_t Fixed)
Definition TypeSize.h:40
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:344
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:201
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
static unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET, unsigned Imm)
getArithExtendImm - Encode the extend type and shift amount for an arithmetic instruction: imm: 3-bit...
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
const unsigned StackProbeMaxUnprobedStack
Maximum allowed number of unprobed bytes above SP at an ABI boundary.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
Definition CallingConv.h:50
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Define
Register definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
MCCFIInstruction createDefCFA(const TargetRegisterInfo &TRI, unsigned FrameReg, unsigned Reg, const StackOffset &Offset, bool LastAdjustmentWasScalable=true)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static bool isSVECalleeSave(MachineBasicBlock::iterator I)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
unsigned getBLRCallOpcode(const MachineFunction &MF)
Return opcode to be used for indirect calls.
static bool matchLibcall(const TargetLowering &TLI, const MachineOperand &MO, RTLIB::Libcall LC)
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:1712
static bool isFuncletReturnInstr(const MachineInstr &MI)
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
static void getLivePhysRegsUpTo(MachineInstr &MI, const TargetRegisterInfo &TRI, LivePhysRegs &LiveRegs)
Collect live registers from the end of MI's parent up to (including) MI in LiveRegs.
@ DeploymentBased
Determine whether to set the bit statically or dynamically based on the deployment target.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
void emitFrameOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, StackOffset Offset, const TargetInstrInfo *TII, MachineInstr::MIFlag=MachineInstr::NoFlags, bool SetNZCV=false, bool NeedsWinCFI=false, bool *HasWinCFI=nullptr, bool EmitCFAOffset=false, StackOffset InitialOffset={}, unsigned FrameReg=AArch64::SP)
emitFrameOffset - Emit instructions as needed to set DestReg to SrcReg plus Offset.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
@ Success
The lock was released successfully.
static void fixupSEHOpcode(MachineBasicBlock::iterator MBBI, unsigned LocalStackSize)
MCCFIInstruction createCFAOffset(const TargetRegisterInfo &MRI, unsigned Reg, const StackOffset &OffsetFromDefCFA, std::optional< int64_t > IncomingVGOffsetFromDefCFA)
DWARFExpression::Operation Op
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1738
static int64_t upperBound(StackOffset Size)
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:180
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77