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 "AArch64PointerAuth.h"
13#include "AArch64Subtarget.h"
15#include "llvm/ADT/Statistic.h"
18#include "llvm/MC/MCContext.h"
19
20#define DEBUG_TYPE "frame-info"
21
22STATISTIC(NumRedZoneFunctions, "Number of functions using red zone");
23
24namespace llvm {
25
26static bool matchLibcall(const TargetLowering &TLI, const MachineOperand &MO,
27 RTLIB::Libcall LC) {
28 return MO.isSymbol() &&
29 StringRef(TLI.getLibcallName(LC)) == MO.getSymbolName();
30}
31
33 return AFI->hasStreamingModeChanges() &&
34 !MF.getSubtarget<AArch64Subtarget>().hasSVE();
35}
36
39 unsigned Opc = MBBI->getOpcode();
40 if (Opc == AArch64::CNTD_XPiI)
41 return true;
42
43 if (!requiresGetVGCall())
44 return false;
45
46 if (Opc == AArch64::BL)
47 return matchLibcall(TLI, MBBI->getOperand(0), RTLIB::SMEABI_GET_CURRENT_VG);
48
49 return Opc == TargetOpcode::COPY;
50}
51
52// Convenience function to determine whether I is part of the ZPR callee saves.
54 switch (I->getOpcode()) {
55 default:
56 return false;
57 case AArch64::LD1B_2Z_IMM:
58 case AArch64::ST1B_2Z_IMM:
59 case AArch64::LD1B_4Z_IMM:
60 case AArch64::ST1B_4Z_IMM:
61 case AArch64::STR_ZXI:
62 case AArch64::LDR_ZXI:
63 case AArch64::PTRUE_C_B:
64 return I->getFlag(MachineInstr::FrameSetup) ||
66 case AArch64::SEH_SaveZReg:
67 return true;
68 }
69}
70
71// Convenience function to determine whether I is part of the PPR callee saves.
73 switch (I->getOpcode()) {
74 default:
75 return false;
76 case AArch64::STR_PXI:
77 case AArch64::LDR_PXI:
78 return I->getFlag(MachineInstr::FrameSetup) ||
80 case AArch64::SEH_SavePReg:
81 return true;
82 }
83}
84
85// Convenience function to determine whether I is part of the SVE callee saves.
89
93 : MF(MF), MBB(MBB), MFI(MF.getFrameInfo()),
94 Subtarget(MF.getSubtarget<AArch64Subtarget>()), AFL(AFL),
95 RegInfo(*Subtarget.getRegisterInfo()) {
96 TII = Subtarget.getInstrInfo();
97 AFI = MF.getInfo<AArch64FunctionInfo>();
98
99 HasFP = AFL.hasFP(MF);
100 NeedsWinCFI = MF.needsWinCFI();
101
102 if (AFL.hasSVECalleeSavesAboveFrameRecord(MF)) {
103 if (AFI->hasStackHazardSlotIndex())
104 reportFatalUsageError("SME hazard padding is not supported on Windows");
105 SVELayout = SVEStackLayout::CalleeSavesAboveFrameRecord;
106 } else if (AFI->hasSplitSVEObjects()) {
107 SVELayout = SVEStackLayout::Split;
108 }
109}
110
113 MachineBasicBlock::iterator MBBI, const DebugLoc &DL, int CSStackSizeInc,
114 bool EmitCFI, MachineInstr::MIFlag FrameFlag, int CFAOffset) const {
115 unsigned NewOpc;
116
117 // If the function contains streaming mode changes, we expect instructions
118 // to calculate the value of VG before spilling. Move past these instructions
119 // if necessary.
120 if (AFL.requiresSaveVG(MF)) {
121 auto &TLI = *Subtarget.getTargetLowering();
122 while (isVGInstruction(MBBI, TLI))
123 ++MBBI;
124 }
125
126 switch (MBBI->getOpcode()) {
127 default:
128 llvm_unreachable("Unexpected callee-save save/restore opcode!");
129 case AArch64::STPXi:
130 NewOpc = AArch64::STPXpre;
131 break;
132 case AArch64::STPDi:
133 NewOpc = AArch64::STPDpre;
134 break;
135 case AArch64::STPQi:
136 NewOpc = AArch64::STPQpre;
137 break;
138 case AArch64::STRXui:
139 NewOpc = AArch64::STRXpre;
140 break;
141 case AArch64::STRDui:
142 NewOpc = AArch64::STRDpre;
143 break;
144 case AArch64::STRQui:
145 NewOpc = AArch64::STRQpre;
146 break;
147 case AArch64::LDPXi:
148 NewOpc = AArch64::LDPXpost;
149 break;
150 case AArch64::LDPDi:
151 NewOpc = AArch64::LDPDpost;
152 break;
153 case AArch64::LDPQi:
154 NewOpc = AArch64::LDPQpost;
155 break;
156 case AArch64::LDRXui:
157 NewOpc = AArch64::LDRXpost;
158 break;
159 case AArch64::LDRDui:
160 NewOpc = AArch64::LDRDpost;
161 break;
162 case AArch64::LDRQui:
163 NewOpc = AArch64::LDRQpost;
164 break;
165 }
166 TypeSize Scale = TypeSize::getFixed(1), Width = TypeSize::getFixed(0);
167 int64_t MinOffset, MaxOffset;
168 bool Success = TII->getMemOpInfo(NewOpc, Scale, Width, MinOffset, MaxOffset);
169 (void)Success;
170 assert(Success && "unknown load/store opcode");
171
172 // If the first store isn't right where we want SP then we can't fold the
173 // update in so create a normal arithmetic instruction instead.
174 //
175 // On Windows, some register pairs involving LR can't be folded because
176 // there isn't a corresponding unwind opcode.
177 if (MBBI->getOperand(MBBI->getNumOperands() - 1).getImm() != 0 ||
178 CSStackSizeInc < MinOffset * (int64_t)Scale.getFixedValue() ||
179 CSStackSizeInc > MaxOffset * (int64_t)Scale.getFixedValue() ||
180 (NeedsWinCFI &&
181 (NewOpc == AArch64::LDPXpost || NewOpc == AArch64::STPXpre) &&
182 RegInfo.getEncodingValue(MBBI->getOperand(0).getReg()) + 1 !=
183 RegInfo.getEncodingValue(MBBI->getOperand(1).getReg()))) {
184 // If we are destroying the frame, make sure we add the increment after the
185 // last frame operation.
186 if (FrameFlag == MachineInstr::FrameDestroy) {
187 ++MBBI;
188 // Also skip the SEH instruction, if needed
189 if (NeedsWinCFI && AArch64InstrInfo::isSEHInstruction(*MBBI))
190 ++MBBI;
191 }
192 emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP,
193 StackOffset::getFixed(CSStackSizeInc), TII, FrameFlag,
194 false, NeedsWinCFI, &HasWinCFI, EmitCFI,
195 StackOffset::getFixed(CFAOffset));
196
197 return std::prev(MBBI);
198 }
199
200 // Get rid of the SEH code associated with the old instruction.
201 if (NeedsWinCFI) {
202 auto SEH = std::next(MBBI);
203 if (AArch64InstrInfo::isSEHInstruction(*SEH))
204 SEH->eraseFromParent();
205 }
206
207 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(NewOpc));
208 MIB.addReg(AArch64::SP, RegState::Define);
209
210 // Copy all operands other than the immediate offset.
211 unsigned OpndIdx = 0;
212 for (unsigned OpndEnd = MBBI->getNumOperands() - 1; OpndIdx < OpndEnd;
213 ++OpndIdx)
214 MIB.add(MBBI->getOperand(OpndIdx));
215
216 assert(MBBI->getOperand(OpndIdx).getImm() == 0 &&
217 "Unexpected immediate offset in first/last callee-save save/restore "
218 "instruction!");
219 assert(MBBI->getOperand(OpndIdx - 1).getReg() == AArch64::SP &&
220 "Unexpected base register in callee-save save/restore instruction!");
221 assert(CSStackSizeInc % Scale == 0);
222 MIB.addImm(CSStackSizeInc / (int)Scale);
223
224 MIB.setMIFlags(MBBI->getFlags());
225 MIB.setMemRefs(MBBI->memoperands());
226
227 // Generate a new SEH code that corresponds to the new instruction.
228 if (NeedsWinCFI) {
229 HasWinCFI = true;
230 AFL.insertSEH(*MIB, *TII, FrameFlag);
231 }
232
233 if (EmitCFI)
234 CFIInstBuilder(MBB, MBBI, FrameFlag)
235 .buildDefCFAOffset(CFAOffset - CSStackSizeInc);
236
237 return std::prev(MBB.erase(MBBI));
238}
239
240// Fix up the SEH opcode associated with the save/restore instruction.
242 unsigned LocalStackSize) {
243 MachineOperand *ImmOpnd = nullptr;
244 unsigned ImmIdx = MBBI->getNumOperands() - 1;
245 switch (MBBI->getOpcode()) {
246 default:
247 llvm_unreachable("Fix the offset in the SEH instruction");
248 case AArch64::SEH_SaveFPLR:
249 case AArch64::SEH_SaveRegP:
250 case AArch64::SEH_SaveReg:
251 case AArch64::SEH_SaveFRegP:
252 case AArch64::SEH_SaveFReg:
253 case AArch64::SEH_SaveAnyRegI:
254 case AArch64::SEH_SaveAnyRegIP:
255 case AArch64::SEH_SaveAnyRegQP:
256 case AArch64::SEH_SaveAnyRegQPX:
257 ImmOpnd = &MBBI->getOperand(ImmIdx);
258 break;
259 }
260 if (ImmOpnd)
261 ImmOpnd->setImm(ImmOpnd->getImm() + LocalStackSize);
262}
263
265 MachineInstr &MI, uint64_t LocalStackSize) const {
266 if (AArch64InstrInfo::isSEHInstruction(MI))
267 return;
268
269 unsigned Opc = MI.getOpcode();
270 unsigned Scale;
271 switch (Opc) {
272 case AArch64::STPXi:
273 case AArch64::STRXui:
274 case AArch64::STPDi:
275 case AArch64::STRDui:
276 case AArch64::LDPXi:
277 case AArch64::LDRXui:
278 case AArch64::LDPDi:
279 case AArch64::LDRDui:
280 Scale = 8;
281 break;
282 case AArch64::STPQi:
283 case AArch64::STRQui:
284 case AArch64::LDPQi:
285 case AArch64::LDRQui:
286 Scale = 16;
287 break;
288 default:
289 llvm_unreachable("Unexpected callee-save save/restore opcode!");
290 }
291
292 unsigned OffsetIdx = MI.getNumExplicitOperands() - 1;
293 assert(MI.getOperand(OffsetIdx - 1).getReg() == AArch64::SP &&
294 "Unexpected base register in callee-save save/restore instruction!");
295 // Last operand is immediate offset that needs fixing.
296 MachineOperand &OffsetOpnd = MI.getOperand(OffsetIdx);
297 // All generated opcodes have scaled offsets.
298 assert(LocalStackSize % Scale == 0);
299 OffsetOpnd.setImm(OffsetOpnd.getImm() + LocalStackSize / Scale);
300
301 if (NeedsWinCFI) {
302 HasWinCFI = true;
303 auto MBBI = std::next(MachineBasicBlock::iterator(MI));
304 assert(MBBI != MI.getParent()->end() && "Expecting a valid instruction");
305 assert(AArch64InstrInfo::isSEHInstruction(*MBBI) &&
306 "Expecting a SEH instruction");
307 fixupSEHOpcode(MBBI, LocalStackSize);
308 }
309}
310
312 uint64_t StackBumpBytes) const {
313 if (AFL.homogeneousPrologEpilog(MF))
314 return false;
315
316 if (AFI->getLocalStackSize() == 0)
317 return false;
318
319 // For WinCFI, if optimizing for size, prefer to not combine the stack bump
320 // (to force a stp with predecrement) to match the packed unwind format,
321 // provided that there actually are any callee saved registers to merge the
322 // decrement with.
323 //
324 // Note that for certain paired saves, like "x19, lr", we can't actually
325 // emit an predecrement stp, but packed unwind still expects a separate stack
326 // adjustment.
327 //
328 // This is potentially marginally slower, but allows using the packed
329 // unwind format for functions that both have a local area and callee saved
330 // registers. Using the packed unwind format notably reduces the size of
331 // the unwind info.
332 if (MF.needsWinCFI() && AFI->getCalleeSavedStackSize() > 0 &&
333 MF.getFunction().hasOptSize())
334 return false;
335
336 // 512 is the maximum immediate for stp/ldp that will be used for
337 // callee-save save/restores
338 if (StackBumpBytes >= 512 ||
339 AFL.windowsRequiresStackProbe(MF, StackBumpBytes))
340 return false;
341
342 if (MFI.hasVarSizedObjects())
343 return false;
344
345 if (RegInfo.hasStackRealignment(MF))
346 return false;
347
348 // This isn't strictly necessary, but it simplifies things a bit since the
349 // current RedZone handling code assumes the SP is adjusted by the
350 // callee-save save/restore code.
351 if (AFL.canUseRedZone(MF))
352 return false;
353
354 // When there is an SVE area on the stack, always allocate the
355 // callee-saves and spills/locals separately.
356 if (AFI->hasSVEStackSize())
357 return false;
358
359 return true;
360}
361
363 StackOffset PPRCalleeSavesSize =
364 StackOffset::getScalable(AFI->getPPRCalleeSavedStackSize());
365 StackOffset ZPRCalleeSavesSize =
366 StackOffset::getScalable(AFI->getZPRCalleeSavedStackSize());
367 StackOffset PPRLocalsSize = AFL.getPPRStackSize(MF) - PPRCalleeSavesSize;
368 StackOffset ZPRLocalsSize = AFL.getZPRStackSize(MF) - ZPRCalleeSavesSize;
370 return {{PPRCalleeSavesSize, PPRLocalsSize},
371 {ZPRCalleeSavesSize, ZPRLocalsSize}};
372 // For simplicity, attribute all locals to ZPRs when split SVE is disabled.
373 return {{PPRCalleeSavesSize, StackOffset{}},
374 {ZPRCalleeSavesSize, PPRLocalsSize + ZPRLocalsSize}};
375}
376
378 SVEFrameSizes const &SVE) {
379 StackOffset AfterZPRs = SVE.ZPR.LocalsSize;
380 StackOffset BeforePPRs = SVE.ZPR.CalleeSavesSize + SVE.PPR.CalleeSavesSize;
381 StackOffset AfterPPRs = {};
383 BeforePPRs = SVE.PPR.CalleeSavesSize;
384 // If there are no ZPR CSRs, place all local allocations after the ZPRs.
385 if (SVE.ZPR.CalleeSavesSize)
386 AfterPPRs += SVE.PPR.LocalsSize + SVE.ZPR.CalleeSavesSize;
387 else
388 AfterZPRs += SVE.PPR.LocalsSize; // Group allocation of locals.
389 }
390 return {BeforePPRs, AfterPPRs, AfterZPRs};
391}
392
398
401 StackOffset PPRCalleeSavesSize,
402 StackOffset ZPRCalleeSavesSize,
403 bool IsEpilogue) {
406 IsEpilogue ? MBB.begin() : MBB.getFirstTerminator();
407 auto AdjustI = [&](auto MBBI) { return IsEpilogue ? std::prev(MBBI) : MBBI; };
408 // Process the SVE CS to find the starts/ends of the ZPR and PPR areas.
409 if (PPRCalleeSavesSize) {
410 PPRsI = AdjustI(PPRsI);
411 assert(isPartOfPPRCalleeSaves(*PPRsI) && "Unexpected instruction");
412 while (PPRsI != End && isPartOfPPRCalleeSaves(AdjustI(PPRsI)))
413 IsEpilogue ? (--PPRsI) : (++PPRsI);
414 }
415 MachineBasicBlock::iterator ZPRsI = PPRsI;
416 if (ZPRCalleeSavesSize) {
417 ZPRsI = AdjustI(ZPRsI);
418 assert(isPartOfZPRCalleeSaves(*ZPRsI) && "Unexpected instruction");
419 while (ZPRsI != End && isPartOfZPRCalleeSaves(AdjustI(ZPRsI)))
420 IsEpilogue ? (--ZPRsI) : (++ZPRsI);
421 }
422 if (IsEpilogue)
423 return {{PPRsI, MBBI}, {ZPRsI, PPRsI}};
424 return {{MBBI, PPRsI}, {PPRsI, ZPRsI}};
425}
426
431 EmitCFI = AFI->needsDwarfUnwindInfo(MF);
432 EmitAsyncCFI = AFI->needsAsyncDwarfUnwindInfo(MF);
433 IsFunclet = MBB.isEHFuncletEntry();
434 HomPrologEpilog = AFL.homogeneousPrologEpilog(MF);
435
436#ifndef NDEBUG
437 collectBlockLiveins();
438#endif
439}
440
441#ifndef NDEBUG
442/// Collect live registers from the end of \p MI's parent up to (including) \p
443/// MI in \p LiveRegs.
446
447 MachineBasicBlock &MBB = *MI.getParent();
448 LiveRegs.addLiveOuts(MBB);
449 for (const MachineInstr &MI :
450 reverse(make_range(MI.getIterator(), MBB.instr_end())))
451 LiveRegs.stepBackward(MI);
452}
453
454void AArch64PrologueEmitter::collectBlockLiveins() {
455 // Collect live register from the end of MBB up to the start of the existing
456 // frame setup instructions.
457 PrologueEndI = MBB.begin();
458 while (PrologueEndI != MBB.end() &&
459 PrologueEndI->getFlag(MachineInstr::FrameSetup))
460 ++PrologueEndI;
461
462 if (PrologueEndI != MBB.end()) {
463 getLivePhysRegsUpTo(*PrologueEndI, RegInfo, LiveRegs);
464 // Ignore registers used for stack management for now.
465 LiveRegs.removeReg(AArch64::SP);
466 LiveRegs.removeReg(AArch64::X19);
467 LiveRegs.removeReg(AArch64::FP);
468 LiveRegs.removeReg(AArch64::LR);
469
470 // X0 will be clobbered by a call to __arm_get_current_vg in the prologue.
471 // This is necessary to spill VG if required where SVE is unavailable, but
472 // X0 is preserved around this call.
473 if (requiresGetVGCall())
474 LiveRegs.removeReg(AArch64::X0);
475 }
476}
477
478void AArch64PrologueEmitter::verifyPrologueClobbers() const {
479 if (PrologueEndI == MBB.end())
480 return;
481 // Check if any of the newly instructions clobber any of the live registers.
482 for (MachineInstr &MI :
483 make_range(MBB.instr_begin(), PrologueEndI->getIterator())) {
484 for (auto &Op : MI.operands())
485 if (Op.isReg() && Op.isDef())
486 assert(!LiveRegs.contains(Op.getReg()) &&
487 "live register clobbered by inserted prologue instructions");
488 }
489}
490#endif
491
492void AArch64PrologueEmitter::determineLocalsStackSize(
493 uint64_t StackSize, uint64_t PrologueSaveSize) {
494 AFI->setLocalStackSize(StackSize - PrologueSaveSize);
495 CombineSPBump = shouldCombineCSRLocalStackBump(StackSize);
496}
497
498// Return the maximum possible number of bytes for `Size` due to the
499// architectural limit on the size of a SVE register.
500static int64_t upperBound(StackOffset Size) {
501 static const int64_t MAX_BYTES_PER_SCALABLE_BYTE = 16;
502 return Size.getScalable() * MAX_BYTES_PER_SCALABLE_BYTE + Size.getFixed();
503}
504
505void AArch64PrologueEmitter::allocateStackSpace(
506 MachineBasicBlock::iterator MBBI, int64_t RealignmentPadding,
507 StackOffset AllocSize, bool EmitCFI, StackOffset InitialOffset,
508 bool FollowupAllocs) {
509
510 if (!AllocSize)
511 return;
512
513 DebugLoc DL;
514 const int64_t MaxAlign = MFI.getMaxAlign().value();
515 const uint64_t AndMask = ~(MaxAlign - 1);
516
518 Register TargetReg = RealignmentPadding
519 ? AFL.findScratchNonCalleeSaveRegister(&MBB)
520 : AArch64::SP;
521 // SUB Xd/SP, SP, AllocSize
522 emitFrameOffset(MBB, MBBI, DL, TargetReg, AArch64::SP, -AllocSize, TII,
524 EmitCFI, InitialOffset);
525
526 if (RealignmentPadding) {
527 // AND SP, X9, 0b11111...0000
528 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), AArch64::SP)
529 .addReg(TargetReg, RegState::Kill)
532 AFI->setStackRealigned(true);
533
534 // No need for SEH instructions here; if we're realigning the stack,
535 // we've set a frame pointer and already finished the SEH prologue.
537 }
538 return;
539 }
540
541 //
542 // Stack probing allocation.
543 //
544
545 // Fixed length allocation. If we don't need to re-align the stack and don't
546 // have SVE objects, we can use a more efficient sequence for stack probing.
547 if (AllocSize.getScalable() == 0 && RealignmentPadding == 0) {
548 Register ScratchReg = AFL.findScratchNonCalleeSaveRegister(&MBB);
549 assert(ScratchReg.isValid());
550 BuildMI(MBB, MBBI, DL, TII->get(AArch64::PROBED_STACKALLOC))
551 .addDef(ScratchReg)
552 .addImm(AllocSize.getFixed())
553 .addImm(InitialOffset.getFixed())
554 .addImm(InitialOffset.getScalable());
555 // The fixed allocation may leave unprobed bytes at the top of the
556 // stack. If we have subsequent allocation (e.g. if we have variable-sized
557 // objects), we need to issue an extra probe, so these allocations start in
558 // a known state.
559 if (FollowupAllocs) {
560 // LDR XZR, [SP]
561 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui))
562 .addDef(AArch64::XZR)
563 .addReg(AArch64::SP)
564 .addImm(0)
565 .addMemOperand(MF.getMachineMemOperand(
568 Align(8)))
570 }
571
572 return;
573 }
574
575 // Variable length allocation.
576
577 // If the (unknown) allocation size cannot exceed the probe size, decrement
578 // the stack pointer right away.
579 int64_t ProbeSize = AFI->getStackProbeSize();
580 if (upperBound(AllocSize) + RealignmentPadding <= ProbeSize) {
581 Register ScratchReg = RealignmentPadding
582 ? AFL.findScratchNonCalleeSaveRegister(&MBB)
583 : AArch64::SP;
584 assert(ScratchReg.isValid());
585 // SUB Xd, SP, AllocSize
586 emitFrameOffset(MBB, MBBI, DL, ScratchReg, AArch64::SP, -AllocSize, TII,
588 EmitCFI, InitialOffset);
589 if (RealignmentPadding) {
590 // AND SP, Xn, 0b11111...0000
591 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), AArch64::SP)
592 .addReg(ScratchReg, RegState::Kill)
595 AFI->setStackRealigned(true);
596 }
597 if (FollowupAllocs || upperBound(AllocSize) + RealignmentPadding >
599 // LDR XZR, [SP]
600 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui))
601 .addDef(AArch64::XZR)
602 .addReg(AArch64::SP)
603 .addImm(0)
604 .addMemOperand(MF.getMachineMemOperand(
607 Align(8)))
609 }
610 return;
611 }
612
613 // Emit a variable-length allocation probing loop.
614 // TODO: As an optimisation, the loop can be "unrolled" into a few parts,
615 // each of them guaranteed to adjust the stack by less than the probe size.
616 Register TargetReg = AFL.findScratchNonCalleeSaveRegister(&MBB);
617 assert(TargetReg.isValid());
618 // SUB Xd, SP, AllocSize
619 emitFrameOffset(MBB, MBBI, DL, TargetReg, AArch64::SP, -AllocSize, TII,
621 EmitCFI, InitialOffset);
622 if (RealignmentPadding) {
623 // AND Xn, Xn, 0b11111...0000
624 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), TargetReg)
625 .addReg(TargetReg, RegState::Kill)
628 }
629
630 BuildMI(MBB, MBBI, DL, TII->get(AArch64::PROBED_STACKALLOC_VAR))
631 .addReg(TargetReg);
632 if (EmitCFI) {
633 // Set the CFA register back to SP.
634 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
635 .buildDefCFARegister(AArch64::SP);
636 }
637 if (RealignmentPadding)
638 AFI->setStackRealigned(true);
639}
640
642 const MachineBasicBlock::iterator PrologueBeginI = MBB.begin();
643 const MachineBasicBlock::iterator EndI = MBB.end();
644
645 // At this point, we're going to decide whether or not the function uses a
646 // redzone. In most cases, the function doesn't have a redzone so let's
647 // assume that's false and set it to true in the case that there's a redzone.
648 AFI->setHasRedZone(false);
649
650 // Debug location must be unknown since the first debug location is used
651 // to determine the end of the prologue.
652 DebugLoc DL;
653
654 // In some cases, particularly with CallingConv::SwiftTail, it is possible to
655 // have a tail-call where the caller only needs to adjust the stack pointer in
656 // the epilogue. In this case, we still need to emit a SEH prologue sequence.
657 // See `seh-minimal-prologue-epilogue.ll` test cases.
658 if (int64_t ArgBytes = AFI->getArgumentStackToRestore()) {
660
661 // The callee pops its stack arguments, so once the unwinder has undone
662 // the prologue it must also pop them to recover the caller's SP. The
663 // opcodes before end_c don't correspond to instructions, so describe the
664 // pop there.
665 if (NeedsWinCFI && !IsFunclet) {
666 BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::SEH_StackAlloc))
667 .addImm(ArgBytes)
669 BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::SEH_EndC))
671 }
672 }
673
674 if (AFI->shouldSignReturnAddress(MF)) {
675 // If pac-ret+leaf is in effect, PAUTH_PROLOGUE pseudo instructions
676 // are inserted by emitPacRetPlusLeafHardening().
677 if (!AFL.shouldSignReturnAddressEverywhere(MF)) {
678 BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::PAUTH_PROLOGUE))
680 }
681 // AArch64PointerAuth pass will insert SEH_PACSignLR
683 }
684
685 if (AFI->needsShadowCallStackPrologueEpilogue(MF)) {
686 emitShadowCallStackPrologue(PrologueBeginI, DL);
688 }
689
690 if (EmitCFI && AFI->isMTETagged())
691 BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::EMITMTETAGGED))
693
694 // We signal the presence of a Swift extended frame to external tools by
695 // storing FP with 0b0001 in bits 63:60. In normal userland operation a simple
696 // ORR is sufficient, it is assumed a Swift kernel would initialize the TBI
697 // bits so that is still true.
698 if (HasFP && AFI->hasSwiftAsyncContext())
699 emitSwiftAsyncContextFramePointer(PrologueBeginI, DL);
700
701 // All calls are tail calls in GHC calling conv, and functions have no
702 // prologue/epilogue.
703 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
704 return;
705
706 // Set tagged base pointer to the requested stack slot. Ideally it should
707 // match SP value after prologue.
708 if (std::optional<int> TBPI = AFI->getTaggedBasePointerIndex())
709 AFI->setTaggedBasePointerOffset(-MFI.getObjectOffset(*TBPI));
710 else
711 AFI->setTaggedBasePointerOffset(MFI.getStackSize());
712
713 // getStackSize() includes all the locals in its size calculation. We don't
714 // include these locals when computing the stack size of a funclet, as they
715 // are allocated in the parent's stack frame and accessed via the frame
716 // pointer from the funclet. We only save the callee saved registers in the
717 // funclet, which are really the callee saved registers of the parent
718 // function, including the funclet.
719 int64_t NumBytes =
720 IsFunclet ? AFL.getWinEHFuncletFrameSize(MF) : MFI.getStackSize();
721 if (!AFI->hasStackFrame() && !AFL.windowsRequiresStackProbe(MF, NumBytes))
722 return emitEmptyStackFramePrologue(NumBytes, PrologueBeginI, DL);
723
724 bool IsWin64 = Subtarget.isCallingConvWin64(F.getCallingConv(), F.isVarArg());
725 unsigned FixedObject = AFL.getFixedObjectSize(MF, AFI, IsWin64, IsFunclet);
726
727 auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
728 // All of the remaining stack allocations are for locals.
729 determineLocalsStackSize(NumBytes, PrologueSaveSize);
730
731 auto [PPR, ZPR] = getSVEStackFrameSizes();
732 SVEStackAllocations SVEAllocs = getSVEStackAllocations({PPR, ZPR});
733
734 MachineBasicBlock::iterator FirstGPRSaveI = PrologueBeginI;
736 assert(!SVEAllocs.AfterPPRs &&
737 "unexpected SVE allocs after PPRs with CalleeSavesAboveFrameRecord");
738 // If we're doing SVE saves first, we need to immediately allocate space
739 // for fixed objects, then space for the SVE callee saves.
740 //
741 // Windows unwind requires that the scalable size is a multiple of 16;
742 // that's handled when the callee-saved size is computed.
743 auto SaveSize = SVEAllocs.BeforePPRs + StackOffset::getFixed(FixedObject);
744 allocateStackSpace(PrologueBeginI, 0, SaveSize, false, StackOffset{},
745 /*FollowupAllocs=*/true);
746 NumBytes -= FixedObject;
747
748 // Now allocate space for the GPR callee saves.
749 MachineBasicBlock::iterator MBBI = PrologueBeginI;
750 while (MBBI != EndI && isPartOfSVECalleeSaves(MBBI))
751 ++MBBI;
753 MBBI, DL, -AFI->getCalleeSavedStackSize(), EmitAsyncCFI);
754 NumBytes -= AFI->getCalleeSavedStackSize();
755 } else if (CombineSPBump) {
756 assert(!AFL.getSVEStackSize(MF) && "Cannot combine SP bump with SVE");
757 emitFrameOffset(MBB, PrologueBeginI, DL, AArch64::SP, AArch64::SP,
758 StackOffset::getFixed(-NumBytes), TII,
760 EmitAsyncCFI);
761 NumBytes = 0;
762 } else if (HomPrologEpilog) {
763 // Stack has been already adjusted.
764 NumBytes -= PrologueSaveSize;
765 } else if (PrologueSaveSize != 0) {
767 PrologueBeginI, DL, -PrologueSaveSize, EmitAsyncCFI);
768 NumBytes -= PrologueSaveSize;
769 }
770 assert(NumBytes >= 0 && "Negative stack allocation size!?");
771
772 // Move past the saves of the callee-saved registers, fixing up the offsets
773 // and pre-inc if we decided to combine the callee-save and local stack
774 // pointer bump above.
775 auto &TLI = *Subtarget.getTargetLowering();
776
777 MachineBasicBlock::iterator AfterGPRSavesI = FirstGPRSaveI;
778 while (AfterGPRSavesI != EndI &&
779 AfterGPRSavesI->getFlag(MachineInstr::FrameSetup) &&
780 !isPartOfSVECalleeSaves(AfterGPRSavesI)) {
781 if (CombineSPBump &&
782 // Only fix-up frame-setup load/store instructions.
783 (!AFL.requiresSaveVG(MF) || !isVGInstruction(AfterGPRSavesI, TLI)))
784 fixupCalleeSaveRestoreStackOffset(*AfterGPRSavesI,
785 AFI->getLocalStackSize());
786 ++AfterGPRSavesI;
787 }
788
789 // For funclets the FP belongs to the containing function. Only set up FP if
790 // we actually need to.
791 if (!IsFunclet && HasFP)
792 emitFramePointerSetup(AfterGPRSavesI, DL, FixedObject);
793
794 // Now emit the moves for whatever callee saved regs we have (including FP,
795 // LR if those are saved). Frame instructions for SVE register are emitted
796 // later, after the instruction which actually save SVE regs.
797 if (EmitAsyncCFI)
798 emitCalleeSavedGPRLocations(AfterGPRSavesI);
799
800 // Alignment is required for the parent frame, not the funclet
801 const bool NeedsRealignment =
802 NumBytes && !IsFunclet && RegInfo.hasStackRealignment(MF);
803 const int64_t RealignmentPadding =
804 (NeedsRealignment && MFI.getMaxAlign() > Align(16))
805 ? MFI.getMaxAlign().value() - 16
806 : 0;
807
808 if (AFL.windowsRequiresStackProbe(MF, NumBytes + RealignmentPadding))
809 emitWindowsStackProbe(AfterGPRSavesI, DL, NumBytes, RealignmentPadding);
810
811 StackOffset NonSVELocalsSize = StackOffset::getFixed(NumBytes);
812 SVEAllocs.AfterZPRs += NonSVELocalsSize;
813
814 StackOffset CFAOffset =
815 StackOffset::getFixed(MFI.getStackSize()) - NonSVELocalsSize;
816 MachineBasicBlock::iterator AfterSVESavesI = AfterGPRSavesI;
817 // Allocate space for the callee saves and PPR locals (if any).
819 auto [PPRRange, ZPRRange] =
820 partitionSVECS(MBB, AfterGPRSavesI, PPR.CalleeSavesSize,
821 ZPR.CalleeSavesSize, /*IsEpilogue=*/false);
822 AfterSVESavesI = ZPRRange.End;
823 if (EmitAsyncCFI)
824 emitCalleeSavedSVELocations(AfterSVESavesI);
825
826 allocateStackSpace(PPRRange.Begin, 0, SVEAllocs.BeforePPRs,
827 EmitAsyncCFI && !HasFP, CFAOffset,
828 MFI.hasVarSizedObjects() || SVEAllocs.AfterPPRs ||
829 SVEAllocs.AfterZPRs);
830 CFAOffset += SVEAllocs.BeforePPRs;
831 assert(PPRRange.End == ZPRRange.Begin &&
832 "Expected ZPR callee saves after PPR locals");
833 allocateStackSpace(PPRRange.End, 0, SVEAllocs.AfterPPRs,
834 EmitAsyncCFI && !HasFP, CFAOffset,
835 MFI.hasVarSizedObjects() || SVEAllocs.AfterZPRs);
836 CFAOffset += SVEAllocs.AfterPPRs;
837 } else {
839 // Note: With CalleeSavesAboveFrameRecord, the SVE CS (BeforePPRs) have
840 // already been allocated. PPR locals (included in AfterPPRs) are not
841 // supported (note: this is asserted above).
842 CFAOffset += SVEAllocs.BeforePPRs;
843 }
844
845 // Allocate space for the rest of the frame including ZPR locals. Align the
846 // stack as necessary.
847 assert(!(AFL.canUseRedZone(MF) && NeedsRealignment) &&
848 "Cannot use redzone with stack realignment");
849 if (!AFL.canUseRedZone(MF)) {
850 // FIXME: in the case of dynamic re-alignment, NumBytes doesn't have the
851 // correct value here, as NumBytes also includes padding bytes, which
852 // shouldn't be counted here.
853 allocateStackSpace(AfterSVESavesI, RealignmentPadding, SVEAllocs.AfterZPRs,
854 EmitAsyncCFI && !HasFP, CFAOffset,
855 MFI.hasVarSizedObjects());
856 }
857
858 // If we need a base pointer, set it up here. It's whatever the value of the
859 // stack pointer is at this point. Any variable size objects will be
860 // allocated after this, so we can still use the base pointer to reference
861 // locals.
862 //
863 // FIXME: Clarify FrameSetup flags here.
864 // Note: Use emitFrameOffset() like above for FP if the FrameSetup flag is
865 // needed.
866 // For funclets the BP belongs to the containing function.
867 if (!IsFunclet && RegInfo.hasBasePointer(MF)) {
868 TII->copyPhysReg(MBB, AfterSVESavesI, DL, RegInfo.getBaseRegister(),
869 AArch64::SP, false);
870 if (NeedsWinCFI) {
871 HasWinCFI = true;
872 BuildMI(MBB, AfterSVESavesI, DL, TII->get(AArch64::SEH_Nop))
874 }
875 }
876
877 // The very last FrameSetup instruction indicates the end of prologue. Emit a
878 // SEH opcode indicating the prologue end.
879 if (NeedsWinCFI && HasWinCFI) {
880 BuildMI(MBB, AfterSVESavesI, DL, TII->get(AArch64::SEH_PrologEnd))
882 }
883
884 // SEH funclets are passed the frame pointer in X1. If the parent
885 // function uses the base register, then the base register is used
886 // directly, and is not retrieved from X1.
887 if (IsFunclet && F.hasPersonalityFn()) {
888 EHPersonality Per = classifyEHPersonality(F.getPersonalityFn());
890 BuildMI(MBB, AfterSVESavesI, DL, TII->get(TargetOpcode::COPY),
891 AArch64::FP)
892 .addReg(AArch64::X1)
894 MBB.addLiveIn(AArch64::X1);
895 }
896 }
897
898 if (EmitCFI && !EmitAsyncCFI) {
899 if (HasFP) {
900 emitDefineCFAWithFP(AfterSVESavesI, FixedObject);
901 } else {
902 StackOffset TotalSize =
903 AFL.getSVEStackSize(MF) +
904 StackOffset::getFixed((int64_t)MFI.getStackSize());
905 CFIInstBuilder CFIBuilder(MBB, AfterSVESavesI, MachineInstr::FrameSetup);
906 CFIBuilder.insertCFIInst(
907 createDefCFA(RegInfo, /*FrameReg=*/AArch64::SP, /*Reg=*/AArch64::SP,
908 TotalSize, /*LastAdjustmentWasScalable=*/false));
909 }
910 emitCalleeSavedGPRLocations(AfterSVESavesI);
911 emitCalleeSavedSVELocations(AfterSVESavesI);
912 }
913}
914
915void AArch64PrologueEmitter::emitShadowCallStackPrologue(
917 // Shadow call stack prolog: str x30, [x18], #8
918 BuildMI(MBB, MBBI, DL, TII->get(AArch64::STRXpost))
919 .addReg(AArch64::X18, RegState::Define)
920 .addReg(AArch64::LR)
921 .addReg(AArch64::X18)
922 .addImm(8)
924
925 // This instruction also makes x18 live-in to the entry block.
926 MBB.addLiveIn(AArch64::X18);
927
928 if (NeedsWinCFI)
929 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
931
932 if (EmitCFI) {
933 // Emit a CFI instruction that causes 8 to be subtracted from the value of
934 // x18 when unwinding past this frame.
935 static const char CFIInst[] = {
936 dwarf::DW_CFA_val_expression,
937 18, // register
938 2, // length
939 static_cast<char>(unsigned(dwarf::DW_OP_breg18)),
940 static_cast<char>(-8) & 0x7f, // addend (sleb128)
941 };
942 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
943 .buildEscape(StringRef(CFIInst, sizeof(CFIInst)));
944 }
945}
946
947void AArch64PrologueEmitter::emitSwiftAsyncContextFramePointer(
949 switch (MF.getTarget().Options.SwiftAsyncFramePointer) {
951 if (Subtarget.swiftAsyncContextIsDynamicallySet()) {
952 // The special symbol below is absolute and has a *value* that can be
953 // combined with the frame pointer to signal an extended frame.
954 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LOADgot), AArch64::X16)
955 .addExternalSymbol("swift_async_extendedFramePointerFlags",
957 if (NeedsWinCFI) {
958 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
960 HasWinCFI = true;
961 }
962 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::FP)
963 .addUse(AArch64::FP)
964 .addUse(AArch64::X16)
965 .addImm(Subtarget.isTargetILP32() ? 32 : 0);
966 if (NeedsWinCFI) {
967 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
969 HasWinCFI = true;
970 }
971 break;
972 }
973 [[fallthrough]];
974
976 // ORR x29, x29, #0x1000_0000_0000_0000
977 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXri), AArch64::FP)
978 .addUse(AArch64::FP)
979 .addImm(0x1100)
981 if (NeedsWinCFI) {
982 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
984 HasWinCFI = true;
985 }
986 break;
987
989 break;
990 }
991}
992
993void AArch64PrologueEmitter::emitEmptyStackFramePrologue(
994 int64_t NumBytes, MachineBasicBlock::iterator MBBI,
995 const DebugLoc &DL) const {
996 assert(!HasFP && "unexpected function without stack frame but with FP");
997 assert(!AFL.getSVEStackSize(MF) &&
998 "unexpected function without stack frame but with SVE objects");
999 // All of the stack allocation is for locals.
1000 AFI->setLocalStackSize(NumBytes);
1001 if (!NumBytes) {
1002 if (NeedsWinCFI && HasWinCFI) {
1003 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
1005 }
1006 return;
1007 }
1008 // REDZONE: If the stack size is less than 128 bytes, we don't need
1009 // to actually allocate.
1010 if (AFL.canUseRedZone(MF)) {
1011 AFI->setHasRedZone(true);
1012 ++NumRedZoneFunctions;
1013 } else {
1014 emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP,
1015 StackOffset::getFixed(-NumBytes), TII,
1017 if (EmitCFI) {
1018 // Label used to tie together the PROLOG_LABEL and the MachineMoves.
1019 MCSymbol *FrameLabel = MF.getContext().createTempSymbol();
1020 // Encode the stack size of the leaf function.
1021 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
1022 .buildDefCFAOffset(NumBytes, FrameLabel);
1023 }
1024 }
1025
1026 if (NeedsWinCFI) {
1027 HasWinCFI = true;
1028 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
1030 }
1031}
1032
1033void AArch64PrologueEmitter::emitFramePointerSetup(
1035 unsigned FixedObject) {
1036 int64_t FPOffset = AFI->getCalleeSaveBaseToFrameRecordOffset();
1037 if (CombineSPBump)
1038 FPOffset += AFI->getLocalStackSize();
1039
1040 if (AFI->hasSwiftAsyncContext()) {
1041 // Before we update the live FP we have to ensure there's a valid (or
1042 // null) asynchronous context in its slot just before FP in the frame
1043 // record, so store it now.
1044 const auto &Attrs = MF.getFunction().getAttributes();
1045 bool HaveInitialContext = Attrs.hasAttrSomewhere(Attribute::SwiftAsync);
1046 if (HaveInitialContext)
1047 MBB.addLiveIn(AArch64::X22);
1048 Register Reg = HaveInitialContext ? AArch64::X22 : AArch64::XZR;
1049 BuildMI(MBB, MBBI, DL, TII->get(AArch64::StoreSwiftAsyncContext))
1050 .addUse(Reg)
1051 .addUse(AArch64::SP)
1052 .addImm(FPOffset - 8)
1054 if (NeedsWinCFI) {
1055 // WinCFI and arm64e, where StoreSwiftAsyncContext is expanded
1056 // to multiple instructions, should be mutually-exclusive.
1057 assert(Subtarget.getTargetTriple().getArchName() != "arm64e");
1058 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1060 HasWinCFI = true;
1061 }
1062 }
1063
1064 if (HomPrologEpilog) {
1065 auto Prolog = MBBI;
1066 --Prolog;
1067 assert(Prolog->getOpcode() == AArch64::HOM_Prolog);
1068 Prolog->addOperand(MachineOperand::CreateImm(FPOffset));
1069 } else {
1070 // Issue sub fp, sp, FPOffset or
1071 // mov fp,sp when FPOffset is zero.
1072 // Note: All stores of callee-saved registers are marked as "FrameSetup".
1073 // This code marks the instruction(s) that set the FP also.
1074 emitFrameOffset(MBB, MBBI, DL, AArch64::FP, AArch64::SP,
1075 StackOffset::getFixed(FPOffset), TII,
1077 if (NeedsWinCFI && HasWinCFI) {
1078 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
1080 // After setting up the FP, the rest of the prolog doesn't need to be
1081 // included in the SEH unwind info.
1082 NeedsWinCFI = false;
1083 }
1084 }
1085 if (EmitAsyncCFI)
1086 emitDefineCFAWithFP(MBBI, FixedObject);
1087}
1088
1089// Define the current CFA rule to use the provided FP.
1090void AArch64PrologueEmitter::emitDefineCFAWithFP(
1091 MachineBasicBlock::iterator MBBI, unsigned FixedObject) const {
1092 const int OffsetToFirstCalleeSaveFromFP =
1093 AFI->getCalleeSaveBaseToFrameRecordOffset() -
1094 AFI->getCalleeSavedStackSize();
1095 Register FramePtr = RegInfo.getFrameRegister(MF);
1096 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
1097 .buildDefCFA(FramePtr, FixedObject - OffsetToFirstCalleeSaveFromFP);
1098}
1099
1100void AArch64PrologueEmitter::emitWindowsStackProbe(
1101 MachineBasicBlock::iterator MBBI, const DebugLoc &DL, int64_t &NumBytes,
1102 int64_t RealignmentPadding) const {
1103 if (AFI->getSVECalleeSavedStackSize())
1104 report_fatal_error("SVE callee saves not yet supported with stack probing");
1105
1106 // Find an available register to spill the value of X15 to, if X15 is being
1107 // used already for nest.
1108 Register X15Scratch;
1109 if (llvm::any_of(MBB.liveins(),
1110 [this](const MachineBasicBlock::RegisterMaskPair &LiveIn) {
1111 return RegInfo.isSuperOrSubRegisterEq(AArch64::X15,
1112 LiveIn.PhysReg);
1113 })) {
1114 X15Scratch = AFL.findScratchNonCalleeSaveRegister(&MBB, /*HasCall=*/true);
1115 assert(X15Scratch.isValid() &&
1116 (X15Scratch < AArch64::X15 || X15Scratch > AArch64::X17));
1117#ifndef NDEBUG
1118 LiveRegs.removeReg(AArch64::X15); // ignore X15 since we restore it
1119#endif
1120 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrr), X15Scratch)
1121 .addReg(AArch64::XZR)
1122 .addReg(AArch64::X15, RegState::Undef)
1123 .addReg(AArch64::X15, RegState::Implicit)
1125 }
1126
1127 uint64_t NumWords = (NumBytes + RealignmentPadding) >> 4;
1128 if (NeedsWinCFI) {
1129 HasWinCFI = true;
1130 // alloc_l can hold at most 256MB, so assume that NumBytes doesn't
1131 // exceed this amount. We need to move at most 2^24 - 1 into x15.
1132 // This is at most two instructions, MOVZ followed by MOVK.
1133 // TODO: Fix to use multiple stack alloc unwind codes for stacks
1134 // exceeding 256MB in size.
1135 if (NumBytes >= (1 << 28))
1136 report_fatal_error("Stack size cannot exceed 256MB for stack "
1137 "unwinding purposes");
1138
1139 uint32_t LowNumWords = NumWords & 0xFFFF;
1140 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVZXi), AArch64::X15)
1141 .addImm(LowNumWords)
1144 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1146 if ((NumWords & 0xFFFF0000) != 0) {
1147 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVKXi), AArch64::X15)
1148 .addReg(AArch64::X15)
1149 .addImm((NumWords & 0xFFFF0000) >> 16) // High half
1152 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1154 }
1155 } else {
1156 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVi64imm), AArch64::X15)
1157 .addImm(NumWords)
1159 }
1160
1161 const AArch64TargetLowering *TLI = Subtarget.getTargetLowering();
1162 RTLIB::LibcallImpl ChkStkLibcall = TLI->getLibcallImpl(RTLIB::STACK_PROBE);
1163 if (ChkStkLibcall == RTLIB::Unsupported)
1164 reportFatalUsageError("no available implementation of __chkstk");
1165
1166 const char *ChkStk = TLI->getLibcallImplName(ChkStkLibcall).data();
1167 switch (MF.getTarget().getCodeModel()) {
1168 case CodeModel::Tiny:
1169 case CodeModel::Small:
1170 case CodeModel::Medium:
1171 case CodeModel::Kernel:
1172 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
1173 .addExternalSymbol(ChkStk)
1174 .addReg(AArch64::X15, RegState::Implicit)
1175 .addReg(AArch64::X16,
1177 .addReg(AArch64::X17,
1179 .addReg(AArch64::NZCV,
1182 if (NeedsWinCFI) {
1183 HasWinCFI = true;
1184 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1186 }
1187 break;
1188 case CodeModel::Large:
1189 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVaddrEXT))
1190 .addReg(AArch64::X16, RegState::Define)
1191 .addExternalSymbol(ChkStk)
1192 .addExternalSymbol(ChkStk)
1194 if (NeedsWinCFI) {
1195 HasWinCFI = true;
1196 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1198 }
1199
1201 .addReg(AArch64::X16, RegState::Kill)
1203 .addReg(AArch64::X16,
1205 .addReg(AArch64::X17,
1207 .addReg(AArch64::NZCV,
1210 if (NeedsWinCFI) {
1211 HasWinCFI = true;
1212 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1214 }
1215 break;
1216 }
1217
1218 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SUBXrx64), AArch64::SP)
1219 .addReg(AArch64::SP, RegState::Kill)
1220 .addReg(AArch64::X15, RegState::Kill)
1223 if (NeedsWinCFI) {
1224 HasWinCFI = true;
1225 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
1226 .addImm(NumBytes)
1228 }
1229 NumBytes = 0;
1230
1231 if (RealignmentPadding > 0) {
1232 if (RealignmentPadding >= 4096) {
1233 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVi64imm))
1234 .addReg(AArch64::X16, RegState::Define)
1235 .addImm(RealignmentPadding)
1237 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXrx64), AArch64::X15)
1238 .addReg(AArch64::SP)
1239 .addReg(AArch64::X16, RegState::Kill)
1242 } else {
1243 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXri), AArch64::X15)
1244 .addReg(AArch64::SP)
1245 .addImm(RealignmentPadding)
1246 .addImm(0)
1248 }
1249
1250 uint64_t AndMask = ~(MFI.getMaxAlign().value() - 1);
1251 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), AArch64::SP)
1252 .addReg(AArch64::X15, RegState::Kill)
1254 AFI->setStackRealigned(true);
1255
1256 // No need for SEH instructions here; if we're realigning the stack,
1257 // we've set a frame pointer and already finished the SEH prologue.
1259 }
1260 if (X15Scratch.isValid()) {
1261 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrr), AArch64::X15)
1262 .addReg(AArch64::XZR)
1263 .addReg(X15Scratch, RegState::Undef)
1264 .addReg(X15Scratch, RegState::Implicit)
1266 }
1267}
1268
1269void AArch64PrologueEmitter::emitCalleeSavedGPRLocations(
1271 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
1272 if (CSI.empty())
1273 return;
1274
1275 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameSetup);
1276 for (const auto &Info : CSI) {
1277 unsigned FrameIdx = Info.getFrameIdx();
1278 if (MFI.hasScalableStackID(FrameIdx))
1279 continue;
1280
1281 assert(!Info.isSpilledToReg() && "Spilling to registers not implemented");
1282 int64_t Offset = MFI.getObjectOffset(FrameIdx) - AFL.getOffsetOfLocalArea();
1283 CFIBuilder.buildOffset(Info.getReg(), Offset);
1284 }
1285}
1286
1287void AArch64PrologueEmitter::emitCalleeSavedSVELocations(
1289 // Add callee saved registers to move list.
1290 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
1291 if (CSI.empty())
1292 return;
1293
1294 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameSetup);
1295
1296 std::optional<int64_t> IncomingVGOffsetFromDefCFA;
1297 if (AFL.requiresSaveVG(MF)) {
1298 auto IncomingVG = *find_if(
1299 reverse(CSI), [](auto &Info) { return Info.getReg() == AArch64::VG; });
1300 IncomingVGOffsetFromDefCFA = MFI.getObjectOffset(IncomingVG.getFrameIdx()) -
1301 AFL.getOffsetOfLocalArea();
1302 }
1303
1304 StackOffset PPRStackSize = AFL.getPPRStackSize(MF);
1305 for (const auto &Info : CSI) {
1306 int FI = Info.getFrameIdx();
1307 if (!MFI.hasScalableStackID(FI))
1308 continue;
1309
1310 // Not all unwinders may know about SVE registers, so assume the lowest
1311 // common denominator.
1312 assert(!Info.isSpilledToReg() && "Spilling to registers not implemented");
1313 MCRegister Reg = Info.getReg();
1314 if (!RegInfo.regNeedsCFI(Reg, Reg))
1315 continue;
1316
1317 StackOffset Offset =
1318 StackOffset::getScalable(MFI.getObjectOffset(FI)) -
1319 StackOffset::getFixed(AFI->getCalleeSavedStackSize(MFI));
1320
1321 // The scalable vectors are below (lower address) the scalable predicates
1322 // with split SVE objects, so we must subtract the size of the predicates.
1324 MFI.getStackID(FI) == TargetStackID::ScalableVector)
1325 Offset -= PPRStackSize;
1326
1327 CFIBuilder.insertCFIInst(
1328 createCFAOffset(RegInfo, Reg, Offset, IncomingVGOffsetFromDefCFA));
1329 }
1330}
1331
1333 switch (MI.getOpcode()) {
1334 default:
1335 return false;
1336 case AArch64::CATCHRET:
1337 case AArch64::CLEANUPRET:
1338 return true;
1339 }
1340}
1341
1346 EmitCFI = AFI->needsAsyncDwarfUnwindInfo(MF);
1347 HomPrologEpilog = AFL.homogeneousPrologEpilog(MF, &MBB);
1348 SEHEpilogueStartI = MBB.end();
1349}
1350
1351void AArch64EpilogueEmitter::moveSPBelowFP(MachineBasicBlock::iterator MBBI,
1353 // Other combinations could be supported, but are not currently needed.
1354 assert(Offset.getScalable() < 0 && Offset.getFixed() <= 0 &&
1355 "expected negative offset (with optional fixed portion)");
1356 Register Base = AArch64::FP;
1357 if (int64_t FixedOffset = Offset.getFixed()) {
1358 // If we have a negative fixed offset, we need to first subtract it in a
1359 // temporary register first (to avoid briefly deallocating the scalable
1360 // portion of the offset).
1361 Base = MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
1362 emitFrameOffset(MBB, MBBI, DL, Base, AArch64::FP,
1363 StackOffset::getFixed(FixedOffset), TII,
1365 }
1366 emitFrameOffset(MBB, MBBI, DL, AArch64::SP, Base,
1367 StackOffset::getScalable(Offset.getScalable()), TII,
1369}
1370
1372 MachineBasicBlock::iterator EpilogueEndI = MBB.getLastNonDebugInstr();
1373 if (MBB.end() != EpilogueEndI) {
1374 DL = EpilogueEndI->getDebugLoc();
1375 IsFunclet = isFuncletReturnInstr(*EpilogueEndI);
1376 }
1377
1378 int64_t NumBytes =
1379 IsFunclet ? AFL.getWinEHFuncletFrameSize(MF) : MFI.getStackSize();
1380
1381 // All calls are tail calls in GHC calling conv, and functions have no
1382 // prologue/epilogue.
1383 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
1384 return;
1385
1386 // How much of the stack used by incoming arguments this function is expected
1387 // to restore in this particular epilogue.
1388 int64_t ArgumentStackToRestore = AFL.getArgumentStackToRestore(MF, MBB);
1389 bool IsWin64 = Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv(),
1390 MF.getFunction().isVarArg());
1391 unsigned FixedObject = AFL.getFixedObjectSize(MF, AFI, IsWin64, IsFunclet);
1392
1393 const bool AuthenticateReturnAddressEarly =
1394 !IsFunclet && AFL.authenticatesReturnAddressEarly(MF, MBB);
1395
1396 int64_t AfterCSRPopSize = ArgumentStackToRestore;
1397 auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
1398 // We cannot rely on the local stack size set in emitPrologue if the function
1399 // has funclets, as funclets have different local stack size requirements, and
1400 // the current value set in emitPrologue may be that of the containing
1401 // function.
1402 if (MF.hasEHFunclets())
1403 AFI->setLocalStackSize(NumBytes - PrologueSaveSize);
1404
1405 if (HomPrologEpilog) {
1407 auto FirstHomogenousEpilogI = MBB.getFirstTerminator();
1408 if (FirstHomogenousEpilogI != MBB.begin()) {
1409 auto HomogeneousEpilog = std::prev(FirstHomogenousEpilogI);
1410 if (HomogeneousEpilog->getOpcode() == AArch64::HOM_Epilog)
1411 FirstHomogenousEpilogI = HomogeneousEpilog;
1412 }
1413
1414 // Adjust local stack
1415 emitFrameOffset(MBB, FirstHomogenousEpilogI, DL, AArch64::SP, AArch64::SP,
1416 StackOffset::getFixed(AFI->getLocalStackSize()), TII,
1418
1419 // SP has been already adjusted while restoring callee save regs.
1420 // We've bailed-out the case with adjusting SP for arguments.
1421 assert(AfterCSRPopSize == 0);
1422 return;
1423 }
1424
1425 bool CombineSPBump = shouldCombineCSRLocalStackBump(NumBytes);
1426
1427 unsigned ProloguePopSize = PrologueSaveSize;
1429 // With CalleeSavesAboveFrameRecord ProloguePopSize is the amount of stack
1430 // that needs to be popped until we reach the start of the SVE save area.
1431 // The "FixedObject" stack occurs after the SVE area and must be popped
1432 // later.
1433 ProloguePopSize -= FixedObject;
1434 AfterCSRPopSize += FixedObject;
1435 }
1436
1437 // Assume we can't combine the last pop with the sp restore. If the return
1438 // address is authenticated early, it wasn't restored, so the last pop may
1439 // not exist, and in any case the SP adjustment is made explicitly.
1440 if (!CombineSPBump && ProloguePopSize != 0 &&
1441 AuthenticateReturnAddressEarly) {
1442 AfterCSRPopSize += ProloguePopSize;
1443 } else if (!CombineSPBump && ProloguePopSize != 0) {
1444 MachineBasicBlock::iterator Pop = std::prev(MBB.getFirstTerminator());
1445 while (Pop->getOpcode() == TargetOpcode::CFI_INSTRUCTION ||
1446 AArch64InstrInfo::isSEHInstruction(*Pop) ||
1449 Pop = std::prev(Pop);
1450 // Converting the last ldp to a post-index ldp is valid only if the last
1451 // ldp's offset is 0.
1452 const MachineOperand &OffsetOp = Pop->getOperand(Pop->getNumOperands() - 1);
1453 // If the offset is 0 and the AfterCSR pop is not actually trying to
1454 // allocate more stack for arguments (in space that an untimely interrupt
1455 // may clobber), convert it to a post-index ldp.
1456 if (OffsetOp.getImm() == 0 && AfterCSRPopSize >= 0) {
1458 Pop, DL, ProloguePopSize, EmitCFI, MachineInstr::FrameDestroy,
1459 ProloguePopSize);
1461 MachineBasicBlock::iterator AfterLastPop = std::next(Pop);
1462 if (AArch64InstrInfo::isSEHInstruction(*AfterLastPop))
1463 ++AfterLastPop;
1464 // If not, and CalleeSavesAboveFrameRecord is enabled, deallocate
1465 // callee-save non-SVE registers to move the stack pointer to the start of
1466 // the SVE area.
1467 emitFrameOffset(MBB, AfterLastPop, DL, AArch64::SP, AArch64::SP,
1468 StackOffset::getFixed(ProloguePopSize), TII,
1470 &HasWinCFI);
1471 } else {
1472 // Otherwise, make sure to emit an add after the last ldp.
1473 // We're doing this by transferring the size to be restored from the
1474 // adjustment *before* the CSR pops to the adjustment *after* the CSR
1475 // pops.
1476 AfterCSRPopSize += ProloguePopSize;
1477 }
1478 }
1479
1480 // Move past the restores of the callee-saved registers.
1481 // If we plan on combining the sp bump of the local stack size and the callee
1482 // save stack size, we might need to adjust the CSR save and restore offsets.
1483 MachineBasicBlock::iterator FirstGPRRestoreI = MBB.getFirstTerminator();
1484 MachineBasicBlock::iterator Begin = MBB.begin();
1485 while (FirstGPRRestoreI != Begin) {
1486 --FirstGPRRestoreI;
1487 if (!FirstGPRRestoreI->getFlag(MachineInstr::FrameDestroy) ||
1489 isPartOfSVECalleeSaves(FirstGPRRestoreI))) {
1490 ++FirstGPRRestoreI;
1491 break;
1492 } else if (CombineSPBump)
1493 fixupCalleeSaveRestoreStackOffset(*FirstGPRRestoreI,
1494 AFI->getLocalStackSize());
1495 }
1496
1497 // The unwind info can't describe authenticating the return address in an
1498 // epilogue that leaves SP somewhere other than where it was on entry, so do
1499 // it before the epilogue starts instead.
1500 if (AuthenticateReturnAddressEarly)
1501 emitEarlyReturnAddressAuthentication(FirstGPRRestoreI, MFI.getStackSize(),
1502 PrologueSaveSize);
1503
1504 if (NeedsWinCFI) {
1505 // Note that there are cases where we insert SEH opcodes in the
1506 // epilogue when we had no SEH opcodes in the prologue. For
1507 // example, when there is no stack frame but there are stack
1508 // arguments. Insert the SEH_EpilogStart and remove it later if it
1509 // we didn't emit any SEH opcodes to avoid generating WinCFI for
1510 // functions that don't need it.
1511 BuildMI(MBB, FirstGPRRestoreI, DL, TII->get(AArch64::SEH_EpilogStart))
1513 SEHEpilogueStartI = FirstGPRRestoreI;
1514 --SEHEpilogueStartI;
1515 }
1516
1517 // Determine the ranges of SVE callee-saves. This is done before emitting any
1518 // code at the end of the epilogue (for Swift async), which can get in the way
1519 // of finding SVE callee-saves with CalleeSavesAboveFrameRecord.
1520 auto [PPR, ZPR] = getSVEStackFrameSizes();
1521 auto [PPRRange, ZPRRange] = partitionSVECS(
1522 MBB,
1524 ? MBB.getFirstTerminator()
1525 : FirstGPRRestoreI,
1526 PPR.CalleeSavesSize, ZPR.CalleeSavesSize, /*IsEpilogue=*/true);
1527
1528 if (HasFP && AFI->hasSwiftAsyncContext())
1529 emitSwiftAsyncContextFramePointer(EpilogueEndI, DL);
1530
1531 // If there is a single SP update, insert it before the ret and we're done.
1532 if (CombineSPBump) {
1533 assert(!AFI->hasSVEStackSize() && "Cannot combine SP bump with SVE");
1534
1535 // When we are about to restore the CSRs, the CFA register is SP again.
1536 if (EmitCFI && HasFP)
1538 .buildDefCFA(AArch64::SP, NumBytes);
1539
1540 emitFrameOffset(MBB, MBB.getFirstTerminator(), DL, AArch64::SP, AArch64::SP,
1541 StackOffset::getFixed(NumBytes + AfterCSRPopSize), TII,
1543 EmitCFI, StackOffset::getFixed(NumBytes));
1544 return;
1545 }
1546
1547 NumBytes -= PrologueSaveSize;
1548 assert(NumBytes >= 0 && "Negative stack allocation size!?");
1549
1550 StackOffset SVECalleeSavesSize = ZPR.CalleeSavesSize + PPR.CalleeSavesSize;
1551 SVEStackAllocations SVEAllocs = getSVEStackAllocations({PPR, ZPR});
1552
1553 // Deallocate the SVE area.
1555 assert(!SVEAllocs.AfterPPRs &&
1556 "unexpected SVE allocs after PPRs with CalleeSavesAboveFrameRecord");
1557 // If the callee-save area is before FP, restoring the FP implicitly
1558 // deallocates non-callee-save SVE allocations. Otherwise, deallocate them
1559 // explicitly.
1560 if (!AFI->isStackRealigned() && !MFI.hasVarSizedObjects()) {
1561 emitFrameOffset(MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::SP,
1563 false, NeedsWinCFI, &HasWinCFI);
1564 }
1565
1566 // Deallocate callee-save SVE registers.
1567 emitFrameOffset(MBB, PPRRange.End, DL, AArch64::SP, AArch64::SP,
1569 false, NeedsWinCFI, &HasWinCFI);
1570 } else if (AFI->hasSVEStackSize()) {
1571 // If we have stack realignment or variable-sized objects we must use the FP
1572 // to restore SVE callee saves (as there is an unknown amount of
1573 // data/padding between the SP and SVE CS area).
1574 Register BaseForSVEDealloc =
1575 (AFI->isStackRealigned() || MFI.hasVarSizedObjects()) ? AArch64::FP
1576 : AArch64::SP;
1577 if (SVECalleeSavesSize && BaseForSVEDealloc == AArch64::FP) {
1578 if (ZPR.CalleeSavesSize || SVELayout != SVEStackLayout::Split) {
1579 // The offset from the frame-pointer to the start of the ZPR saves.
1580 StackOffset FPOffsetZPR =
1581 -SVECalleeSavesSize - PPR.LocalsSize -
1582 StackOffset::getFixed(AFI->getCalleeSaveBaseToFrameRecordOffset());
1583 // Deallocate the stack space space by moving the SP to the start of the
1584 // ZPR/PPR callee-save area.
1585 moveSPBelowFP(ZPRRange.Begin, FPOffsetZPR);
1586 }
1587 // With split SVE, the predicates are stored in a separate area above the
1588 // ZPR saves, so we must adjust the stack to the start of the PPRs.
1589 if (PPR.CalleeSavesSize && SVELayout == SVEStackLayout::Split) {
1590 // The offset from the frame-pointer to the start of the PPR saves.
1591 StackOffset FPOffsetPPR = -PPR.CalleeSavesSize;
1592 // Move to the start of the PPR area.
1593 assert(!FPOffsetPPR.getFixed() && "expected only scalable offset");
1594 emitFrameOffset(MBB, ZPRRange.End, DL, AArch64::SP, AArch64::FP,
1595 FPOffsetPPR, TII, MachineInstr::FrameDestroy);
1596 }
1597 } else if (BaseForSVEDealloc == AArch64::SP) {
1598 auto NonSVELocals = StackOffset::getFixed(NumBytes);
1599 auto CFAOffset = NonSVELocals + StackOffset::getFixed(PrologueSaveSize) +
1600 SVEAllocs.totalSize();
1601
1602 if (SVECalleeSavesSize || SVELayout == SVEStackLayout::Split) {
1603 // Deallocate non-SVE locals now. This is needed to reach the SVE callee
1604 // saves, but may also allow combining stack hazard bumps for split SVE.
1605 SVEAllocs.AfterZPRs += NonSVELocals;
1606 NumBytes -= NonSVELocals.getFixed();
1607 }
1608 // To deallocate the SVE stack adjust by the allocations in reverse.
1609 emitFrameOffset(MBB, ZPRRange.Begin, DL, AArch64::SP, AArch64::SP,
1611 false, NeedsWinCFI, &HasWinCFI, EmitCFI && !HasFP,
1612 CFAOffset);
1613 CFAOffset -= SVEAllocs.AfterZPRs;
1614 assert(PPRRange.Begin == ZPRRange.End &&
1615 "Expected PPR restores after ZPR");
1616 emitFrameOffset(MBB, PPRRange.Begin, DL, AArch64::SP, AArch64::SP,
1618 false, NeedsWinCFI, &HasWinCFI, EmitCFI && !HasFP,
1619 CFAOffset);
1620 CFAOffset -= SVEAllocs.AfterPPRs;
1621 emitFrameOffset(MBB, PPRRange.End, DL, AArch64::SP, AArch64::SP,
1623 false, NeedsWinCFI, &HasWinCFI, EmitCFI && !HasFP,
1624 CFAOffset);
1625 }
1626
1627 if (EmitCFI)
1628 emitCalleeSavedSVERestores(
1629 SVELayout == SVEStackLayout::Split ? ZPRRange.End : PPRRange.End);
1630 }
1631
1632 if (!HasFP) {
1633 bool RedZone = AFL.canUseRedZone(MF);
1634 // If this was a redzone leaf function, we don't need to restore the
1635 // stack pointer (but we may need to pop stack args for fastcc).
1636 if (RedZone && AfterCSRPopSize == 0)
1637 return;
1638
1639 // Pop the local variables off the stack. If there are no callee-saved
1640 // registers, it means we are actually positioned at the terminator and can
1641 // combine stack increment for the locals and the stack increment for
1642 // callee-popped arguments into (possibly) a single instruction and be done.
1643 bool NoCalleeSaveRestore = PrologueSaveSize == 0;
1644 int64_t StackRestoreBytes = RedZone ? 0 : NumBytes;
1645 if (NoCalleeSaveRestore)
1646 StackRestoreBytes += AfterCSRPopSize;
1647
1649 MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::SP,
1650 StackOffset::getFixed(StackRestoreBytes), TII,
1652 StackOffset::getFixed((RedZone ? 0 : NumBytes) + PrologueSaveSize));
1653
1654 // If we were able to combine the local stack pop with the argument pop,
1655 // then we're done.
1656 if (NoCalleeSaveRestore || AfterCSRPopSize == 0)
1657 return;
1658
1659 NumBytes = 0;
1660 }
1661
1662 // Restore the original stack pointer.
1663 // FIXME: Rather than doing the math here, we should instead just use
1664 // non-post-indexed loads for the restores if we aren't actually going to
1665 // be able to save any instructions.
1666 if (!IsFunclet && (MFI.hasVarSizedObjects() || AFI->isStackRealigned())) {
1668 MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::FP,
1669 StackOffset::getFixed(-AFI->getCalleeSaveBaseToFrameRecordOffset()),
1671 } else if (NumBytes)
1672 emitFrameOffset(MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::SP,
1673 StackOffset::getFixed(NumBytes), TII,
1675
1676 // When we are about to restore the CSRs, the CFA register is SP again.
1677 if (EmitCFI && HasFP)
1679 .buildDefCFA(AArch64::SP, PrologueSaveSize);
1680
1681 // This must be placed after the callee-save restore code because that code
1682 // assumes the SP is at the same location as it was after the callee-save save
1683 // code in the prologue.
1684 if (AfterCSRPopSize) {
1685 assert(AfterCSRPopSize > 0 && "attempting to reallocate arg stack that an "
1686 "interrupt may have clobbered");
1687
1689 MBB, MBB.getFirstTerminator(), DL, AArch64::SP, AArch64::SP,
1691 false, NeedsWinCFI, &HasWinCFI, EmitCFI,
1692 StackOffset::getFixed(AfterCSRPopSize - ArgumentStackToRestore));
1693 }
1694}
1695
1696bool AArch64EpilogueEmitter::shouldCombineCSRLocalStackBump(
1697 uint64_t StackBumpBytes) const {
1699 StackBumpBytes))
1700 return false;
1701 if (MBB.empty())
1702 return true;
1703
1704 // Disable combined SP bump if the last instruction is an MTE tag store. It
1705 // is almost always better to merge SP adjustment into those instructions.
1706 MachineBasicBlock::iterator LastI = MBB.getFirstTerminator();
1707 MachineBasicBlock::iterator Begin = MBB.begin();
1708 while (LastI != Begin) {
1709 --LastI;
1710 if (LastI->isTransient())
1711 continue;
1712 if (!LastI->getFlag(MachineInstr::FrameDestroy))
1713 break;
1714 }
1715 switch (LastI->getOpcode()) {
1716 case AArch64::STGloop:
1717 case AArch64::STZGloop:
1718 case AArch64::STGi:
1719 case AArch64::STZGi:
1720 case AArch64::ST2Gi:
1721 case AArch64::STZ2Gi:
1722 return false;
1723 default:
1724 return true;
1725 }
1726 llvm_unreachable("unreachable");
1727}
1728
1729void AArch64EpilogueEmitter::emitSwiftAsyncContextFramePointer(
1731 switch (MF.getTarget().Options.SwiftAsyncFramePointer) {
1733 // Avoid the reload as it is GOT relative, and instead fall back to the
1734 // hardcoded value below. This allows a mismatch between the OS and
1735 // application without immediately terminating on the difference.
1736 [[fallthrough]];
1738 // We need to reset FP to its untagged state on return. Bit 60 is
1739 // currently used to show the presence of an extended frame.
1740
1741 // BIC x29, x29, #0x1000_0000_0000_0000
1742 BuildMI(MBB, MBB.getFirstTerminator(), DL, TII->get(AArch64::ANDXri),
1743 AArch64::FP)
1744 .addUse(AArch64::FP)
1745 .addImm(0x10fe)
1747 if (NeedsWinCFI) {
1748 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1750 HasWinCFI = true;
1751 }
1752 break;
1753
1755 break;
1756 }
1757}
1758
1759void AArch64EpilogueEmitter::emitShadowCallStackEpilogue(
1761 // Shadow call stack epilog: ldr x30, [x18, #-8]!
1762 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXpre))
1763 .addReg(AArch64::X18, RegState::Define)
1764 .addReg(AArch64::LR, RegState::Define)
1765 .addReg(AArch64::X18)
1766 .addImm(-8)
1768
1769 if (NeedsWinCFI)
1770 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1772
1773 if (AFI->needsAsyncDwarfUnwindInfo(MF))
1774 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameDestroy)
1775 .buildRestore(AArch64::X18);
1776}
1777
1778void AArch64EpilogueEmitter::emitEarlyReturnAddressAuthentication(
1779 MachineBasicBlock::iterator MBBI, int64_t StackSize,
1780 int64_t PrologueSaveSize) {
1781 // Windows unwind info describes authenticating the return address with a
1782 // pac_sign_lr unwind code, which the unwinder applies using the SP it has at
1783 // that point; that is only the SP the return address was signed with if the
1784 // epilogue ends with SP back at its entry value. When it doesn't, we
1785 // authenticate the return address here instead, in the body, where the
1786 // prologue's unwind codes apply and the return address is still signed. The
1787 // epilogue's unwind codes then have no pac_sign_lr, and nor do they restore
1788 // LR: the authenticated return address stays in LR (it is never written back
1789 // to the stack) and the epilogue doesn't reload it. There is no window in
1790 // which the unwinder sees the wrong state: this sequence is immediately
1791 // before the start of the epilogue, so the prologue's codes apply to every
1792 // instruction up to and including the last of it, which recover the signed
1793 // return address from its slot on the stack, and the epilogue's apply after.
1794 if (AFI->hasSVEStackSize())
1795 report_fatal_error("Can't handle a tail call that changes the stack "
1796 "argument size in a function with SVE stack objects "
1797 "that signs its return address on Windows");
1798
1799 // The return address is only on the stack if it was spilled.
1800 std::optional<int> LRFrameIdx;
1801 for (const CalleeSavedInfo &CSI : MFI.getCalleeSavedInfo())
1802 if (CSI.getReg() == AArch64::LR)
1803 LRFrameIdx = CSI.getFrameIdx();
1804
1805 // When the frame is addressed via the FP, the return address is in the frame
1806 // record, at FP + 8. We don't refer to its frame index there because the SP
1807 // is not reliable as a base, and the frame index of a callee-saved register
1808 // isn't always recognised as one on Windows when there is a tail call
1809 // reserve.
1810 bool UseFP = MFI.hasVarSizedObjects() || AFI->isStackRealigned();
1811
1812 // Compute the SP the return address was signed with, which is SP on entry.
1813 int64_t Adjustment =
1814 UseFP ? PrologueSaveSize - AFI->getCalleeSaveBaseToFrameRecordOffset()
1815 : StackSize;
1817 MBB, MBBI, DL, AArch64::X16, UseFP ? AArch64::FP : AArch64::SP,
1819
1820 // LR holds whatever the last call left in it; get the signed return address.
1821 // The authentication sequence expects it in X17 if it works on that and moves
1822 // the result to LR, which saves a copy.
1824 AFI->branchProtectionPAuthLR(), Subtarget.hasPAuth());
1825 Register SignedLR = InX17 ? Register(AArch64::X17) : Register(AArch64::LR);
1826 if (LRFrameIdx) {
1827 MachineInstrBuilder MIB =
1828 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui), SignedLR);
1829 if (UseFP)
1830 MIB.addReg(AArch64::FP).addImm(1);
1831 else
1832 MIB.addFrameIndex(*LRFrameIdx).addImm(0);
1833 MIB.addMemOperand(MF.getMachineMemOperand(
1836 } else if (InX17) {
1837 // The return address was never spilled, so it is still in LR.
1838 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::X17)
1839 .addReg(AArch64::XZR)
1840 .addReg(AArch64::LR)
1841 .addImm(0);
1842 }
1843
1844 auto Builder =
1845 BuildMI(MBB, MBBI, DL, TII->get(AArch64::PAUTH_EPILOGUE_ENTRY_SP));
1846 Builder.addReg(AArch64::X16, RegState::Implicit);
1847 if (InX17) {
1848 Builder.addReg(AArch64::X17, RegState::Implicit);
1849 // The pseudo's implicit use of LR is not a real one here; the signed return
1850 // address is in X17, and LR only gets written.
1851 Builder->findRegisterUseOperand(AArch64::LR, &RegInfo)->setIsUndef();
1852 }
1853 Builder.addReg(AArch64::X17, RegState::ImplicitDefine);
1854 if (AFI->branchProtectionPAuthLR())
1855 Builder.addReg(AArch64::X15, RegState::ImplicitDefine);
1856
1857 // This takes the place of the pseudo that would otherwise go at the end.
1858 for (MachineInstr &MI : llvm::make_early_inc_range(MBB))
1859 if (MI.getOpcode() == AArch64::PAUTH_EPILOGUE)
1860 MI.eraseFromParent();
1861 AuthenticatedReturnAddressEarly = true;
1862}
1863
1864void AArch64EpilogueEmitter::emitCalleeSavedRestores(
1865 MachineBasicBlock::iterator MBBI, bool SVE) const {
1866 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
1867 if (CSI.empty())
1868 return;
1869
1870 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameDestroy);
1871
1872 for (const auto &Info : CSI) {
1873 if (SVE != MFI.hasScalableStackID(Info.getFrameIdx()))
1874 continue;
1875
1876 MCRegister Reg = Info.getReg();
1877 if (SVE && !RegInfo.regNeedsCFI(Reg, Reg))
1878 continue;
1879
1880 CFIBuilder.buildRestore(Info.getReg());
1881 }
1882}
1883
1884bool AArch64EpilogueEmitter::hasEpilogueUnwindOps() const {
1885 // The return address is authenticated by an unwind op that the
1886 // AArch64PointerAuth pass adds later, or, if it was authenticated early, the
1887 // epilogue's unwind codes are what keep the prologue's pac_sign_lr from being
1888 // applied again, even if there is nothing else in them.
1889 if (AFI->shouldSignReturnAddress(MF))
1890 return true;
1891 return std::any_of(std::next(SEHEpilogueStartI), MBB.end(),
1892 [](const MachineInstr &MI) {
1893 return AArch64InstrInfo::isSEHInstruction(MI) &&
1894 MI.getOpcode() != AArch64::SEH_EpilogEnd;
1895 });
1896}
1897
1898void AArch64EpilogueEmitter::finalizeEpilogue() const {
1899 // All calls are tail calls in GHC calling conv, and functions have no
1900 // prologue/epilogue.
1901 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
1902 return;
1903
1904 if (AFI->needsShadowCallStackPrologueEpilogue(MF)) {
1905 emitShadowCallStackEpilogue(MBB.getFirstTerminator(), DL);
1907 }
1908 if (EmitCFI)
1909 emitCalleeSavedGPRRestores(MBB.getFirstTerminator());
1910 if (AFI->shouldSignReturnAddress(MF)) {
1911 // If pac-ret+leaf is in effect, PAUTH_EPILOGUE pseudo instructions
1912 // are inserted by emitPacRetPlusLeafHardening().
1913 if (!AFL.shouldSignReturnAddressEverywhere(MF) &&
1914 !AuthenticatedReturnAddressEarly)
1915 TII->createPauthEpilogueInstr(MBB, DL);
1916 // AArch64PointerAuth pass will insert SEH_PACSignLR, unless the return
1917 // address was authenticated early (see
1918 // emitEarlyReturnAddressAuthentication()).
1920 }
1921 // A tail call leaves the stack arguments for the tail callee, which pops them
1922 // itself. Until then the unwinder must pop them to recover the caller's SP,
1923 // as in the prologue; there is no instruction to describe that, so it goes
1924 // after end_c. An epilogue with no unwind ops of its own gains nothing from
1925 // this, as the prologue's codes cover it.
1926 if (NeedsWinCFI && HasWinCFI && !IsFunclet && hasEpilogueUnwindOps()) {
1927 int64_t TailCalleePopBytes = AFI->getArgumentStackToRestore() -
1928 AFL.getArgumentStackToRestore(MF, MBB);
1929 if (TailCalleePopBytes > 0) {
1930 BuildMI(MBB, MBB.getFirstTerminator(), DL, TII->get(AArch64::SEH_EndC))
1932 BuildMI(MBB, MBB.getFirstTerminator(), DL,
1933 TII->get(AArch64::SEH_StackAlloc))
1934 .addImm(TailCalleePopBytes)
1936 HasWinCFI = true;
1937 }
1938 }
1939 if (HasWinCFI) {
1940 BuildMI(MBB, MBB.getFirstTerminator(), DL, TII->get(AArch64::SEH_EpilogEnd))
1942 if (!MF.hasWinCFI())
1943 MF.setHasWinCFI(true);
1944 }
1945 if (NeedsWinCFI) {
1946 assert(SEHEpilogueStartI != MBB.end());
1947 if (!HasWinCFI)
1948 MBB.erase(SEHEpilogueStartI);
1949 }
1950}
1951
1952} // 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:352
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...
constexpr bool authenticatesLRViaX17(bool BranchProtectionPAuthLR, bool HasPAuth)
Controls whether, for PAUTH_EPILOGUE_ENTRY_SP, we use the hint-space AUTI[AB]1716 instruction to auth...
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.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:649
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.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
MachineBasicBlock::iterator End
struct llvm::SVEPartitions::@327166152017175235362202041204223104077330276266 ZPR
struct llvm::SVEPartitions::@327166152017175235362202041204223104077330276266 PPR
MachineBasicBlock::iterator Begin