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 if (AFI->shouldSignReturnAddress(MF)) {
545 // If pac-ret+leaf is in effect, PAUTH_PROLOGUE pseudo instructions
546 // are inserted by emitPacRetPlusLeafHardening().
547 if (!AFL.shouldSignReturnAddressEverywhere(MF)) {
548 BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::PAUTH_PROLOGUE))
550 }
551 // AArch64PointerAuth pass will insert SEH_PACSignLR
553 }
554
555 if (AFI->needsShadowCallStackPrologueEpilogue(MF)) {
556 emitShadowCallStackPrologue(PrologueBeginI, DL);
558 }
559
560 if (EmitCFI && AFI->isMTETagged())
561 BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::EMITMTETAGGED))
563
564 // We signal the presence of a Swift extended frame to external tools by
565 // storing FP with 0b0001 in bits 63:60. In normal userland operation a simple
566 // ORR is sufficient, it is assumed a Swift kernel would initialize the TBI
567 // bits so that is still true.
568 if (HasFP && AFI->hasSwiftAsyncContext())
569 emitSwiftAsyncContextFramePointer(PrologueBeginI, DL);
570
571 // All calls are tail calls in GHC calling conv, and functions have no
572 // prologue/epilogue.
573 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
574 return;
575
576 // Set tagged base pointer to the requested stack slot. Ideally it should
577 // match SP value after prologue.
578 if (std::optional<int> TBPI = AFI->getTaggedBasePointerIndex())
579 AFI->setTaggedBasePointerOffset(-MFI.getObjectOffset(*TBPI));
580 else
581 AFI->setTaggedBasePointerOffset(MFI.getStackSize());
582
583 // getStackSize() includes all the locals in its size calculation. We don't
584 // include these locals when computing the stack size of a funclet, as they
585 // are allocated in the parent's stack frame and accessed via the frame
586 // pointer from the funclet. We only save the callee saved registers in the
587 // funclet, which are really the callee saved registers of the parent
588 // function, including the funclet.
589 int64_t NumBytes =
590 IsFunclet ? AFL.getWinEHFuncletFrameSize(MF) : MFI.getStackSize();
591 if (!AFI->hasStackFrame() && !AFL.windowsRequiresStackProbe(MF, NumBytes))
592 return emitEmptyStackFramePrologue(NumBytes, PrologueBeginI, DL);
593
594 bool IsWin64 = Subtarget.isCallingConvWin64(F.getCallingConv(), F.isVarArg());
595 unsigned FixedObject = AFL.getFixedObjectSize(MF, AFI, IsWin64, IsFunclet);
596
597 // Windows unwind can't represent the required stack adjustments if we have
598 // both SVE callee-saves and dynamic stack allocations, and the frame
599 // pointer is before the SVE spills. The allocation of the frame pointer
600 // must be the last instruction in the prologue so the unwinder can restore
601 // the stack pointer correctly. (And there isn't any unwind opcode for
602 // `addvl sp, x29, -17`.)
603 //
604 // Because of this, we do spills in the opposite order on Windows: first SVE,
605 // then GPRs. The main side-effect of this is that it makes accessing
606 // parameters passed on the stack more expensive.
607 //
608 // We could consider rearranging the spills for simpler cases.
609 bool FPAfterSVECalleeSaves =
610 Subtarget.isTargetWindows() && AFI->getSVECalleeSavedStackSize();
611
612 if (FPAfterSVECalleeSaves && AFI->hasStackHazardSlotIndex())
613 reportFatalUsageError("SME hazard padding is not supported on Windows");
614
615 auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
616 // All of the remaining stack allocations are for locals.
617 determineLocalsStackSize(NumBytes, PrologueSaveSize);
618
619 MachineBasicBlock::iterator FirstGPRSaveI = PrologueBeginI;
620 if (FPAfterSVECalleeSaves) {
621 // If we're doing SVE saves first, we need to immediately allocate space
622 // for fixed objects, then space for the SVE callee saves.
623 //
624 // Windows unwind requires that the scalable size is a multiple of 16;
625 // that's handled when the callee-saved size is computed.
626 auto SaveSize =
627 StackOffset::getScalable(AFI->getSVECalleeSavedStackSize()) +
628 StackOffset::getFixed(FixedObject);
629 allocateStackSpace(PrologueBeginI, 0, SaveSize, false, StackOffset{},
630 /*FollowupAllocs=*/true);
631 NumBytes -= FixedObject;
632
633 // Now allocate space for the GPR callee saves.
634 MachineBasicBlock::iterator MBBI = PrologueBeginI;
635 while (MBBI != EndI && isSVECalleeSave(MBBI))
636 ++MBBI;
638 MBBI, DL, -AFI->getCalleeSavedStackSize(), EmitAsyncCFI);
639 NumBytes -= AFI->getCalleeSavedStackSize();
640 } else if (CombineSPBump) {
641 assert(!AFL.getSVEStackSize(MF) && "Cannot combine SP bump with SVE");
642 emitFrameOffset(MBB, PrologueBeginI, DL, AArch64::SP, AArch64::SP,
643 StackOffset::getFixed(-NumBytes), TII,
645 EmitAsyncCFI);
646 NumBytes = 0;
647 } else if (HomPrologEpilog) {
648 // Stack has been already adjusted.
649 NumBytes -= PrologueSaveSize;
650 } else if (PrologueSaveSize != 0) {
652 PrologueBeginI, DL, -PrologueSaveSize, EmitAsyncCFI);
653 NumBytes -= PrologueSaveSize;
654 }
655 assert(NumBytes >= 0 && "Negative stack allocation size!?");
656
657 // Move past the saves of the callee-saved registers, fixing up the offsets
658 // and pre-inc if we decided to combine the callee-save and local stack
659 // pointer bump above.
660 auto &TLI = *Subtarget.getTargetLowering();
661
662 MachineBasicBlock::iterator AfterGPRSavesI = FirstGPRSaveI;
663 while (AfterGPRSavesI != EndI &&
664 AfterGPRSavesI->getFlag(MachineInstr::FrameSetup) &&
665 !isSVECalleeSave(AfterGPRSavesI)) {
666 if (CombineSPBump &&
667 // Only fix-up frame-setup load/store instructions.
668 (!AFL.requiresSaveVG(MF) || !isVGInstruction(AfterGPRSavesI, TLI)))
669 fixupCalleeSaveRestoreStackOffset(*AfterGPRSavesI,
670 AFI->getLocalStackSize());
671 ++AfterGPRSavesI;
672 }
673
674 // For funclets the FP belongs to the containing function. Only set up FP if
675 // we actually need to.
676 if (!IsFunclet && HasFP)
677 emitFramePointerSetup(AfterGPRSavesI, DL, FixedObject);
678
679 // Now emit the moves for whatever callee saved regs we have (including FP,
680 // LR if those are saved). Frame instructions for SVE register are emitted
681 // later, after the instruction which actually save SVE regs.
682 if (EmitAsyncCFI)
683 emitCalleeSavedGPRLocations(AfterGPRSavesI);
684
685 // Alignment is required for the parent frame, not the funclet
686 const bool NeedsRealignment =
687 NumBytes && !IsFunclet && RegInfo.hasStackRealignment(MF);
688 const int64_t RealignmentPadding =
689 (NeedsRealignment && MFI.getMaxAlign() > Align(16))
690 ? MFI.getMaxAlign().value() - 16
691 : 0;
692
693 if (AFL.windowsRequiresStackProbe(MF, NumBytes + RealignmentPadding))
694 emitWindowsStackProbe(AfterGPRSavesI, DL, NumBytes, RealignmentPadding);
695
696 StackOffset SVEStackSize = AFL.getSVEStackSize(MF);
697 StackOffset SVECalleeSavesSize = {}, SVELocalsSize = SVEStackSize;
698 MachineBasicBlock::iterator CalleeSavesEnd = AfterGPRSavesI;
699
700 StackOffset CFAOffset =
701 StackOffset::getFixed((int64_t)MFI.getStackSize() - NumBytes);
702
703 // Process the SVE callee-saves to determine what space needs to be
704 // allocated.
705 MachineBasicBlock::iterator AfterSVESavesI = AfterGPRSavesI;
706 if (int64_t CalleeSavedSize = AFI->getSVECalleeSavedStackSize()) {
707 LLVM_DEBUG(dbgs() << "SVECalleeSavedStackSize = " << CalleeSavedSize
708 << "\n");
709 SVECalleeSavesSize = StackOffset::getScalable(CalleeSavedSize);
710 SVELocalsSize = SVEStackSize - SVECalleeSavesSize;
711 // Find callee save instructions in frame.
712 // Note: With FPAfterSVECalleeSaves the callee saves have already been
713 // allocated.
714 if (!FPAfterSVECalleeSaves) {
715 MachineBasicBlock::iterator CalleeSavesBegin = AfterGPRSavesI;
716 assert(isSVECalleeSave(CalleeSavesBegin) && "Unexpected instruction");
717 while (isSVECalleeSave(AfterSVESavesI) &&
718 AfterSVESavesI != MBB.getFirstTerminator())
719 ++AfterSVESavesI;
720 CalleeSavesEnd = AfterSVESavesI;
721
722 StackOffset LocalsSize = SVELocalsSize + StackOffset::getFixed(NumBytes);
723 // Allocate space for the callee saves (if any).
724 allocateStackSpace(CalleeSavesBegin, 0, SVECalleeSavesSize,
725 EmitAsyncCFI && !HasFP, CFAOffset,
726 MFI.hasVarSizedObjects() || LocalsSize);
727 }
728 }
729 CFAOffset += SVECalleeSavesSize;
730
731 if (EmitAsyncCFI)
732 emitCalleeSavedSVELocations(CalleeSavesEnd);
733
734 // Allocate space for the rest of the frame including SVE locals. Align the
735 // stack as necessary.
736 assert(!(AFL.canUseRedZone(MF) && NeedsRealignment) &&
737 "Cannot use redzone with stack realignment");
738 if (!AFL.canUseRedZone(MF)) {
739 // FIXME: in the case of dynamic re-alignment, NumBytes doesn't have
740 // the correct value here, as NumBytes also includes padding bytes,
741 // which shouldn't be counted here.
742 allocateStackSpace(CalleeSavesEnd, RealignmentPadding,
743 SVELocalsSize + StackOffset::getFixed(NumBytes),
744 EmitAsyncCFI && !HasFP, CFAOffset,
745 MFI.hasVarSizedObjects());
746 }
747
748 // If we need a base pointer, set it up here. It's whatever the value of the
749 // stack pointer is at this point. Any variable size objects will be allocated
750 // after this, so we can still use the base pointer to reference locals.
751 //
752 // FIXME: Clarify FrameSetup flags here.
753 // Note: Use emitFrameOffset() like above for FP if the FrameSetup flag is
754 // needed.
755 // For funclets the BP belongs to the containing function.
756 if (!IsFunclet && RegInfo.hasBasePointer(MF)) {
757 TII->copyPhysReg(MBB, AfterSVESavesI, DL, RegInfo.getBaseRegister(),
758 AArch64::SP, false);
759 if (NeedsWinCFI) {
760 HasWinCFI = true;
761 BuildMI(MBB, AfterSVESavesI, DL, TII->get(AArch64::SEH_Nop))
763 }
764 }
765
766 // The very last FrameSetup instruction indicates the end of prologue. Emit a
767 // SEH opcode indicating the prologue end.
768 if (NeedsWinCFI && HasWinCFI) {
769 BuildMI(MBB, AfterSVESavesI, DL, TII->get(AArch64::SEH_PrologEnd))
771 }
772
773 // SEH funclets are passed the frame pointer in X1. If the parent
774 // function uses the base register, then the base register is used
775 // directly, and is not retrieved from X1.
776 if (IsFunclet && F.hasPersonalityFn()) {
777 EHPersonality Per = classifyEHPersonality(F.getPersonalityFn());
779 BuildMI(MBB, AfterSVESavesI, DL, TII->get(TargetOpcode::COPY),
780 AArch64::FP)
781 .addReg(AArch64::X1)
783 MBB.addLiveIn(AArch64::X1);
784 }
785 }
786
787 if (EmitCFI && !EmitAsyncCFI) {
788 if (HasFP) {
789 emitDefineCFAWithFP(AfterSVESavesI, FixedObject);
790 } else {
791 StackOffset TotalSize =
792 SVEStackSize + StackOffset::getFixed((int64_t)MFI.getStackSize());
793 CFIInstBuilder CFIBuilder(MBB, AfterSVESavesI, MachineInstr::FrameSetup);
794 CFIBuilder.insertCFIInst(
795 createDefCFA(RegInfo, /*FrameReg=*/AArch64::SP, /*Reg=*/AArch64::SP,
796 TotalSize, /*LastAdjustmentWasScalable=*/false));
797 }
798 emitCalleeSavedGPRLocations(AfterSVESavesI);
799 emitCalleeSavedSVELocations(AfterSVESavesI);
800 }
801}
802
803void AArch64PrologueEmitter::emitShadowCallStackPrologue(
805 // Shadow call stack prolog: str x30, [x18], #8
806 BuildMI(MBB, MBBI, DL, TII->get(AArch64::STRXpost))
807 .addReg(AArch64::X18, RegState::Define)
808 .addReg(AArch64::LR)
809 .addReg(AArch64::X18)
810 .addImm(8)
812
813 // This instruction also makes x18 live-in to the entry block.
814 MBB.addLiveIn(AArch64::X18);
815
816 if (NeedsWinCFI)
817 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
819
820 if (EmitCFI) {
821 // Emit a CFI instruction that causes 8 to be subtracted from the value of
822 // x18 when unwinding past this frame.
823 static const char CFIInst[] = {
824 dwarf::DW_CFA_val_expression,
825 18, // register
826 2, // length
827 static_cast<char>(unsigned(dwarf::DW_OP_breg18)),
828 static_cast<char>(-8) & 0x7f, // addend (sleb128)
829 };
830 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
831 .buildEscape(StringRef(CFIInst, sizeof(CFIInst)));
832 }
833}
834
835void AArch64PrologueEmitter::emitSwiftAsyncContextFramePointer(
837 switch (MF.getTarget().Options.SwiftAsyncFramePointer) {
839 if (Subtarget.swiftAsyncContextIsDynamicallySet()) {
840 // The special symbol below is absolute and has a *value* that can be
841 // combined with the frame pointer to signal an extended frame.
842 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LOADgot), AArch64::X16)
843 .addExternalSymbol("swift_async_extendedFramePointerFlags",
845 if (NeedsWinCFI) {
846 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
848 HasWinCFI = true;
849 }
850 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::FP)
851 .addUse(AArch64::FP)
852 .addUse(AArch64::X16)
853 .addImm(Subtarget.isTargetILP32() ? 32 : 0);
854 if (NeedsWinCFI) {
855 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
857 HasWinCFI = true;
858 }
859 break;
860 }
861 [[fallthrough]];
862
864 // ORR x29, x29, #0x1000_0000_0000_0000
865 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXri), AArch64::FP)
866 .addUse(AArch64::FP)
867 .addImm(0x1100)
869 if (NeedsWinCFI) {
870 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
872 HasWinCFI = true;
873 }
874 break;
875
877 break;
878 }
879}
880
881void AArch64PrologueEmitter::emitEmptyStackFramePrologue(
882 int64_t NumBytes, MachineBasicBlock::iterator MBBI,
883 const DebugLoc &DL) const {
884 assert(!HasFP && "unexpected function without stack frame but with FP");
885 assert(!AFL.getSVEStackSize(MF) &&
886 "unexpected function without stack frame but with SVE objects");
887 // All of the stack allocation is for locals.
888 AFI->setLocalStackSize(NumBytes);
889 if (!NumBytes) {
890 if (NeedsWinCFI && HasWinCFI) {
891 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
893 }
894 return;
895 }
896 // REDZONE: If the stack size is less than 128 bytes, we don't need
897 // to actually allocate.
898 if (AFL.canUseRedZone(MF)) {
899 AFI->setHasRedZone(true);
900 ++NumRedZoneFunctions;
901 } else {
902 emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP,
903 StackOffset::getFixed(-NumBytes), TII,
905 if (EmitCFI) {
906 // Label used to tie together the PROLOG_LABEL and the MachineMoves.
907 MCSymbol *FrameLabel = MF.getContext().createTempSymbol();
908 // Encode the stack size of the leaf function.
909 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
910 .buildDefCFAOffset(NumBytes, FrameLabel);
911 }
912 }
913
914 if (NeedsWinCFI) {
915 HasWinCFI = true;
916 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
918 }
919}
920
921void AArch64PrologueEmitter::emitFramePointerSetup(
923 unsigned FixedObject) {
924 int64_t FPOffset = AFI->getCalleeSaveBaseToFrameRecordOffset();
925 if (CombineSPBump)
926 FPOffset += AFI->getLocalStackSize();
927
928 if (AFI->hasSwiftAsyncContext()) {
929 // Before we update the live FP we have to ensure there's a valid (or
930 // null) asynchronous context in its slot just before FP in the frame
931 // record, so store it now.
932 const auto &Attrs = MF.getFunction().getAttributes();
933 bool HaveInitialContext = Attrs.hasAttrSomewhere(Attribute::SwiftAsync);
934 if (HaveInitialContext)
935 MBB.addLiveIn(AArch64::X22);
936 Register Reg = HaveInitialContext ? AArch64::X22 : AArch64::XZR;
937 BuildMI(MBB, MBBI, DL, TII->get(AArch64::StoreSwiftAsyncContext))
938 .addUse(Reg)
939 .addUse(AArch64::SP)
940 .addImm(FPOffset - 8)
942 if (NeedsWinCFI) {
943 // WinCFI and arm64e, where StoreSwiftAsyncContext is expanded
944 // to multiple instructions, should be mutually-exclusive.
945 assert(Subtarget.getTargetTriple().getArchName() != "arm64e");
946 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
948 HasWinCFI = true;
949 }
950 }
951
952 if (HomPrologEpilog) {
953 auto Prolog = MBBI;
954 --Prolog;
955 assert(Prolog->getOpcode() == AArch64::HOM_Prolog);
956 Prolog->addOperand(MachineOperand::CreateImm(FPOffset));
957 } else {
958 // Issue sub fp, sp, FPOffset or
959 // mov fp,sp when FPOffset is zero.
960 // Note: All stores of callee-saved registers are marked as "FrameSetup".
961 // This code marks the instruction(s) that set the FP also.
962 emitFrameOffset(MBB, MBBI, DL, AArch64::FP, AArch64::SP,
963 StackOffset::getFixed(FPOffset), TII,
965 if (NeedsWinCFI && HasWinCFI) {
966 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
968 // After setting up the FP, the rest of the prolog doesn't need to be
969 // included in the SEH unwind info.
970 NeedsWinCFI = false;
971 }
972 }
973 if (EmitAsyncCFI)
974 emitDefineCFAWithFP(MBBI, FixedObject);
975}
976
977// Define the current CFA rule to use the provided FP.
978void AArch64PrologueEmitter::emitDefineCFAWithFP(
979 MachineBasicBlock::iterator MBBI, unsigned FixedObject) const {
980 const int OffsetToFirstCalleeSaveFromFP =
981 AFI->getCalleeSaveBaseToFrameRecordOffset() -
982 AFI->getCalleeSavedStackSize();
983 Register FramePtr = RegInfo.getFrameRegister(MF);
984 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
985 .buildDefCFA(FramePtr, FixedObject - OffsetToFirstCalleeSaveFromFP);
986}
987
988void AArch64PrologueEmitter::emitWindowsStackProbe(
989 MachineBasicBlock::iterator MBBI, const DebugLoc &DL, int64_t &NumBytes,
990 int64_t RealignmentPadding) const {
991 if (AFI->getSVECalleeSavedStackSize())
992 report_fatal_error("SVE callee saves not yet supported with stack probing");
993
994 // Find an available register to spill the value of X15 to, if X15 is being
995 // used already for nest.
996 unsigned X15Scratch = AArch64::NoRegister;
997 if (llvm::any_of(MBB.liveins(),
998 [this](const MachineBasicBlock::RegisterMaskPair &LiveIn) {
999 return RegInfo.isSuperOrSubRegisterEq(AArch64::X15,
1000 LiveIn.PhysReg);
1001 })) {
1002 X15Scratch = AFL.findScratchNonCalleeSaveRegister(&MBB, /*HasCall=*/true);
1003 assert(X15Scratch != AArch64::NoRegister &&
1004 (X15Scratch < AArch64::X15 || X15Scratch > AArch64::X17));
1005#ifndef NDEBUG
1006 LiveRegs.removeReg(AArch64::X15); // ignore X15 since we restore it
1007#endif
1008 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrr), X15Scratch)
1009 .addReg(AArch64::XZR)
1010 .addReg(AArch64::X15, RegState::Undef)
1011 .addReg(AArch64::X15, RegState::Implicit)
1013 }
1014
1015 uint64_t NumWords = (NumBytes + RealignmentPadding) >> 4;
1016 if (NeedsWinCFI) {
1017 HasWinCFI = true;
1018 // alloc_l can hold at most 256MB, so assume that NumBytes doesn't
1019 // exceed this amount. We need to move at most 2^24 - 1 into x15.
1020 // This is at most two instructions, MOVZ followed by MOVK.
1021 // TODO: Fix to use multiple stack alloc unwind codes for stacks
1022 // exceeding 256MB in size.
1023 if (NumBytes >= (1 << 28))
1024 report_fatal_error("Stack size cannot exceed 256MB for stack "
1025 "unwinding purposes");
1026
1027 uint32_t LowNumWords = NumWords & 0xFFFF;
1028 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVZXi), AArch64::X15)
1029 .addImm(LowNumWords)
1032 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1034 if ((NumWords & 0xFFFF0000) != 0) {
1035 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVKXi), AArch64::X15)
1036 .addReg(AArch64::X15)
1037 .addImm((NumWords & 0xFFFF0000) >> 16) // High half
1040 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1042 }
1043 } else {
1044 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVi64imm), AArch64::X15)
1045 .addImm(NumWords)
1047 }
1048
1049 const char *ChkStk = Subtarget.getChkStkName();
1050 switch (MF.getTarget().getCodeModel()) {
1051 case CodeModel::Tiny:
1052 case CodeModel::Small:
1053 case CodeModel::Medium:
1054 case CodeModel::Kernel:
1055 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
1056 .addExternalSymbol(ChkStk)
1057 .addReg(AArch64::X15, RegState::Implicit)
1058 .addReg(AArch64::X16,
1060 .addReg(AArch64::X17,
1062 .addReg(AArch64::NZCV,
1065 if (NeedsWinCFI) {
1066 HasWinCFI = true;
1067 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1069 }
1070 break;
1071 case CodeModel::Large:
1072 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVaddrEXT))
1073 .addReg(AArch64::X16, RegState::Define)
1074 .addExternalSymbol(ChkStk)
1075 .addExternalSymbol(ChkStk)
1077 if (NeedsWinCFI) {
1078 HasWinCFI = true;
1079 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1081 }
1082
1084 .addReg(AArch64::X16, RegState::Kill)
1086 .addReg(AArch64::X16,
1088 .addReg(AArch64::X17,
1090 .addReg(AArch64::NZCV,
1093 if (NeedsWinCFI) {
1094 HasWinCFI = true;
1095 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1097 }
1098 break;
1099 }
1100
1101 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SUBXrx64), AArch64::SP)
1102 .addReg(AArch64::SP, RegState::Kill)
1103 .addReg(AArch64::X15, RegState::Kill)
1106 if (NeedsWinCFI) {
1107 HasWinCFI = true;
1108 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
1109 .addImm(NumBytes)
1111 }
1112 NumBytes = 0;
1113
1114 if (RealignmentPadding > 0) {
1115 if (RealignmentPadding >= 4096) {
1116 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVi64imm))
1117 .addReg(AArch64::X16, RegState::Define)
1118 .addImm(RealignmentPadding)
1120 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXrx64), AArch64::X15)
1121 .addReg(AArch64::SP)
1122 .addReg(AArch64::X16, RegState::Kill)
1125 } else {
1126 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXri), AArch64::X15)
1127 .addReg(AArch64::SP)
1128 .addImm(RealignmentPadding)
1129 .addImm(0)
1131 }
1132
1133 uint64_t AndMask = ~(MFI.getMaxAlign().value() - 1);
1134 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), AArch64::SP)
1135 .addReg(AArch64::X15, RegState::Kill)
1137 AFI->setStackRealigned(true);
1138
1139 // No need for SEH instructions here; if we're realigning the stack,
1140 // we've set a frame pointer and already finished the SEH prologue.
1142 }
1143 if (X15Scratch != AArch64::NoRegister) {
1144 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrr), AArch64::X15)
1145 .addReg(AArch64::XZR)
1146 .addReg(X15Scratch, RegState::Undef)
1147 .addReg(X15Scratch, RegState::Implicit)
1149 }
1150}
1151
1152void AArch64PrologueEmitter::emitCalleeSavedGPRLocations(
1154 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
1155 if (CSI.empty())
1156 return;
1157
1158 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameSetup);
1159 for (const auto &Info : CSI) {
1160 unsigned FrameIdx = Info.getFrameIdx();
1161 if (MFI.getStackID(FrameIdx) == TargetStackID::ScalableVector)
1162 continue;
1163
1164 assert(!Info.isSpilledToReg() && "Spilling to registers not implemented");
1165 int64_t Offset = MFI.getObjectOffset(FrameIdx) - AFL.getOffsetOfLocalArea();
1166 CFIBuilder.buildOffset(Info.getReg(), Offset);
1167 }
1168}
1169
1170void AArch64PrologueEmitter::emitCalleeSavedSVELocations(
1172 // Add callee saved registers to move list.
1173 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
1174 if (CSI.empty())
1175 return;
1176
1177 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameSetup);
1178
1179 std::optional<int64_t> IncomingVGOffsetFromDefCFA;
1180 if (AFL.requiresSaveVG(MF)) {
1181 auto IncomingVG = *find_if(
1182 reverse(CSI), [](auto &Info) { return Info.getReg() == AArch64::VG; });
1183 IncomingVGOffsetFromDefCFA = MFI.getObjectOffset(IncomingVG.getFrameIdx()) -
1184 AFL.getOffsetOfLocalArea();
1185 }
1186
1187 for (const auto &Info : CSI) {
1188 if (MFI.getStackID(Info.getFrameIdx()) != TargetStackID::ScalableVector)
1189 continue;
1190
1191 // Not all unwinders may know about SVE registers, so assume the lowest
1192 // common denominator.
1193 assert(!Info.isSpilledToReg() && "Spilling to registers not implemented");
1194 MCRegister Reg = Info.getReg();
1195 if (!RegInfo.regNeedsCFI(Reg, Reg))
1196 continue;
1197
1198 StackOffset Offset =
1199 StackOffset::getScalable(MFI.getObjectOffset(Info.getFrameIdx())) -
1200 StackOffset::getFixed(AFI->getCalleeSavedStackSize(MFI));
1201
1202 CFIBuilder.insertCFIInst(
1203 createCFAOffset(RegInfo, Reg, Offset, IncomingVGOffsetFromDefCFA));
1204 }
1205}
1206
1208 switch (MI.getOpcode()) {
1209 default:
1210 return false;
1211 case AArch64::CATCHRET:
1212 case AArch64::CLEANUPRET:
1213 return true;
1214 }
1215}
1216
1221 EmitCFI = AFI->needsAsyncDwarfUnwindInfo(MF);
1222 HomPrologEpilog = AFL.homogeneousPrologEpilog(MF, &MBB);
1223 SEHEpilogueStartI = MBB.end();
1224}
1225
1227 MachineBasicBlock::iterator EpilogueEndI = MBB.getLastNonDebugInstr();
1228 if (MBB.end() != EpilogueEndI) {
1229 DL = EpilogueEndI->getDebugLoc();
1230 IsFunclet = isFuncletReturnInstr(*EpilogueEndI);
1231 }
1232
1233 int64_t NumBytes =
1234 IsFunclet ? AFL.getWinEHFuncletFrameSize(MF) : MFI.getStackSize();
1235
1236 // All calls are tail calls in GHC calling conv, and functions have no
1237 // prologue/epilogue.
1238 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
1239 return;
1240
1241 // How much of the stack used by incoming arguments this function is expected
1242 // to restore in this particular epilogue.
1243 int64_t ArgumentStackToRestore = AFL.getArgumentStackToRestore(MF, MBB);
1244 bool IsWin64 = Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv(),
1245 MF.getFunction().isVarArg());
1246 unsigned FixedObject = AFL.getFixedObjectSize(MF, AFI, IsWin64, IsFunclet);
1247
1248 int64_t AfterCSRPopSize = ArgumentStackToRestore;
1249 auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
1250 // We cannot rely on the local stack size set in emitPrologue if the function
1251 // has funclets, as funclets have different local stack size requirements, and
1252 // the current value set in emitPrologue may be that of the containing
1253 // function.
1254 if (MF.hasEHFunclets())
1255 AFI->setLocalStackSize(NumBytes - PrologueSaveSize);
1256
1257 if (HomPrologEpilog) {
1259 auto FirstHomogenousEpilogI = MBB.getFirstTerminator();
1260 if (FirstHomogenousEpilogI != MBB.begin()) {
1261 auto HomogeneousEpilog = std::prev(FirstHomogenousEpilogI);
1262 if (HomogeneousEpilog->getOpcode() == AArch64::HOM_Epilog)
1263 FirstHomogenousEpilogI = HomogeneousEpilog;
1264 }
1265
1266 // Adjust local stack
1267 emitFrameOffset(MBB, FirstHomogenousEpilogI, DL, AArch64::SP, AArch64::SP,
1268 StackOffset::getFixed(AFI->getLocalStackSize()), TII,
1270
1271 // SP has been already adjusted while restoring callee save regs.
1272 // We've bailed-out the case with adjusting SP for arguments.
1273 assert(AfterCSRPopSize == 0);
1274 return;
1275 }
1276
1277 bool FPAfterSVECalleeSaves =
1278 Subtarget.isTargetWindows() && AFI->getSVECalleeSavedStackSize();
1279
1280 bool CombineSPBump = shouldCombineCSRLocalStackBump(NumBytes);
1281 // Assume we can't combine the last pop with the sp restore.
1282 bool CombineAfterCSRBump = false;
1283 if (FPAfterSVECalleeSaves) {
1284 AfterCSRPopSize += FixedObject;
1285 } else if (!CombineSPBump && PrologueSaveSize != 0) {
1286 MachineBasicBlock::iterator Pop = std::prev(MBB.getFirstTerminator());
1287 while (Pop->getOpcode() == TargetOpcode::CFI_INSTRUCTION ||
1288 AArch64InstrInfo::isSEHInstruction(*Pop))
1289 Pop = std::prev(Pop);
1290 // Converting the last ldp to a post-index ldp is valid only if the last
1291 // ldp's offset is 0.
1292 const MachineOperand &OffsetOp = Pop->getOperand(Pop->getNumOperands() - 1);
1293 // If the offset is 0 and the AfterCSR pop is not actually trying to
1294 // allocate more stack for arguments (in space that an untimely interrupt
1295 // may clobber), convert it to a post-index ldp.
1296 if (OffsetOp.getImm() == 0 && AfterCSRPopSize >= 0) {
1298 Pop, DL, PrologueSaveSize, EmitCFI, MachineInstr::FrameDestroy,
1299 PrologueSaveSize);
1300 } else {
1301 // If not, make sure to emit an add after the last ldp.
1302 // We're doing this by transferring the size to be restored from the
1303 // adjustment *before* the CSR pops to the adjustment *after* the CSR
1304 // pops.
1305 AfterCSRPopSize += PrologueSaveSize;
1306 CombineAfterCSRBump = true;
1307 }
1308 }
1309
1310 // Move past the restores of the callee-saved registers.
1311 // If we plan on combining the sp bump of the local stack size and the callee
1312 // save stack size, we might need to adjust the CSR save and restore offsets.
1313 MachineBasicBlock::iterator FirstGPRRestoreI = MBB.getFirstTerminator();
1314 MachineBasicBlock::iterator Begin = MBB.begin();
1315 while (FirstGPRRestoreI != Begin) {
1316 --FirstGPRRestoreI;
1317 if (!FirstGPRRestoreI->getFlag(MachineInstr::FrameDestroy) ||
1318 (!FPAfterSVECalleeSaves && isSVECalleeSave(FirstGPRRestoreI))) {
1319 ++FirstGPRRestoreI;
1320 break;
1321 } else if (CombineSPBump)
1322 fixupCalleeSaveRestoreStackOffset(*FirstGPRRestoreI,
1323 AFI->getLocalStackSize());
1324 }
1325
1326 if (NeedsWinCFI) {
1327 // Note that there are cases where we insert SEH opcodes in the
1328 // epilogue when we had no SEH opcodes in the prologue. For
1329 // example, when there is no stack frame but there are stack
1330 // arguments. Insert the SEH_EpilogStart and remove it later if it
1331 // we didn't emit any SEH opcodes to avoid generating WinCFI for
1332 // functions that don't need it.
1333 BuildMI(MBB, FirstGPRRestoreI, DL, TII->get(AArch64::SEH_EpilogStart))
1335 SEHEpilogueStartI = FirstGPRRestoreI;
1336 --SEHEpilogueStartI;
1337 }
1338
1339 if (HasFP && AFI->hasSwiftAsyncContext())
1340 emitSwiftAsyncContextFramePointer(EpilogueEndI, DL);
1341
1342 const StackOffset &SVEStackSize = AFL.getSVEStackSize(MF);
1343
1344 // If there is a single SP update, insert it before the ret and we're done.
1345 if (CombineSPBump) {
1346 assert(!SVEStackSize && "Cannot combine SP bump with SVE");
1347
1348 // When we are about to restore the CSRs, the CFA register is SP again.
1349 if (EmitCFI && HasFP)
1351 .buildDefCFA(AArch64::SP, NumBytes);
1352
1353 emitFrameOffset(MBB, MBB.getFirstTerminator(), DL, AArch64::SP, AArch64::SP,
1354 StackOffset::getFixed(NumBytes + AfterCSRPopSize), TII,
1356 EmitCFI, StackOffset::getFixed(NumBytes));
1357 return;
1358 }
1359
1360 NumBytes -= PrologueSaveSize;
1361 assert(NumBytes >= 0 && "Negative stack allocation size!?");
1362
1363 // Process the SVE callee-saves to determine what space needs to be
1364 // deallocated.
1365 StackOffset DeallocateBefore = {}, DeallocateAfter = SVEStackSize;
1366 MachineBasicBlock::iterator RestoreBegin = FirstGPRRestoreI,
1367 RestoreEnd = FirstGPRRestoreI;
1368 if (int64_t CalleeSavedSize = AFI->getSVECalleeSavedStackSize()) {
1369 if (FPAfterSVECalleeSaves)
1370 RestoreEnd = MBB.getFirstTerminator();
1371
1372 RestoreBegin = std::prev(RestoreEnd);
1373 while (RestoreBegin != MBB.begin() &&
1374 isSVECalleeSave(std::prev(RestoreBegin)))
1375 --RestoreBegin;
1376
1377 assert(isSVECalleeSave(RestoreBegin) &&
1378 isSVECalleeSave(std::prev(RestoreEnd)) && "Unexpected instruction");
1379
1380 StackOffset CalleeSavedSizeAsOffset =
1381 StackOffset::getScalable(CalleeSavedSize);
1382 DeallocateBefore = SVEStackSize - CalleeSavedSizeAsOffset;
1383 DeallocateAfter = CalleeSavedSizeAsOffset;
1384 }
1385
1386 // Deallocate the SVE area.
1387 if (FPAfterSVECalleeSaves) {
1388 // If the callee-save area is before FP, restoring the FP implicitly
1389 // deallocates non-callee-save SVE allocations. Otherwise, deallocate
1390 // them explicitly.
1391 if (!AFI->isStackRealigned() && !MFI.hasVarSizedObjects()) {
1392 emitFrameOffset(MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::SP,
1393 DeallocateBefore, TII, MachineInstr::FrameDestroy, false,
1395 }
1396
1397 // Deallocate callee-save non-SVE registers.
1398 emitFrameOffset(MBB, RestoreBegin, DL, AArch64::SP, AArch64::SP,
1399 StackOffset::getFixed(AFI->getCalleeSavedStackSize()), TII,
1401
1402 // Deallocate fixed objects.
1403 emitFrameOffset(MBB, RestoreEnd, DL, AArch64::SP, AArch64::SP,
1404 StackOffset::getFixed(FixedObject), TII,
1406
1407 // Deallocate callee-save SVE registers.
1408 emitFrameOffset(MBB, RestoreEnd, DL, AArch64::SP, AArch64::SP,
1409 DeallocateAfter, TII, MachineInstr::FrameDestroy, false,
1411 } else if (SVEStackSize) {
1412 int64_t SVECalleeSavedSize = AFI->getSVECalleeSavedStackSize();
1413 // If we have stack realignment or variable-sized objects we must use the
1414 // FP to restore SVE callee saves (as there is an unknown amount of
1415 // data/padding between the SP and SVE CS area).
1416 Register BaseForSVEDealloc =
1417 (AFI->isStackRealigned() || MFI.hasVarSizedObjects()) ? AArch64::FP
1418 : AArch64::SP;
1419 if (SVECalleeSavedSize && BaseForSVEDealloc == AArch64::FP) {
1420 Register CalleeSaveBase = AArch64::FP;
1421 if (int64_t CalleeSaveBaseOffset =
1422 AFI->getCalleeSaveBaseToFrameRecordOffset()) {
1423 // If we have have an non-zero offset to the non-SVE CS base we need to
1424 // compute the base address by subtracting the offest in a temporary
1425 // register first (to avoid briefly deallocating the SVE CS).
1426 CalleeSaveBase =
1427 MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
1428 emitFrameOffset(MBB, RestoreBegin, DL, CalleeSaveBase, AArch64::FP,
1429 StackOffset::getFixed(-CalleeSaveBaseOffset), TII,
1431 }
1432 // The code below will deallocate the stack space space by moving the
1433 // SP to the start of the SVE callee-save area.
1434 emitFrameOffset(MBB, RestoreBegin, DL, AArch64::SP, CalleeSaveBase,
1435 StackOffset::getScalable(-SVECalleeSavedSize), TII,
1437 } else if (BaseForSVEDealloc == AArch64::SP) {
1438 if (SVECalleeSavedSize) {
1439 // Deallocate the non-SVE locals first before we can deallocate (and
1440 // restore callee saves) from the SVE area.
1442 MBB, RestoreBegin, DL, AArch64::SP, AArch64::SP,
1444 false, NeedsWinCFI, &HasWinCFI, EmitCFI && !HasFP,
1445 SVEStackSize + StackOffset::getFixed(NumBytes + PrologueSaveSize));
1446 NumBytes = 0;
1447 }
1448
1449 emitFrameOffset(MBB, RestoreBegin, DL, AArch64::SP, AArch64::SP,
1450 DeallocateBefore, TII, MachineInstr::FrameDestroy, false,
1452 SVEStackSize +
1453 StackOffset::getFixed(NumBytes + PrologueSaveSize));
1454
1455 emitFrameOffset(MBB, RestoreEnd, DL, AArch64::SP, AArch64::SP,
1456 DeallocateAfter, TII, MachineInstr::FrameDestroy, false,
1458 DeallocateAfter +
1459 StackOffset::getFixed(NumBytes + PrologueSaveSize));
1460 }
1461 if (EmitCFI)
1462 emitCalleeSavedSVERestores(RestoreEnd);
1463 }
1464
1465 if (!HasFP) {
1466 bool RedZone = AFL.canUseRedZone(MF);
1467 // If this was a redzone leaf function, we don't need to restore the
1468 // stack pointer (but we may need to pop stack args for fastcc).
1469 if (RedZone && AfterCSRPopSize == 0)
1470 return;
1471
1472 // Pop the local variables off the stack. If there are no callee-saved
1473 // registers, it means we are actually positioned at the terminator and can
1474 // combine stack increment for the locals and the stack increment for
1475 // callee-popped arguments into (possibly) a single instruction and be done.
1476 bool NoCalleeSaveRestore = PrologueSaveSize == 0;
1477 int64_t StackRestoreBytes = RedZone ? 0 : NumBytes;
1478 if (NoCalleeSaveRestore)
1479 StackRestoreBytes += AfterCSRPopSize;
1480
1482 MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::SP,
1483 StackOffset::getFixed(StackRestoreBytes), TII,
1485 StackOffset::getFixed((RedZone ? 0 : NumBytes) + PrologueSaveSize));
1486
1487 // If we were able to combine the local stack pop with the argument pop,
1488 // then we're done.
1489 if (NoCalleeSaveRestore || AfterCSRPopSize == 0)
1490 return;
1491
1492 NumBytes = 0;
1493 }
1494
1495 // Restore the original stack pointer.
1496 // FIXME: Rather than doing the math here, we should instead just use
1497 // non-post-indexed loads for the restores if we aren't actually going to
1498 // be able to save any instructions.
1499 if (!IsFunclet && (MFI.hasVarSizedObjects() || AFI->isStackRealigned())) {
1501 MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::FP,
1502 StackOffset::getFixed(-AFI->getCalleeSaveBaseToFrameRecordOffset()),
1504 } else if (NumBytes)
1505 emitFrameOffset(MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::SP,
1506 StackOffset::getFixed(NumBytes), TII,
1508
1509 // When we are about to restore the CSRs, the CFA register is SP again.
1510 if (EmitCFI && HasFP)
1512 .buildDefCFA(AArch64::SP, PrologueSaveSize);
1513
1514 // This must be placed after the callee-save restore code because that code
1515 // assumes the SP is at the same location as it was after the callee-save save
1516 // code in the prologue.
1517 if (AfterCSRPopSize) {
1518 assert(AfterCSRPopSize > 0 && "attempting to reallocate arg stack that an "
1519 "interrupt may have clobbered");
1520
1522 MBB, MBB.getFirstTerminator(), DL, AArch64::SP, AArch64::SP,
1524 false, NeedsWinCFI, &HasWinCFI, EmitCFI,
1525 StackOffset::getFixed(CombineAfterCSRBump ? PrologueSaveSize : 0));
1526 }
1527}
1528
1529bool AArch64EpilogueEmitter::shouldCombineCSRLocalStackBump(
1530 uint64_t StackBumpBytes) const {
1532 StackBumpBytes))
1533 return false;
1534 if (MBB.empty())
1535 return true;
1536
1537 // Disable combined SP bump if the last instruction is an MTE tag store. It
1538 // is almost always better to merge SP adjustment into those instructions.
1539 MachineBasicBlock::iterator LastI = MBB.getFirstTerminator();
1540 MachineBasicBlock::iterator Begin = MBB.begin();
1541 while (LastI != Begin) {
1542 --LastI;
1543 if (LastI->isTransient())
1544 continue;
1545 if (!LastI->getFlag(MachineInstr::FrameDestroy))
1546 break;
1547 }
1548 switch (LastI->getOpcode()) {
1549 case AArch64::STGloop:
1550 case AArch64::STZGloop:
1551 case AArch64::STGi:
1552 case AArch64::STZGi:
1553 case AArch64::ST2Gi:
1554 case AArch64::STZ2Gi:
1555 return false;
1556 default:
1557 return true;
1558 }
1559 llvm_unreachable("unreachable");
1560}
1561
1562void AArch64EpilogueEmitter::emitSwiftAsyncContextFramePointer(
1564 switch (MF.getTarget().Options.SwiftAsyncFramePointer) {
1566 // Avoid the reload as it is GOT relative, and instead fall back to the
1567 // hardcoded value below. This allows a mismatch between the OS and
1568 // application without immediately terminating on the difference.
1569 [[fallthrough]];
1571 // We need to reset FP to its untagged state on return. Bit 60 is
1572 // currently used to show the presence of an extended frame.
1573
1574 // BIC x29, x29, #0x1000_0000_0000_0000
1575 BuildMI(MBB, MBB.getFirstTerminator(), DL, TII->get(AArch64::ANDXri),
1576 AArch64::FP)
1577 .addUse(AArch64::FP)
1578 .addImm(0x10fe)
1580 if (NeedsWinCFI) {
1581 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1583 HasWinCFI = true;
1584 }
1585 break;
1586
1588 break;
1589 }
1590}
1591
1592void AArch64EpilogueEmitter::emitShadowCallStackEpilogue(
1594 // Shadow call stack epilog: ldr x30, [x18, #-8]!
1595 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXpre))
1596 .addReg(AArch64::X18, RegState::Define)
1597 .addReg(AArch64::LR, RegState::Define)
1598 .addReg(AArch64::X18)
1599 .addImm(-8)
1601
1602 if (NeedsWinCFI)
1603 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1605
1606 if (AFI->needsAsyncDwarfUnwindInfo(MF))
1607 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameDestroy)
1608 .buildRestore(AArch64::X18);
1609}
1610
1611void AArch64EpilogueEmitter::emitCalleeSavedRestores(
1612 MachineBasicBlock::iterator MBBI, bool SVE) const {
1613 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
1614 if (CSI.empty())
1615 return;
1616
1617 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameDestroy);
1618
1619 for (const auto &Info : CSI) {
1620 if (SVE !=
1621 (MFI.getStackID(Info.getFrameIdx()) == TargetStackID::ScalableVector))
1622 continue;
1623
1624 MCRegister Reg = Info.getReg();
1625 if (SVE && !RegInfo.regNeedsCFI(Reg, Reg))
1626 continue;
1627
1628 CFIBuilder.buildRestore(Info.getReg());
1629 }
1630}
1631
1632void AArch64EpilogueEmitter::finalizeEpilogue() const {
1633 if (AFI->needsShadowCallStackPrologueEpilogue(MF)) {
1634 emitShadowCallStackEpilogue(MBB.getFirstTerminator(), DL);
1636 }
1637 if (EmitCFI)
1638 emitCalleeSavedGPRRestores(MBB.getFirstTerminator());
1639 if (AFI->shouldSignReturnAddress(MF)) {
1640 // If pac-ret+leaf is in effect, PAUTH_EPILOGUE pseudo instructions
1641 // are inserted by emitPacRetPlusLeafHardening().
1642 if (!AFL.shouldSignReturnAddressEverywhere(MF)) {
1643 BuildMI(MBB, MBB.getFirstTerminator(), DL,
1644 TII->get(AArch64::PAUTH_EPILOGUE))
1646 }
1647 // AArch64PointerAuth pass will insert SEH_PACSignLR
1649 }
1650 if (HasWinCFI) {
1651 BuildMI(MBB, MBB.getFirstTerminator(), DL, TII->get(AArch64::SEH_EpilogEnd))
1653 if (!MF.hasWinCFI())
1654 MF.setHasWinCFI(true);
1655 }
1656 if (NeedsWinCFI) {
1657 assert(SEHEpilogueStartI != MBB.end());
1658 if (!HasWinCFI)
1659 MBB.erase(SEHEpilogueStartI);
1660 }
1661}
1662
1663} // 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:343
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
#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
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:85