LLVM 24.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 part of the ZPR callee saves.
53 switch (I->getOpcode()) {
54 default:
55 return false;
56 case AArch64::LD1B_2Z_IMM:
57 case AArch64::ST1B_2Z_IMM:
58 case AArch64::LD1B_4Z_IMM:
59 case AArch64::ST1B_4Z_IMM:
60 case AArch64::STR_ZXI:
61 case AArch64::LDR_ZXI:
62 case AArch64::PTRUE_C_B:
63 return I->getFlag(MachineInstr::FrameSetup) ||
65 case AArch64::SEH_SaveZReg:
66 return true;
67 }
68}
69
70// Convenience function to determine whether I is part of the PPR callee saves.
72 switch (I->getOpcode()) {
73 default:
74 return false;
75 case AArch64::STR_PXI:
76 case AArch64::LDR_PXI:
77 return I->getFlag(MachineInstr::FrameSetup) ||
79 case AArch64::SEH_SavePReg:
80 return true;
81 }
82}
83
84// Convenience function to determine whether I is part of the SVE callee saves.
88
92 : MF(MF), MBB(MBB), MFI(MF.getFrameInfo()),
93 Subtarget(MF.getSubtarget<AArch64Subtarget>()), AFL(AFL),
94 RegInfo(*Subtarget.getRegisterInfo()) {
95 TII = Subtarget.getInstrInfo();
96 AFI = MF.getInfo<AArch64FunctionInfo>();
97
98 HasFP = AFL.hasFP(MF);
99 NeedsWinCFI = MF.needsWinCFI();
100
101 if (AFL.hasSVECalleeSavesAboveFrameRecord(MF)) {
102 if (AFI->hasStackHazardSlotIndex())
103 reportFatalUsageError("SME hazard padding is not supported on Windows");
104 SVELayout = SVEStackLayout::CalleeSavesAboveFrameRecord;
105 } else if (AFI->hasSplitSVEObjects()) {
106 SVELayout = SVEStackLayout::Split;
107 }
108}
109
112 MachineBasicBlock::iterator MBBI, const DebugLoc &DL, int CSStackSizeInc,
113 bool EmitCFI, MachineInstr::MIFlag FrameFlag, int CFAOffset) const {
114 unsigned NewOpc;
115
116 // If the function contains streaming mode changes, we expect instructions
117 // to calculate the value of VG before spilling. Move past these instructions
118 // if necessary.
119 if (AFL.requiresSaveVG(MF)) {
120 auto &TLI = *Subtarget.getTargetLowering();
121 while (isVGInstruction(MBBI, TLI))
122 ++MBBI;
123 }
124
125 switch (MBBI->getOpcode()) {
126 default:
127 llvm_unreachable("Unexpected callee-save save/restore opcode!");
128 case AArch64::STPXi:
129 NewOpc = AArch64::STPXpre;
130 break;
131 case AArch64::STPDi:
132 NewOpc = AArch64::STPDpre;
133 break;
134 case AArch64::STPQi:
135 NewOpc = AArch64::STPQpre;
136 break;
137 case AArch64::STRXui:
138 NewOpc = AArch64::STRXpre;
139 break;
140 case AArch64::STRDui:
141 NewOpc = AArch64::STRDpre;
142 break;
143 case AArch64::STRQui:
144 NewOpc = AArch64::STRQpre;
145 break;
146 case AArch64::LDPXi:
147 NewOpc = AArch64::LDPXpost;
148 break;
149 case AArch64::LDPDi:
150 NewOpc = AArch64::LDPDpost;
151 break;
152 case AArch64::LDPQi:
153 NewOpc = AArch64::LDPQpost;
154 break;
155 case AArch64::LDRXui:
156 NewOpc = AArch64::LDRXpost;
157 break;
158 case AArch64::LDRDui:
159 NewOpc = AArch64::LDRDpost;
160 break;
161 case AArch64::LDRQui:
162 NewOpc = AArch64::LDRQpost;
163 break;
164 }
165 TypeSize Scale = TypeSize::getFixed(1), Width = TypeSize::getFixed(0);
166 int64_t MinOffset, MaxOffset;
167 bool Success = TII->getMemOpInfo(NewOpc, Scale, Width, MinOffset, MaxOffset);
168 (void)Success;
169 assert(Success && "unknown load/store opcode");
170
171 // If the first store isn't right where we want SP then we can't fold the
172 // update in so create a normal arithmetic instruction instead.
173 //
174 // On Windows, some register pairs involving LR can't be folded because
175 // there isn't a corresponding unwind opcode.
176 if (MBBI->getOperand(MBBI->getNumOperands() - 1).getImm() != 0 ||
177 CSStackSizeInc < MinOffset * (int64_t)Scale.getFixedValue() ||
178 CSStackSizeInc > MaxOffset * (int64_t)Scale.getFixedValue() ||
179 (NeedsWinCFI &&
180 (NewOpc == AArch64::LDPXpost || NewOpc == AArch64::STPXpre) &&
181 RegInfo.getEncodingValue(MBBI->getOperand(0).getReg()) + 1 !=
182 RegInfo.getEncodingValue(MBBI->getOperand(1).getReg()))) {
183 // If we are destroying the frame, make sure we add the increment after the
184 // last frame operation.
185 if (FrameFlag == MachineInstr::FrameDestroy) {
186 ++MBBI;
187 // Also skip the SEH instruction, if needed
188 if (NeedsWinCFI && AArch64InstrInfo::isSEHInstruction(*MBBI))
189 ++MBBI;
190 }
191 emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP,
192 StackOffset::getFixed(CSStackSizeInc), TII, FrameFlag,
193 false, NeedsWinCFI, &HasWinCFI, EmitCFI,
194 StackOffset::getFixed(CFAOffset));
195
196 return std::prev(MBBI);
197 }
198
199 // Get rid of the SEH code associated with the old instruction.
200 if (NeedsWinCFI) {
201 auto SEH = std::next(MBBI);
202 if (AArch64InstrInfo::isSEHInstruction(*SEH))
203 SEH->eraseFromParent();
204 }
205
206 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(NewOpc));
207 MIB.addReg(AArch64::SP, RegState::Define);
208
209 // Copy all operands other than the immediate offset.
210 unsigned OpndIdx = 0;
211 for (unsigned OpndEnd = MBBI->getNumOperands() - 1; OpndIdx < OpndEnd;
212 ++OpndIdx)
213 MIB.add(MBBI->getOperand(OpndIdx));
214
215 assert(MBBI->getOperand(OpndIdx).getImm() == 0 &&
216 "Unexpected immediate offset in first/last callee-save save/restore "
217 "instruction!");
218 assert(MBBI->getOperand(OpndIdx - 1).getReg() == AArch64::SP &&
219 "Unexpected base register in callee-save save/restore instruction!");
220 assert(CSStackSizeInc % Scale == 0);
221 MIB.addImm(CSStackSizeInc / (int)Scale);
222
223 MIB.setMIFlags(MBBI->getFlags());
224 MIB.setMemRefs(MBBI->memoperands());
225
226 // Generate a new SEH code that corresponds to the new instruction.
227 if (NeedsWinCFI) {
228 HasWinCFI = true;
229 AFL.insertSEH(*MIB, *TII, FrameFlag);
230 }
231
232 if (EmitCFI)
233 CFIInstBuilder(MBB, MBBI, FrameFlag)
234 .buildDefCFAOffset(CFAOffset - CSStackSizeInc);
235
236 return std::prev(MBB.erase(MBBI));
237}
238
239// Fix up the SEH opcode associated with the save/restore instruction.
241 unsigned LocalStackSize) {
242 MachineOperand *ImmOpnd = nullptr;
243 unsigned ImmIdx = MBBI->getNumOperands() - 1;
244 switch (MBBI->getOpcode()) {
245 default:
246 llvm_unreachable("Fix the offset in the SEH instruction");
247 case AArch64::SEH_SaveFPLR:
248 case AArch64::SEH_SaveRegP:
249 case AArch64::SEH_SaveReg:
250 case AArch64::SEH_SaveFRegP:
251 case AArch64::SEH_SaveFReg:
252 case AArch64::SEH_SaveAnyRegI:
253 case AArch64::SEH_SaveAnyRegIP:
254 case AArch64::SEH_SaveAnyRegQP:
255 case AArch64::SEH_SaveAnyRegQPX:
256 ImmOpnd = &MBBI->getOperand(ImmIdx);
257 break;
258 }
259 if (ImmOpnd)
260 ImmOpnd->setImm(ImmOpnd->getImm() + LocalStackSize);
261}
262
264 MachineInstr &MI, uint64_t LocalStackSize) const {
265 if (AArch64InstrInfo::isSEHInstruction(MI))
266 return;
267
268 unsigned Opc = MI.getOpcode();
269 unsigned Scale;
270 switch (Opc) {
271 case AArch64::STPXi:
272 case AArch64::STRXui:
273 case AArch64::STPDi:
274 case AArch64::STRDui:
275 case AArch64::LDPXi:
276 case AArch64::LDRXui:
277 case AArch64::LDPDi:
278 case AArch64::LDRDui:
279 Scale = 8;
280 break;
281 case AArch64::STPQi:
282 case AArch64::STRQui:
283 case AArch64::LDPQi:
284 case AArch64::LDRQui:
285 Scale = 16;
286 break;
287 default:
288 llvm_unreachable("Unexpected callee-save save/restore opcode!");
289 }
290
291 unsigned OffsetIdx = MI.getNumExplicitOperands() - 1;
292 assert(MI.getOperand(OffsetIdx - 1).getReg() == AArch64::SP &&
293 "Unexpected base register in callee-save save/restore instruction!");
294 // Last operand is immediate offset that needs fixing.
295 MachineOperand &OffsetOpnd = MI.getOperand(OffsetIdx);
296 // All generated opcodes have scaled offsets.
297 assert(LocalStackSize % Scale == 0);
298 OffsetOpnd.setImm(OffsetOpnd.getImm() + LocalStackSize / Scale);
299
300 if (NeedsWinCFI) {
301 HasWinCFI = true;
302 auto MBBI = std::next(MachineBasicBlock::iterator(MI));
303 assert(MBBI != MI.getParent()->end() && "Expecting a valid instruction");
304 assert(AArch64InstrInfo::isSEHInstruction(*MBBI) &&
305 "Expecting a SEH instruction");
306 fixupSEHOpcode(MBBI, LocalStackSize);
307 }
308}
309
311 uint64_t StackBumpBytes) const {
312 if (AFL.homogeneousPrologEpilog(MF))
313 return false;
314
315 if (AFI->getLocalStackSize() == 0)
316 return false;
317
318 // For WinCFI, if optimizing for size, prefer to not combine the stack bump
319 // (to force a stp with predecrement) to match the packed unwind format,
320 // provided that there actually are any callee saved registers to merge the
321 // decrement with.
322 //
323 // Note that for certain paired saves, like "x19, lr", we can't actually
324 // emit an predecrement stp, but packed unwind still expects a separate stack
325 // adjustment.
326 //
327 // This is potentially marginally slower, but allows using the packed
328 // unwind format for functions that both have a local area and callee saved
329 // registers. Using the packed unwind format notably reduces the size of
330 // the unwind info.
331 if (MF.needsWinCFI() && AFI->getCalleeSavedStackSize() > 0 &&
332 MF.getFunction().hasOptSize())
333 return false;
334
335 // 512 is the maximum immediate for stp/ldp that will be used for
336 // callee-save save/restores
337 if (StackBumpBytes >= 512 ||
338 AFL.windowsRequiresStackProbe(MF, StackBumpBytes))
339 return false;
340
341 if (MFI.hasVarSizedObjects())
342 return false;
343
344 if (RegInfo.hasStackRealignment(MF))
345 return false;
346
347 // This isn't strictly necessary, but it simplifies things a bit since the
348 // current RedZone handling code assumes the SP is adjusted by the
349 // callee-save save/restore code.
350 if (AFL.canUseRedZone(MF))
351 return false;
352
353 // When there is an SVE area on the stack, always allocate the
354 // callee-saves and spills/locals separately.
355 if (AFI->hasSVEStackSize())
356 return false;
357
358 return true;
359}
360
362 StackOffset PPRCalleeSavesSize =
363 StackOffset::getScalable(AFI->getPPRCalleeSavedStackSize());
364 StackOffset ZPRCalleeSavesSize =
365 StackOffset::getScalable(AFI->getZPRCalleeSavedStackSize());
366 StackOffset PPRLocalsSize = AFL.getPPRStackSize(MF) - PPRCalleeSavesSize;
367 StackOffset ZPRLocalsSize = AFL.getZPRStackSize(MF) - ZPRCalleeSavesSize;
369 return {{PPRCalleeSavesSize, PPRLocalsSize},
370 {ZPRCalleeSavesSize, ZPRLocalsSize}};
371 // For simplicity, attribute all locals to ZPRs when split SVE is disabled.
372 return {{PPRCalleeSavesSize, StackOffset{}},
373 {ZPRCalleeSavesSize, PPRLocalsSize + ZPRLocalsSize}};
374}
375
377 SVEFrameSizes const &SVE) {
378 StackOffset AfterZPRs = SVE.ZPR.LocalsSize;
379 StackOffset BeforePPRs = SVE.ZPR.CalleeSavesSize + SVE.PPR.CalleeSavesSize;
380 StackOffset AfterPPRs = {};
382 BeforePPRs = SVE.PPR.CalleeSavesSize;
383 // If there are no ZPR CSRs, place all local allocations after the ZPRs.
384 if (SVE.ZPR.CalleeSavesSize)
385 AfterPPRs += SVE.PPR.LocalsSize + SVE.ZPR.CalleeSavesSize;
386 else
387 AfterZPRs += SVE.PPR.LocalsSize; // Group allocation of locals.
388 }
389 return {BeforePPRs, AfterPPRs, AfterZPRs};
390}
391
397
400 StackOffset PPRCalleeSavesSize,
401 StackOffset ZPRCalleeSavesSize,
402 bool IsEpilogue) {
405 IsEpilogue ? MBB.begin() : MBB.getFirstTerminator();
406 auto AdjustI = [&](auto MBBI) { return IsEpilogue ? std::prev(MBBI) : MBBI; };
407 // Process the SVE CS to find the starts/ends of the ZPR and PPR areas.
408 if (PPRCalleeSavesSize) {
409 PPRsI = AdjustI(PPRsI);
410 assert(isPartOfPPRCalleeSaves(*PPRsI) && "Unexpected instruction");
411 while (PPRsI != End && isPartOfPPRCalleeSaves(AdjustI(PPRsI)))
412 IsEpilogue ? (--PPRsI) : (++PPRsI);
413 }
414 MachineBasicBlock::iterator ZPRsI = PPRsI;
415 if (ZPRCalleeSavesSize) {
416 ZPRsI = AdjustI(ZPRsI);
417 assert(isPartOfZPRCalleeSaves(*ZPRsI) && "Unexpected instruction");
418 while (ZPRsI != End && isPartOfZPRCalleeSaves(AdjustI(ZPRsI)))
419 IsEpilogue ? (--ZPRsI) : (++ZPRsI);
420 }
421 if (IsEpilogue)
422 return {{PPRsI, MBBI}, {ZPRsI, PPRsI}};
423 return {{MBBI, PPRsI}, {PPRsI, ZPRsI}};
424}
425
430 EmitCFI = AFI->needsDwarfUnwindInfo(MF);
431 EmitAsyncCFI = AFI->needsAsyncDwarfUnwindInfo(MF);
432 IsFunclet = MBB.isEHFuncletEntry();
433 HomPrologEpilog = AFL.homogeneousPrologEpilog(MF);
434
435#ifndef NDEBUG
436 collectBlockLiveins();
437#endif
438}
439
440#ifndef NDEBUG
441/// Collect live registers from the end of \p MI's parent up to (including) \p
442/// MI in \p LiveRegs.
445
446 MachineBasicBlock &MBB = *MI.getParent();
447 LiveRegs.addLiveOuts(MBB);
448 for (const MachineInstr &MI :
449 reverse(make_range(MI.getIterator(), MBB.instr_end())))
450 LiveRegs.stepBackward(MI);
451}
452
453void AArch64PrologueEmitter::collectBlockLiveins() {
454 // Collect live register from the end of MBB up to the start of the existing
455 // frame setup instructions.
456 PrologueEndI = MBB.begin();
457 while (PrologueEndI != MBB.end() &&
458 PrologueEndI->getFlag(MachineInstr::FrameSetup))
459 ++PrologueEndI;
460
461 if (PrologueEndI != MBB.end()) {
462 getLivePhysRegsUpTo(*PrologueEndI, RegInfo, LiveRegs);
463 // Ignore registers used for stack management for now.
464 LiveRegs.removeReg(AArch64::SP);
465 LiveRegs.removeReg(AArch64::X19);
466 LiveRegs.removeReg(AArch64::FP);
467 LiveRegs.removeReg(AArch64::LR);
468
469 // X0 will be clobbered by a call to __arm_get_current_vg in the prologue.
470 // This is necessary to spill VG if required where SVE is unavailable, but
471 // X0 is preserved around this call.
472 if (requiresGetVGCall())
473 LiveRegs.removeReg(AArch64::X0);
474 }
475}
476
477void AArch64PrologueEmitter::verifyPrologueClobbers() const {
478 if (PrologueEndI == MBB.end())
479 return;
480 // Check if any of the newly instructions clobber any of the live registers.
481 for (MachineInstr &MI :
482 make_range(MBB.instr_begin(), PrologueEndI->getIterator())) {
483 for (auto &Op : MI.operands())
484 if (Op.isReg() && Op.isDef())
485 assert(!LiveRegs.contains(Op.getReg()) &&
486 "live register clobbered by inserted prologue instructions");
487 }
488}
489#endif
490
491void AArch64PrologueEmitter::determineLocalsStackSize(
492 uint64_t StackSize, uint64_t PrologueSaveSize) {
493 AFI->setLocalStackSize(StackSize - PrologueSaveSize);
494 CombineSPBump = shouldCombineCSRLocalStackBump(StackSize);
495}
496
497// Return the maximum possible number of bytes for `Size` due to the
498// architectural limit on the size of a SVE register.
499static int64_t upperBound(StackOffset Size) {
500 static const int64_t MAX_BYTES_PER_SCALABLE_BYTE = 16;
501 return Size.getScalable() * MAX_BYTES_PER_SCALABLE_BYTE + Size.getFixed();
502}
503
504void AArch64PrologueEmitter::allocateStackSpace(
505 MachineBasicBlock::iterator MBBI, int64_t RealignmentPadding,
506 StackOffset AllocSize, bool EmitCFI, StackOffset InitialOffset,
507 bool FollowupAllocs) {
508
509 if (!AllocSize)
510 return;
511
512 DebugLoc DL;
513 const int64_t MaxAlign = MFI.getMaxAlign().value();
514 const uint64_t AndMask = ~(MaxAlign - 1);
515
517 Register TargetReg = RealignmentPadding
518 ? AFL.findScratchNonCalleeSaveRegister(&MBB)
519 : AArch64::SP;
520 // SUB Xd/SP, SP, AllocSize
521 emitFrameOffset(MBB, MBBI, DL, TargetReg, AArch64::SP, -AllocSize, TII,
523 EmitCFI, InitialOffset);
524
525 if (RealignmentPadding) {
526 // AND SP, X9, 0b11111...0000
527 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), AArch64::SP)
528 .addReg(TargetReg, RegState::Kill)
531 AFI->setStackRealigned(true);
532
533 // No need for SEH instructions here; if we're realigning the stack,
534 // we've set a frame pointer and already finished the SEH prologue.
536 }
537 return;
538 }
539
540 //
541 // Stack probing allocation.
542 //
543
544 // Fixed length allocation. If we don't need to re-align the stack and don't
545 // have SVE objects, we can use a more efficient sequence for stack probing.
546 if (AllocSize.getScalable() == 0 && RealignmentPadding == 0) {
547 Register ScratchReg = AFL.findScratchNonCalleeSaveRegister(&MBB);
548 assert(ScratchReg.isValid());
549 BuildMI(MBB, MBBI, DL, TII->get(AArch64::PROBED_STACKALLOC))
550 .addDef(ScratchReg)
551 .addImm(AllocSize.getFixed())
552 .addImm(InitialOffset.getFixed())
553 .addImm(InitialOffset.getScalable());
554 // The fixed allocation may leave unprobed bytes at the top of the
555 // stack. If we have subsequent allocation (e.g. if we have variable-sized
556 // objects), we need to issue an extra probe, so these allocations start in
557 // a known state.
558 if (FollowupAllocs) {
559 // LDR XZR, [SP]
560 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui))
561 .addDef(AArch64::XZR)
562 .addReg(AArch64::SP)
563 .addImm(0)
564 .addMemOperand(MF.getMachineMemOperand(
567 Align(8)))
569 }
570
571 return;
572 }
573
574 // Variable length allocation.
575
576 // If the (unknown) allocation size cannot exceed the probe size, decrement
577 // the stack pointer right away.
578 int64_t ProbeSize = AFI->getStackProbeSize();
579 if (upperBound(AllocSize) + RealignmentPadding <= ProbeSize) {
580 Register ScratchReg = RealignmentPadding
581 ? AFL.findScratchNonCalleeSaveRegister(&MBB)
582 : AArch64::SP;
583 assert(ScratchReg.isValid());
584 // SUB Xd, SP, AllocSize
585 emitFrameOffset(MBB, MBBI, DL, ScratchReg, AArch64::SP, -AllocSize, TII,
587 EmitCFI, InitialOffset);
588 if (RealignmentPadding) {
589 // AND SP, Xn, 0b11111...0000
590 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), AArch64::SP)
591 .addReg(ScratchReg, RegState::Kill)
594 AFI->setStackRealigned(true);
595 }
596 if (FollowupAllocs || upperBound(AllocSize) + RealignmentPadding >
598 // LDR XZR, [SP]
599 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui))
600 .addDef(AArch64::XZR)
601 .addReg(AArch64::SP)
602 .addImm(0)
603 .addMemOperand(MF.getMachineMemOperand(
606 Align(8)))
608 }
609 return;
610 }
611
612 // Emit a variable-length allocation probing loop.
613 // TODO: As an optimisation, the loop can be "unrolled" into a few parts,
614 // each of them guaranteed to adjust the stack by less than the probe size.
615 Register TargetReg = AFL.findScratchNonCalleeSaveRegister(&MBB);
616 assert(TargetReg.isValid());
617 // SUB Xd, SP, AllocSize
618 emitFrameOffset(MBB, MBBI, DL, TargetReg, AArch64::SP, -AllocSize, TII,
620 EmitCFI, InitialOffset);
621 if (RealignmentPadding) {
622 // AND Xn, Xn, 0b11111...0000
623 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), TargetReg)
624 .addReg(TargetReg, RegState::Kill)
627 }
628
629 BuildMI(MBB, MBBI, DL, TII->get(AArch64::PROBED_STACKALLOC_VAR))
630 .addReg(TargetReg);
631 if (EmitCFI) {
632 // Set the CFA register back to SP.
633 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
634 .buildDefCFARegister(AArch64::SP);
635 }
636 if (RealignmentPadding)
637 AFI->setStackRealigned(true);
638}
639
641 const MachineBasicBlock::iterator PrologueBeginI = MBB.begin();
642 const MachineBasicBlock::iterator EndI = MBB.end();
643
644 // At this point, we're going to decide whether or not the function uses a
645 // redzone. In most cases, the function doesn't have a redzone so let's
646 // assume that's false and set it to true in the case that there's a redzone.
647 AFI->setHasRedZone(false);
648
649 // Debug location must be unknown since the first debug location is used
650 // to determine the end of the prologue.
651 DebugLoc DL;
652
653 // In some cases, particularly with CallingConv::SwiftTail, it is possible to
654 // have a tail-call where the caller only needs to adjust the stack pointer in
655 // the epilogue. In this case, we still need to emit a SEH prologue sequence.
656 // See `seh-minimal-prologue-epilogue.ll` test cases.
657 if (AFI->getArgumentStackToRestore())
659
660 if (AFI->shouldSignReturnAddress(MF)) {
661 // If pac-ret+leaf is in effect, PAUTH_PROLOGUE pseudo instructions
662 // are inserted by emitPacRetPlusLeafHardening().
663 if (!AFL.shouldSignReturnAddressEverywhere(MF)) {
664 BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::PAUTH_PROLOGUE))
666 }
667 // AArch64PointerAuth pass will insert SEH_PACSignLR
669 }
670
671 if (AFI->needsShadowCallStackPrologueEpilogue(MF)) {
672 emitShadowCallStackPrologue(PrologueBeginI, DL);
674 }
675
676 if (EmitCFI && AFI->isMTETagged())
677 BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::EMITMTETAGGED))
679
680 // We signal the presence of a Swift extended frame to external tools by
681 // storing FP with 0b0001 in bits 63:60. In normal userland operation a simple
682 // ORR is sufficient, it is assumed a Swift kernel would initialize the TBI
683 // bits so that is still true.
684 if (HasFP && AFI->hasSwiftAsyncContext())
685 emitSwiftAsyncContextFramePointer(PrologueBeginI, DL);
686
687 // All calls are tail calls in GHC calling conv, and functions have no
688 // prologue/epilogue.
689 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
690 return;
691
692 // Set tagged base pointer to the requested stack slot. Ideally it should
693 // match SP value after prologue.
694 if (std::optional<int> TBPI = AFI->getTaggedBasePointerIndex())
695 AFI->setTaggedBasePointerOffset(-MFI.getObjectOffset(*TBPI));
696 else
697 AFI->setTaggedBasePointerOffset(MFI.getStackSize());
698
699 // getStackSize() includes all the locals in its size calculation. We don't
700 // include these locals when computing the stack size of a funclet, as they
701 // are allocated in the parent's stack frame and accessed via the frame
702 // pointer from the funclet. We only save the callee saved registers in the
703 // funclet, which are really the callee saved registers of the parent
704 // function, including the funclet.
705 int64_t NumBytes =
706 IsFunclet ? AFL.getWinEHFuncletFrameSize(MF) : MFI.getStackSize();
707 if (!AFI->hasStackFrame() && !AFL.windowsRequiresStackProbe(MF, NumBytes))
708 return emitEmptyStackFramePrologue(NumBytes, PrologueBeginI, DL);
709
710 bool IsWin64 = Subtarget.isCallingConvWin64(F.getCallingConv(), F.isVarArg());
711 unsigned FixedObject = AFL.getFixedObjectSize(MF, AFI, IsWin64, IsFunclet);
712
713 auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
714 // All of the remaining stack allocations are for locals.
715 determineLocalsStackSize(NumBytes, PrologueSaveSize);
716
717 auto [PPR, ZPR] = getSVEStackFrameSizes();
718 SVEStackAllocations SVEAllocs = getSVEStackAllocations({PPR, ZPR});
719
720 MachineBasicBlock::iterator FirstGPRSaveI = PrologueBeginI;
722 assert(!SVEAllocs.AfterPPRs &&
723 "unexpected SVE allocs after PPRs with CalleeSavesAboveFrameRecord");
724 // If we're doing SVE saves first, we need to immediately allocate space
725 // for fixed objects, then space for the SVE callee saves.
726 //
727 // Windows unwind requires that the scalable size is a multiple of 16;
728 // that's handled when the callee-saved size is computed.
729 auto SaveSize = SVEAllocs.BeforePPRs + StackOffset::getFixed(FixedObject);
730 allocateStackSpace(PrologueBeginI, 0, SaveSize, false, StackOffset{},
731 /*FollowupAllocs=*/true);
732 NumBytes -= FixedObject;
733
734 // Now allocate space for the GPR callee saves.
735 MachineBasicBlock::iterator MBBI = PrologueBeginI;
736 while (MBBI != EndI && isPartOfSVECalleeSaves(MBBI))
737 ++MBBI;
739 MBBI, DL, -AFI->getCalleeSavedStackSize(), EmitAsyncCFI);
740 NumBytes -= AFI->getCalleeSavedStackSize();
741 } else if (CombineSPBump) {
742 assert(!AFL.getSVEStackSize(MF) && "Cannot combine SP bump with SVE");
743 emitFrameOffset(MBB, PrologueBeginI, DL, AArch64::SP, AArch64::SP,
744 StackOffset::getFixed(-NumBytes), TII,
746 EmitAsyncCFI);
747 NumBytes = 0;
748 } else if (HomPrologEpilog) {
749 // Stack has been already adjusted.
750 NumBytes -= PrologueSaveSize;
751 } else if (PrologueSaveSize != 0) {
753 PrologueBeginI, DL, -PrologueSaveSize, EmitAsyncCFI);
754 NumBytes -= PrologueSaveSize;
755 }
756 assert(NumBytes >= 0 && "Negative stack allocation size!?");
757
758 // Move past the saves of the callee-saved registers, fixing up the offsets
759 // and pre-inc if we decided to combine the callee-save and local stack
760 // pointer bump above.
761 auto &TLI = *Subtarget.getTargetLowering();
762
763 MachineBasicBlock::iterator AfterGPRSavesI = FirstGPRSaveI;
764 while (AfterGPRSavesI != EndI &&
765 AfterGPRSavesI->getFlag(MachineInstr::FrameSetup) &&
766 !isPartOfSVECalleeSaves(AfterGPRSavesI)) {
767 if (CombineSPBump &&
768 // Only fix-up frame-setup load/store instructions.
769 (!AFL.requiresSaveVG(MF) || !isVGInstruction(AfterGPRSavesI, TLI)))
770 fixupCalleeSaveRestoreStackOffset(*AfterGPRSavesI,
771 AFI->getLocalStackSize());
772 ++AfterGPRSavesI;
773 }
774
775 // For funclets the FP belongs to the containing function. Only set up FP if
776 // we actually need to.
777 if (!IsFunclet && HasFP)
778 emitFramePointerSetup(AfterGPRSavesI, DL, FixedObject);
779
780 // Now emit the moves for whatever callee saved regs we have (including FP,
781 // LR if those are saved). Frame instructions for SVE register are emitted
782 // later, after the instruction which actually save SVE regs.
783 if (EmitAsyncCFI)
784 emitCalleeSavedGPRLocations(AfterGPRSavesI);
785
786 // Alignment is required for the parent frame, not the funclet
787 const bool NeedsRealignment =
788 NumBytes && !IsFunclet && RegInfo.hasStackRealignment(MF);
789 const int64_t RealignmentPadding =
790 (NeedsRealignment && MFI.getMaxAlign() > Align(16))
791 ? MFI.getMaxAlign().value() - 16
792 : 0;
793
794 if (AFL.windowsRequiresStackProbe(MF, NumBytes + RealignmentPadding))
795 emitWindowsStackProbe(AfterGPRSavesI, DL, NumBytes, RealignmentPadding);
796
797 StackOffset NonSVELocalsSize = StackOffset::getFixed(NumBytes);
798 SVEAllocs.AfterZPRs += NonSVELocalsSize;
799
800 StackOffset CFAOffset =
801 StackOffset::getFixed(MFI.getStackSize()) - NonSVELocalsSize;
802 MachineBasicBlock::iterator AfterSVESavesI = AfterGPRSavesI;
803 // Allocate space for the callee saves and PPR locals (if any).
805 auto [PPRRange, ZPRRange] =
806 partitionSVECS(MBB, AfterGPRSavesI, PPR.CalleeSavesSize,
807 ZPR.CalleeSavesSize, /*IsEpilogue=*/false);
808 AfterSVESavesI = ZPRRange.End;
809 if (EmitAsyncCFI)
810 emitCalleeSavedSVELocations(AfterSVESavesI);
811
812 allocateStackSpace(PPRRange.Begin, 0, SVEAllocs.BeforePPRs,
813 EmitAsyncCFI && !HasFP, CFAOffset,
814 MFI.hasVarSizedObjects() || SVEAllocs.AfterPPRs ||
815 SVEAllocs.AfterZPRs);
816 CFAOffset += SVEAllocs.BeforePPRs;
817 assert(PPRRange.End == ZPRRange.Begin &&
818 "Expected ZPR callee saves after PPR locals");
819 allocateStackSpace(PPRRange.End, 0, SVEAllocs.AfterPPRs,
820 EmitAsyncCFI && !HasFP, CFAOffset,
821 MFI.hasVarSizedObjects() || SVEAllocs.AfterZPRs);
822 CFAOffset += SVEAllocs.AfterPPRs;
823 } else {
825 // Note: With CalleeSavesAboveFrameRecord, the SVE CS (BeforePPRs) have
826 // already been allocated. PPR locals (included in AfterPPRs) are not
827 // supported (note: this is asserted above).
828 CFAOffset += SVEAllocs.BeforePPRs;
829 }
830
831 // Allocate space for the rest of the frame including ZPR locals. Align the
832 // stack as necessary.
833 assert(!(AFL.canUseRedZone(MF) && NeedsRealignment) &&
834 "Cannot use redzone with stack realignment");
835 if (!AFL.canUseRedZone(MF)) {
836 // FIXME: in the case of dynamic re-alignment, NumBytes doesn't have the
837 // correct value here, as NumBytes also includes padding bytes, which
838 // shouldn't be counted here.
839 allocateStackSpace(AfterSVESavesI, RealignmentPadding, SVEAllocs.AfterZPRs,
840 EmitAsyncCFI && !HasFP, CFAOffset,
841 MFI.hasVarSizedObjects());
842 }
843
844 // If we need a base pointer, set it up here. It's whatever the value of the
845 // stack pointer is at this point. Any variable size objects will be
846 // allocated after this, so we can still use the base pointer to reference
847 // locals.
848 //
849 // FIXME: Clarify FrameSetup flags here.
850 // Note: Use emitFrameOffset() like above for FP if the FrameSetup flag is
851 // needed.
852 // For funclets the BP belongs to the containing function.
853 if (!IsFunclet && RegInfo.hasBasePointer(MF)) {
854 TII->copyPhysReg(MBB, AfterSVESavesI, DL, RegInfo.getBaseRegister(),
855 AArch64::SP, false);
856 if (NeedsWinCFI) {
857 HasWinCFI = true;
858 BuildMI(MBB, AfterSVESavesI, DL, TII->get(AArch64::SEH_Nop))
860 }
861 }
862
863 // The very last FrameSetup instruction indicates the end of prologue. Emit a
864 // SEH opcode indicating the prologue end.
865 if (NeedsWinCFI && HasWinCFI) {
866 BuildMI(MBB, AfterSVESavesI, DL, TII->get(AArch64::SEH_PrologEnd))
868 }
869
870 // SEH funclets are passed the frame pointer in X1. If the parent
871 // function uses the base register, then the base register is used
872 // directly, and is not retrieved from X1.
873 if (IsFunclet && F.hasPersonalityFn()) {
874 EHPersonality Per = classifyEHPersonality(F.getPersonalityFn());
876 BuildMI(MBB, AfterSVESavesI, DL, TII->get(TargetOpcode::COPY),
877 AArch64::FP)
878 .addReg(AArch64::X1)
880 MBB.addLiveIn(AArch64::X1);
881 }
882 }
883
884 if (EmitCFI && !EmitAsyncCFI) {
885 if (HasFP) {
886 emitDefineCFAWithFP(AfterSVESavesI, FixedObject);
887 } else {
888 StackOffset TotalSize =
889 AFL.getSVEStackSize(MF) +
890 StackOffset::getFixed((int64_t)MFI.getStackSize());
891 CFIInstBuilder CFIBuilder(MBB, AfterSVESavesI, MachineInstr::FrameSetup);
892 CFIBuilder.insertCFIInst(
893 createDefCFA(RegInfo, /*FrameReg=*/AArch64::SP, /*Reg=*/AArch64::SP,
894 TotalSize, /*LastAdjustmentWasScalable=*/false));
895 }
896 emitCalleeSavedGPRLocations(AfterSVESavesI);
897 emitCalleeSavedSVELocations(AfterSVESavesI);
898 }
899}
900
901void AArch64PrologueEmitter::emitShadowCallStackPrologue(
903 // Shadow call stack prolog: str x30, [x18], #8
904 BuildMI(MBB, MBBI, DL, TII->get(AArch64::STRXpost))
905 .addReg(AArch64::X18, RegState::Define)
906 .addReg(AArch64::LR)
907 .addReg(AArch64::X18)
908 .addImm(8)
910
911 // This instruction also makes x18 live-in to the entry block.
912 MBB.addLiveIn(AArch64::X18);
913
914 if (NeedsWinCFI)
915 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
917
918 if (EmitCFI) {
919 // Emit a CFI instruction that causes 8 to be subtracted from the value of
920 // x18 when unwinding past this frame.
921 static const char CFIInst[] = {
922 dwarf::DW_CFA_val_expression,
923 18, // register
924 2, // length
925 static_cast<char>(unsigned(dwarf::DW_OP_breg18)),
926 static_cast<char>(-8) & 0x7f, // addend (sleb128)
927 };
928 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
929 .buildEscape(StringRef(CFIInst, sizeof(CFIInst)));
930 }
931}
932
933void AArch64PrologueEmitter::emitSwiftAsyncContextFramePointer(
935 switch (MF.getTarget().Options.SwiftAsyncFramePointer) {
937 if (Subtarget.swiftAsyncContextIsDynamicallySet()) {
938 // The special symbol below is absolute and has a *value* that can be
939 // combined with the frame pointer to signal an extended frame.
940 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LOADgot), AArch64::X16)
941 .addExternalSymbol("swift_async_extendedFramePointerFlags",
943 if (NeedsWinCFI) {
944 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
946 HasWinCFI = true;
947 }
948 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::FP)
949 .addUse(AArch64::FP)
950 .addUse(AArch64::X16)
951 .addImm(Subtarget.isTargetILP32() ? 32 : 0);
952 if (NeedsWinCFI) {
953 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
955 HasWinCFI = true;
956 }
957 break;
958 }
959 [[fallthrough]];
960
962 // ORR x29, x29, #0x1000_0000_0000_0000
963 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXri), AArch64::FP)
964 .addUse(AArch64::FP)
965 .addImm(0x1100)
967 if (NeedsWinCFI) {
968 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
970 HasWinCFI = true;
971 }
972 break;
973
975 break;
976 }
977}
978
979void AArch64PrologueEmitter::emitEmptyStackFramePrologue(
980 int64_t NumBytes, MachineBasicBlock::iterator MBBI,
981 const DebugLoc &DL) const {
982 assert(!HasFP && "unexpected function without stack frame but with FP");
983 assert(!AFL.getSVEStackSize(MF) &&
984 "unexpected function without stack frame but with SVE objects");
985 // All of the stack allocation is for locals.
986 AFI->setLocalStackSize(NumBytes);
987 if (!NumBytes) {
988 if (NeedsWinCFI && HasWinCFI) {
989 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
991 }
992 return;
993 }
994 // REDZONE: If the stack size is less than 128 bytes, we don't need
995 // to actually allocate.
996 if (AFL.canUseRedZone(MF)) {
997 AFI->setHasRedZone(true);
998 ++NumRedZoneFunctions;
999 } else {
1000 emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP,
1001 StackOffset::getFixed(-NumBytes), TII,
1003 if (EmitCFI) {
1004 // Label used to tie together the PROLOG_LABEL and the MachineMoves.
1005 MCSymbol *FrameLabel = MF.getContext().createTempSymbol();
1006 // Encode the stack size of the leaf function.
1007 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
1008 .buildDefCFAOffset(NumBytes, FrameLabel);
1009 }
1010 }
1011
1012 if (NeedsWinCFI) {
1013 HasWinCFI = true;
1014 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
1016 }
1017}
1018
1019void AArch64PrologueEmitter::emitFramePointerSetup(
1021 unsigned FixedObject) {
1022 int64_t FPOffset = AFI->getCalleeSaveBaseToFrameRecordOffset();
1023 if (CombineSPBump)
1024 FPOffset += AFI->getLocalStackSize();
1025
1026 if (AFI->hasSwiftAsyncContext()) {
1027 // Before we update the live FP we have to ensure there's a valid (or
1028 // null) asynchronous context in its slot just before FP in the frame
1029 // record, so store it now.
1030 const auto &Attrs = MF.getFunction().getAttributes();
1031 bool HaveInitialContext = Attrs.hasAttrSomewhere(Attribute::SwiftAsync);
1032 if (HaveInitialContext)
1033 MBB.addLiveIn(AArch64::X22);
1034 Register Reg = HaveInitialContext ? AArch64::X22 : AArch64::XZR;
1035 BuildMI(MBB, MBBI, DL, TII->get(AArch64::StoreSwiftAsyncContext))
1036 .addUse(Reg)
1037 .addUse(AArch64::SP)
1038 .addImm(FPOffset - 8)
1040 if (NeedsWinCFI) {
1041 // WinCFI and arm64e, where StoreSwiftAsyncContext is expanded
1042 // to multiple instructions, should be mutually-exclusive.
1043 assert(Subtarget.getTargetTriple().getArchName() != "arm64e");
1044 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1046 HasWinCFI = true;
1047 }
1048 }
1049
1050 if (HomPrologEpilog) {
1051 auto Prolog = MBBI;
1052 --Prolog;
1053 assert(Prolog->getOpcode() == AArch64::HOM_Prolog);
1054 Prolog->addOperand(MachineOperand::CreateImm(FPOffset));
1055 } else {
1056 // Issue sub fp, sp, FPOffset or
1057 // mov fp,sp when FPOffset is zero.
1058 // Note: All stores of callee-saved registers are marked as "FrameSetup".
1059 // This code marks the instruction(s) that set the FP also.
1060 emitFrameOffset(MBB, MBBI, DL, AArch64::FP, AArch64::SP,
1061 StackOffset::getFixed(FPOffset), TII,
1063 if (NeedsWinCFI && HasWinCFI) {
1064 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
1066 // After setting up the FP, the rest of the prolog doesn't need to be
1067 // included in the SEH unwind info.
1068 NeedsWinCFI = false;
1069 }
1070 }
1071 if (EmitAsyncCFI)
1072 emitDefineCFAWithFP(MBBI, FixedObject);
1073}
1074
1075// Define the current CFA rule to use the provided FP.
1076void AArch64PrologueEmitter::emitDefineCFAWithFP(
1077 MachineBasicBlock::iterator MBBI, unsigned FixedObject) const {
1078 const int OffsetToFirstCalleeSaveFromFP =
1079 AFI->getCalleeSaveBaseToFrameRecordOffset() -
1080 AFI->getCalleeSavedStackSize();
1081 Register FramePtr = RegInfo.getFrameRegister(MF);
1082 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
1083 .buildDefCFA(FramePtr, FixedObject - OffsetToFirstCalleeSaveFromFP);
1084}
1085
1086void AArch64PrologueEmitter::emitWindowsStackProbe(
1087 MachineBasicBlock::iterator MBBI, const DebugLoc &DL, int64_t &NumBytes,
1088 int64_t RealignmentPadding) const {
1089 if (AFI->getSVECalleeSavedStackSize())
1090 report_fatal_error("SVE callee saves not yet supported with stack probing");
1091
1092 // Find an available register to spill the value of X15 to, if X15 is being
1093 // used already for nest.
1094 Register X15Scratch;
1095 if (llvm::any_of(MBB.liveins(),
1096 [this](const MachineBasicBlock::RegisterMaskPair &LiveIn) {
1097 return RegInfo.isSuperOrSubRegisterEq(AArch64::X15,
1098 LiveIn.PhysReg);
1099 })) {
1100 X15Scratch = AFL.findScratchNonCalleeSaveRegister(&MBB, /*HasCall=*/true);
1101 assert(X15Scratch.isValid() &&
1102 (X15Scratch < AArch64::X15 || X15Scratch > AArch64::X17));
1103#ifndef NDEBUG
1104 LiveRegs.removeReg(AArch64::X15); // ignore X15 since we restore it
1105#endif
1106 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrr), X15Scratch)
1107 .addReg(AArch64::XZR)
1108 .addReg(AArch64::X15, RegState::Undef)
1109 .addReg(AArch64::X15, RegState::Implicit)
1111 }
1112
1113 uint64_t NumWords = (NumBytes + RealignmentPadding) >> 4;
1114 if (NeedsWinCFI) {
1115 HasWinCFI = true;
1116 // alloc_l can hold at most 256MB, so assume that NumBytes doesn't
1117 // exceed this amount. We need to move at most 2^24 - 1 into x15.
1118 // This is at most two instructions, MOVZ followed by MOVK.
1119 // TODO: Fix to use multiple stack alloc unwind codes for stacks
1120 // exceeding 256MB in size.
1121 if (NumBytes >= (1 << 28))
1122 report_fatal_error("Stack size cannot exceed 256MB for stack "
1123 "unwinding purposes");
1124
1125 uint32_t LowNumWords = NumWords & 0xFFFF;
1126 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVZXi), AArch64::X15)
1127 .addImm(LowNumWords)
1130 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1132 if ((NumWords & 0xFFFF0000) != 0) {
1133 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVKXi), AArch64::X15)
1134 .addReg(AArch64::X15)
1135 .addImm((NumWords & 0xFFFF0000) >> 16) // High half
1138 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1140 }
1141 } else {
1142 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVi64imm), AArch64::X15)
1143 .addImm(NumWords)
1145 }
1146
1147 const AArch64TargetLowering *TLI = Subtarget.getTargetLowering();
1148 RTLIB::LibcallImpl ChkStkLibcall = TLI->getLibcallImpl(RTLIB::STACK_PROBE);
1149 if (ChkStkLibcall == RTLIB::Unsupported)
1150 reportFatalUsageError("no available implementation of __chkstk");
1151
1152 const char *ChkStk = TLI->getLibcallImplName(ChkStkLibcall).data();
1153 switch (MF.getTarget().getCodeModel()) {
1154 case CodeModel::Tiny:
1155 case CodeModel::Small:
1156 case CodeModel::Medium:
1157 case CodeModel::Kernel:
1158 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
1159 .addExternalSymbol(ChkStk)
1160 .addReg(AArch64::X15, RegState::Implicit)
1161 .addReg(AArch64::X16,
1163 .addReg(AArch64::X17,
1165 .addReg(AArch64::NZCV,
1168 if (NeedsWinCFI) {
1169 HasWinCFI = true;
1170 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1172 }
1173 break;
1174 case CodeModel::Large:
1175 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVaddrEXT))
1176 .addReg(AArch64::X16, RegState::Define)
1177 .addExternalSymbol(ChkStk)
1178 .addExternalSymbol(ChkStk)
1180 if (NeedsWinCFI) {
1181 HasWinCFI = true;
1182 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1184 }
1185
1187 .addReg(AArch64::X16, RegState::Kill)
1189 .addReg(AArch64::X16,
1191 .addReg(AArch64::X17,
1193 .addReg(AArch64::NZCV,
1196 if (NeedsWinCFI) {
1197 HasWinCFI = true;
1198 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1200 }
1201 break;
1202 }
1203
1204 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SUBXrx64), AArch64::SP)
1205 .addReg(AArch64::SP, RegState::Kill)
1206 .addReg(AArch64::X15, RegState::Kill)
1209 if (NeedsWinCFI) {
1210 HasWinCFI = true;
1211 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
1212 .addImm(NumBytes)
1214 }
1215 NumBytes = 0;
1216
1217 if (RealignmentPadding > 0) {
1218 if (RealignmentPadding >= 4096) {
1219 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVi64imm))
1220 .addReg(AArch64::X16, RegState::Define)
1221 .addImm(RealignmentPadding)
1223 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXrx64), AArch64::X15)
1224 .addReg(AArch64::SP)
1225 .addReg(AArch64::X16, RegState::Kill)
1228 } else {
1229 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXri), AArch64::X15)
1230 .addReg(AArch64::SP)
1231 .addImm(RealignmentPadding)
1232 .addImm(0)
1234 }
1235
1236 uint64_t AndMask = ~(MFI.getMaxAlign().value() - 1);
1237 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), AArch64::SP)
1238 .addReg(AArch64::X15, RegState::Kill)
1240 AFI->setStackRealigned(true);
1241
1242 // No need for SEH instructions here; if we're realigning the stack,
1243 // we've set a frame pointer and already finished the SEH prologue.
1245 }
1246 if (X15Scratch.isValid()) {
1247 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrr), AArch64::X15)
1248 .addReg(AArch64::XZR)
1249 .addReg(X15Scratch, RegState::Undef)
1250 .addReg(X15Scratch, RegState::Implicit)
1252 }
1253}
1254
1255void AArch64PrologueEmitter::emitCalleeSavedGPRLocations(
1257 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
1258 if (CSI.empty())
1259 return;
1260
1261 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameSetup);
1262 for (const auto &Info : CSI) {
1263 unsigned FrameIdx = Info.getFrameIdx();
1264 if (MFI.hasScalableStackID(FrameIdx))
1265 continue;
1266
1267 assert(!Info.isSpilledToReg() && "Spilling to registers not implemented");
1268 int64_t Offset = MFI.getObjectOffset(FrameIdx) - AFL.getOffsetOfLocalArea();
1269 CFIBuilder.buildOffset(Info.getReg(), Offset);
1270 }
1271}
1272
1273void AArch64PrologueEmitter::emitCalleeSavedSVELocations(
1275 // Add callee saved registers to move list.
1276 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
1277 if (CSI.empty())
1278 return;
1279
1280 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameSetup);
1281
1282 std::optional<int64_t> IncomingVGOffsetFromDefCFA;
1283 if (AFL.requiresSaveVG(MF)) {
1284 auto IncomingVG = *find_if(
1285 reverse(CSI), [](auto &Info) { return Info.getReg() == AArch64::VG; });
1286 IncomingVGOffsetFromDefCFA = MFI.getObjectOffset(IncomingVG.getFrameIdx()) -
1287 AFL.getOffsetOfLocalArea();
1288 }
1289
1290 StackOffset PPRStackSize = AFL.getPPRStackSize(MF);
1291 for (const auto &Info : CSI) {
1292 int FI = Info.getFrameIdx();
1293 if (!MFI.hasScalableStackID(FI))
1294 continue;
1295
1296 // Not all unwinders may know about SVE registers, so assume the lowest
1297 // common denominator.
1298 assert(!Info.isSpilledToReg() && "Spilling to registers not implemented");
1299 MCRegister Reg = Info.getReg();
1300 if (!RegInfo.regNeedsCFI(Reg, Reg))
1301 continue;
1302
1303 StackOffset Offset =
1304 StackOffset::getScalable(MFI.getObjectOffset(FI)) -
1305 StackOffset::getFixed(AFI->getCalleeSavedStackSize(MFI));
1306
1307 // The scalable vectors are below (lower address) the scalable predicates
1308 // with split SVE objects, so we must subtract the size of the predicates.
1310 MFI.getStackID(FI) == TargetStackID::ScalableVector)
1311 Offset -= PPRStackSize;
1312
1313 CFIBuilder.insertCFIInst(
1314 createCFAOffset(RegInfo, Reg, Offset, IncomingVGOffsetFromDefCFA));
1315 }
1316}
1317
1319 switch (MI.getOpcode()) {
1320 default:
1321 return false;
1322 case AArch64::CATCHRET:
1323 case AArch64::CLEANUPRET:
1324 return true;
1325 }
1326}
1327
1332 EmitCFI = AFI->needsAsyncDwarfUnwindInfo(MF);
1333 HomPrologEpilog = AFL.homogeneousPrologEpilog(MF, &MBB);
1334 SEHEpilogueStartI = MBB.end();
1335}
1336
1337void AArch64EpilogueEmitter::moveSPBelowFP(MachineBasicBlock::iterator MBBI,
1339 // Other combinations could be supported, but are not currently needed.
1340 assert(Offset.getScalable() < 0 && Offset.getFixed() <= 0 &&
1341 "expected negative offset (with optional fixed portion)");
1342 Register Base = AArch64::FP;
1343 if (int64_t FixedOffset = Offset.getFixed()) {
1344 // If we have a negative fixed offset, we need to first subtract it in a
1345 // temporary register first (to avoid briefly deallocating the scalable
1346 // portion of the offset).
1347 Base = MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
1348 emitFrameOffset(MBB, MBBI, DL, Base, AArch64::FP,
1349 StackOffset::getFixed(FixedOffset), TII,
1351 }
1352 emitFrameOffset(MBB, MBBI, DL, AArch64::SP, Base,
1353 StackOffset::getScalable(Offset.getScalable()), TII,
1355}
1356
1358 MachineBasicBlock::iterator EpilogueEndI = MBB.getLastNonDebugInstr();
1359 if (MBB.end() != EpilogueEndI) {
1360 DL = EpilogueEndI->getDebugLoc();
1361 IsFunclet = isFuncletReturnInstr(*EpilogueEndI);
1362 }
1363
1364 int64_t NumBytes =
1365 IsFunclet ? AFL.getWinEHFuncletFrameSize(MF) : MFI.getStackSize();
1366
1367 // All calls are tail calls in GHC calling conv, and functions have no
1368 // prologue/epilogue.
1369 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
1370 return;
1371
1372 // How much of the stack used by incoming arguments this function is expected
1373 // to restore in this particular epilogue.
1374 int64_t ArgumentStackToRestore = AFL.getArgumentStackToRestore(MF, MBB);
1375 bool IsWin64 = Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv(),
1376 MF.getFunction().isVarArg());
1377 unsigned FixedObject = AFL.getFixedObjectSize(MF, AFI, IsWin64, IsFunclet);
1378
1379 int64_t AfterCSRPopSize = ArgumentStackToRestore;
1380 auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
1381 // We cannot rely on the local stack size set in emitPrologue if the function
1382 // has funclets, as funclets have different local stack size requirements, and
1383 // the current value set in emitPrologue may be that of the containing
1384 // function.
1385 if (MF.hasEHFunclets())
1386 AFI->setLocalStackSize(NumBytes - PrologueSaveSize);
1387
1388 if (HomPrologEpilog) {
1390 auto FirstHomogenousEpilogI = MBB.getFirstTerminator();
1391 if (FirstHomogenousEpilogI != MBB.begin()) {
1392 auto HomogeneousEpilog = std::prev(FirstHomogenousEpilogI);
1393 if (HomogeneousEpilog->getOpcode() == AArch64::HOM_Epilog)
1394 FirstHomogenousEpilogI = HomogeneousEpilog;
1395 }
1396
1397 // Adjust local stack
1398 emitFrameOffset(MBB, FirstHomogenousEpilogI, DL, AArch64::SP, AArch64::SP,
1399 StackOffset::getFixed(AFI->getLocalStackSize()), TII,
1401
1402 // SP has been already adjusted while restoring callee save regs.
1403 // We've bailed-out the case with adjusting SP for arguments.
1404 assert(AfterCSRPopSize == 0);
1405 return;
1406 }
1407
1408 bool CombineSPBump = shouldCombineCSRLocalStackBump(NumBytes);
1409
1410 unsigned ProloguePopSize = PrologueSaveSize;
1412 // With CalleeSavesAboveFrameRecord ProloguePopSize is the amount of stack
1413 // that needs to be popped until we reach the start of the SVE save area.
1414 // The "FixedObject" stack occurs after the SVE area and must be popped
1415 // later.
1416 ProloguePopSize -= FixedObject;
1417 AfterCSRPopSize += FixedObject;
1418 }
1419
1420 // Assume we can't combine the last pop with the sp restore.
1421 if (!CombineSPBump && ProloguePopSize != 0) {
1422 MachineBasicBlock::iterator Pop = std::prev(MBB.getFirstTerminator());
1423 while (Pop->getOpcode() == TargetOpcode::CFI_INSTRUCTION ||
1424 AArch64InstrInfo::isSEHInstruction(*Pop) ||
1427 Pop = std::prev(Pop);
1428 // Converting the last ldp to a post-index ldp is valid only if the last
1429 // ldp's offset is 0.
1430 const MachineOperand &OffsetOp = Pop->getOperand(Pop->getNumOperands() - 1);
1431 // If the offset is 0 and the AfterCSR pop is not actually trying to
1432 // allocate more stack for arguments (in space that an untimely interrupt
1433 // may clobber), convert it to a post-index ldp.
1434 if (OffsetOp.getImm() == 0 && AfterCSRPopSize >= 0) {
1436 Pop, DL, ProloguePopSize, EmitCFI, MachineInstr::FrameDestroy,
1437 ProloguePopSize);
1439 MachineBasicBlock::iterator AfterLastPop = std::next(Pop);
1440 if (AArch64InstrInfo::isSEHInstruction(*AfterLastPop))
1441 ++AfterLastPop;
1442 // If not, and CalleeSavesAboveFrameRecord is enabled, deallocate
1443 // callee-save non-SVE registers to move the stack pointer to the start of
1444 // the SVE area.
1445 emitFrameOffset(MBB, AfterLastPop, DL, AArch64::SP, AArch64::SP,
1446 StackOffset::getFixed(ProloguePopSize), TII,
1448 &HasWinCFI);
1449 } else {
1450 // Otherwise, make sure to emit an add after the last ldp.
1451 // We're doing this by transferring the size to be restored from the
1452 // adjustment *before* the CSR pops to the adjustment *after* the CSR
1453 // pops.
1454 AfterCSRPopSize += ProloguePopSize;
1455 }
1456 }
1457
1458 // Move past the restores of the callee-saved registers.
1459 // If we plan on combining the sp bump of the local stack size and the callee
1460 // save stack size, we might need to adjust the CSR save and restore offsets.
1461 MachineBasicBlock::iterator FirstGPRRestoreI = MBB.getFirstTerminator();
1462 MachineBasicBlock::iterator Begin = MBB.begin();
1463 while (FirstGPRRestoreI != Begin) {
1464 --FirstGPRRestoreI;
1465 if (!FirstGPRRestoreI->getFlag(MachineInstr::FrameDestroy) ||
1467 isPartOfSVECalleeSaves(FirstGPRRestoreI))) {
1468 ++FirstGPRRestoreI;
1469 break;
1470 } else if (CombineSPBump)
1471 fixupCalleeSaveRestoreStackOffset(*FirstGPRRestoreI,
1472 AFI->getLocalStackSize());
1473 }
1474
1475 if (NeedsWinCFI) {
1476 // Note that there are cases where we insert SEH opcodes in the
1477 // epilogue when we had no SEH opcodes in the prologue. For
1478 // example, when there is no stack frame but there are stack
1479 // arguments. Insert the SEH_EpilogStart and remove it later if it
1480 // we didn't emit any SEH opcodes to avoid generating WinCFI for
1481 // functions that don't need it.
1482 BuildMI(MBB, FirstGPRRestoreI, DL, TII->get(AArch64::SEH_EpilogStart))
1484 SEHEpilogueStartI = FirstGPRRestoreI;
1485 --SEHEpilogueStartI;
1486 }
1487
1488 // Determine the ranges of SVE callee-saves. This is done before emitting any
1489 // code at the end of the epilogue (for Swift async), which can get in the way
1490 // of finding SVE callee-saves with CalleeSavesAboveFrameRecord.
1491 auto [PPR, ZPR] = getSVEStackFrameSizes();
1492 auto [PPRRange, ZPRRange] = partitionSVECS(
1493 MBB,
1495 ? MBB.getFirstTerminator()
1496 : FirstGPRRestoreI,
1497 PPR.CalleeSavesSize, ZPR.CalleeSavesSize, /*IsEpilogue=*/true);
1498
1499 if (HasFP && AFI->hasSwiftAsyncContext())
1500 emitSwiftAsyncContextFramePointer(EpilogueEndI, DL);
1501
1502 // If there is a single SP update, insert it before the ret and we're done.
1503 if (CombineSPBump) {
1504 assert(!AFI->hasSVEStackSize() && "Cannot combine SP bump with SVE");
1505
1506 // When we are about to restore the CSRs, the CFA register is SP again.
1507 if (EmitCFI && HasFP)
1509 .buildDefCFA(AArch64::SP, NumBytes);
1510
1511 emitFrameOffset(MBB, MBB.getFirstTerminator(), DL, AArch64::SP, AArch64::SP,
1512 StackOffset::getFixed(NumBytes + AfterCSRPopSize), TII,
1514 EmitCFI, StackOffset::getFixed(NumBytes));
1515 return;
1516 }
1517
1518 NumBytes -= PrologueSaveSize;
1519 assert(NumBytes >= 0 && "Negative stack allocation size!?");
1520
1521 StackOffset SVECalleeSavesSize = ZPR.CalleeSavesSize + PPR.CalleeSavesSize;
1522 SVEStackAllocations SVEAllocs = getSVEStackAllocations({PPR, ZPR});
1523
1524 // Deallocate the SVE area.
1526 assert(!SVEAllocs.AfterPPRs &&
1527 "unexpected SVE allocs after PPRs with CalleeSavesAboveFrameRecord");
1528 // If the callee-save area is before FP, restoring the FP implicitly
1529 // deallocates non-callee-save SVE allocations. Otherwise, deallocate them
1530 // explicitly.
1531 if (!AFI->isStackRealigned() && !MFI.hasVarSizedObjects()) {
1532 emitFrameOffset(MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::SP,
1534 false, NeedsWinCFI, &HasWinCFI);
1535 }
1536
1537 // Deallocate callee-save SVE registers.
1538 emitFrameOffset(MBB, PPRRange.End, DL, AArch64::SP, AArch64::SP,
1540 false, NeedsWinCFI, &HasWinCFI);
1541 } else if (AFI->hasSVEStackSize()) {
1542 // If we have stack realignment or variable-sized objects we must use the FP
1543 // to restore SVE callee saves (as there is an unknown amount of
1544 // data/padding between the SP and SVE CS area).
1545 Register BaseForSVEDealloc =
1546 (AFI->isStackRealigned() || MFI.hasVarSizedObjects()) ? AArch64::FP
1547 : AArch64::SP;
1548 if (SVECalleeSavesSize && BaseForSVEDealloc == AArch64::FP) {
1549 if (ZPR.CalleeSavesSize || SVELayout != SVEStackLayout::Split) {
1550 // The offset from the frame-pointer to the start of the ZPR saves.
1551 StackOffset FPOffsetZPR =
1552 -SVECalleeSavesSize - PPR.LocalsSize -
1553 StackOffset::getFixed(AFI->getCalleeSaveBaseToFrameRecordOffset());
1554 // Deallocate the stack space space by moving the SP to the start of the
1555 // ZPR/PPR callee-save area.
1556 moveSPBelowFP(ZPRRange.Begin, FPOffsetZPR);
1557 }
1558 // With split SVE, the predicates are stored in a separate area above the
1559 // ZPR saves, so we must adjust the stack to the start of the PPRs.
1560 if (PPR.CalleeSavesSize && SVELayout == SVEStackLayout::Split) {
1561 // The offset from the frame-pointer to the start of the PPR saves.
1562 StackOffset FPOffsetPPR = -PPR.CalleeSavesSize;
1563 // Move to the start of the PPR area.
1564 assert(!FPOffsetPPR.getFixed() && "expected only scalable offset");
1565 emitFrameOffset(MBB, ZPRRange.End, DL, AArch64::SP, AArch64::FP,
1566 FPOffsetPPR, TII, MachineInstr::FrameDestroy);
1567 }
1568 } else if (BaseForSVEDealloc == AArch64::SP) {
1569 auto NonSVELocals = StackOffset::getFixed(NumBytes);
1570 auto CFAOffset = NonSVELocals + StackOffset::getFixed(PrologueSaveSize) +
1571 SVEAllocs.totalSize();
1572
1573 if (SVECalleeSavesSize || SVELayout == SVEStackLayout::Split) {
1574 // Deallocate non-SVE locals now. This is needed to reach the SVE callee
1575 // saves, but may also allow combining stack hazard bumps for split SVE.
1576 SVEAllocs.AfterZPRs += NonSVELocals;
1577 NumBytes -= NonSVELocals.getFixed();
1578 }
1579 // To deallocate the SVE stack adjust by the allocations in reverse.
1580 emitFrameOffset(MBB, ZPRRange.Begin, DL, AArch64::SP, AArch64::SP,
1582 false, NeedsWinCFI, &HasWinCFI, EmitCFI && !HasFP,
1583 CFAOffset);
1584 CFAOffset -= SVEAllocs.AfterZPRs;
1585 assert(PPRRange.Begin == ZPRRange.End &&
1586 "Expected PPR restores after ZPR");
1587 emitFrameOffset(MBB, PPRRange.Begin, DL, AArch64::SP, AArch64::SP,
1589 false, NeedsWinCFI, &HasWinCFI, EmitCFI && !HasFP,
1590 CFAOffset);
1591 CFAOffset -= SVEAllocs.AfterPPRs;
1592 emitFrameOffset(MBB, PPRRange.End, DL, AArch64::SP, AArch64::SP,
1594 false, NeedsWinCFI, &HasWinCFI, EmitCFI && !HasFP,
1595 CFAOffset);
1596 }
1597
1598 if (EmitCFI)
1599 emitCalleeSavedSVERestores(
1600 SVELayout == SVEStackLayout::Split ? ZPRRange.End : PPRRange.End);
1601 }
1602
1603 if (!HasFP) {
1604 bool RedZone = AFL.canUseRedZone(MF);
1605 // If this was a redzone leaf function, we don't need to restore the
1606 // stack pointer (but we may need to pop stack args for fastcc).
1607 if (RedZone && AfterCSRPopSize == 0)
1608 return;
1609
1610 // Pop the local variables off the stack. If there are no callee-saved
1611 // registers, it means we are actually positioned at the terminator and can
1612 // combine stack increment for the locals and the stack increment for
1613 // callee-popped arguments into (possibly) a single instruction and be done.
1614 bool NoCalleeSaveRestore = PrologueSaveSize == 0;
1615 int64_t StackRestoreBytes = RedZone ? 0 : NumBytes;
1616 if (NoCalleeSaveRestore)
1617 StackRestoreBytes += AfterCSRPopSize;
1618
1620 MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::SP,
1621 StackOffset::getFixed(StackRestoreBytes), TII,
1623 StackOffset::getFixed((RedZone ? 0 : NumBytes) + PrologueSaveSize));
1624
1625 // If we were able to combine the local stack pop with the argument pop,
1626 // then we're done.
1627 if (NoCalleeSaveRestore || AfterCSRPopSize == 0)
1628 return;
1629
1630 NumBytes = 0;
1631 }
1632
1633 // Restore the original stack pointer.
1634 // FIXME: Rather than doing the math here, we should instead just use
1635 // non-post-indexed loads for the restores if we aren't actually going to
1636 // be able to save any instructions.
1637 if (!IsFunclet && (MFI.hasVarSizedObjects() || AFI->isStackRealigned())) {
1639 MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::FP,
1640 StackOffset::getFixed(-AFI->getCalleeSaveBaseToFrameRecordOffset()),
1642 } else if (NumBytes)
1643 emitFrameOffset(MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::SP,
1644 StackOffset::getFixed(NumBytes), TII,
1646
1647 // When we are about to restore the CSRs, the CFA register is SP again.
1648 if (EmitCFI && HasFP)
1650 .buildDefCFA(AArch64::SP, PrologueSaveSize);
1651
1652 // This must be placed after the callee-save restore code because that code
1653 // assumes the SP is at the same location as it was after the callee-save save
1654 // code in the prologue.
1655 if (AfterCSRPopSize) {
1656 assert(AfterCSRPopSize > 0 && "attempting to reallocate arg stack that an "
1657 "interrupt may have clobbered");
1658
1660 MBB, MBB.getFirstTerminator(), DL, AArch64::SP, AArch64::SP,
1662 false, NeedsWinCFI, &HasWinCFI, EmitCFI,
1663 StackOffset::getFixed(AfterCSRPopSize - ArgumentStackToRestore));
1664 }
1665}
1666
1667bool AArch64EpilogueEmitter::shouldCombineCSRLocalStackBump(
1668 uint64_t StackBumpBytes) const {
1670 StackBumpBytes))
1671 return false;
1672 if (MBB.empty())
1673 return true;
1674
1675 // Disable combined SP bump if the last instruction is an MTE tag store. It
1676 // is almost always better to merge SP adjustment into those instructions.
1677 MachineBasicBlock::iterator LastI = MBB.getFirstTerminator();
1678 MachineBasicBlock::iterator Begin = MBB.begin();
1679 while (LastI != Begin) {
1680 --LastI;
1681 if (LastI->isTransient())
1682 continue;
1683 if (!LastI->getFlag(MachineInstr::FrameDestroy))
1684 break;
1685 }
1686 switch (LastI->getOpcode()) {
1687 case AArch64::STGloop:
1688 case AArch64::STZGloop:
1689 case AArch64::STGi:
1690 case AArch64::STZGi:
1691 case AArch64::ST2Gi:
1692 case AArch64::STZ2Gi:
1693 return false;
1694 default:
1695 return true;
1696 }
1697 llvm_unreachable("unreachable");
1698}
1699
1700void AArch64EpilogueEmitter::emitSwiftAsyncContextFramePointer(
1702 switch (MF.getTarget().Options.SwiftAsyncFramePointer) {
1704 // Avoid the reload as it is GOT relative, and instead fall back to the
1705 // hardcoded value below. This allows a mismatch between the OS and
1706 // application without immediately terminating on the difference.
1707 [[fallthrough]];
1709 // We need to reset FP to its untagged state on return. Bit 60 is
1710 // currently used to show the presence of an extended frame.
1711
1712 // BIC x29, x29, #0x1000_0000_0000_0000
1713 BuildMI(MBB, MBB.getFirstTerminator(), DL, TII->get(AArch64::ANDXri),
1714 AArch64::FP)
1715 .addUse(AArch64::FP)
1716 .addImm(0x10fe)
1718 if (NeedsWinCFI) {
1719 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1721 HasWinCFI = true;
1722 }
1723 break;
1724
1726 break;
1727 }
1728}
1729
1730void AArch64EpilogueEmitter::emitShadowCallStackEpilogue(
1732 // Shadow call stack epilog: ldr x30, [x18, #-8]!
1733 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXpre))
1734 .addReg(AArch64::X18, RegState::Define)
1735 .addReg(AArch64::LR, RegState::Define)
1736 .addReg(AArch64::X18)
1737 .addImm(-8)
1739
1740 if (NeedsWinCFI)
1741 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1743
1744 if (AFI->needsAsyncDwarfUnwindInfo(MF))
1745 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameDestroy)
1746 .buildRestore(AArch64::X18);
1747}
1748
1749void AArch64EpilogueEmitter::emitCalleeSavedRestores(
1750 MachineBasicBlock::iterator MBBI, bool SVE) const {
1751 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
1752 if (CSI.empty())
1753 return;
1754
1755 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameDestroy);
1756
1757 for (const auto &Info : CSI) {
1758 if (SVE != MFI.hasScalableStackID(Info.getFrameIdx()))
1759 continue;
1760
1761 MCRegister Reg = Info.getReg();
1762 if (SVE && !RegInfo.regNeedsCFI(Reg, Reg))
1763 continue;
1764
1765 CFIBuilder.buildRestore(Info.getReg());
1766 }
1767}
1768
1769void AArch64EpilogueEmitter::finalizeEpilogue() const {
1770 if (AFI->needsShadowCallStackPrologueEpilogue(MF)) {
1771 emitShadowCallStackEpilogue(MBB.getFirstTerminator(), DL);
1773 }
1774 if (EmitCFI)
1775 emitCalleeSavedGPRRestores(MBB.getFirstTerminator());
1776 if (AFI->shouldSignReturnAddress(MF)) {
1777 // If pac-ret+leaf is in effect, PAUTH_EPILOGUE pseudo instructions
1778 // are inserted by emitPacRetPlusLeafHardening().
1779 if (!AFL.shouldSignReturnAddressEverywhere(MF))
1780 TII->createPauthEpilogueInstr(MBB, DL);
1781 // AArch64PointerAuth pass will insert SEH_PACSignLR
1783 }
1784 if (HasWinCFI) {
1785 BuildMI(MBB, MBB.getFirstTerminator(), DL, TII->get(AArch64::SEH_EpilogEnd))
1787 if (!MF.hasWinCFI())
1788 MF.setHasWinCFI(true);
1789 }
1790 if (NeedsWinCFI) {
1791 assert(SEHEpilogueStartI != MBB.end());
1792 if (!HasWinCFI)
1793 MBB.erase(SEHEpilogueStartI);
1794 }
1795}
1796
1797} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file contains the declaration of the AArch64PrologueEmitter and AArch64EpilogueEmitter classes,...
uint64_t uint64_t
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
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:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
if(PassOpts->AAPipeline)
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
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
SVEStackAllocations getSVEStackAllocations(SVEFrameSizes 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:126
A set of physical registers with utility functions to track liveness when walking backward/forward th...
MachineInstrBundleIterator< MachineInstr > iterator
Align getMaxAlign() const
Return alignment of this function's frame.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
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 & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
@ MOVolatile
The memory access is volatile.
@ MOLoad
The memory access reads data.
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
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
Wrapper class representing virtual and physical registers.
Definition Register.h:20
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 getFixed(int64_t Fixed)
Definition TypeSize.h:40
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
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 Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
Definition CallingConv.h:50
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
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.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
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)
static bool isPartOfSVECalleeSaves(MachineBasicBlock::iterator I)
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:1762
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.
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:163
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
static bool isPartOfPPRCalleeSaves(MachineBasicBlock::iterator I)
@ 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.
static SVEPartitions partitionSVECS(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, StackOffset PPRCalleeSavesSize, StackOffset ZPRCalleeSavesSize, bool IsEpilogue)
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:1788
static bool isPartOfZPRCalleeSaves(MachineBasicBlock::iterator I)
static int64_t upperBound(StackOffset Size)
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:267
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
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:82
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
MachineBasicBlock::iterator End
struct llvm::SVEPartitions::@327166152017175235362202041204223104077330276266 ZPR
struct llvm::SVEPartitions::@327166152017175235362202041204223104077330276266 PPR
MachineBasicBlock::iterator Begin