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_SaveAnyRegQ:
256 case AArch64::SEH_SaveAnyRegQX:
257 case AArch64::SEH_SaveAnyRegQP:
258 case AArch64::SEH_SaveAnyRegQPX:
259 ImmOpnd = &MBBI->getOperand(ImmIdx);
260 break;
261 }
262 if (ImmOpnd)
263 ImmOpnd->setImm(ImmOpnd->getImm() + LocalStackSize);
264}
265
267 MachineInstr &MI, uint64_t LocalStackSize) const {
268 if (AArch64InstrInfo::isSEHInstruction(MI))
269 return;
270
271 unsigned Opc = MI.getOpcode();
272 unsigned Scale;
273 switch (Opc) {
274 case AArch64::STPXi:
275 case AArch64::STRXui:
276 case AArch64::STPDi:
277 case AArch64::STRDui:
278 case AArch64::LDPXi:
279 case AArch64::LDRXui:
280 case AArch64::LDPDi:
281 case AArch64::LDRDui:
282 Scale = 8;
283 break;
284 case AArch64::STPQi:
285 case AArch64::STRQui:
286 case AArch64::LDPQi:
287 case AArch64::LDRQui:
288 Scale = 16;
289 break;
290 default:
291 llvm_unreachable("Unexpected callee-save save/restore opcode!");
292 }
293
294 unsigned OffsetIdx = MI.getNumExplicitOperands() - 1;
295 assert(MI.getOperand(OffsetIdx - 1).getReg() == AArch64::SP &&
296 "Unexpected base register in callee-save save/restore instruction!");
297 // Last operand is immediate offset that needs fixing.
298 MachineOperand &OffsetOpnd = MI.getOperand(OffsetIdx);
299 // All generated opcodes have scaled offsets.
300 assert(LocalStackSize % Scale == 0);
301 OffsetOpnd.setImm(OffsetOpnd.getImm() + LocalStackSize / Scale);
302
303 if (NeedsWinCFI) {
304 HasWinCFI = true;
305 auto MBBI = std::next(MachineBasicBlock::iterator(MI));
306 assert(MBBI != MI.getParent()->end() && "Expecting a valid instruction");
307 assert(AArch64InstrInfo::isSEHInstruction(*MBBI) &&
308 "Expecting a SEH instruction");
309 fixupSEHOpcode(MBBI, LocalStackSize);
310 }
311}
312
314 uint64_t StackBumpBytes) const {
315 if (AFL.homogeneousPrologEpilog(MF))
316 return false;
317
318 if (AFI->getLocalStackSize() == 0)
319 return false;
320
321 // For WinCFI, if optimizing for size, prefer to not combine the stack bump
322 // (to force a stp with predecrement) to match the packed unwind format,
323 // provided that there actually are any callee saved registers to merge the
324 // decrement with.
325 //
326 // Note that for certain paired saves, like "x19, lr", we can't actually
327 // emit an predecrement stp, but packed unwind still expects a separate stack
328 // adjustment.
329 //
330 // This is potentially marginally slower, but allows using the packed
331 // unwind format for functions that both have a local area and callee saved
332 // registers. Using the packed unwind format notably reduces the size of
333 // the unwind info.
334 if (MF.needsWinCFI() && AFI->getCalleeSavedStackSize() > 0 &&
335 MF.getFunction().hasOptSize())
336 return false;
337
338 // 512 is the maximum immediate for stp/ldp that will be used for
339 // callee-save save/restores
340 if (StackBumpBytes >= 512 ||
341 AFL.windowsRequiresStackProbe(MF, StackBumpBytes))
342 return false;
343
344 if (MFI.hasVarSizedObjects())
345 return false;
346
347 if (RegInfo.hasStackRealignment(MF))
348 return false;
349
350 // This isn't strictly necessary, but it simplifies things a bit since the
351 // current RedZone handling code assumes the SP is adjusted by the
352 // callee-save save/restore code.
353 if (AFL.canUseRedZone(MF))
354 return false;
355
356 // When there is an SVE area on the stack, always allocate the
357 // callee-saves and spills/locals separately.
358 if (AFI->hasSVEStackSize())
359 return false;
360
361 return true;
362}
363
365 StackOffset PPRCalleeSavesSize =
366 StackOffset::getScalable(AFI->getPPRCalleeSavedStackSize());
367 StackOffset ZPRCalleeSavesSize =
368 StackOffset::getScalable(AFI->getZPRCalleeSavedStackSize());
369 StackOffset PPRLocalsSize = AFL.getPPRStackSize(MF) - PPRCalleeSavesSize;
370 StackOffset ZPRLocalsSize = AFL.getZPRStackSize(MF) - ZPRCalleeSavesSize;
372 return {{PPRCalleeSavesSize, PPRLocalsSize},
373 {ZPRCalleeSavesSize, ZPRLocalsSize}};
374 // For simplicity, attribute all locals to ZPRs when split SVE is disabled.
375 return {{PPRCalleeSavesSize, StackOffset{}},
376 {ZPRCalleeSavesSize, PPRLocalsSize + ZPRLocalsSize}};
377}
378
380 SVEFrameSizes const &SVE) {
381 StackOffset AfterZPRs = SVE.ZPR.LocalsSize;
382 StackOffset BeforePPRs = SVE.ZPR.CalleeSavesSize + SVE.PPR.CalleeSavesSize;
383 StackOffset AfterPPRs = {};
385 BeforePPRs = SVE.PPR.CalleeSavesSize;
386 // If there are no ZPR CSRs, place all local allocations after the ZPRs.
387 if (SVE.ZPR.CalleeSavesSize)
388 AfterPPRs += SVE.PPR.LocalsSize + SVE.ZPR.CalleeSavesSize;
389 else
390 AfterZPRs += SVE.PPR.LocalsSize; // Group allocation of locals.
391 }
392 return {BeforePPRs, AfterPPRs, AfterZPRs};
393}
394
400
403 StackOffset PPRCalleeSavesSize,
404 StackOffset ZPRCalleeSavesSize,
405 bool IsEpilogue) {
408 IsEpilogue ? MBB.begin() : MBB.getFirstTerminator();
409 auto AdjustI = [&](auto MBBI) { return IsEpilogue ? std::prev(MBBI) : MBBI; };
410 // Process the SVE CS to find the starts/ends of the ZPR and PPR areas.
411 if (PPRCalleeSavesSize) {
412 PPRsI = AdjustI(PPRsI);
413 assert(isPartOfPPRCalleeSaves(*PPRsI) && "Unexpected instruction");
414 while (PPRsI != End && isPartOfPPRCalleeSaves(AdjustI(PPRsI)))
415 IsEpilogue ? (--PPRsI) : (++PPRsI);
416 }
417 MachineBasicBlock::iterator ZPRsI = PPRsI;
418 if (ZPRCalleeSavesSize) {
419 ZPRsI = AdjustI(ZPRsI);
420 assert(isPartOfZPRCalleeSaves(*ZPRsI) && "Unexpected instruction");
421 while (ZPRsI != End && isPartOfZPRCalleeSaves(AdjustI(ZPRsI)))
422 IsEpilogue ? (--ZPRsI) : (++ZPRsI);
423 }
424 if (IsEpilogue)
425 return {{PPRsI, MBBI}, {ZPRsI, PPRsI}};
426 return {{MBBI, PPRsI}, {PPRsI, ZPRsI}};
427}
428
433 EmitCFI = AFI->needsDwarfUnwindInfo(MF);
434 EmitAsyncCFI = AFI->needsAsyncDwarfUnwindInfo(MF);
435 IsFunclet = MBB.isEHFuncletEntry();
436 HomPrologEpilog = AFL.homogeneousPrologEpilog(MF);
437
438#ifndef NDEBUG
439 collectBlockLiveins();
440#endif
441}
442
443#ifndef NDEBUG
444/// Collect live registers from the end of \p MI's parent up to (including) \p
445/// MI in \p LiveRegs.
448
449 MachineBasicBlock &MBB = *MI.getParent();
450 LiveRegs.addLiveOuts(MBB);
451 for (const MachineInstr &MI :
452 reverse(make_range(MI.getIterator(), MBB.instr_end())))
453 LiveRegs.stepBackward(MI);
454}
455
456void AArch64PrologueEmitter::collectBlockLiveins() {
457 // Collect live register from the end of MBB up to the start of the existing
458 // frame setup instructions.
459 PrologueEndI = MBB.begin();
460 while (PrologueEndI != MBB.end() &&
461 PrologueEndI->getFlag(MachineInstr::FrameSetup))
462 ++PrologueEndI;
463
464 if (PrologueEndI != MBB.end()) {
465 getLivePhysRegsUpTo(*PrologueEndI, RegInfo, LiveRegs);
466 // Ignore registers used for stack management for now.
467 LiveRegs.removeReg(AArch64::SP);
468 LiveRegs.removeReg(AArch64::X19);
469 LiveRegs.removeReg(AArch64::FP);
470 LiveRegs.removeReg(AArch64::LR);
471
472 // X0 will be clobbered by a call to __arm_get_current_vg in the prologue.
473 // This is necessary to spill VG if required where SVE is unavailable, but
474 // X0 is preserved around this call.
475 if (requiresGetVGCall())
476 LiveRegs.removeReg(AArch64::X0);
477 }
478}
479
480void AArch64PrologueEmitter::verifyPrologueClobbers() const {
481 if (PrologueEndI == MBB.end())
482 return;
483 // Check if any of the newly instructions clobber any of the live registers.
484 for (MachineInstr &MI :
485 make_range(MBB.instr_begin(), PrologueEndI->getIterator())) {
486 for (auto &Op : MI.operands())
487 if (Op.isReg() && Op.isDef())
488 assert(!LiveRegs.contains(Op.getReg()) &&
489 "live register clobbered by inserted prologue instructions");
490 }
491}
492#endif
493
494void AArch64PrologueEmitter::determineLocalsStackSize(
495 uint64_t StackSize, uint64_t PrologueSaveSize) {
496 AFI->setLocalStackSize(StackSize - PrologueSaveSize);
497 CombineSPBump = shouldCombineCSRLocalStackBump(StackSize);
498}
499
500// Return the maximum possible number of bytes for `Size` due to the
501// architectural limit on the size of a SVE register.
502static int64_t upperBound(StackOffset Size) {
503 static const int64_t MAX_BYTES_PER_SCALABLE_BYTE = 16;
504 return Size.getScalable() * MAX_BYTES_PER_SCALABLE_BYTE + Size.getFixed();
505}
506
507void AArch64PrologueEmitter::allocateStackSpace(
508 MachineBasicBlock::iterator MBBI, int64_t RealignmentPadding,
509 StackOffset AllocSize, bool EmitCFI, StackOffset InitialOffset,
510 bool FollowupAllocs) {
511
512 if (!AllocSize)
513 return;
514
515 DebugLoc DL;
516 const int64_t MaxAlign = MFI.getMaxAlign().value();
517 const uint64_t AndMask = ~(MaxAlign - 1);
518
520 Register TargetReg = RealignmentPadding
521 ? AFL.findScratchNonCalleeSaveRegister(&MBB)
522 : AArch64::SP;
523 // SUB Xd/SP, SP, AllocSize
524 emitFrameOffset(MBB, MBBI, DL, TargetReg, AArch64::SP, -AllocSize, TII,
526 EmitCFI, InitialOffset);
527
528 if (RealignmentPadding) {
529 // AND SP, X9, 0b11111...0000
530 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), AArch64::SP)
531 .addReg(TargetReg, RegState::Kill)
534 AFI->setStackRealigned(true);
535
536 // No need for SEH instructions here; if we're realigning the stack,
537 // we've set a frame pointer and already finished the SEH prologue.
539 }
540 return;
541 }
542
543 //
544 // Stack probing allocation.
545 //
546
547 // Fixed length allocation. If we don't need to re-align the stack and don't
548 // have SVE objects, we can use a more efficient sequence for stack probing.
549 if (AllocSize.getScalable() == 0 && RealignmentPadding == 0) {
550 Register ScratchReg = AFL.findScratchNonCalleeSaveRegister(&MBB);
551 assert(ScratchReg.isValid());
552 BuildMI(MBB, MBBI, DL, TII->get(AArch64::PROBED_STACKALLOC))
553 .addDef(ScratchReg)
554 .addImm(AllocSize.getFixed())
555 .addImm(InitialOffset.getFixed())
556 .addImm(InitialOffset.getScalable());
557 // The fixed allocation may leave unprobed bytes at the top of the
558 // stack. If we have subsequent allocation (e.g. if we have variable-sized
559 // objects), we need to issue an extra probe, so these allocations start in
560 // a known state.
561 if (FollowupAllocs) {
562 // LDR XZR, [SP]
563 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui))
564 .addDef(AArch64::XZR)
565 .addReg(AArch64::SP)
566 .addImm(0)
567 .addMemOperand(MF.getMachineMemOperand(
570 Align(8)))
572 }
573
574 return;
575 }
576
577 // Variable length allocation.
578
579 // If the (unknown) allocation size cannot exceed the probe size, decrement
580 // the stack pointer right away.
581 int64_t ProbeSize = AFI->getStackProbeSize();
582 if (upperBound(AllocSize) + RealignmentPadding <= ProbeSize) {
583 Register ScratchReg = RealignmentPadding
584 ? AFL.findScratchNonCalleeSaveRegister(&MBB)
585 : AArch64::SP;
586 assert(ScratchReg.isValid());
587 // SUB Xd, SP, AllocSize
588 emitFrameOffset(MBB, MBBI, DL, ScratchReg, AArch64::SP, -AllocSize, TII,
590 EmitCFI, InitialOffset);
591 if (RealignmentPadding) {
592 // AND SP, Xn, 0b11111...0000
593 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), AArch64::SP)
594 .addReg(ScratchReg, RegState::Kill)
597 AFI->setStackRealigned(true);
598 }
599 if (FollowupAllocs || upperBound(AllocSize) + RealignmentPadding >
601 // LDR XZR, [SP]
602 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui))
603 .addDef(AArch64::XZR)
604 .addReg(AArch64::SP)
605 .addImm(0)
606 .addMemOperand(MF.getMachineMemOperand(
609 Align(8)))
611 }
612 return;
613 }
614
615 // Emit a variable-length allocation probing loop.
616 // TODO: As an optimisation, the loop can be "unrolled" into a few parts,
617 // each of them guaranteed to adjust the stack by less than the probe size.
618 Register TargetReg = AFL.findScratchNonCalleeSaveRegister(&MBB);
619 assert(TargetReg.isValid());
620 // SUB Xd, SP, AllocSize
621 emitFrameOffset(MBB, MBBI, DL, TargetReg, AArch64::SP, -AllocSize, TII,
623 EmitCFI, InitialOffset);
624 if (RealignmentPadding) {
625 // AND Xn, Xn, 0b11111...0000
626 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), TargetReg)
627 .addReg(TargetReg, RegState::Kill)
630 }
631
632 BuildMI(MBB, MBBI, DL, TII->get(AArch64::PROBED_STACKALLOC_VAR))
633 .addReg(TargetReg);
634 if (EmitCFI) {
635 // Set the CFA register back to SP.
636 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
637 .buildDefCFARegister(AArch64::SP);
638 }
639 if (RealignmentPadding)
640 AFI->setStackRealigned(true);
641}
642
644 const MachineBasicBlock::iterator PrologueBeginI = MBB.begin();
645 const MachineBasicBlock::iterator EndI = MBB.end();
646
647 // At this point, we're going to decide whether or not the function uses a
648 // redzone. In most cases, the function doesn't have a redzone so let's
649 // assume that's false and set it to true in the case that there's a redzone.
650 AFI->setHasRedZone(false);
651
652 // Debug location must be unknown since the first debug location is used
653 // to determine the end of the prologue.
654 DebugLoc DL;
655
656 // In some cases, particularly with CallingConv::SwiftTail, it is possible to
657 // have a tail-call where the caller only needs to adjust the stack pointer in
658 // the epilogue. In this case, we still need to emit a SEH prologue sequence.
659 // See `seh-minimal-prologue-epilogue.ll` test cases.
660 if (int64_t ArgBytes = AFI->getArgumentStackToRestore()) {
662
663 // The callee pops its stack arguments, so once the unwinder has undone
664 // the prologue it must also pop them to recover the caller's SP. The
665 // opcodes before end_c don't correspond to instructions, so describe the
666 // pop there.
667 if (NeedsWinCFI && !IsFunclet) {
668 BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::SEH_StackAlloc))
669 .addImm(ArgBytes)
671 BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::SEH_EndC))
673 }
674 }
675
676 if (AFI->shouldSignReturnAddress(MF)) {
677 // If pac-ret+leaf is in effect, PAUTH_PROLOGUE pseudo instructions
678 // are inserted by emitPacRetPlusLeafHardening().
679 if (!AFL.shouldSignReturnAddressEverywhere(MF)) {
680 BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::PAUTH_PROLOGUE))
682 }
683 // AArch64PointerAuth pass will insert SEH_PACSignLR
685 }
686
687 if (AFI->needsShadowCallStackPrologueEpilogue(MF)) {
688 emitShadowCallStackPrologue(PrologueBeginI, DL);
690 }
691
692 if (EmitCFI && AFI->isMTETagged())
693 BuildMI(MBB, PrologueBeginI, DL, TII->get(AArch64::EMITMTETAGGED))
695
696 // We signal the presence of a Swift extended frame to external tools by
697 // storing FP with 0b0001 in bits 63:60. In normal userland operation a simple
698 // ORR is sufficient, it is assumed a Swift kernel would initialize the TBI
699 // bits so that is still true.
700 if (HasFP && AFI->hasSwiftAsyncContext())
701 emitSwiftAsyncContextFramePointer(PrologueBeginI, DL);
702
703 // All calls are tail calls in GHC calling conv, and functions have no
704 // prologue/epilogue.
705 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
706 return;
707
708 // Set tagged base pointer to the requested stack slot. Ideally it should
709 // match SP value after prologue.
710 if (std::optional<int> TBPI = AFI->getTaggedBasePointerIndex())
711 AFI->setTaggedBasePointerOffset(-MFI.getObjectOffset(*TBPI));
712 else
713 AFI->setTaggedBasePointerOffset(MFI.getStackSize());
714
715 // getStackSize() includes all the locals in its size calculation. We don't
716 // include these locals when computing the stack size of a funclet, as they
717 // are allocated in the parent's stack frame and accessed via the frame
718 // pointer from the funclet. We only save the callee saved registers in the
719 // funclet, which are really the callee saved registers of the parent
720 // function, including the funclet.
721 int64_t NumBytes =
722 IsFunclet ? AFL.getWinEHFuncletFrameSize(MF) : MFI.getStackSize();
723 if (!AFI->hasStackFrame() && !AFL.windowsRequiresStackProbe(MF, NumBytes))
724 return emitEmptyStackFramePrologue(NumBytes, PrologueBeginI, DL);
725
726 bool IsWin64 = Subtarget.isCallingConvWin64(F.getCallingConv(), F.isVarArg());
727 unsigned FixedObject = AFL.getFixedObjectSize(MF, AFI, IsWin64, IsFunclet);
728
729 auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
730 // All of the remaining stack allocations are for locals.
731 determineLocalsStackSize(NumBytes, PrologueSaveSize);
732
733 auto [PPR, ZPR] = getSVEStackFrameSizes();
734 SVEStackAllocations SVEAllocs = getSVEStackAllocations({PPR, ZPR});
735
736 MachineBasicBlock::iterator FirstGPRSaveI = PrologueBeginI;
738 assert(!SVEAllocs.AfterPPRs &&
739 "unexpected SVE allocs after PPRs with CalleeSavesAboveFrameRecord");
740 // If we're doing SVE saves first, we need to immediately allocate space
741 // for fixed objects, then space for the SVE callee saves.
742 //
743 // Windows unwind requires that the scalable size is a multiple of 16;
744 // that's handled when the callee-saved size is computed.
745 auto SaveSize = SVEAllocs.BeforePPRs + StackOffset::getFixed(FixedObject);
746 allocateStackSpace(PrologueBeginI, 0, SaveSize, false, StackOffset{},
747 /*FollowupAllocs=*/true);
748 NumBytes -= FixedObject;
749
750 // Now allocate space for the GPR callee saves.
751 MachineBasicBlock::iterator MBBI = PrologueBeginI;
752 while (MBBI != EndI && isPartOfSVECalleeSaves(MBBI))
753 ++MBBI;
755 MBBI, DL, -AFI->getCalleeSavedStackSize(), EmitAsyncCFI);
756 NumBytes -= AFI->getCalleeSavedStackSize();
757 } else if (CombineSPBump) {
758 assert(!AFL.getSVEStackSize(MF) && "Cannot combine SP bump with SVE");
759 emitFrameOffset(MBB, PrologueBeginI, DL, AArch64::SP, AArch64::SP,
760 StackOffset::getFixed(-NumBytes), TII,
762 EmitAsyncCFI);
763 NumBytes = 0;
764 } else if (HomPrologEpilog) {
765 // Stack has been already adjusted.
766 NumBytes -= PrologueSaveSize;
767 } else if (PrologueSaveSize != 0) {
769 PrologueBeginI, DL, -PrologueSaveSize, EmitAsyncCFI);
770 NumBytes -= PrologueSaveSize;
771 }
772 assert(NumBytes >= 0 && "Negative stack allocation size!?");
773
774 // Move past the saves of the callee-saved registers, fixing up the offsets
775 // and pre-inc if we decided to combine the callee-save and local stack
776 // pointer bump above.
777 auto &TLI = *Subtarget.getTargetLowering();
778
779 MachineBasicBlock::iterator AfterGPRSavesI = FirstGPRSaveI;
780 while (AfterGPRSavesI != EndI &&
781 AfterGPRSavesI->getFlag(MachineInstr::FrameSetup) &&
782 !isPartOfSVECalleeSaves(AfterGPRSavesI)) {
783 if (CombineSPBump &&
784 // Only fix-up frame-setup load/store instructions.
785 (!AFL.requiresSaveVG(MF) || !isVGInstruction(AfterGPRSavesI, TLI)))
786 fixupCalleeSaveRestoreStackOffset(*AfterGPRSavesI,
787 AFI->getLocalStackSize());
788 ++AfterGPRSavesI;
789 }
790
791 // For funclets the FP belongs to the containing function. Only set up FP if
792 // we actually need to.
793 if (!IsFunclet && HasFP)
794 emitFramePointerSetup(AfterGPRSavesI, DL, FixedObject);
795
796 // Now emit the moves for whatever callee saved regs we have (including FP,
797 // LR if those are saved). Frame instructions for SVE register are emitted
798 // later, after the instruction which actually save SVE regs.
799 if (EmitAsyncCFI)
800 emitCalleeSavedGPRLocations(AfterGPRSavesI);
801
802 // Alignment is required for the parent frame, not the funclet
803 const bool NeedsRealignment =
804 NumBytes && !IsFunclet && RegInfo.hasStackRealignment(MF);
805 const int64_t RealignmentPadding =
806 (NeedsRealignment && MFI.getMaxAlign() > Align(16))
807 ? MFI.getMaxAlign().value() - 16
808 : 0;
809
810 if (AFL.windowsRequiresStackProbe(MF, NumBytes + RealignmentPadding))
811 emitWindowsStackProbe(AfterGPRSavesI, DL, NumBytes, RealignmentPadding);
812
813 StackOffset NonSVELocalsSize = StackOffset::getFixed(NumBytes);
814 SVEAllocs.AfterZPRs += NonSVELocalsSize;
815
816 StackOffset CFAOffset =
817 StackOffset::getFixed(MFI.getStackSize()) - NonSVELocalsSize;
818 MachineBasicBlock::iterator AfterSVESavesI = AfterGPRSavesI;
819 // Allocate space for the callee saves and PPR locals (if any).
821 auto [PPRRange, ZPRRange] =
822 partitionSVECS(MBB, AfterGPRSavesI, PPR.CalleeSavesSize,
823 ZPR.CalleeSavesSize, /*IsEpilogue=*/false);
824 AfterSVESavesI = ZPRRange.End;
825 if (EmitAsyncCFI)
826 emitCalleeSavedSVELocations(AfterSVESavesI);
827
828 allocateStackSpace(PPRRange.Begin, 0, SVEAllocs.BeforePPRs,
829 EmitAsyncCFI && !HasFP, CFAOffset,
830 MFI.hasVarSizedObjects() || SVEAllocs.AfterPPRs ||
831 SVEAllocs.AfterZPRs);
832 CFAOffset += SVEAllocs.BeforePPRs;
833 assert(PPRRange.End == ZPRRange.Begin &&
834 "Expected ZPR callee saves after PPR locals");
835 allocateStackSpace(PPRRange.End, 0, SVEAllocs.AfterPPRs,
836 EmitAsyncCFI && !HasFP, CFAOffset,
837 MFI.hasVarSizedObjects() || SVEAllocs.AfterZPRs);
838 CFAOffset += SVEAllocs.AfterPPRs;
839 } else {
841 // Note: With CalleeSavesAboveFrameRecord, the SVE CS (BeforePPRs) have
842 // already been allocated. PPR locals (included in AfterPPRs) are not
843 // supported (note: this is asserted above).
844 CFAOffset += SVEAllocs.BeforePPRs;
845 }
846
847 // Allocate space for the rest of the frame including ZPR locals. Align the
848 // stack as necessary.
849 assert(!(AFL.canUseRedZone(MF) && NeedsRealignment) &&
850 "Cannot use redzone with stack realignment");
851 if (!AFL.canUseRedZone(MF)) {
852 // FIXME: in the case of dynamic re-alignment, NumBytes doesn't have the
853 // correct value here, as NumBytes also includes padding bytes, which
854 // shouldn't be counted here.
855 allocateStackSpace(AfterSVESavesI, RealignmentPadding, SVEAllocs.AfterZPRs,
856 EmitAsyncCFI && !HasFP, CFAOffset,
857 MFI.hasVarSizedObjects());
858 }
859
860 // If we need a base pointer, set it up here. It's whatever the value of the
861 // stack pointer is at this point. Any variable size objects will be
862 // allocated after this, so we can still use the base pointer to reference
863 // locals.
864 //
865 // FIXME: Clarify FrameSetup flags here.
866 // Note: Use emitFrameOffset() like above for FP if the FrameSetup flag is
867 // needed.
868 // For funclets the BP belongs to the containing function.
869 if (!IsFunclet && RegInfo.hasBasePointer(MF)) {
870 TII->copyPhysReg(MBB, AfterSVESavesI, DL, RegInfo.getBaseRegister(),
871 AArch64::SP, false);
872 if (NeedsWinCFI) {
873 HasWinCFI = true;
874 BuildMI(MBB, AfterSVESavesI, DL, TII->get(AArch64::SEH_Nop))
876 }
877 }
878
879 // The very last FrameSetup instruction indicates the end of prologue. Emit a
880 // SEH opcode indicating the prologue end.
881 if (NeedsWinCFI && HasWinCFI) {
882 BuildMI(MBB, AfterSVESavesI, DL, TII->get(AArch64::SEH_PrologEnd))
884 }
885
886 // SEH funclets are passed the frame pointer in X1. If the parent
887 // function uses the base register, then the base register is used
888 // directly, and is not retrieved from X1.
889 if (IsFunclet && F.hasPersonalityFn()) {
890 EHPersonality Per = classifyEHPersonality(F.getPersonalityFn());
892 BuildMI(MBB, AfterSVESavesI, DL, TII->get(TargetOpcode::COPY),
893 AArch64::FP)
894 .addReg(AArch64::X1)
896 MBB.addLiveIn(AArch64::X1);
897 }
898 }
899
900 if (EmitCFI && !EmitAsyncCFI) {
901 if (HasFP) {
902 emitDefineCFAWithFP(AfterSVESavesI, FixedObject);
903 } else {
904 StackOffset TotalSize =
905 AFL.getSVEStackSize(MF) +
906 StackOffset::getFixed((int64_t)MFI.getStackSize());
907 CFIInstBuilder CFIBuilder(MBB, AfterSVESavesI, MachineInstr::FrameSetup);
908 CFIBuilder.insertCFIInst(
909 createDefCFA(RegInfo, /*FrameReg=*/AArch64::SP, /*Reg=*/AArch64::SP,
910 TotalSize, /*LastAdjustmentWasScalable=*/false));
911 }
912 emitCalleeSavedGPRLocations(AfterSVESavesI);
913 emitCalleeSavedSVELocations(AfterSVESavesI);
914 }
915}
916
917void AArch64PrologueEmitter::emitShadowCallStackPrologue(
919 // Shadow call stack prolog: str x30, [x18], #8
920 BuildMI(MBB, MBBI, DL, TII->get(AArch64::STRXpost))
921 .addReg(AArch64::X18, RegState::Define)
922 .addReg(AArch64::LR)
923 .addReg(AArch64::X18)
924 .addImm(8)
926
927 // This instruction also makes x18 live-in to the entry block.
928 MBB.addLiveIn(AArch64::X18);
929
930 if (NeedsWinCFI)
931 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
933
934 if (EmitCFI) {
935 // Emit a CFI instruction that causes 8 to be subtracted from the value of
936 // x18 when unwinding past this frame.
937 static const char CFIInst[] = {
938 dwarf::DW_CFA_val_expression,
939 18, // register
940 2, // length
941 static_cast<char>(unsigned(dwarf::DW_OP_breg18)),
942 static_cast<char>(-8) & 0x7f, // addend (sleb128)
943 };
944 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
945 .buildEscape(StringRef(CFIInst, sizeof(CFIInst)));
946 }
947}
948
949void AArch64PrologueEmitter::emitSwiftAsyncContextFramePointer(
951 switch (MF.getTarget().Options.SwiftAsyncFramePointer) {
953 if (Subtarget.swiftAsyncContextIsDynamicallySet()) {
954 // The special symbol below is absolute and has a *value* that can be
955 // combined with the frame pointer to signal an extended frame.
956 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LOADgot), AArch64::X16)
957 .addExternalSymbol("swift_async_extendedFramePointerFlags",
959 if (NeedsWinCFI) {
960 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
962 HasWinCFI = true;
963 }
964 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::FP)
965 .addUse(AArch64::FP)
966 .addUse(AArch64::X16)
967 .addImm(Subtarget.isTargetILP32() ? 32 : 0);
968 if (NeedsWinCFI) {
969 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
971 HasWinCFI = true;
972 }
973 break;
974 }
975 [[fallthrough]];
976
978 // ORR x29, x29, #0x1000_0000_0000_0000
979 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXri), AArch64::FP)
980 .addUse(AArch64::FP)
981 .addImm(0x1100)
983 if (NeedsWinCFI) {
984 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
986 HasWinCFI = true;
987 }
988 break;
989
991 break;
992 }
993}
994
995void AArch64PrologueEmitter::emitEmptyStackFramePrologue(
996 int64_t NumBytes, MachineBasicBlock::iterator MBBI,
997 const DebugLoc &DL) const {
998 assert(!HasFP && "unexpected function without stack frame but with FP");
999 assert(!AFL.getSVEStackSize(MF) &&
1000 "unexpected function without stack frame but with SVE objects");
1001 // All of the stack allocation is for locals.
1002 AFI->setLocalStackSize(NumBytes);
1003 if (!NumBytes) {
1004 if (NeedsWinCFI && HasWinCFI) {
1005 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
1007 }
1008 return;
1009 }
1010 // REDZONE: If the stack size is less than 128 bytes, we don't need
1011 // to actually allocate.
1012 if (AFL.canUseRedZone(MF)) {
1013 AFI->setHasRedZone(true);
1014 ++NumRedZoneFunctions;
1015 } else {
1016 emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP,
1017 StackOffset::getFixed(-NumBytes), TII,
1019 if (EmitCFI) {
1020 // Label used to tie together the PROLOG_LABEL and the MachineMoves.
1021 MCSymbol *FrameLabel = MF.getContext().createTempSymbol();
1022 // Encode the stack size of the leaf function.
1023 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
1024 .buildDefCFAOffset(NumBytes, FrameLabel);
1025 }
1026 }
1027
1028 if (NeedsWinCFI) {
1029 HasWinCFI = true;
1030 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
1032 }
1033}
1034
1035void AArch64PrologueEmitter::emitFramePointerSetup(
1037 unsigned FixedObject) {
1038 int64_t FPOffset = AFI->getCalleeSaveBaseToFrameRecordOffset();
1039 if (CombineSPBump)
1040 FPOffset += AFI->getLocalStackSize();
1041
1042 if (AFI->hasSwiftAsyncContext()) {
1043 // Before we update the live FP we have to ensure there's a valid (or
1044 // null) asynchronous context in its slot just before FP in the frame
1045 // record, so store it now.
1046 const auto &Attrs = MF.getFunction().getAttributes();
1047 bool HaveInitialContext = Attrs.hasAttrSomewhere(Attribute::SwiftAsync);
1048 if (HaveInitialContext)
1049 MBB.addLiveIn(AArch64::X22);
1050 Register Reg = HaveInitialContext ? AArch64::X22 : AArch64::XZR;
1051 BuildMI(MBB, MBBI, DL, TII->get(AArch64::StoreSwiftAsyncContext))
1052 .addUse(Reg)
1053 .addUse(AArch64::SP)
1054 .addImm(FPOffset - 8)
1056 if (NeedsWinCFI) {
1057 // WinCFI and arm64e, where StoreSwiftAsyncContext is expanded
1058 // to multiple instructions, should be mutually-exclusive.
1059 assert(Subtarget.getTargetTriple().getArchName() != "arm64e");
1060 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1062 HasWinCFI = true;
1063 }
1064 }
1065
1066 if (HomPrologEpilog) {
1067 auto Prolog = MBBI;
1068 --Prolog;
1069 assert(Prolog->getOpcode() == AArch64::HOM_Prolog);
1070 Prolog->addOperand(MachineOperand::CreateImm(FPOffset));
1071 } else {
1072 // Issue sub fp, sp, FPOffset or
1073 // mov fp,sp when FPOffset is zero.
1074 // Note: All stores of callee-saved registers are marked as "FrameSetup".
1075 // This code marks the instruction(s) that set the FP also.
1076 emitFrameOffset(MBB, MBBI, DL, AArch64::FP, AArch64::SP,
1077 StackOffset::getFixed(FPOffset), TII,
1079 if (NeedsWinCFI && HasWinCFI) {
1080 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
1082 // After setting up the FP, the rest of the prolog doesn't need to be
1083 // included in the SEH unwind info.
1084 NeedsWinCFI = false;
1085 }
1086 }
1087 if (EmitAsyncCFI)
1088 emitDefineCFAWithFP(MBBI, FixedObject);
1089}
1090
1091// Define the current CFA rule to use the provided FP.
1092void AArch64PrologueEmitter::emitDefineCFAWithFP(
1093 MachineBasicBlock::iterator MBBI, unsigned FixedObject) const {
1094 const int OffsetToFirstCalleeSaveFromFP =
1095 AFI->getCalleeSaveBaseToFrameRecordOffset() -
1096 AFI->getCalleeSavedStackSize();
1097 Register FramePtr = RegInfo.getFrameRegister(MF);
1098 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
1099 .buildDefCFA(FramePtr, FixedObject - OffsetToFirstCalleeSaveFromFP);
1100}
1101
1102void AArch64PrologueEmitter::emitWindowsStackProbe(
1103 MachineBasicBlock::iterator MBBI, const DebugLoc &DL, int64_t &NumBytes,
1104 int64_t RealignmentPadding) const {
1105 if (AFI->getSVECalleeSavedStackSize())
1106 report_fatal_error("SVE callee saves not yet supported with stack probing");
1107
1108 // Find an available register to spill the value of X15 to, if X15 is being
1109 // used already for nest.
1110 Register X15Scratch;
1111 if (llvm::any_of(MBB.liveins(),
1112 [this](const MachineBasicBlock::RegisterMaskPair &LiveIn) {
1113 return RegInfo.isSuperOrSubRegisterEq(AArch64::X15,
1114 LiveIn.PhysReg);
1115 })) {
1116 X15Scratch = AFL.findScratchNonCalleeSaveRegister(&MBB, /*HasCall=*/true);
1117 assert(X15Scratch.isValid() &&
1118 (X15Scratch < AArch64::X15 || X15Scratch > AArch64::X17));
1119#ifndef NDEBUG
1120 LiveRegs.removeReg(AArch64::X15); // ignore X15 since we restore it
1121#endif
1122 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrr), X15Scratch)
1123 .addReg(AArch64::XZR)
1124 .addReg(AArch64::X15, RegState::Undef)
1125 .addReg(AArch64::X15, RegState::Implicit)
1127 }
1128
1129 uint64_t NumWords = (NumBytes + RealignmentPadding) >> 4;
1130 if (NeedsWinCFI) {
1131 HasWinCFI = true;
1132 // alloc_l can hold at most 256MB, so assume that NumBytes doesn't
1133 // exceed this amount. We need to move at most 2^24 - 1 into x15.
1134 // This is at most two instructions, MOVZ followed by MOVK.
1135 // TODO: Fix to use multiple stack alloc unwind codes for stacks
1136 // exceeding 256MB in size.
1137 if (NumBytes >= (1 << 28))
1138 report_fatal_error("Stack size cannot exceed 256MB for stack "
1139 "unwinding purposes");
1140
1141 uint32_t LowNumWords = NumWords & 0xFFFF;
1142 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVZXi), AArch64::X15)
1143 .addImm(LowNumWords)
1146 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1148 if ((NumWords & 0xFFFF0000) != 0) {
1149 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVKXi), AArch64::X15)
1150 .addReg(AArch64::X15)
1151 .addImm((NumWords & 0xFFFF0000) >> 16) // High half
1154 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1156 }
1157 } else {
1158 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVi64imm), AArch64::X15)
1159 .addImm(NumWords)
1161 }
1162
1163 const AArch64TargetLowering *TLI = Subtarget.getTargetLowering();
1164 RTLIB::LibcallImpl ChkStkLibcall = TLI->getLibcallImpl(RTLIB::STACK_PROBE);
1165 if (ChkStkLibcall == RTLIB::Unsupported)
1166 reportFatalUsageError("no available implementation of __chkstk");
1167
1168 const char *ChkStk = TLI->getLibcallImplName(ChkStkLibcall).data();
1169 switch (MF.getTarget().getCodeModel()) {
1170 case CodeModel::Tiny:
1171 case CodeModel::Small:
1172 case CodeModel::Medium:
1173 case CodeModel::Kernel:
1174 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
1175 .addExternalSymbol(ChkStk)
1176 .addReg(AArch64::X15, RegState::Implicit)
1177 .addReg(AArch64::X16,
1179 .addReg(AArch64::X17,
1181 .addReg(AArch64::NZCV,
1184 if (NeedsWinCFI) {
1185 HasWinCFI = true;
1186 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1188 }
1189 break;
1190 case CodeModel::Large:
1191 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVaddrEXT))
1192 .addReg(AArch64::X16, RegState::Define)
1193 .addExternalSymbol(ChkStk)
1194 .addExternalSymbol(ChkStk)
1196 if (NeedsWinCFI) {
1197 HasWinCFI = true;
1198 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1200 }
1201
1203 .addReg(AArch64::X16, RegState::Kill)
1205 .addReg(AArch64::X16,
1207 .addReg(AArch64::X17,
1209 .addReg(AArch64::NZCV,
1212 if (NeedsWinCFI) {
1213 HasWinCFI = true;
1214 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1216 }
1217 break;
1218 }
1219
1220 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SUBXrx64), AArch64::SP)
1221 .addReg(AArch64::SP, RegState::Kill)
1222 .addReg(AArch64::X15, RegState::Kill)
1225 if (NeedsWinCFI) {
1226 HasWinCFI = true;
1227 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
1228 .addImm(NumBytes)
1230 }
1231 NumBytes = 0;
1232
1233 if (RealignmentPadding > 0) {
1234 if (RealignmentPadding >= 4096) {
1235 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVi64imm))
1236 .addReg(AArch64::X16, RegState::Define)
1237 .addImm(RealignmentPadding)
1239 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXrx64), AArch64::X15)
1240 .addReg(AArch64::SP)
1241 .addReg(AArch64::X16, RegState::Kill)
1244 } else {
1245 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXri), AArch64::X15)
1246 .addReg(AArch64::SP)
1247 .addImm(RealignmentPadding)
1248 .addImm(0)
1250 }
1251
1252 uint64_t AndMask = ~(MFI.getMaxAlign().value() - 1);
1253 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), AArch64::SP)
1254 .addReg(AArch64::X15, RegState::Kill)
1256 AFI->setStackRealigned(true);
1257
1258 // No need for SEH instructions here; if we're realigning the stack,
1259 // we've set a frame pointer and already finished the SEH prologue.
1261 }
1262 if (X15Scratch.isValid()) {
1263 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrr), AArch64::X15)
1264 .addReg(AArch64::XZR)
1265 .addReg(X15Scratch, RegState::Undef)
1266 .addReg(X15Scratch, RegState::Implicit)
1268 }
1269}
1270
1271void AArch64PrologueEmitter::emitCalleeSavedGPRLocations(
1273 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
1274 if (CSI.empty())
1275 return;
1276
1277 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameSetup);
1278 for (const auto &Info : CSI) {
1279 unsigned FrameIdx = Info.getFrameIdx();
1280 if (MFI.hasScalableStackID(FrameIdx))
1281 continue;
1282
1283 assert(!Info.isSpilledToReg() && "Spilling to registers not implemented");
1284 int64_t Offset = MFI.getObjectOffset(FrameIdx) - AFL.getOffsetOfLocalArea();
1285 CFIBuilder.buildOffset(Info.getReg(), Offset);
1286 }
1287}
1288
1289void AArch64PrologueEmitter::emitCalleeSavedSVELocations(
1291 // Add callee saved registers to move list.
1292 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
1293 if (CSI.empty())
1294 return;
1295
1296 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameSetup);
1297
1298 std::optional<int64_t> IncomingVGOffsetFromDefCFA;
1299 if (AFL.requiresSaveVG(MF)) {
1300 auto IncomingVG = *find_if(
1301 reverse(CSI), [](auto &Info) { return Info.getReg() == AArch64::VG; });
1302 IncomingVGOffsetFromDefCFA = MFI.getObjectOffset(IncomingVG.getFrameIdx()) -
1303 AFL.getOffsetOfLocalArea();
1304 }
1305
1306 StackOffset PPRStackSize = AFL.getPPRStackSize(MF);
1307 for (const auto &Info : CSI) {
1308 int FI = Info.getFrameIdx();
1309 if (!MFI.hasScalableStackID(FI))
1310 continue;
1311
1312 // Not all unwinders may know about SVE registers, so assume the lowest
1313 // common denominator.
1314 assert(!Info.isSpilledToReg() && "Spilling to registers not implemented");
1315 MCRegister Reg = Info.getReg();
1316 if (!RegInfo.regNeedsCFI(Reg, Reg))
1317 continue;
1318
1319 StackOffset Offset =
1320 StackOffset::getScalable(MFI.getObjectOffset(FI)) -
1321 StackOffset::getFixed(AFI->getCalleeSavedStackSize(MFI));
1322
1323 // The scalable vectors are below (lower address) the scalable predicates
1324 // with split SVE objects, so we must subtract the size of the predicates.
1326 MFI.getStackID(FI) == TargetStackID::ScalableVector)
1327 Offset -= PPRStackSize;
1328
1329 CFIBuilder.insertCFIInst(
1330 createCFAOffset(RegInfo, Reg, Offset, IncomingVGOffsetFromDefCFA));
1331 }
1332}
1333
1335 switch (MI.getOpcode()) {
1336 default:
1337 return false;
1338 case AArch64::CATCHRET:
1339 case AArch64::CLEANUPRET:
1340 return true;
1341 }
1342}
1343
1348 EmitCFI = AFI->needsAsyncDwarfUnwindInfo(MF);
1349 HomPrologEpilog = AFL.homogeneousPrologEpilog(MF, &MBB);
1350 SEHEpilogueStartI = MBB.end();
1351}
1352
1353void AArch64EpilogueEmitter::moveSPBelowFP(MachineBasicBlock::iterator MBBI,
1355 // Other combinations could be supported, but are not currently needed.
1356 assert(Offset.getScalable() < 0 && Offset.getFixed() <= 0 &&
1357 "expected negative offset (with optional fixed portion)");
1358 Register Base = AArch64::FP;
1359 if (int64_t FixedOffset = Offset.getFixed()) {
1360 // If we have a negative fixed offset, we need to first subtract it in a
1361 // temporary register first (to avoid briefly deallocating the scalable
1362 // portion of the offset).
1363 Base = MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
1364 emitFrameOffset(MBB, MBBI, DL, Base, AArch64::FP,
1365 StackOffset::getFixed(FixedOffset), TII,
1367 }
1368 emitFrameOffset(MBB, MBBI, DL, AArch64::SP, Base,
1369 StackOffset::getScalable(Offset.getScalable()), TII,
1371}
1372
1374 MachineBasicBlock::iterator EpilogueEndI = MBB.getLastNonDebugInstr();
1375 if (MBB.end() != EpilogueEndI) {
1376 DL = EpilogueEndI->getDebugLoc();
1377 IsFunclet = isFuncletReturnInstr(*EpilogueEndI);
1378 }
1379
1380 int64_t NumBytes =
1381 IsFunclet ? AFL.getWinEHFuncletFrameSize(MF) : MFI.getStackSize();
1382
1383 // All calls are tail calls in GHC calling conv, and functions have no
1384 // prologue/epilogue.
1385 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
1386 return;
1387
1388 // How much of the stack used by incoming arguments this function is expected
1389 // to restore in this particular epilogue.
1390 int64_t ArgumentStackToRestore = AFL.getArgumentStackToRestore(MF, MBB);
1391 bool IsWin64 = Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv(),
1392 MF.getFunction().isVarArg());
1393 unsigned FixedObject = AFL.getFixedObjectSize(MF, AFI, IsWin64, IsFunclet);
1394
1395 const bool AuthenticateReturnAddressEarly =
1396 !IsFunclet && AFL.authenticatesReturnAddressEarly(MF, MBB);
1397
1398 int64_t AfterCSRPopSize = ArgumentStackToRestore;
1399 auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
1400 // We cannot rely on the local stack size set in emitPrologue if the function
1401 // has funclets, as funclets have different local stack size requirements, and
1402 // the current value set in emitPrologue may be that of the containing
1403 // function.
1404 if (MF.hasEHFunclets())
1405 AFI->setLocalStackSize(NumBytes - PrologueSaveSize);
1406
1407 if (HomPrologEpilog) {
1409 auto FirstHomogenousEpilogI = MBB.getFirstTerminator();
1410 if (FirstHomogenousEpilogI != MBB.begin()) {
1411 auto HomogeneousEpilog = std::prev(FirstHomogenousEpilogI);
1412 if (HomogeneousEpilog->getOpcode() == AArch64::HOM_Epilog)
1413 FirstHomogenousEpilogI = HomogeneousEpilog;
1414 }
1415
1416 // Adjust local stack
1417 emitFrameOffset(MBB, FirstHomogenousEpilogI, DL, AArch64::SP, AArch64::SP,
1418 StackOffset::getFixed(AFI->getLocalStackSize()), TII,
1420
1421 // SP has been already adjusted while restoring callee save regs.
1422 // We've bailed-out the case with adjusting SP for arguments.
1423 assert(AfterCSRPopSize == 0);
1424 return;
1425 }
1426
1427 bool CombineSPBump = shouldCombineCSRLocalStackBump(NumBytes);
1428
1429 unsigned ProloguePopSize = PrologueSaveSize;
1431 // With CalleeSavesAboveFrameRecord ProloguePopSize is the amount of stack
1432 // that needs to be popped until we reach the start of the SVE save area.
1433 // The "FixedObject" stack occurs after the SVE area and must be popped
1434 // later.
1435 ProloguePopSize -= FixedObject;
1436 AfterCSRPopSize += FixedObject;
1437 }
1438
1439 // Assume we can't combine the last pop with the sp restore. If the return
1440 // address is authenticated early, it wasn't restored, so the last pop may
1441 // not exist, and in any case the SP adjustment is made explicitly.
1442 if (!CombineSPBump && ProloguePopSize != 0 &&
1443 AuthenticateReturnAddressEarly) {
1444 AfterCSRPopSize += ProloguePopSize;
1445 } else if (!CombineSPBump && ProloguePopSize != 0) {
1446 MachineBasicBlock::iterator Pop = std::prev(MBB.getFirstTerminator());
1447 while (Pop->getOpcode() == TargetOpcode::CFI_INSTRUCTION ||
1448 AArch64InstrInfo::isSEHInstruction(*Pop) ||
1451 Pop = std::prev(Pop);
1452 // Converting the last ldp to a post-index ldp is valid only if the last
1453 // ldp's offset is 0.
1454 const MachineOperand &OffsetOp = Pop->getOperand(Pop->getNumOperands() - 1);
1455 // If the offset is 0 and the AfterCSR pop is not actually trying to
1456 // allocate more stack for arguments (in space that an untimely interrupt
1457 // may clobber), convert it to a post-index ldp.
1458 if (OffsetOp.getImm() == 0 && AfterCSRPopSize >= 0) {
1460 Pop, DL, ProloguePopSize, EmitCFI, MachineInstr::FrameDestroy,
1461 ProloguePopSize);
1463 MachineBasicBlock::iterator AfterLastPop = std::next(Pop);
1464 if (AArch64InstrInfo::isSEHInstruction(*AfterLastPop))
1465 ++AfterLastPop;
1466 // If not, and CalleeSavesAboveFrameRecord is enabled, deallocate
1467 // callee-save non-SVE registers to move the stack pointer to the start of
1468 // the SVE area.
1469 emitFrameOffset(MBB, AfterLastPop, DL, AArch64::SP, AArch64::SP,
1470 StackOffset::getFixed(ProloguePopSize), TII,
1472 &HasWinCFI);
1473 } else {
1474 // Otherwise, make sure to emit an add after the last ldp.
1475 // We're doing this by transferring the size to be restored from the
1476 // adjustment *before* the CSR pops to the adjustment *after* the CSR
1477 // pops.
1478 AfterCSRPopSize += ProloguePopSize;
1479 }
1480 }
1481
1482 // Move past the restores of the callee-saved registers.
1483 // If we plan on combining the sp bump of the local stack size and the callee
1484 // save stack size, we might need to adjust the CSR save and restore offsets.
1485 MachineBasicBlock::iterator FirstGPRRestoreI = MBB.getFirstTerminator();
1486 MachineBasicBlock::iterator Begin = MBB.begin();
1487 while (FirstGPRRestoreI != Begin) {
1488 --FirstGPRRestoreI;
1489 if (!FirstGPRRestoreI->getFlag(MachineInstr::FrameDestroy) ||
1491 isPartOfSVECalleeSaves(FirstGPRRestoreI))) {
1492 ++FirstGPRRestoreI;
1493 break;
1494 } else if (CombineSPBump)
1495 fixupCalleeSaveRestoreStackOffset(*FirstGPRRestoreI,
1496 AFI->getLocalStackSize());
1497 }
1498
1499 // The unwind info can't describe authenticating the return address in an
1500 // epilogue that leaves SP somewhere other than where it was on entry, so do
1501 // it before the epilogue starts instead.
1502 if (AuthenticateReturnAddressEarly)
1503 emitEarlyReturnAddressAuthentication(FirstGPRRestoreI, MFI.getStackSize(),
1504 PrologueSaveSize);
1505
1506 if (NeedsWinCFI) {
1507 // Note that there are cases where we insert SEH opcodes in the
1508 // epilogue when we had no SEH opcodes in the prologue. For
1509 // example, when there is no stack frame but there are stack
1510 // arguments. Insert the SEH_EpilogStart and remove it later if it
1511 // we didn't emit any SEH opcodes to avoid generating WinCFI for
1512 // functions that don't need it.
1513 BuildMI(MBB, FirstGPRRestoreI, DL, TII->get(AArch64::SEH_EpilogStart))
1515 SEHEpilogueStartI = FirstGPRRestoreI;
1516 --SEHEpilogueStartI;
1517 }
1518
1519 // Determine the ranges of SVE callee-saves. This is done before emitting any
1520 // code at the end of the epilogue (for Swift async), which can get in the way
1521 // of finding SVE callee-saves with CalleeSavesAboveFrameRecord.
1522 auto [PPR, ZPR] = getSVEStackFrameSizes();
1523 auto [PPRRange, ZPRRange] = partitionSVECS(
1524 MBB,
1526 ? MBB.getFirstTerminator()
1527 : FirstGPRRestoreI,
1528 PPR.CalleeSavesSize, ZPR.CalleeSavesSize, /*IsEpilogue=*/true);
1529
1530 if (HasFP && AFI->hasSwiftAsyncContext())
1531 emitSwiftAsyncContextFramePointer(EpilogueEndI, DL);
1532
1533 // If there is a single SP update, insert it before the ret and we're done.
1534 if (CombineSPBump) {
1535 assert(!AFI->hasSVEStackSize() && "Cannot combine SP bump with SVE");
1536
1537 // When we are about to restore the CSRs, the CFA register is SP again.
1538 if (EmitCFI && HasFP)
1540 .buildDefCFA(AArch64::SP, NumBytes);
1541
1542 emitFrameOffset(MBB, MBB.getFirstTerminator(), DL, AArch64::SP, AArch64::SP,
1543 StackOffset::getFixed(NumBytes + AfterCSRPopSize), TII,
1545 EmitCFI, StackOffset::getFixed(NumBytes));
1546 return;
1547 }
1548
1549 NumBytes -= PrologueSaveSize;
1550 assert(NumBytes >= 0 && "Negative stack allocation size!?");
1551
1552 StackOffset SVECalleeSavesSize = ZPR.CalleeSavesSize + PPR.CalleeSavesSize;
1553 SVEStackAllocations SVEAllocs = getSVEStackAllocations({PPR, ZPR});
1554
1555 // Deallocate the SVE area.
1557 assert(!SVEAllocs.AfterPPRs &&
1558 "unexpected SVE allocs after PPRs with CalleeSavesAboveFrameRecord");
1559 // If the callee-save area is before FP, restoring the FP implicitly
1560 // deallocates non-callee-save SVE allocations. Otherwise, deallocate them
1561 // explicitly.
1562 if (!AFI->isStackRealigned() && !MFI.hasVarSizedObjects()) {
1563 emitFrameOffset(MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::SP,
1565 false, NeedsWinCFI, &HasWinCFI);
1566 }
1567
1568 // Deallocate callee-save SVE registers.
1569 emitFrameOffset(MBB, PPRRange.End, DL, AArch64::SP, AArch64::SP,
1571 false, NeedsWinCFI, &HasWinCFI);
1572 } else if (AFI->hasSVEStackSize()) {
1573 // If we have stack realignment or variable-sized objects we must use the FP
1574 // to restore SVE callee saves (as there is an unknown amount of
1575 // data/padding between the SP and SVE CS area).
1576 Register BaseForSVEDealloc =
1577 (AFI->isStackRealigned() || MFI.hasVarSizedObjects()) ? AArch64::FP
1578 : AArch64::SP;
1579 if (SVECalleeSavesSize && BaseForSVEDealloc == AArch64::FP) {
1580 if (ZPR.CalleeSavesSize || SVELayout != SVEStackLayout::Split) {
1581 // The offset from the frame-pointer to the start of the ZPR saves.
1582 StackOffset FPOffsetZPR =
1583 -SVECalleeSavesSize - PPR.LocalsSize -
1584 StackOffset::getFixed(AFI->getCalleeSaveBaseToFrameRecordOffset());
1585 // Deallocate the stack space space by moving the SP to the start of the
1586 // ZPR/PPR callee-save area.
1587 moveSPBelowFP(ZPRRange.Begin, FPOffsetZPR);
1588 }
1589 // With split SVE, the predicates are stored in a separate area above the
1590 // ZPR saves, so we must adjust the stack to the start of the PPRs.
1591 if (PPR.CalleeSavesSize && SVELayout == SVEStackLayout::Split) {
1592 // The offset from the frame-pointer to the start of the PPR saves.
1593 StackOffset FPOffsetPPR = -PPR.CalleeSavesSize;
1594 // Move to the start of the PPR area.
1595 assert(!FPOffsetPPR.getFixed() && "expected only scalable offset");
1596 emitFrameOffset(MBB, ZPRRange.End, DL, AArch64::SP, AArch64::FP,
1597 FPOffsetPPR, TII, MachineInstr::FrameDestroy);
1598 }
1599 } else if (BaseForSVEDealloc == AArch64::SP) {
1600 auto NonSVELocals = StackOffset::getFixed(NumBytes);
1601 auto CFAOffset = NonSVELocals + StackOffset::getFixed(PrologueSaveSize) +
1602 SVEAllocs.totalSize();
1603
1604 if (SVECalleeSavesSize || SVELayout == SVEStackLayout::Split) {
1605 // Deallocate non-SVE locals now. This is needed to reach the SVE callee
1606 // saves, but may also allow combining stack hazard bumps for split SVE.
1607 SVEAllocs.AfterZPRs += NonSVELocals;
1608 NumBytes -= NonSVELocals.getFixed();
1609 }
1610 // To deallocate the SVE stack adjust by the allocations in reverse.
1611 emitFrameOffset(MBB, ZPRRange.Begin, DL, AArch64::SP, AArch64::SP,
1613 false, NeedsWinCFI, &HasWinCFI, EmitCFI && !HasFP,
1614 CFAOffset);
1615 CFAOffset -= SVEAllocs.AfterZPRs;
1616 assert(PPRRange.Begin == ZPRRange.End &&
1617 "Expected PPR restores after ZPR");
1618 emitFrameOffset(MBB, PPRRange.Begin, DL, AArch64::SP, AArch64::SP,
1620 false, NeedsWinCFI, &HasWinCFI, EmitCFI && !HasFP,
1621 CFAOffset);
1622 CFAOffset -= SVEAllocs.AfterPPRs;
1623 emitFrameOffset(MBB, PPRRange.End, DL, AArch64::SP, AArch64::SP,
1625 false, NeedsWinCFI, &HasWinCFI, EmitCFI && !HasFP,
1626 CFAOffset);
1627 }
1628
1629 if (EmitCFI)
1630 emitCalleeSavedSVERestores(
1631 SVELayout == SVEStackLayout::Split ? ZPRRange.End : PPRRange.End);
1632 }
1633
1634 if (!HasFP) {
1635 bool RedZone = AFL.canUseRedZone(MF);
1636 // If this was a redzone leaf function, we don't need to restore the
1637 // stack pointer (but we may need to pop stack args for fastcc).
1638 if (RedZone && AfterCSRPopSize == 0)
1639 return;
1640
1641 // Pop the local variables off the stack. If there are no callee-saved
1642 // registers, it means we are actually positioned at the terminator and can
1643 // combine stack increment for the locals and the stack increment for
1644 // callee-popped arguments into (possibly) a single instruction and be done.
1645 bool NoCalleeSaveRestore = PrologueSaveSize == 0;
1646 int64_t StackRestoreBytes = RedZone ? 0 : NumBytes;
1647 if (NoCalleeSaveRestore)
1648 StackRestoreBytes += AfterCSRPopSize;
1649
1651 MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::SP,
1652 StackOffset::getFixed(StackRestoreBytes), TII,
1654 StackOffset::getFixed((RedZone ? 0 : NumBytes) + PrologueSaveSize));
1655
1656 // If we were able to combine the local stack pop with the argument pop,
1657 // then we're done.
1658 if (NoCalleeSaveRestore || AfterCSRPopSize == 0)
1659 return;
1660
1661 NumBytes = 0;
1662 }
1663
1664 // Restore the original stack pointer.
1665 // FIXME: Rather than doing the math here, we should instead just use
1666 // non-post-indexed loads for the restores if we aren't actually going to
1667 // be able to save any instructions.
1668 if (!IsFunclet && (MFI.hasVarSizedObjects() || AFI->isStackRealigned())) {
1670 MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::FP,
1671 StackOffset::getFixed(-AFI->getCalleeSaveBaseToFrameRecordOffset()),
1673 } else if (NumBytes)
1674 emitFrameOffset(MBB, FirstGPRRestoreI, DL, AArch64::SP, AArch64::SP,
1675 StackOffset::getFixed(NumBytes), TII,
1677
1678 // When we are about to restore the CSRs, the CFA register is SP again.
1679 if (EmitCFI && HasFP)
1681 .buildDefCFA(AArch64::SP, PrologueSaveSize);
1682
1683 // This must be placed after the callee-save restore code because that code
1684 // assumes the SP is at the same location as it was after the callee-save save
1685 // code in the prologue.
1686 if (AfterCSRPopSize) {
1687 assert(AfterCSRPopSize > 0 && "attempting to reallocate arg stack that an "
1688 "interrupt may have clobbered");
1689
1691 MBB, MBB.getFirstTerminator(), DL, AArch64::SP, AArch64::SP,
1693 false, NeedsWinCFI, &HasWinCFI, EmitCFI,
1694 StackOffset::getFixed(AfterCSRPopSize - ArgumentStackToRestore));
1695 }
1696}
1697
1698bool AArch64EpilogueEmitter::shouldCombineCSRLocalStackBump(
1699 uint64_t StackBumpBytes) const {
1701 StackBumpBytes))
1702 return false;
1703 if (MBB.empty())
1704 return true;
1705
1706 // Disable combined SP bump if the last instruction is an MTE tag store. It
1707 // is almost always better to merge SP adjustment into those instructions.
1708 MachineBasicBlock::iterator LastI = MBB.getFirstTerminator();
1709 MachineBasicBlock::iterator Begin = MBB.begin();
1710 while (LastI != Begin) {
1711 --LastI;
1712 if (LastI->isTransient())
1713 continue;
1714 if (!LastI->getFlag(MachineInstr::FrameDestroy))
1715 break;
1716 }
1717 switch (LastI->getOpcode()) {
1718 case AArch64::STGloop:
1719 case AArch64::STZGloop:
1720 case AArch64::STGi:
1721 case AArch64::STZGi:
1722 case AArch64::ST2Gi:
1723 case AArch64::STZ2Gi:
1724 return false;
1725 default:
1726 return true;
1727 }
1728 llvm_unreachable("unreachable");
1729}
1730
1731void AArch64EpilogueEmitter::emitSwiftAsyncContextFramePointer(
1733 switch (MF.getTarget().Options.SwiftAsyncFramePointer) {
1735 // Avoid the reload as it is GOT relative, and instead fall back to the
1736 // hardcoded value below. This allows a mismatch between the OS and
1737 // application without immediately terminating on the difference.
1738 [[fallthrough]];
1740 // We need to reset FP to its untagged state on return. Bit 60 is
1741 // currently used to show the presence of an extended frame.
1742
1743 // BIC x29, x29, #0x1000_0000_0000_0000
1744 BuildMI(MBB, MBB.getFirstTerminator(), DL, TII->get(AArch64::ANDXri),
1745 AArch64::FP)
1746 .addUse(AArch64::FP)
1747 .addImm(0x10fe)
1749 if (NeedsWinCFI) {
1750 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1752 HasWinCFI = true;
1753 }
1754 break;
1755
1757 break;
1758 }
1759}
1760
1761void AArch64EpilogueEmitter::emitShadowCallStackEpilogue(
1763 // Shadow call stack epilog: ldr x30, [x18, #-8]!
1764 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXpre))
1765 .addReg(AArch64::X18, RegState::Define)
1766 .addReg(AArch64::LR, RegState::Define)
1767 .addReg(AArch64::X18)
1768 .addImm(-8)
1770
1771 if (NeedsWinCFI)
1772 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1774
1775 if (AFI->needsAsyncDwarfUnwindInfo(MF))
1776 CFIInstBuilder(MBB, MBBI, MachineInstr::FrameDestroy)
1777 .buildRestore(AArch64::X18);
1778}
1779
1780void AArch64EpilogueEmitter::emitEarlyReturnAddressAuthentication(
1781 MachineBasicBlock::iterator MBBI, int64_t StackSize,
1782 int64_t PrologueSaveSize) {
1783 // Windows unwind info describes authenticating the return address with a
1784 // pac_sign_lr unwind code, which the unwinder applies using the SP it has at
1785 // that point; that is only the SP the return address was signed with if the
1786 // epilogue ends with SP back at its entry value. When it doesn't, we
1787 // authenticate the return address here instead, in the body, where the
1788 // prologue's unwind codes apply and the return address is still signed. The
1789 // epilogue's unwind codes then have no pac_sign_lr, and nor do they restore
1790 // LR: the authenticated return address stays in LR (it is never written back
1791 // to the stack) and the epilogue doesn't reload it. There is no window in
1792 // which the unwinder sees the wrong state: this sequence is immediately
1793 // before the start of the epilogue, so the prologue's codes apply to every
1794 // instruction up to and including the last of it, which recover the signed
1795 // return address from its slot on the stack, and the epilogue's apply after.
1796 if (AFI->hasSVEStackSize())
1797 report_fatal_error("Can't handle a tail call that changes the stack "
1798 "argument size in a function with SVE stack objects "
1799 "that signs its return address on Windows");
1800
1801 // The return address is only on the stack if it was spilled.
1802 std::optional<int> LRFrameIdx;
1803 for (const CalleeSavedInfo &CSI : MFI.getCalleeSavedInfo())
1804 if (CSI.getReg() == AArch64::LR)
1805 LRFrameIdx = CSI.getFrameIdx();
1806
1807 // When the frame is addressed via the FP, the return address is in the frame
1808 // record, at FP + 8. We don't refer to its frame index there because the SP
1809 // is not reliable as a base, and the frame index of a callee-saved register
1810 // isn't always recognised as one on Windows when there is a tail call
1811 // reserve.
1812 bool UseFP = MFI.hasVarSizedObjects() || AFI->isStackRealigned();
1813
1814 // Compute the SP the return address was signed with, which is SP on entry.
1815 int64_t Adjustment =
1816 UseFP ? PrologueSaveSize - AFI->getCalleeSaveBaseToFrameRecordOffset()
1817 : StackSize;
1819 MBB, MBBI, DL, AArch64::X16, UseFP ? AArch64::FP : AArch64::SP,
1821
1822 // LR holds whatever the last call left in it; get the signed return address.
1823 // The authentication sequence expects it in X17 if it works on that and moves
1824 // the result to LR, which saves a copy.
1826 AFI->branchProtectionPAuthLR(), Subtarget.hasPAuth());
1827 Register SignedLR = InX17 ? Register(AArch64::X17) : Register(AArch64::LR);
1828 if (LRFrameIdx) {
1829 MachineInstrBuilder MIB =
1830 BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui), SignedLR);
1831 if (UseFP)
1832 MIB.addReg(AArch64::FP).addImm(1);
1833 else
1834 MIB.addFrameIndex(*LRFrameIdx).addImm(0);
1835 MIB.addMemOperand(MF.getMachineMemOperand(
1838 } else if (InX17) {
1839 // The return address was never spilled, so it is still in LR.
1840 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::X17)
1841 .addReg(AArch64::XZR)
1842 .addReg(AArch64::LR)
1843 .addImm(0);
1844 }
1845
1846 auto Builder =
1847 BuildMI(MBB, MBBI, DL, TII->get(AArch64::PAUTH_EPILOGUE_ENTRY_SP));
1848 Builder.addReg(AArch64::X16, RegState::Implicit);
1849 if (InX17) {
1850 Builder.addReg(AArch64::X17, RegState::Implicit);
1851 // The pseudo's implicit use of LR is not a real one here; the signed return
1852 // address is in X17, and LR only gets written.
1853 Builder->findRegisterUseOperand(AArch64::LR, &RegInfo)->setIsUndef();
1854 }
1855 Builder.addReg(AArch64::X17, RegState::ImplicitDefine);
1856 if (AFI->branchProtectionPAuthLR())
1857 Builder.addReg(AArch64::X15, RegState::ImplicitDefine);
1858
1859 // This takes the place of the pseudo that would otherwise go at the end.
1860 for (MachineInstr &MI : llvm::make_early_inc_range(MBB))
1861 if (MI.getOpcode() == AArch64::PAUTH_EPILOGUE)
1862 MI.eraseFromParent();
1863 AuthenticatedReturnAddressEarly = true;
1864}
1865
1866void AArch64EpilogueEmitter::emitCalleeSavedRestores(
1867 MachineBasicBlock::iterator MBBI, bool SVE) const {
1868 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
1869 if (CSI.empty())
1870 return;
1871
1872 CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameDestroy);
1873
1874 for (const auto &Info : CSI) {
1875 if (SVE != MFI.hasScalableStackID(Info.getFrameIdx()))
1876 continue;
1877
1878 MCRegister Reg = Info.getReg();
1879 if (SVE && !RegInfo.regNeedsCFI(Reg, Reg))
1880 continue;
1881
1882 CFIBuilder.buildRestore(Info.getReg());
1883 }
1884}
1885
1886bool AArch64EpilogueEmitter::hasEpilogueUnwindOps() const {
1887 // The return address is authenticated by an unwind op that the
1888 // AArch64PointerAuth pass adds later, or, if it was authenticated early, the
1889 // epilogue's unwind codes are what keep the prologue's pac_sign_lr from being
1890 // applied again, even if there is nothing else in them.
1891 if (AFI->shouldSignReturnAddress(MF))
1892 return true;
1893 return std::any_of(std::next(SEHEpilogueStartI), MBB.end(),
1894 [](const MachineInstr &MI) {
1895 return AArch64InstrInfo::isSEHInstruction(MI) &&
1896 MI.getOpcode() != AArch64::SEH_EpilogEnd;
1897 });
1898}
1899
1900void AArch64EpilogueEmitter::finalizeEpilogue() const {
1901 // All calls are tail calls in GHC calling conv, and functions have no
1902 // prologue/epilogue.
1903 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
1904 return;
1905
1906 if (AFI->needsShadowCallStackPrologueEpilogue(MF)) {
1907 emitShadowCallStackEpilogue(MBB.getFirstTerminator(), DL);
1909 }
1910 if (EmitCFI)
1911 emitCalleeSavedGPRRestores(MBB.getFirstTerminator());
1912 if (AFI->shouldSignReturnAddress(MF)) {
1913 // If pac-ret+leaf is in effect, PAUTH_EPILOGUE pseudo instructions
1914 // are inserted by emitPacRetPlusLeafHardening().
1915 if (!AFL.shouldSignReturnAddressEverywhere(MF) &&
1916 !AuthenticatedReturnAddressEarly)
1917 TII->createPauthEpilogueInstr(MBB, DL);
1918 // AArch64PointerAuth pass will insert SEH_PACSignLR, unless the return
1919 // address was authenticated early (see
1920 // emitEarlyReturnAddressAuthentication()).
1922 }
1923 // A tail call leaves the stack arguments for the tail callee, which pops them
1924 // itself. Until then the unwinder must pop them to recover the caller's SP,
1925 // as in the prologue; there is no instruction to describe that, so it goes
1926 // after end_c. An epilogue with no unwind ops of its own gains nothing from
1927 // this, as the prologue's codes cover it.
1928 if (NeedsWinCFI && HasWinCFI && !IsFunclet && hasEpilogueUnwindOps()) {
1929 int64_t TailCalleePopBytes = AFI->getArgumentStackToRestore() -
1930 AFL.getArgumentStackToRestore(MF, MBB);
1931 if (TailCalleePopBytes > 0) {
1932 BuildMI(MBB, MBB.getFirstTerminator(), DL, TII->get(AArch64::SEH_EndC))
1934 BuildMI(MBB, MBB.getFirstTerminator(), DL,
1935 TII->get(AArch64::SEH_StackAlloc))
1936 .addImm(TailCalleePopBytes)
1938 HasWinCFI = true;
1939 }
1940 }
1941 if (HasWinCFI) {
1942 BuildMI(MBB, MBB.getFirstTerminator(), DL, TII->get(AArch64::SEH_EpilogEnd))
1944 if (!MF.hasWinCFI())
1945 MF.setHasWinCFI(true);
1946 }
1947 if (NeedsWinCFI) {
1948 assert(SEHEpilogueStartI != MBB.end());
1949 if (!HasWinCFI)
1950 MBB.erase(SEHEpilogueStartI);
1951 }
1952}
1953
1954} // 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:320
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