Bug Summary

File:llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
Warning:line 2577, column 3
1st function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name AArch64FrameLowering.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=none -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/build-llvm/lib/Target/AArch64 -I /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64 -I /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/build-llvm/include -I /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/build-llvm/lib/Target/AArch64 -fdebug-prefix-map=/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809=. -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -o /tmp/scan-build-2019-12-11-181444-25759-1 -x c++ /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
1//===- AArch64FrameLowering.cpp - AArch64 Frame Lowering -------*- C++ -*-====//
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//
9// This file contains the AArch64 implementation of TargetFrameLowering class.
10//
11// On AArch64, stack frames are structured as follows:
12//
13// The stack grows downward.
14//
15// All of the individual frame areas on the frame below are optional, i.e. it's
16// possible to create a function so that the particular area isn't present
17// in the frame.
18//
19// At function entry, the "frame" looks as follows:
20//
21// | | Higher address
22// |-----------------------------------|
23// | |
24// | arguments passed on the stack |
25// | |
26// |-----------------------------------| <- sp
27// | | Lower address
28//
29//
30// After the prologue has run, the frame has the following general structure.
31// Note that this doesn't depict the case where a red-zone is used. Also,
32// technically the last frame area (VLAs) doesn't get created until in the
33// main function body, after the prologue is run. However, it's depicted here
34// for completeness.
35//
36// | | Higher address
37// |-----------------------------------|
38// | |
39// | arguments passed on the stack |
40// | |
41// |-----------------------------------|
42// | |
43// | (Win64 only) varargs from reg |
44// | |
45// |-----------------------------------|
46// | |
47// | callee-saved gpr registers | <--.
48// | | | On Darwin platforms these
49// |- - - - - - - - - - - - - - - - - -| | callee saves are swapped,
50// | | | (frame record first)
51// | prev_fp, prev_lr | <--'
52// | (a.k.a. "frame record") |
53// |-----------------------------------| <- fp(=x29)
54// | |
55// | callee-saved fp/simd/SVE regs |
56// | |
57// |-----------------------------------|
58// | |
59// | SVE stack objects |
60// | |
61// |-----------------------------------|
62// |.empty.space.to.make.part.below....|
63// |.aligned.in.case.it.needs.more.than| (size of this area is unknown at
64// |.the.standard.16-byte.alignment....| compile time; if present)
65// |-----------------------------------|
66// | |
67// | local variables of fixed size |
68// | including spill slots |
69// |-----------------------------------| <- bp(not defined by ABI,
70// |.variable-sized.local.variables....| LLVM chooses X19)
71// |.(VLAs)............................| (size of this area is unknown at
72// |...................................| compile time)
73// |-----------------------------------| <- sp
74// | | Lower address
75//
76//
77// To access the data in a frame, at-compile time, a constant offset must be
78// computable from one of the pointers (fp, bp, sp) to access it. The size
79// of the areas with a dotted background cannot be computed at compile-time
80// if they are present, making it required to have all three of fp, bp and
81// sp to be set up to be able to access all contents in the frame areas,
82// assuming all of the frame areas are non-empty.
83//
84// For most functions, some of the frame areas are empty. For those functions,
85// it may not be necessary to set up fp or bp:
86// * A base pointer is definitely needed when there are both VLAs and local
87// variables with more-than-default alignment requirements.
88// * A frame pointer is definitely needed when there are local variables with
89// more-than-default alignment requirements.
90//
91// For Darwin platforms the frame-record (fp, lr) is stored at the top of the
92// callee-saved area, since the unwind encoding does not allow for encoding
93// this dynamically and existing tools depend on this layout. For other
94// platforms, the frame-record is stored at the bottom of the (gpr) callee-saved
95// area to allow SVE stack objects (allocated directly below the callee-saves,
96// if available) to be accessed directly from the framepointer.
97// The SVE spill/fill instructions have VL-scaled addressing modes such
98// as:
99// ldr z8, [fp, #-7 mul vl]
100// For SVE the size of the vector length (VL) is not known at compile-time, so
101// '#-7 mul vl' is an offset that can only be evaluated at runtime. With this
102// layout, we don't need to add an unscaled offset to the framepointer before
103// accessing the SVE object in the frame.
104//
105// In some cases when a base pointer is not strictly needed, it is generated
106// anyway when offsets from the frame pointer to access local variables become
107// so large that the offset can't be encoded in the immediate fields of loads
108// or stores.
109//
110// FIXME: also explain the redzone concept.
111// FIXME: also explain the concept of reserved call frames.
112//
113//===----------------------------------------------------------------------===//
114
115#include "AArch64FrameLowering.h"
116#include "AArch64InstrInfo.h"
117#include "AArch64MachineFunctionInfo.h"
118#include "AArch64RegisterInfo.h"
119#include "AArch64StackOffset.h"
120#include "AArch64Subtarget.h"
121#include "AArch64TargetMachine.h"
122#include "MCTargetDesc/AArch64AddressingModes.h"
123#include "llvm/ADT/ScopeExit.h"
124#include "llvm/ADT/SmallVector.h"
125#include "llvm/ADT/Statistic.h"
126#include "llvm/CodeGen/LivePhysRegs.h"
127#include "llvm/CodeGen/MachineBasicBlock.h"
128#include "llvm/CodeGen/MachineFrameInfo.h"
129#include "llvm/CodeGen/MachineFunction.h"
130#include "llvm/CodeGen/MachineInstr.h"
131#include "llvm/CodeGen/MachineInstrBuilder.h"
132#include "llvm/CodeGen/MachineMemOperand.h"
133#include "llvm/CodeGen/MachineModuleInfo.h"
134#include "llvm/CodeGen/MachineOperand.h"
135#include "llvm/CodeGen/MachineRegisterInfo.h"
136#include "llvm/CodeGen/RegisterScavenging.h"
137#include "llvm/CodeGen/TargetInstrInfo.h"
138#include "llvm/CodeGen/TargetRegisterInfo.h"
139#include "llvm/CodeGen/TargetSubtargetInfo.h"
140#include "llvm/CodeGen/WinEHFuncInfo.h"
141#include "llvm/IR/Attributes.h"
142#include "llvm/IR/CallingConv.h"
143#include "llvm/IR/DataLayout.h"
144#include "llvm/IR/DebugLoc.h"
145#include "llvm/IR/Function.h"
146#include "llvm/MC/MCAsmInfo.h"
147#include "llvm/MC/MCDwarf.h"
148#include "llvm/Support/CommandLine.h"
149#include "llvm/Support/Debug.h"
150#include "llvm/Support/ErrorHandling.h"
151#include "llvm/Support/MathExtras.h"
152#include "llvm/Support/raw_ostream.h"
153#include "llvm/Target/TargetMachine.h"
154#include "llvm/Target/TargetOptions.h"
155#include <cassert>
156#include <cstdint>
157#include <iterator>
158#include <vector>
159
160using namespace llvm;
161
162#define DEBUG_TYPE"frame-info" "frame-info"
163
164static cl::opt<bool> EnableRedZone("aarch64-redzone",
165 cl::desc("enable use of redzone on AArch64"),
166 cl::init(false), cl::Hidden);
167
168static cl::opt<bool>
169 ReverseCSRRestoreSeq("reverse-csr-restore-seq",
170 cl::desc("reverse the CSR restore sequence"),
171 cl::init(false), cl::Hidden);
172
173STATISTIC(NumRedZoneFunctions, "Number of functions using red zone")static llvm::Statistic NumRedZoneFunctions = {"frame-info", "NumRedZoneFunctions"
, "Number of functions using red zone"}
;
174
175/// This is the biggest offset to the stack pointer we can encode in aarch64
176/// instructions (without using a separate calculation and a temp register).
177/// Note that the exception here are vector stores/loads which cannot encode any
178/// displacements (see estimateRSStackSizeLimit(), isAArch64FrameOffsetLegal()).
179static const unsigned DefaultSafeSPDisplacement = 255;
180
181/// Look at each instruction that references stack frames and return the stack
182/// size limit beyond which some of these instructions will require a scratch
183/// register during their expansion later.
184static unsigned estimateRSStackSizeLimit(MachineFunction &MF) {
185 // FIXME: For now, just conservatively guestimate based on unscaled indexing
186 // range. We'll end up allocating an unnecessary spill slot a lot, but
187 // realistically that's not a big deal at this stage of the game.
188 for (MachineBasicBlock &MBB : MF) {
189 for (MachineInstr &MI : MBB) {
190 if (MI.isDebugInstr() || MI.isPseudo() ||
191 MI.getOpcode() == AArch64::ADDXri ||
192 MI.getOpcode() == AArch64::ADDSXri)
193 continue;
194
195 for (const MachineOperand &MO : MI.operands()) {
196 if (!MO.isFI())
197 continue;
198
199 StackOffset Offset;
200 if (isAArch64FrameOffsetLegal(MI, Offset, nullptr, nullptr, nullptr) ==
201 AArch64FrameOffsetCannotUpdate)
202 return 0;
203 }
204 }
205 }
206 return DefaultSafeSPDisplacement;
207}
208
209/// Returns the size of the entire SVE stackframe (calleesaves + spills).
210static StackOffset getSVEStackSize(const MachineFunction &MF) {
211 const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
212 return {(int64_t)AFI->getStackSizeSVE(), MVT::nxv1i8};
213}
214
215bool AArch64FrameLowering::canUseRedZone(const MachineFunction &MF) const {
216 if (!EnableRedZone)
217 return false;
218 // Don't use the red zone if the function explicitly asks us not to.
219 // This is typically used for kernel code.
220 if (MF.getFunction().hasFnAttribute(Attribute::NoRedZone))
221 return false;
222
223 const MachineFrameInfo &MFI = MF.getFrameInfo();
224 const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
225 unsigned NumBytes = AFI->getLocalStackSize();
226
227 return !(MFI.hasCalls() || hasFP(MF) || NumBytes > 128 ||
228 getSVEStackSize(MF));
229}
230
231/// hasFP - Return true if the specified function should have a dedicated frame
232/// pointer register.
233bool AArch64FrameLowering::hasFP(const MachineFunction &MF) const {
234 const MachineFrameInfo &MFI = MF.getFrameInfo();
235 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
236 // Win64 EH requires a frame pointer if funclets are present, as the locals
237 // are accessed off the frame pointer in both the parent function and the
238 // funclets.
239 if (MF.hasEHFunclets())
240 return true;
241 // Retain behavior of always omitting the FP for leaf functions when possible.
242 if (MFI.hasCalls() && MF.getTarget().Options.DisableFramePointerElim(MF))
243 return true;
244 if (MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken() ||
245 MFI.hasStackMap() || MFI.hasPatchPoint() ||
246 RegInfo->needsStackRealignment(MF))
247 return true;
248 // With large callframes around we may need to use FP to access the scavenging
249 // emergency spillslot.
250 //
251 // Unfortunately some calls to hasFP() like machine verifier ->
252 // getReservedReg() -> hasFP in the middle of global isel are too early
253 // to know the max call frame size. Hopefully conservatively returning "true"
254 // in those cases is fine.
255 // DefaultSafeSPDisplacement is fine as we only emergency spill GP regs.
256 if (!MFI.isMaxCallFrameSizeComputed() ||
257 MFI.getMaxCallFrameSize() > DefaultSafeSPDisplacement)
258 return true;
259
260 return false;
261}
262
263/// hasReservedCallFrame - Under normal circumstances, when a frame pointer is
264/// not required, we reserve argument space for call sites in the function
265/// immediately on entry to the current function. This eliminates the need for
266/// add/sub sp brackets around call sites. Returns true if the call frame is
267/// included as part of the stack frame.
268bool
269AArch64FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
270 return !MF.getFrameInfo().hasVarSizedObjects();
271}
272
273MachineBasicBlock::iterator AArch64FrameLowering::eliminateCallFramePseudoInstr(
274 MachineFunction &MF, MachineBasicBlock &MBB,
275 MachineBasicBlock::iterator I) const {
276 const AArch64InstrInfo *TII =
277 static_cast<const AArch64InstrInfo *>(MF.getSubtarget().getInstrInfo());
278 DebugLoc DL = I->getDebugLoc();
279 unsigned Opc = I->getOpcode();
280 bool IsDestroy = Opc == TII->getCallFrameDestroyOpcode();
281 uint64_t CalleePopAmount = IsDestroy ? I->getOperand(1).getImm() : 0;
282
283 if (!hasReservedCallFrame(MF)) {
284 unsigned Align = getStackAlignment();
285
286 int64_t Amount = I->getOperand(0).getImm();
287 Amount = alignTo(Amount, Align);
288 if (!IsDestroy)
289 Amount = -Amount;
290
291 // N.b. if CalleePopAmount is valid but zero (i.e. callee would pop, but it
292 // doesn't have to pop anything), then the first operand will be zero too so
293 // this adjustment is a no-op.
294 if (CalleePopAmount == 0) {
295 // FIXME: in-function stack adjustment for calls is limited to 24-bits
296 // because there's no guaranteed temporary register available.
297 //
298 // ADD/SUB (immediate) has only LSL #0 and LSL #12 available.
299 // 1) For offset <= 12-bit, we use LSL #0
300 // 2) For 12-bit <= offset <= 24-bit, we use two instructions. One uses
301 // LSL #0, and the other uses LSL #12.
302 //
303 // Most call frames will be allocated at the start of a function so
304 // this is OK, but it is a limitation that needs dealing with.
305 assert(Amount > -0xffffff && Amount < 0xffffff && "call frame too large")((Amount > -0xffffff && Amount < 0xffffff &&
"call frame too large") ? static_cast<void> (0) : __assert_fail
("Amount > -0xffffff && Amount < 0xffffff && \"call frame too large\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 305, __PRETTY_FUNCTION__))
;
306 emitFrameOffset(MBB, I, DL, AArch64::SP, AArch64::SP, {Amount, MVT::i8},
307 TII);
308 }
309 } else if (CalleePopAmount != 0) {
310 // If the calling convention demands that the callee pops arguments from the
311 // stack, we want to add it back if we have a reserved call frame.
312 assert(CalleePopAmount < 0xffffff && "call frame too large")((CalleePopAmount < 0xffffff && "call frame too large"
) ? static_cast<void> (0) : __assert_fail ("CalleePopAmount < 0xffffff && \"call frame too large\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 312, __PRETTY_FUNCTION__))
;
313 emitFrameOffset(MBB, I, DL, AArch64::SP, AArch64::SP,
314 {-(int64_t)CalleePopAmount, MVT::i8}, TII);
315 }
316 return MBB.erase(I);
317}
318
319static bool ShouldSignReturnAddress(MachineFunction &MF) {
320 // The function should be signed in the following situations:
321 // - sign-return-address=all
322 // - sign-return-address=non-leaf and the functions spills the LR
323
324 const Function &F = MF.getFunction();
325 if (!F.hasFnAttribute("sign-return-address"))
326 return false;
327
328 StringRef Scope = F.getFnAttribute("sign-return-address").getValueAsString();
329 if (Scope.equals("none"))
330 return false;
331
332 if (Scope.equals("all"))
333 return true;
334
335 assert(Scope.equals("non-leaf") && "Expected all, none or non-leaf")((Scope.equals("non-leaf") && "Expected all, none or non-leaf"
) ? static_cast<void> (0) : __assert_fail ("Scope.equals(\"non-leaf\") && \"Expected all, none or non-leaf\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 335, __PRETTY_FUNCTION__))
;
336
337 for (const auto &Info : MF.getFrameInfo().getCalleeSavedInfo())
338 if (Info.getReg() == AArch64::LR)
339 return true;
340
341 return false;
342}
343
344void AArch64FrameLowering::emitCalleeSavedFrameMoves(
345 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const {
346 MachineFunction &MF = *MBB.getParent();
347 MachineFrameInfo &MFI = MF.getFrameInfo();
348 const TargetSubtargetInfo &STI = MF.getSubtarget();
349 const MCRegisterInfo *MRI = STI.getRegisterInfo();
350 const TargetInstrInfo *TII = STI.getInstrInfo();
351 DebugLoc DL = MBB.findDebugLoc(MBBI);
352
353 // Add callee saved registers to move list.
354 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
355 if (CSI.empty())
356 return;
357
358 for (const auto &Info : CSI) {
359 unsigned Reg = Info.getReg();
360 int64_t Offset =
361 MFI.getObjectOffset(Info.getFrameIdx()) - getOffsetOfLocalArea();
362 unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
363 unsigned CFIIndex = MF.addFrameInst(
364 MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
365 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
366 .addCFIIndex(CFIIndex)
367 .setMIFlags(MachineInstr::FrameSetup);
368 }
369}
370
371// Find a scratch register that we can use at the start of the prologue to
372// re-align the stack pointer. We avoid using callee-save registers since they
373// may appear to be free when this is called from canUseAsPrologue (during
374// shrink wrapping), but then no longer be free when this is called from
375// emitPrologue.
376//
377// FIXME: This is a bit conservative, since in the above case we could use one
378// of the callee-save registers as a scratch temp to re-align the stack pointer,
379// but we would then have to make sure that we were in fact saving at least one
380// callee-save register in the prologue, which is additional complexity that
381// doesn't seem worth the benefit.
382static unsigned findScratchNonCalleeSaveRegister(MachineBasicBlock *MBB) {
383 MachineFunction *MF = MBB->getParent();
384
385 // If MBB is an entry block, use X9 as the scratch register
386 if (&MF->front() == MBB)
387 return AArch64::X9;
388
389 const AArch64Subtarget &Subtarget = MF->getSubtarget<AArch64Subtarget>();
390 const AArch64RegisterInfo &TRI = *Subtarget.getRegisterInfo();
391 LivePhysRegs LiveRegs(TRI);
392 LiveRegs.addLiveIns(*MBB);
393
394 // Mark callee saved registers as used so we will not choose them.
395 const MCPhysReg *CSRegs = MF->getRegInfo().getCalleeSavedRegs();
396 for (unsigned i = 0; CSRegs[i]; ++i)
397 LiveRegs.addReg(CSRegs[i]);
398
399 // Prefer X9 since it was historically used for the prologue scratch reg.
400 const MachineRegisterInfo &MRI = MF->getRegInfo();
401 if (LiveRegs.available(MRI, AArch64::X9))
402 return AArch64::X9;
403
404 for (unsigned Reg : AArch64::GPR64RegClass) {
405 if (LiveRegs.available(MRI, Reg))
406 return Reg;
407 }
408 return AArch64::NoRegister;
409}
410
411bool AArch64FrameLowering::canUseAsPrologue(
412 const MachineBasicBlock &MBB) const {
413 const MachineFunction *MF = MBB.getParent();
414 MachineBasicBlock *TmpMBB = const_cast<MachineBasicBlock *>(&MBB);
415 const AArch64Subtarget &Subtarget = MF->getSubtarget<AArch64Subtarget>();
416 const AArch64RegisterInfo *RegInfo = Subtarget.getRegisterInfo();
417
418 // Don't need a scratch register if we're not going to re-align the stack.
419 if (!RegInfo->needsStackRealignment(*MF))
420 return true;
421 // Otherwise, we can use any block as long as it has a scratch register
422 // available.
423 return findScratchNonCalleeSaveRegister(TmpMBB) != AArch64::NoRegister;
424}
425
426static bool windowsRequiresStackProbe(MachineFunction &MF,
427 unsigned StackSizeInBytes) {
428 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
429 if (!Subtarget.isTargetWindows())
430 return false;
431 const Function &F = MF.getFunction();
432 // TODO: When implementing stack protectors, take that into account
433 // for the probe threshold.
434 unsigned StackProbeSize = 4096;
435 if (F.hasFnAttribute("stack-probe-size"))
436 F.getFnAttribute("stack-probe-size")
437 .getValueAsString()
438 .getAsInteger(0, StackProbeSize);
439 return (StackSizeInBytes >= StackProbeSize) &&
440 !F.hasFnAttribute("no-stack-arg-probe");
441}
442
443bool AArch64FrameLowering::shouldCombineCSRLocalStackBump(
444 MachineFunction &MF, unsigned StackBumpBytes) const {
445 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
446 const MachineFrameInfo &MFI = MF.getFrameInfo();
447 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
448 const AArch64RegisterInfo *RegInfo = Subtarget.getRegisterInfo();
449
450 if (MF.getFunction().hasOptSize())
451 return false;
452
453 if (AFI->getLocalStackSize() == 0)
454 return false;
455
456 // 512 is the maximum immediate for stp/ldp that will be used for
457 // callee-save save/restores
458 if (StackBumpBytes >= 512 || windowsRequiresStackProbe(MF, StackBumpBytes))
459 return false;
460
461 if (MFI.hasVarSizedObjects())
462 return false;
463
464 if (RegInfo->needsStackRealignment(MF))
465 return false;
466
467 // This isn't strictly necessary, but it simplifies things a bit since the
468 // current RedZone handling code assumes the SP is adjusted by the
469 // callee-save save/restore code.
470 if (canUseRedZone(MF))
471 return false;
472
473 // When there is an SVE area on the stack, always allocate the
474 // callee-saves and spills/locals separately.
475 if (getSVEStackSize(MF))
476 return false;
477
478 return true;
479}
480
481// Given a load or a store instruction, generate an appropriate unwinding SEH
482// code on Windows.
483static MachineBasicBlock::iterator InsertSEH(MachineBasicBlock::iterator MBBI,
484 const TargetInstrInfo &TII,
485 MachineInstr::MIFlag Flag) {
486 unsigned Opc = MBBI->getOpcode();
487 MachineBasicBlock *MBB = MBBI->getParent();
488 MachineFunction &MF = *MBB->getParent();
489 DebugLoc DL = MBBI->getDebugLoc();
490 unsigned ImmIdx = MBBI->getNumOperands() - 1;
491 int Imm = MBBI->getOperand(ImmIdx).getImm();
492 MachineInstrBuilder MIB;
493 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
494 const AArch64RegisterInfo *RegInfo = Subtarget.getRegisterInfo();
495
496 switch (Opc) {
497 default:
498 llvm_unreachable("No SEH Opcode for this instruction")::llvm::llvm_unreachable_internal("No SEH Opcode for this instruction"
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 498)
;
499 case AArch64::LDPDpost:
500 Imm = -Imm;
501 LLVM_FALLTHROUGH[[gnu::fallthrough]];
502 case AArch64::STPDpre: {
503 unsigned Reg0 = RegInfo->getSEHRegNum(MBBI->getOperand(1).getReg());
504 unsigned Reg1 = RegInfo->getSEHRegNum(MBBI->getOperand(2).getReg());
505 MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveFRegP_X))
506 .addImm(Reg0)
507 .addImm(Reg1)
508 .addImm(Imm * 8)
509 .setMIFlag(Flag);
510 break;
511 }
512 case AArch64::LDPXpost:
513 Imm = -Imm;
514 LLVM_FALLTHROUGH[[gnu::fallthrough]];
515 case AArch64::STPXpre: {
516 Register Reg0 = MBBI->getOperand(1).getReg();
517 Register Reg1 = MBBI->getOperand(2).getReg();
518 if (Reg0 == AArch64::FP && Reg1 == AArch64::LR)
519 MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveFPLR_X))
520 .addImm(Imm * 8)
521 .setMIFlag(Flag);
522 else
523 MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveRegP_X))
524 .addImm(RegInfo->getSEHRegNum(Reg0))
525 .addImm(RegInfo->getSEHRegNum(Reg1))
526 .addImm(Imm * 8)
527 .setMIFlag(Flag);
528 break;
529 }
530 case AArch64::LDRDpost:
531 Imm = -Imm;
532 LLVM_FALLTHROUGH[[gnu::fallthrough]];
533 case AArch64::STRDpre: {
534 unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(1).getReg());
535 MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveFReg_X))
536 .addImm(Reg)
537 .addImm(Imm)
538 .setMIFlag(Flag);
539 break;
540 }
541 case AArch64::LDRXpost:
542 Imm = -Imm;
543 LLVM_FALLTHROUGH[[gnu::fallthrough]];
544 case AArch64::STRXpre: {
545 unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(1).getReg());
546 MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveReg_X))
547 .addImm(Reg)
548 .addImm(Imm)
549 .setMIFlag(Flag);
550 break;
551 }
552 case AArch64::STPDi:
553 case AArch64::LDPDi: {
554 unsigned Reg0 = RegInfo->getSEHRegNum(MBBI->getOperand(0).getReg());
555 unsigned Reg1 = RegInfo->getSEHRegNum(MBBI->getOperand(1).getReg());
556 MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveFRegP))
557 .addImm(Reg0)
558 .addImm(Reg1)
559 .addImm(Imm * 8)
560 .setMIFlag(Flag);
561 break;
562 }
563 case AArch64::STPXi:
564 case AArch64::LDPXi: {
565 Register Reg0 = MBBI->getOperand(0).getReg();
566 Register Reg1 = MBBI->getOperand(1).getReg();
567 if (Reg0 == AArch64::FP && Reg1 == AArch64::LR)
568 MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveFPLR))
569 .addImm(Imm * 8)
570 .setMIFlag(Flag);
571 else
572 MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveRegP))
573 .addImm(RegInfo->getSEHRegNum(Reg0))
574 .addImm(RegInfo->getSEHRegNum(Reg1))
575 .addImm(Imm * 8)
576 .setMIFlag(Flag);
577 break;
578 }
579 case AArch64::STRXui:
580 case AArch64::LDRXui: {
581 int Reg = RegInfo->getSEHRegNum(MBBI->getOperand(0).getReg());
582 MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveReg))
583 .addImm(Reg)
584 .addImm(Imm * 8)
585 .setMIFlag(Flag);
586 break;
587 }
588 case AArch64::STRDui:
589 case AArch64::LDRDui: {
590 unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(0).getReg());
591 MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveFReg))
592 .addImm(Reg)
593 .addImm(Imm * 8)
594 .setMIFlag(Flag);
595 break;
596 }
597 }
598 auto I = MBB->insertAfter(MBBI, MIB);
599 return I;
600}
601
602// Fix up the SEH opcode associated with the save/restore instruction.
603static void fixupSEHOpcode(MachineBasicBlock::iterator MBBI,
604 unsigned LocalStackSize) {
605 MachineOperand *ImmOpnd = nullptr;
606 unsigned ImmIdx = MBBI->getNumOperands() - 1;
607 switch (MBBI->getOpcode()) {
608 default:
609 llvm_unreachable("Fix the offset in the SEH instruction")::llvm::llvm_unreachable_internal("Fix the offset in the SEH instruction"
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 609)
;
610 case AArch64::SEH_SaveFPLR:
611 case AArch64::SEH_SaveRegP:
612 case AArch64::SEH_SaveReg:
613 case AArch64::SEH_SaveFRegP:
614 case AArch64::SEH_SaveFReg:
615 ImmOpnd = &MBBI->getOperand(ImmIdx);
616 break;
617 }
618 if (ImmOpnd)
619 ImmOpnd->setImm(ImmOpnd->getImm() + LocalStackSize);
620}
621
622// Convert callee-save register save/restore instruction to do stack pointer
623// decrement/increment to allocate/deallocate the callee-save stack area by
624// converting store/load to use pre/post increment version.
625static MachineBasicBlock::iterator convertCalleeSaveRestoreToSPPrePostIncDec(
626 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
627 const DebugLoc &DL, const TargetInstrInfo *TII, int CSStackSizeInc,
628 bool NeedsWinCFI, bool *HasWinCFI, bool InProlog = true) {
629 // Ignore instructions that do not operate on SP, i.e. shadow call stack
630 // instructions and associated CFI instruction.
631 while (MBBI->getOpcode() == AArch64::STRXpost ||
632 MBBI->getOpcode() == AArch64::LDRXpre ||
633 MBBI->getOpcode() == AArch64::CFI_INSTRUCTION) {
634 if (MBBI->getOpcode() != AArch64::CFI_INSTRUCTION)
635 assert(MBBI->getOperand(0).getReg() != AArch64::SP)((MBBI->getOperand(0).getReg() != AArch64::SP) ? static_cast
<void> (0) : __assert_fail ("MBBI->getOperand(0).getReg() != AArch64::SP"
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 635, __PRETTY_FUNCTION__))
;
636 ++MBBI;
637 }
638 unsigned NewOpc;
639 int Scale = 1;
640 switch (MBBI->getOpcode()) {
641 default:
642 llvm_unreachable("Unexpected callee-save save/restore opcode!")::llvm::llvm_unreachable_internal("Unexpected callee-save save/restore opcode!"
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 642)
;
643 case AArch64::STPXi:
644 NewOpc = AArch64::STPXpre;
645 Scale = 8;
646 break;
647 case AArch64::STPDi:
648 NewOpc = AArch64::STPDpre;
649 Scale = 8;
650 break;
651 case AArch64::STPQi:
652 NewOpc = AArch64::STPQpre;
653 Scale = 16;
654 break;
655 case AArch64::STRXui:
656 NewOpc = AArch64::STRXpre;
657 break;
658 case AArch64::STRDui:
659 NewOpc = AArch64::STRDpre;
660 break;
661 case AArch64::STRQui:
662 NewOpc = AArch64::STRQpre;
663 break;
664 case AArch64::LDPXi:
665 NewOpc = AArch64::LDPXpost;
666 Scale = 8;
667 break;
668 case AArch64::LDPDi:
669 NewOpc = AArch64::LDPDpost;
670 Scale = 8;
671 break;
672 case AArch64::LDPQi:
673 NewOpc = AArch64::LDPQpost;
674 Scale = 16;
675 break;
676 case AArch64::LDRXui:
677 NewOpc = AArch64::LDRXpost;
678 break;
679 case AArch64::LDRDui:
680 NewOpc = AArch64::LDRDpost;
681 break;
682 case AArch64::LDRQui:
683 NewOpc = AArch64::LDRQpost;
684 break;
685 }
686 // Get rid of the SEH code associated with the old instruction.
687 if (NeedsWinCFI) {
688 auto SEH = std::next(MBBI);
689 if (AArch64InstrInfo::isSEHInstruction(*SEH))
690 SEH->eraseFromParent();
691 }
692
693 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(NewOpc));
694 MIB.addReg(AArch64::SP, RegState::Define);
695
696 // Copy all operands other than the immediate offset.
697 unsigned OpndIdx = 0;
698 for (unsigned OpndEnd = MBBI->getNumOperands() - 1; OpndIdx < OpndEnd;
699 ++OpndIdx)
700 MIB.add(MBBI->getOperand(OpndIdx));
701
702 assert(MBBI->getOperand(OpndIdx).getImm() == 0 &&((MBBI->getOperand(OpndIdx).getImm() == 0 && "Unexpected immediate offset in first/last callee-save save/restore "
"instruction!") ? static_cast<void> (0) : __assert_fail
("MBBI->getOperand(OpndIdx).getImm() == 0 && \"Unexpected immediate offset in first/last callee-save save/restore \" \"instruction!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 704, __PRETTY_FUNCTION__))
703 "Unexpected immediate offset in first/last callee-save save/restore "((MBBI->getOperand(OpndIdx).getImm() == 0 && "Unexpected immediate offset in first/last callee-save save/restore "
"instruction!") ? static_cast<void> (0) : __assert_fail
("MBBI->getOperand(OpndIdx).getImm() == 0 && \"Unexpected immediate offset in first/last callee-save save/restore \" \"instruction!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 704, __PRETTY_FUNCTION__))
704 "instruction!")((MBBI->getOperand(OpndIdx).getImm() == 0 && "Unexpected immediate offset in first/last callee-save save/restore "
"instruction!") ? static_cast<void> (0) : __assert_fail
("MBBI->getOperand(OpndIdx).getImm() == 0 && \"Unexpected immediate offset in first/last callee-save save/restore \" \"instruction!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 704, __PRETTY_FUNCTION__))
;
705 assert(MBBI->getOperand(OpndIdx - 1).getReg() == AArch64::SP &&((MBBI->getOperand(OpndIdx - 1).getReg() == AArch64::SP &&
"Unexpected base register in callee-save save/restore instruction!"
) ? static_cast<void> (0) : __assert_fail ("MBBI->getOperand(OpndIdx - 1).getReg() == AArch64::SP && \"Unexpected base register in callee-save save/restore instruction!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 706, __PRETTY_FUNCTION__))
706 "Unexpected base register in callee-save save/restore instruction!")((MBBI->getOperand(OpndIdx - 1).getReg() == AArch64::SP &&
"Unexpected base register in callee-save save/restore instruction!"
) ? static_cast<void> (0) : __assert_fail ("MBBI->getOperand(OpndIdx - 1).getReg() == AArch64::SP && \"Unexpected base register in callee-save save/restore instruction!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 706, __PRETTY_FUNCTION__))
;
707 assert(CSStackSizeInc % Scale == 0)((CSStackSizeInc % Scale == 0) ? static_cast<void> (0) :
__assert_fail ("CSStackSizeInc % Scale == 0", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 707, __PRETTY_FUNCTION__))
;
708 MIB.addImm(CSStackSizeInc / Scale);
709
710 MIB.setMIFlags(MBBI->getFlags());
711 MIB.setMemRefs(MBBI->memoperands());
712
713 // Generate a new SEH code that corresponds to the new instruction.
714 if (NeedsWinCFI) {
715 *HasWinCFI = true;
716 InsertSEH(*MIB, *TII,
717 InProlog ? MachineInstr::FrameSetup : MachineInstr::FrameDestroy);
718 }
719
720 return std::prev(MBB.erase(MBBI));
721}
722
723// Fixup callee-save register save/restore instructions to take into account
724// combined SP bump by adding the local stack size to the stack offsets.
725static void fixupCalleeSaveRestoreStackOffset(MachineInstr &MI,
726 unsigned LocalStackSize,
727 bool NeedsWinCFI,
728 bool *HasWinCFI) {
729 if (AArch64InstrInfo::isSEHInstruction(MI))
730 return;
731
732 unsigned Opc = MI.getOpcode();
733
734 // Ignore instructions that do not operate on SP, i.e. shadow call stack
735 // instructions and associated CFI instruction.
736 if (Opc == AArch64::STRXpost || Opc == AArch64::LDRXpre ||
737 Opc == AArch64::CFI_INSTRUCTION) {
738 if (Opc != AArch64::CFI_INSTRUCTION)
739 assert(MI.getOperand(0).getReg() != AArch64::SP)((MI.getOperand(0).getReg() != AArch64::SP) ? static_cast<
void> (0) : __assert_fail ("MI.getOperand(0).getReg() != AArch64::SP"
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 739, __PRETTY_FUNCTION__))
;
740 return;
741 }
742
743 unsigned Scale;
744 switch (Opc) {
745 case AArch64::STPXi:
746 case AArch64::STRXui:
747 case AArch64::STPDi:
748 case AArch64::STRDui:
749 case AArch64::LDPXi:
750 case AArch64::LDRXui:
751 case AArch64::LDPDi:
752 case AArch64::LDRDui:
753 Scale = 8;
754 break;
755 case AArch64::STPQi:
756 case AArch64::STRQui:
757 case AArch64::LDPQi:
758 case AArch64::LDRQui:
759 Scale = 16;
760 break;
761 default:
762 llvm_unreachable("Unexpected callee-save save/restore opcode!")::llvm::llvm_unreachable_internal("Unexpected callee-save save/restore opcode!"
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 762)
;
763 }
764
765 unsigned OffsetIdx = MI.getNumExplicitOperands() - 1;
766 assert(MI.getOperand(OffsetIdx - 1).getReg() == AArch64::SP &&((MI.getOperand(OffsetIdx - 1).getReg() == AArch64::SP &&
"Unexpected base register in callee-save save/restore instruction!"
) ? static_cast<void> (0) : __assert_fail ("MI.getOperand(OffsetIdx - 1).getReg() == AArch64::SP && \"Unexpected base register in callee-save save/restore instruction!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 767, __PRETTY_FUNCTION__))
767 "Unexpected base register in callee-save save/restore instruction!")((MI.getOperand(OffsetIdx - 1).getReg() == AArch64::SP &&
"Unexpected base register in callee-save save/restore instruction!"
) ? static_cast<void> (0) : __assert_fail ("MI.getOperand(OffsetIdx - 1).getReg() == AArch64::SP && \"Unexpected base register in callee-save save/restore instruction!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 767, __PRETTY_FUNCTION__))
;
768 // Last operand is immediate offset that needs fixing.
769 MachineOperand &OffsetOpnd = MI.getOperand(OffsetIdx);
770 // All generated opcodes have scaled offsets.
771 assert(LocalStackSize % Scale == 0)((LocalStackSize % Scale == 0) ? static_cast<void> (0) :
__assert_fail ("LocalStackSize % Scale == 0", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 771, __PRETTY_FUNCTION__))
;
772 OffsetOpnd.setImm(OffsetOpnd.getImm() + LocalStackSize / Scale);
773
774 if (NeedsWinCFI) {
775 *HasWinCFI = true;
776 auto MBBI = std::next(MachineBasicBlock::iterator(MI));
777 assert(MBBI != MI.getParent()->end() && "Expecting a valid instruction")((MBBI != MI.getParent()->end() && "Expecting a valid instruction"
) ? static_cast<void> (0) : __assert_fail ("MBBI != MI.getParent()->end() && \"Expecting a valid instruction\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 777, __PRETTY_FUNCTION__))
;
778 assert(AArch64InstrInfo::isSEHInstruction(*MBBI) &&((AArch64InstrInfo::isSEHInstruction(*MBBI) && "Expecting a SEH instruction"
) ? static_cast<void> (0) : __assert_fail ("AArch64InstrInfo::isSEHInstruction(*MBBI) && \"Expecting a SEH instruction\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 779, __PRETTY_FUNCTION__))
779 "Expecting a SEH instruction")((AArch64InstrInfo::isSEHInstruction(*MBBI) && "Expecting a SEH instruction"
) ? static_cast<void> (0) : __assert_fail ("AArch64InstrInfo::isSEHInstruction(*MBBI) && \"Expecting a SEH instruction\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 779, __PRETTY_FUNCTION__))
;
780 fixupSEHOpcode(MBBI, LocalStackSize);
781 }
782}
783
784static void adaptForLdStOpt(MachineBasicBlock &MBB,
785 MachineBasicBlock::iterator FirstSPPopI,
786 MachineBasicBlock::iterator LastPopI) {
787 // Sometimes (when we restore in the same order as we save), we can end up
788 // with code like this:
789 //
790 // ldp x26, x25, [sp]
791 // ldp x24, x23, [sp, #16]
792 // ldp x22, x21, [sp, #32]
793 // ldp x20, x19, [sp, #48]
794 // add sp, sp, #64
795 //
796 // In this case, it is always better to put the first ldp at the end, so
797 // that the load-store optimizer can run and merge the ldp and the add into
798 // a post-index ldp.
799 // If we managed to grab the first pop instruction, move it to the end.
800 if (ReverseCSRRestoreSeq)
801 MBB.splice(FirstSPPopI, &MBB, LastPopI);
802 // We should end up with something like this now:
803 //
804 // ldp x24, x23, [sp, #16]
805 // ldp x22, x21, [sp, #32]
806 // ldp x20, x19, [sp, #48]
807 // ldp x26, x25, [sp]
808 // add sp, sp, #64
809 //
810 // and the load-store optimizer can merge the last two instructions into:
811 //
812 // ldp x26, x25, [sp], #64
813 //
814}
815
816static bool ShouldSignWithAKey(MachineFunction &MF) {
817 const Function &F = MF.getFunction();
818 if (!F.hasFnAttribute("sign-return-address-key"))
819 return true;
820
821 const StringRef Key =
822 F.getFnAttribute("sign-return-address-key").getValueAsString();
823 assert(Key.equals_lower("a_key") || Key.equals_lower("b_key"))((Key.equals_lower("a_key") || Key.equals_lower("b_key")) ? static_cast
<void> (0) : __assert_fail ("Key.equals_lower(\"a_key\") || Key.equals_lower(\"b_key\")"
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 823, __PRETTY_FUNCTION__))
;
824 return Key.equals_lower("a_key");
825}
826
827static bool needsWinCFI(const MachineFunction &MF) {
828 const Function &F = MF.getFunction();
829 return MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
830 F.needsUnwindTableEntry();
831}
832
833static bool isTargetDarwin(const MachineFunction &MF) {
834 return MF.getSubtarget<AArch64Subtarget>().isTargetDarwin();
835}
836
837// Convenience function to determine whether I is an SVE callee save.
838bool IsSVECalleeSave(MachineBasicBlock::iterator I) {
839 switch (I->getOpcode()) {
840 default:
841 return false;
842 case AArch64::STR_ZXI:
843 case AArch64::STR_PXI:
844 case AArch64::LDR_ZXI:
845 case AArch64::LDR_PXI:
846 return I->getFlag(MachineInstr::FrameSetup) ||
847 I->getFlag(MachineInstr::FrameDestroy);
848 }
849}
850
851void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
852 MachineBasicBlock &MBB) const {
853 MachineBasicBlock::iterator MBBI = MBB.begin();
854 const MachineFrameInfo &MFI = MF.getFrameInfo();
855 const Function &F = MF.getFunction();
856 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
857 const AArch64RegisterInfo *RegInfo = Subtarget.getRegisterInfo();
858 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
859 MachineModuleInfo &MMI = MF.getMMI();
860 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
861 bool needsFrameMoves =
862 MF.needsFrameMoves() && !MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
863 bool HasFP = hasFP(MF);
864 bool NeedsWinCFI = needsWinCFI(MF);
865 bool HasWinCFI = false;
866 auto Cleanup = make_scope_exit([&]() { MF.setHasWinCFI(HasWinCFI); });
867
868 bool IsFunclet = MBB.isEHFuncletEntry();
869
870 // At this point, we're going to decide whether or not the function uses a
871 // redzone. In most cases, the function doesn't have a redzone so let's
872 // assume that's false and set it to true in the case that there's a redzone.
873 AFI->setHasRedZone(false);
874
875 // Debug location must be unknown since the first debug location is used
876 // to determine the end of the prologue.
877 DebugLoc DL;
878
879 if (ShouldSignReturnAddress(MF)) {
880 if (ShouldSignWithAKey(MF))
881 BuildMI(MBB, MBBI, DL, TII->get(AArch64::PACIASP))
882 .setMIFlag(MachineInstr::FrameSetup);
883 else {
884 BuildMI(MBB, MBBI, DL, TII->get(AArch64::EMITBKEY))
885 .setMIFlag(MachineInstr::FrameSetup);
886 BuildMI(MBB, MBBI, DL, TII->get(AArch64::PACIBSP))
887 .setMIFlag(MachineInstr::FrameSetup);
888 }
889
890 unsigned CFIIndex =
891 MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr));
892 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
893 .addCFIIndex(CFIIndex)
894 .setMIFlags(MachineInstr::FrameSetup);
895 }
896
897 // All calls are tail calls in GHC calling conv, and functions have no
898 // prologue/epilogue.
899 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
900 return;
901
902 // Set tagged base pointer to the bottom of the stack frame.
903 // Ideally it should match SP value after prologue.
904 AFI->setTaggedBasePointerOffset(MFI.getStackSize());
905
906 const StackOffset &SVEStackSize = getSVEStackSize(MF);
907
908 // getStackSize() includes all the locals in its size calculation. We don't
909 // include these locals when computing the stack size of a funclet, as they
910 // are allocated in the parent's stack frame and accessed via the frame
911 // pointer from the funclet. We only save the callee saved registers in the
912 // funclet, which are really the callee saved registers of the parent
913 // function, including the funclet.
914 int NumBytes = IsFunclet ? (int)getWinEHFuncletFrameSize(MF)
915 : (int)MFI.getStackSize();
916 if (!AFI->hasStackFrame() && !windowsRequiresStackProbe(MF, NumBytes)) {
917 assert(!HasFP && "unexpected function without stack frame but with FP")((!HasFP && "unexpected function without stack frame but with FP"
) ? static_cast<void> (0) : __assert_fail ("!HasFP && \"unexpected function without stack frame but with FP\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 917, __PRETTY_FUNCTION__))
;
918 assert(!SVEStackSize &&((!SVEStackSize && "unexpected function without stack frame but with SVE objects"
) ? static_cast<void> (0) : __assert_fail ("!SVEStackSize && \"unexpected function without stack frame but with SVE objects\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 919, __PRETTY_FUNCTION__))
919 "unexpected function without stack frame but with SVE objects")((!SVEStackSize && "unexpected function without stack frame but with SVE objects"
) ? static_cast<void> (0) : __assert_fail ("!SVEStackSize && \"unexpected function without stack frame but with SVE objects\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 919, __PRETTY_FUNCTION__))
;
920 // All of the stack allocation is for locals.
921 AFI->setLocalStackSize(NumBytes);
922 if (!NumBytes)
923 return;
924 // REDZONE: If the stack size is less than 128 bytes, we don't need
925 // to actually allocate.
926 if (canUseRedZone(MF)) {
927 AFI->setHasRedZone(true);
928 ++NumRedZoneFunctions;
929 } else {
930 emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP,
931 {-NumBytes, MVT::i8}, TII, MachineInstr::FrameSetup,
932 false, NeedsWinCFI, &HasWinCFI);
933 if (!NeedsWinCFI) {
934 // Label used to tie together the PROLOG_LABEL and the MachineMoves.
935 MCSymbol *FrameLabel = MMI.getContext().createTempSymbol();
936 // Encode the stack size of the leaf function.
937 unsigned CFIIndex = MF.addFrameInst(
938 MCCFIInstruction::createDefCfaOffset(FrameLabel, -NumBytes));
939 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
940 .addCFIIndex(CFIIndex)
941 .setMIFlags(MachineInstr::FrameSetup);
942 }
943 }
944
945 if (NeedsWinCFI) {
946 HasWinCFI = true;
947 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
948 .setMIFlag(MachineInstr::FrameSetup);
949 }
950
951 return;
952 }
953
954 bool IsWin64 =
955 Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv());
956 // Var args are accounted for in the containing function, so don't
957 // include them for funclets.
958 unsigned FixedObject = (IsWin64 && !IsFunclet) ?
959 alignTo(AFI->getVarArgsGPRSize(), 16) : 0;
960
961 auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
962 // All of the remaining stack allocations are for locals.
963 AFI->setLocalStackSize(NumBytes - PrologueSaveSize);
964 bool CombineSPBump = shouldCombineCSRLocalStackBump(MF, NumBytes);
965 if (CombineSPBump) {
966 assert(!SVEStackSize && "Cannot combine SP bump with SVE")((!SVEStackSize && "Cannot combine SP bump with SVE")
? static_cast<void> (0) : __assert_fail ("!SVEStackSize && \"Cannot combine SP bump with SVE\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 966, __PRETTY_FUNCTION__))
;
967 emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP,
968 {-NumBytes, MVT::i8}, TII, MachineInstr::FrameSetup, false,
969 NeedsWinCFI, &HasWinCFI);
970 NumBytes = 0;
971 } else if (PrologueSaveSize != 0) {
972 MBBI = convertCalleeSaveRestoreToSPPrePostIncDec(
973 MBB, MBBI, DL, TII, -PrologueSaveSize, NeedsWinCFI, &HasWinCFI);
974 NumBytes -= PrologueSaveSize;
975 }
976 assert(NumBytes >= 0 && "Negative stack allocation size!?")((NumBytes >= 0 && "Negative stack allocation size!?"
) ? static_cast<void> (0) : __assert_fail ("NumBytes >= 0 && \"Negative stack allocation size!?\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 976, __PRETTY_FUNCTION__))
;
977
978 // Move past the saves of the callee-saved registers, fixing up the offsets
979 // and pre-inc if we decided to combine the callee-save and local stack
980 // pointer bump above.
981 MachineBasicBlock::iterator End = MBB.end();
982 while (MBBI != End && MBBI->getFlag(MachineInstr::FrameSetup) &&
983 !IsSVECalleeSave(MBBI)) {
984 if (CombineSPBump)
985 fixupCalleeSaveRestoreStackOffset(*MBBI, AFI->getLocalStackSize(),
986 NeedsWinCFI, &HasWinCFI);
987 ++MBBI;
988 }
989
990 // The code below is not applicable to funclets. We have emitted all the SEH
991 // opcodes that we needed to emit. The FP and BP belong to the containing
992 // function.
993 if (IsFunclet) {
994 if (NeedsWinCFI) {
995 HasWinCFI = true;
996 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
997 .setMIFlag(MachineInstr::FrameSetup);
998 }
999
1000 // SEH funclets are passed the frame pointer in X1. If the parent
1001 // function uses the base register, then the base register is used
1002 // directly, and is not retrieved from X1.
1003 if (F.hasPersonalityFn()) {
1004 EHPersonality Per = classifyEHPersonality(F.getPersonalityFn());
1005 if (isAsynchronousEHPersonality(Per)) {
1006 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::COPY), AArch64::FP)
1007 .addReg(AArch64::X1).setMIFlag(MachineInstr::FrameSetup);
1008 MBB.addLiveIn(AArch64::X1);
1009 }
1010 }
1011
1012 return;
1013 }
1014
1015 if (HasFP) {
1016 // Only set up FP if we actually need to.
1017 int FPOffset = isTargetDarwin(MF) ? (AFI->getCalleeSavedStackSize() - 16) : 0;
1018
1019 if (CombineSPBump)
1020 FPOffset += AFI->getLocalStackSize();
1021
1022 // Issue sub fp, sp, FPOffset or
1023 // mov fp,sp when FPOffset is zero.
1024 // Note: All stores of callee-saved registers are marked as "FrameSetup".
1025 // This code marks the instruction(s) that set the FP also.
1026 emitFrameOffset(MBB, MBBI, DL, AArch64::FP, AArch64::SP,
1027 {FPOffset, MVT::i8}, TII, MachineInstr::FrameSetup, false,
1028 NeedsWinCFI, &HasWinCFI);
1029 }
1030
1031 if (windowsRequiresStackProbe(MF, NumBytes)) {
1032 uint32_t NumWords = NumBytes >> 4;
1033 if (NeedsWinCFI) {
1034 HasWinCFI = true;
1035 // alloc_l can hold at most 256MB, so assume that NumBytes doesn't
1036 // exceed this amount. We need to move at most 2^24 - 1 into x15.
1037 // This is at most two instructions, MOVZ follwed by MOVK.
1038 // TODO: Fix to use multiple stack alloc unwind codes for stacks
1039 // exceeding 256MB in size.
1040 if (NumBytes >= (1 << 28))
1041 report_fatal_error("Stack size cannot exceed 256MB for stack "
1042 "unwinding purposes");
1043
1044 uint32_t LowNumWords = NumWords & 0xFFFF;
1045 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVZXi), AArch64::X15)
1046 .addImm(LowNumWords)
1047 .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, 0))
1048 .setMIFlag(MachineInstr::FrameSetup);
1049 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1050 .setMIFlag(MachineInstr::FrameSetup);
1051 if ((NumWords & 0xFFFF0000) != 0) {
1052 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVKXi), AArch64::X15)
1053 .addReg(AArch64::X15)
1054 .addImm((NumWords & 0xFFFF0000) >> 16) // High half
1055 .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, 16))
1056 .setMIFlag(MachineInstr::FrameSetup);
1057 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1058 .setMIFlag(MachineInstr::FrameSetup);
1059 }
1060 } else {
1061 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVi64imm), AArch64::X15)
1062 .addImm(NumWords)
1063 .setMIFlags(MachineInstr::FrameSetup);
1064 }
1065
1066 switch (MF.getTarget().getCodeModel()) {
1067 case CodeModel::Tiny:
1068 case CodeModel::Small:
1069 case CodeModel::Medium:
1070 case CodeModel::Kernel:
1071 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
1072 .addExternalSymbol("__chkstk")
1073 .addReg(AArch64::X15, RegState::Implicit)
1074 .addReg(AArch64::X16, RegState::Implicit | RegState::Define | RegState::Dead)
1075 .addReg(AArch64::X17, RegState::Implicit | RegState::Define | RegState::Dead)
1076 .addReg(AArch64::NZCV, RegState::Implicit | RegState::Define | RegState::Dead)
1077 .setMIFlags(MachineInstr::FrameSetup);
1078 if (NeedsWinCFI) {
1079 HasWinCFI = true;
1080 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1081 .setMIFlag(MachineInstr::FrameSetup);
1082 }
1083 break;
1084 case CodeModel::Large:
1085 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVaddrEXT))
1086 .addReg(AArch64::X16, RegState::Define)
1087 .addExternalSymbol("__chkstk")
1088 .addExternalSymbol("__chkstk")
1089 .setMIFlags(MachineInstr::FrameSetup);
1090 if (NeedsWinCFI) {
1091 HasWinCFI = true;
1092 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1093 .setMIFlag(MachineInstr::FrameSetup);
1094 }
1095
1096 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BLR))
1097 .addReg(AArch64::X16, RegState::Kill)
1098 .addReg(AArch64::X15, RegState::Implicit | RegState::Define)
1099 .addReg(AArch64::X16, RegState::Implicit | RegState::Define | RegState::Dead)
1100 .addReg(AArch64::X17, RegState::Implicit | RegState::Define | RegState::Dead)
1101 .addReg(AArch64::NZCV, RegState::Implicit | RegState::Define | RegState::Dead)
1102 .setMIFlags(MachineInstr::FrameSetup);
1103 if (NeedsWinCFI) {
1104 HasWinCFI = true;
1105 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1106 .setMIFlag(MachineInstr::FrameSetup);
1107 }
1108 break;
1109 }
1110
1111 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SUBXrx64), AArch64::SP)
1112 .addReg(AArch64::SP, RegState::Kill)
1113 .addReg(AArch64::X15, RegState::Kill)
1114 .addImm(AArch64_AM::getArithExtendImm(AArch64_AM::UXTX, 4))
1115 .setMIFlags(MachineInstr::FrameSetup);
1116 if (NeedsWinCFI) {
1117 HasWinCFI = true;
1118 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
1119 .addImm(NumBytes)
1120 .setMIFlag(MachineInstr::FrameSetup);
1121 }
1122 NumBytes = 0;
1123 }
1124
1125 StackOffset AllocateBefore = SVEStackSize, AllocateAfter = {};
1126 MachineBasicBlock::iterator CalleeSavesBegin = MBBI, CalleeSavesEnd = MBBI;
1127
1128 // Process the SVE callee-saves to determine what space needs to be
1129 // allocated.
1130 if (AFI->getSVECalleeSavedStackSize()) {
1131 // Find callee save instructions in frame.
1132 CalleeSavesBegin = MBBI;
1133 assert(IsSVECalleeSave(CalleeSavesBegin) && "Unexpected instruction")((IsSVECalleeSave(CalleeSavesBegin) && "Unexpected instruction"
) ? static_cast<void> (0) : __assert_fail ("IsSVECalleeSave(CalleeSavesBegin) && \"Unexpected instruction\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1133, __PRETTY_FUNCTION__))
;
1134 while (IsSVECalleeSave(MBBI) && MBBI != MBB.getFirstTerminator())
1135 ++MBBI;
1136 CalleeSavesEnd = MBBI;
1137
1138 int64_t OffsetToFirstCalleeSaveFromSP =
1139 MFI.getObjectOffset(AFI->getMaxSVECSFrameIndex());
1140 StackOffset OffsetToCalleeSavesFromSP =
1141 StackOffset(OffsetToFirstCalleeSaveFromSP, MVT::nxv1i8) + SVEStackSize;
1142 AllocateBefore -= OffsetToCalleeSavesFromSP;
1143 AllocateAfter = SVEStackSize - AllocateBefore;
1144 }
1145
1146 // Allocate space for the callee saves (if any).
1147 emitFrameOffset(MBB, CalleeSavesBegin, DL, AArch64::SP, AArch64::SP,
1148 -AllocateBefore, TII,
1149 MachineInstr::FrameSetup);
1150
1151 // Finally allocate remaining SVE stack space.
1152 emitFrameOffset(MBB, CalleeSavesEnd, DL, AArch64::SP, AArch64::SP,
1153 -AllocateAfter, TII,
1154 MachineInstr::FrameSetup);
1155
1156 // Allocate space for the rest of the frame.
1157 if (NumBytes) {
1158 const bool NeedsRealignment = RegInfo->needsStackRealignment(MF);
1159 unsigned scratchSPReg = AArch64::SP;
1160
1161 if (NeedsRealignment) {
1162 scratchSPReg = findScratchNonCalleeSaveRegister(&MBB);
1163 assert(scratchSPReg != AArch64::NoRegister)((scratchSPReg != AArch64::NoRegister) ? static_cast<void>
(0) : __assert_fail ("scratchSPReg != AArch64::NoRegister", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1163, __PRETTY_FUNCTION__))
;
1164 }
1165
1166 // If we're a leaf function, try using the red zone.
1167 if (!canUseRedZone(MF))
1168 // FIXME: in the case of dynamic re-alignment, NumBytes doesn't have
1169 // the correct value here, as NumBytes also includes padding bytes,
1170 // which shouldn't be counted here.
1171 emitFrameOffset(MBB, MBBI, DL, scratchSPReg, AArch64::SP,
1172 {-NumBytes, MVT::i8}, TII, MachineInstr::FrameSetup,
1173 false, NeedsWinCFI, &HasWinCFI);
1174
1175 if (NeedsRealignment) {
1176 const unsigned Alignment = MFI.getMaxAlignment();
1177 const unsigned NrBitsToZero = countTrailingZeros(Alignment);
1178 assert(NrBitsToZero > 1)((NrBitsToZero > 1) ? static_cast<void> (0) : __assert_fail
("NrBitsToZero > 1", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1178, __PRETTY_FUNCTION__))
;
1179 assert(scratchSPReg != AArch64::SP)((scratchSPReg != AArch64::SP) ? static_cast<void> (0) :
__assert_fail ("scratchSPReg != AArch64::SP", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1179, __PRETTY_FUNCTION__))
;
1180
1181 // SUB X9, SP, NumBytes
1182 // -- X9 is temporary register, so shouldn't contain any live data here,
1183 // -- free to use. This is already produced by emitFrameOffset above.
1184 // AND SP, X9, 0b11111...0000
1185 // The logical immediates have a non-trivial encoding. The following
1186 // formula computes the encoded immediate with all ones but
1187 // NrBitsToZero zero bits as least significant bits.
1188 uint32_t andMaskEncoded = (1 << 12) // = N
1189 | ((64 - NrBitsToZero) << 6) // immr
1190 | ((64 - NrBitsToZero - 1) << 0); // imms
1191
1192 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ANDXri), AArch64::SP)
1193 .addReg(scratchSPReg, RegState::Kill)
1194 .addImm(andMaskEncoded);
1195 AFI->setStackRealigned(true);
1196 if (NeedsWinCFI) {
1197 HasWinCFI = true;
1198 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
1199 .addImm(NumBytes & andMaskEncoded)
1200 .setMIFlag(MachineInstr::FrameSetup);
1201 }
1202 }
1203 }
1204
1205 // If we need a base pointer, set it up here. It's whatever the value of the
1206 // stack pointer is at this point. Any variable size objects will be allocated
1207 // after this, so we can still use the base pointer to reference locals.
1208 //
1209 // FIXME: Clarify FrameSetup flags here.
1210 // Note: Use emitFrameOffset() like above for FP if the FrameSetup flag is
1211 // needed.
1212 if (RegInfo->hasBasePointer(MF)) {
1213 TII->copyPhysReg(MBB, MBBI, DL, RegInfo->getBaseRegister(), AArch64::SP,
1214 false);
1215 if (NeedsWinCFI) {
1216 HasWinCFI = true;
1217 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_Nop))
1218 .setMIFlag(MachineInstr::FrameSetup);
1219 }
1220 }
1221
1222 // The very last FrameSetup instruction indicates the end of prologue. Emit a
1223 // SEH opcode indicating the prologue end.
1224 if (NeedsWinCFI && HasWinCFI) {
1225 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
1226 .setMIFlag(MachineInstr::FrameSetup);
1227 }
1228
1229 if (needsFrameMoves) {
1230 const DataLayout &TD = MF.getDataLayout();
1231 const int StackGrowth = isTargetDarwin(MF)
1232 ? (2 * -TD.getPointerSize(0))
1233 : -AFI->getCalleeSavedStackSize();
1234 Register FramePtr = RegInfo->getFrameRegister(MF);
1235 // An example of the prologue:
1236 //
1237 // .globl __foo
1238 // .align 2
1239 // __foo:
1240 // Ltmp0:
1241 // .cfi_startproc
1242 // .cfi_personality 155, ___gxx_personality_v0
1243 // Leh_func_begin:
1244 // .cfi_lsda 16, Lexception33
1245 //
1246 // stp xa,bx, [sp, -#offset]!
1247 // ...
1248 // stp x28, x27, [sp, #offset-32]
1249 // stp fp, lr, [sp, #offset-16]
1250 // add fp, sp, #offset - 16
1251 // sub sp, sp, #1360
1252 //
1253 // The Stack:
1254 // +-------------------------------------------+
1255 // 10000 | ........ | ........ | ........ | ........ |
1256 // 10004 | ........ | ........ | ........ | ........ |
1257 // +-------------------------------------------+
1258 // 10008 | ........ | ........ | ........ | ........ |
1259 // 1000c | ........ | ........ | ........ | ........ |
1260 // +===========================================+
1261 // 10010 | X28 Register |
1262 // 10014 | X28 Register |
1263 // +-------------------------------------------+
1264 // 10018 | X27 Register |
1265 // 1001c | X27 Register |
1266 // +===========================================+
1267 // 10020 | Frame Pointer |
1268 // 10024 | Frame Pointer |
1269 // +-------------------------------------------+
1270 // 10028 | Link Register |
1271 // 1002c | Link Register |
1272 // +===========================================+
1273 // 10030 | ........ | ........ | ........ | ........ |
1274 // 10034 | ........ | ........ | ........ | ........ |
1275 // +-------------------------------------------+
1276 // 10038 | ........ | ........ | ........ | ........ |
1277 // 1003c | ........ | ........ | ........ | ........ |
1278 // +-------------------------------------------+
1279 //
1280 // [sp] = 10030 :: >>initial value<<
1281 // sp = 10020 :: stp fp, lr, [sp, #-16]!
1282 // fp = sp == 10020 :: mov fp, sp
1283 // [sp] == 10020 :: stp x28, x27, [sp, #-16]!
1284 // sp == 10010 :: >>final value<<
1285 //
1286 // The frame pointer (w29) points to address 10020. If we use an offset of
1287 // '16' from 'w29', we get the CFI offsets of -8 for w30, -16 for w29, -24
1288 // for w27, and -32 for w28:
1289 //
1290 // Ltmp1:
1291 // .cfi_def_cfa w29, 16
1292 // Ltmp2:
1293 // .cfi_offset w30, -8
1294 // Ltmp3:
1295 // .cfi_offset w29, -16
1296 // Ltmp4:
1297 // .cfi_offset w27, -24
1298 // Ltmp5:
1299 // .cfi_offset w28, -32
1300
1301 if (HasFP) {
1302 // Define the current CFA rule to use the provided FP.
1303 unsigned Reg = RegInfo->getDwarfRegNum(FramePtr, true);
1304 unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfa(
1305 nullptr, Reg, StackGrowth - FixedObject));
1306 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
1307 .addCFIIndex(CFIIndex)
1308 .setMIFlags(MachineInstr::FrameSetup);
1309 } else {
1310 // Encode the stack size of the leaf function.
1311 unsigned CFIIndex = MF.addFrameInst(
1312 MCCFIInstruction::createDefCfaOffset(nullptr, -MFI.getStackSize()));
1313 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
1314 .addCFIIndex(CFIIndex)
1315 .setMIFlags(MachineInstr::FrameSetup);
1316 }
1317
1318 // Now emit the moves for whatever callee saved regs we have (including FP,
1319 // LR if those are saved).
1320 emitCalleeSavedFrameMoves(MBB, MBBI);
1321 }
1322}
1323
1324static void InsertReturnAddressAuth(MachineFunction &MF,
1325 MachineBasicBlock &MBB) {
1326 if (!ShouldSignReturnAddress(MF))
1327 return;
1328 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
1329 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
1330
1331 MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
1332 DebugLoc DL;
1333 if (MBBI != MBB.end())
1334 DL = MBBI->getDebugLoc();
1335
1336 // The AUTIASP instruction assembles to a hint instruction before v8.3a so
1337 // this instruction can safely used for any v8a architecture.
1338 // From v8.3a onwards there are optimised authenticate LR and return
1339 // instructions, namely RETA{A,B}, that can be used instead.
1340 if (Subtarget.hasV8_3aOps() && MBBI != MBB.end() &&
1341 MBBI->getOpcode() == AArch64::RET_ReallyLR) {
1342 BuildMI(MBB, MBBI, DL,
1343 TII->get(ShouldSignWithAKey(MF) ? AArch64::RETAA : AArch64::RETAB))
1344 .copyImplicitOps(*MBBI);
1345 MBB.erase(MBBI);
1346 } else {
1347 BuildMI(
1348 MBB, MBBI, DL,
1349 TII->get(ShouldSignWithAKey(MF) ? AArch64::AUTIASP : AArch64::AUTIBSP))
1350 .setMIFlag(MachineInstr::FrameDestroy);
1351 }
1352}
1353
1354static bool isFuncletReturnInstr(const MachineInstr &MI) {
1355 switch (MI.getOpcode()) {
1356 default:
1357 return false;
1358 case AArch64::CATCHRET:
1359 case AArch64::CLEANUPRET:
1360 return true;
1361 }
1362}
1363
1364void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
1365 MachineBasicBlock &MBB) const {
1366 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
1367 MachineFrameInfo &MFI = MF.getFrameInfo();
1368 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
1369 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
1370 DebugLoc DL;
1371 bool IsTailCallReturn = false;
1372 bool NeedsWinCFI = needsWinCFI(MF);
1373 bool HasWinCFI = false;
1374 bool IsFunclet = false;
1375 auto WinCFI = make_scope_exit([&]() {
1376 if (!MF.hasWinCFI())
1377 MF.setHasWinCFI(HasWinCFI);
1378 });
1379
1380 if (MBB.end() != MBBI) {
1381 DL = MBBI->getDebugLoc();
1382 unsigned RetOpcode = MBBI->getOpcode();
1383 IsTailCallReturn = RetOpcode == AArch64::TCRETURNdi ||
1384 RetOpcode == AArch64::TCRETURNri ||
1385 RetOpcode == AArch64::TCRETURNriBTI;
1386 IsFunclet = isFuncletReturnInstr(*MBBI);
1387 }
1388
1389 int NumBytes = IsFunclet ? (int)getWinEHFuncletFrameSize(MF)
1390 : MFI.getStackSize();
1391 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
1392
1393 // All calls are tail calls in GHC calling conv, and functions have no
1394 // prologue/epilogue.
1395 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
1396 return;
1397
1398 // Initial and residual are named for consistency with the prologue. Note that
1399 // in the epilogue, the residual adjustment is executed first.
1400 uint64_t ArgumentPopSize = 0;
1401 if (IsTailCallReturn) {
1402 MachineOperand &StackAdjust = MBBI->getOperand(1);
1403
1404 // For a tail-call in a callee-pops-arguments environment, some or all of
1405 // the stack may actually be in use for the call's arguments, this is
1406 // calculated during LowerCall and consumed here...
1407 ArgumentPopSize = StackAdjust.getImm();
1408 } else {
1409 // ... otherwise the amount to pop is *all* of the argument space,
1410 // conveniently stored in the MachineFunctionInfo by
1411 // LowerFormalArguments. This will, of course, be zero for the C calling
1412 // convention.
1413 ArgumentPopSize = AFI->getArgumentStackToRestore();
1414 }
1415
1416 // The stack frame should be like below,
1417 //
1418 // ---------------------- ---
1419 // | | |
1420 // | BytesInStackArgArea| CalleeArgStackSize
1421 // | (NumReusableBytes) | (of tail call)
1422 // | | ---
1423 // | | |
1424 // ---------------------| --- |
1425 // | | | |
1426 // | CalleeSavedReg | | |
1427 // | (CalleeSavedStackSize)| | |
1428 // | | | |
1429 // ---------------------| | NumBytes
1430 // | | StackSize (StackAdjustUp)
1431 // | LocalStackSize | | |
1432 // | (covering callee | | |
1433 // | args) | | |
1434 // | | | |
1435 // ---------------------- --- ---
1436 //
1437 // So NumBytes = StackSize + BytesInStackArgArea - CalleeArgStackSize
1438 // = StackSize + ArgumentPopSize
1439 //
1440 // AArch64TargetLowering::LowerCall figures out ArgumentPopSize and keeps
1441 // it as the 2nd argument of AArch64ISD::TC_RETURN.
1442
1443 auto Cleanup = make_scope_exit([&] { InsertReturnAddressAuth(MF, MBB); });
1444
1445 bool IsWin64 =
1446 Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv());
1447 // Var args are accounted for in the containing function, so don't
1448 // include them for funclets.
1449 unsigned FixedObject =
1450 (IsWin64 && !IsFunclet) ? alignTo(AFI->getVarArgsGPRSize(), 16) : 0;
1451
1452 uint64_t AfterCSRPopSize = ArgumentPopSize;
1453 auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
1454 // We cannot rely on the local stack size set in emitPrologue if the function
1455 // has funclets, as funclets have different local stack size requirements, and
1456 // the current value set in emitPrologue may be that of the containing
1457 // function.
1458 if (MF.hasEHFunclets())
1459 AFI->setLocalStackSize(NumBytes - PrologueSaveSize);
1460 bool CombineSPBump = shouldCombineCSRLocalStackBump(MF, NumBytes);
1461 // Assume we can't combine the last pop with the sp restore.
1462
1463 if (!CombineSPBump && PrologueSaveSize != 0) {
1464 MachineBasicBlock::iterator Pop = std::prev(MBB.getFirstTerminator());
1465 while (AArch64InstrInfo::isSEHInstruction(*Pop))
1466 Pop = std::prev(Pop);
1467 // Converting the last ldp to a post-index ldp is valid only if the last
1468 // ldp's offset is 0.
1469 const MachineOperand &OffsetOp = Pop->getOperand(Pop->getNumOperands() - 1);
1470 // If the offset is 0, convert it to a post-index ldp.
1471 if (OffsetOp.getImm() == 0)
1472 convertCalleeSaveRestoreToSPPrePostIncDec(
1473 MBB, Pop, DL, TII, PrologueSaveSize, NeedsWinCFI, &HasWinCFI, false);
1474 else {
1475 // If not, make sure to emit an add after the last ldp.
1476 // We're doing this by transfering the size to be restored from the
1477 // adjustment *before* the CSR pops to the adjustment *after* the CSR
1478 // pops.
1479 AfterCSRPopSize += PrologueSaveSize;
1480 }
1481 }
1482
1483 // Move past the restores of the callee-saved registers.
1484 // If we plan on combining the sp bump of the local stack size and the callee
1485 // save stack size, we might need to adjust the CSR save and restore offsets.
1486 MachineBasicBlock::iterator LastPopI = MBB.getFirstTerminator();
1487 MachineBasicBlock::iterator Begin = MBB.begin();
1488 while (LastPopI != Begin) {
1489 --LastPopI;
1490 if (!LastPopI->getFlag(MachineInstr::FrameDestroy) ||
1491 IsSVECalleeSave(LastPopI)) {
1492 ++LastPopI;
1493 break;
1494 } else if (CombineSPBump)
1495 fixupCalleeSaveRestoreStackOffset(*LastPopI, AFI->getLocalStackSize(),
1496 NeedsWinCFI, &HasWinCFI);
1497 }
1498
1499 if (NeedsWinCFI) {
1500 HasWinCFI = true;
1501 BuildMI(MBB, LastPopI, DL, TII->get(AArch64::SEH_EpilogStart))
1502 .setMIFlag(MachineInstr::FrameDestroy);
1503 }
1504
1505 const StackOffset &SVEStackSize = getSVEStackSize(MF);
1506
1507 // If there is a single SP update, insert it before the ret and we're done.
1508 if (CombineSPBump) {
1509 assert(!SVEStackSize && "Cannot combine SP bump with SVE")((!SVEStackSize && "Cannot combine SP bump with SVE")
? static_cast<void> (0) : __assert_fail ("!SVEStackSize && \"Cannot combine SP bump with SVE\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1509, __PRETTY_FUNCTION__))
;
1510 emitFrameOffset(MBB, MBB.getFirstTerminator(), DL, AArch64::SP, AArch64::SP,
1511 {NumBytes + (int64_t)AfterCSRPopSize, MVT::i8}, TII,
1512 MachineInstr::FrameDestroy, false, NeedsWinCFI, &HasWinCFI);
1513 if (NeedsWinCFI && HasWinCFI)
1514 BuildMI(MBB, MBB.getFirstTerminator(), DL,
1515 TII->get(AArch64::SEH_EpilogEnd))
1516 .setMIFlag(MachineInstr::FrameDestroy);
1517 return;
1518 }
1519
1520 NumBytes -= PrologueSaveSize;
1521 assert(NumBytes >= 0 && "Negative stack allocation size!?")((NumBytes >= 0 && "Negative stack allocation size!?"
) ? static_cast<void> (0) : __assert_fail ("NumBytes >= 0 && \"Negative stack allocation size!?\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1521, __PRETTY_FUNCTION__))
;
1522
1523 // Process the SVE callee-saves to determine what space needs to be
1524 // deallocated.
1525 StackOffset DeallocateBefore = {}, DeallocateAfter = SVEStackSize;
1526 MachineBasicBlock::iterator RestoreBegin = LastPopI, RestoreEnd = LastPopI;
1527 if (AFI->getSVECalleeSavedStackSize()) {
1528 RestoreBegin = std::prev(RestoreEnd);;
1529 while (IsSVECalleeSave(RestoreBegin) &&
1530 RestoreBegin != MBB.begin())
1531 --RestoreBegin;
1532 ++RestoreBegin;
1533
1534 assert(IsSVECalleeSave(RestoreBegin) &&((IsSVECalleeSave(RestoreBegin) && IsSVECalleeSave(std
::prev(RestoreEnd)) && "Unexpected instruction") ? static_cast
<void> (0) : __assert_fail ("IsSVECalleeSave(RestoreBegin) && IsSVECalleeSave(std::prev(RestoreEnd)) && \"Unexpected instruction\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1535, __PRETTY_FUNCTION__))
1535 IsSVECalleeSave(std::prev(RestoreEnd)) && "Unexpected instruction")((IsSVECalleeSave(RestoreBegin) && IsSVECalleeSave(std
::prev(RestoreEnd)) && "Unexpected instruction") ? static_cast
<void> (0) : __assert_fail ("IsSVECalleeSave(RestoreBegin) && IsSVECalleeSave(std::prev(RestoreEnd)) && \"Unexpected instruction\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1535, __PRETTY_FUNCTION__))
;
1536
1537 int64_t OffsetToFirstCalleeSaveFromSP =
1538 MFI.getObjectOffset(AFI->getMaxSVECSFrameIndex());
1539 StackOffset OffsetToCalleeSavesFromSP =
1540 StackOffset(OffsetToFirstCalleeSaveFromSP, MVT::nxv1i8) + SVEStackSize;
1541 DeallocateBefore = OffsetToCalleeSavesFromSP;
1542 DeallocateAfter = SVEStackSize - DeallocateBefore;
1543 }
1544
1545 // Deallocate the SVE area.
1546 if (SVEStackSize) {
1547 if (AFI->isStackRealigned()) {
1548 if (AFI->getSVECalleeSavedStackSize())
1549 // Set SP to start of SVE area, from which the callee-save reloads
1550 // can be done. The code below will deallocate the stack space
1551 // space by moving FP -> SP.
1552 emitFrameOffset(MBB, RestoreBegin, DL, AArch64::SP, AArch64::FP,
1553 -SVEStackSize, TII, MachineInstr::FrameDestroy);
1554 } else {
1555 if (AFI->getSVECalleeSavedStackSize()) {
1556 // Deallocate the non-SVE locals first before we can deallocate (and
1557 // restore callee saves) from the SVE area.
1558 emitFrameOffset(MBB, RestoreBegin, DL, AArch64::SP, AArch64::SP,
1559 {NumBytes, MVT::i8}, TII, MachineInstr::FrameDestroy);
1560 NumBytes = 0;
1561 }
1562
1563 emitFrameOffset(MBB, RestoreBegin, DL, AArch64::SP, AArch64::SP,
1564 DeallocateBefore, TII, MachineInstr::FrameDestroy);
1565
1566 emitFrameOffset(MBB, RestoreEnd, DL, AArch64::SP, AArch64::SP,
1567 DeallocateAfter, TII, MachineInstr::FrameDestroy);
1568 }
1569 }
1570
1571 if (!hasFP(MF)) {
1572 bool RedZone = canUseRedZone(MF);
1573 // If this was a redzone leaf function, we don't need to restore the
1574 // stack pointer (but we may need to pop stack args for fastcc).
1575 if (RedZone && AfterCSRPopSize == 0)
1576 return;
1577
1578 bool NoCalleeSaveRestore = PrologueSaveSize == 0;
1579 int StackRestoreBytes = RedZone ? 0 : NumBytes;
1580 if (NoCalleeSaveRestore)
1581 StackRestoreBytes += AfterCSRPopSize;
1582
1583 // If we were able to combine the local stack pop with the argument pop,
1584 // then we're done.
1585 bool Done = NoCalleeSaveRestore || AfterCSRPopSize == 0;
1586
1587 // If we're done after this, make sure to help the load store optimizer.
1588 if (Done)
1589 adaptForLdStOpt(MBB, MBB.getFirstTerminator(), LastPopI);
1590
1591 emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::SP,
1592 {StackRestoreBytes, MVT::i8}, TII,
1593 MachineInstr::FrameDestroy, false, NeedsWinCFI, &HasWinCFI);
1594 if (Done) {
1595 if (NeedsWinCFI) {
1596 HasWinCFI = true;
1597 BuildMI(MBB, MBB.getFirstTerminator(), DL,
1598 TII->get(AArch64::SEH_EpilogEnd))
1599 .setMIFlag(MachineInstr::FrameDestroy);
1600 }
1601 return;
1602 }
1603
1604 NumBytes = 0;
1605 }
1606
1607 // Restore the original stack pointer.
1608 // FIXME: Rather than doing the math here, we should instead just use
1609 // non-post-indexed loads for the restores if we aren't actually going to
1610 // be able to save any instructions.
1611 if (!IsFunclet && (MFI.hasVarSizedObjects() || AFI->isStackRealigned())) {
1612 int64_t OffsetToFrameRecord =
1613 isTargetDarwin(MF) ? (-(int64_t)AFI->getCalleeSavedStackSize() + 16) : 0;
1614 emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::FP,
1615 {OffsetToFrameRecord, MVT::i8},
1616 TII, MachineInstr::FrameDestroy, false, NeedsWinCFI);
1617 } else if (NumBytes)
1618 emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::SP,
1619 {NumBytes, MVT::i8}, TII, MachineInstr::FrameDestroy, false,
1620 NeedsWinCFI);
1621
1622 // This must be placed after the callee-save restore code because that code
1623 // assumes the SP is at the same location as it was after the callee-save save
1624 // code in the prologue.
1625 if (AfterCSRPopSize) {
1626 // Find an insertion point for the first ldp so that it goes before the
1627 // shadow call stack epilog instruction. This ensures that the restore of
1628 // lr from x18 is placed after the restore from sp.
1629 auto FirstSPPopI = MBB.getFirstTerminator();
1630 while (FirstSPPopI != Begin) {
1631 auto Prev = std::prev(FirstSPPopI);
1632 if (Prev->getOpcode() != AArch64::LDRXpre ||
1633 Prev->getOperand(0).getReg() == AArch64::SP)
1634 break;
1635 FirstSPPopI = Prev;
1636 }
1637
1638 adaptForLdStOpt(MBB, FirstSPPopI, LastPopI);
1639
1640 emitFrameOffset(MBB, FirstSPPopI, DL, AArch64::SP, AArch64::SP,
1641 {(int64_t)AfterCSRPopSize, MVT::i8}, TII,
1642 MachineInstr::FrameDestroy, false, NeedsWinCFI, &HasWinCFI);
1643 }
1644 if (NeedsWinCFI && HasWinCFI)
1645 BuildMI(MBB, MBB.getFirstTerminator(), DL, TII->get(AArch64::SEH_EpilogEnd))
1646 .setMIFlag(MachineInstr::FrameDestroy);
1647
1648 MF.setHasWinCFI(HasWinCFI);
1649}
1650
1651/// getFrameIndexReference - Provide a base+offset reference to an FI slot for
1652/// debug info. It's the same as what we use for resolving the code-gen
1653/// references for now. FIXME: This can go wrong when references are
1654/// SP-relative and simple call frames aren't used.
1655int AArch64FrameLowering::getFrameIndexReference(const MachineFunction &MF,
1656 int FI,
1657 unsigned &FrameReg) const {
1658 return resolveFrameIndexReference(
1659 MF, FI, FrameReg,
1660 /*PreferFP=*/
1661 MF.getFunction().hasFnAttribute(Attribute::SanitizeHWAddress),
1662 /*ForSimm=*/false)
1663 .getBytes();
1664}
1665
1666int AArch64FrameLowering::getNonLocalFrameIndexReference(
1667 const MachineFunction &MF, int FI) const {
1668 return getSEHFrameIndexOffset(MF, FI);
1669}
1670
1671static StackOffset getFPOffset(const MachineFunction &MF, int ObjectOffset) {
1672 const auto *AFI = MF.getInfo<AArch64FunctionInfo>();
1673 const auto &Subtarget = MF.getSubtarget<AArch64Subtarget>();
1674 bool IsWin64 =
1675 Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv());
1676 unsigned FixedObject = IsWin64 ? alignTo(AFI->getVarArgsGPRSize(), 16) : 0;
1677 unsigned FPAdjust = isTargetDarwin(MF)
1678 ? 16 : AFI->getCalleeSavedStackSize(MF.getFrameInfo());
1679 return {ObjectOffset + FixedObject + FPAdjust, MVT::i8};
1680}
1681
1682static StackOffset getStackOffset(const MachineFunction &MF, int ObjectOffset) {
1683 const auto &MFI = MF.getFrameInfo();
1684 return {ObjectOffset + (int)MFI.getStackSize(), MVT::i8};
1685}
1686
1687int AArch64FrameLowering::getSEHFrameIndexOffset(const MachineFunction &MF,
1688 int FI) const {
1689 const auto *RegInfo = static_cast<const AArch64RegisterInfo *>(
1690 MF.getSubtarget().getRegisterInfo());
1691 int ObjectOffset = MF.getFrameInfo().getObjectOffset(FI);
1692 return RegInfo->getLocalAddressRegister(MF) == AArch64::FP
1693 ? getFPOffset(MF, ObjectOffset).getBytes()
1694 : getStackOffset(MF, ObjectOffset).getBytes();
1695}
1696
1697StackOffset AArch64FrameLowering::resolveFrameIndexReference(
1698 const MachineFunction &MF, int FI, unsigned &FrameReg, bool PreferFP,
1699 bool ForSimm) const {
1700 const auto &MFI = MF.getFrameInfo();
1701 int ObjectOffset = MFI.getObjectOffset(FI);
1702 bool isFixed = MFI.isFixedObjectIndex(FI);
1703 bool isSVE = MFI.getStackID(FI) == TargetStackID::SVEVector;
1704 return resolveFrameOffsetReference(MF, ObjectOffset, isFixed, isSVE, FrameReg,
1705 PreferFP, ForSimm);
1706}
1707
1708StackOffset AArch64FrameLowering::resolveFrameOffsetReference(
1709 const MachineFunction &MF, int ObjectOffset, bool isFixed, bool isSVE,
1710 unsigned &FrameReg, bool PreferFP, bool ForSimm) const {
1711 const auto &MFI = MF.getFrameInfo();
1712 const auto *RegInfo = static_cast<const AArch64RegisterInfo *>(
1713 MF.getSubtarget().getRegisterInfo());
1714 const auto *AFI = MF.getInfo<AArch64FunctionInfo>();
1715 const auto &Subtarget = MF.getSubtarget<AArch64Subtarget>();
1716
1717 int FPOffset = getFPOffset(MF, ObjectOffset).getBytes();
1718 int Offset = getStackOffset(MF, ObjectOffset).getBytes();
1719 bool isCSR =
1720 !isFixed && ObjectOffset >= -((int)AFI->getCalleeSavedStackSize(MFI));
1721
1722 const StackOffset &SVEStackSize = getSVEStackSize(MF);
1723
1724 // Use frame pointer to reference fixed objects. Use it for locals if
1725 // there are VLAs or a dynamically realigned SP (and thus the SP isn't
1726 // reliable as a base). Make sure useFPForScavengingIndex() does the
1727 // right thing for the emergency spill slot.
1728 bool UseFP = false;
1729 if (AFI->hasStackFrame() && !isSVE) {
1730 // We shouldn't prefer using the FP when there is an SVE area
1731 // in between the FP and the non-SVE locals/spills.
1732 PreferFP &= !SVEStackSize;
1733
1734 // Note: Keeping the following as multiple 'if' statements rather than
1735 // merging to a single expression for readability.
1736 //
1737 // Argument access should always use the FP.
1738 if (isFixed) {
1739 UseFP = hasFP(MF);
1740 } else if (isCSR && RegInfo->needsStackRealignment(MF)) {
1741 // References to the CSR area must use FP if we're re-aligning the stack
1742 // since the dynamically-sized alignment padding is between the SP/BP and
1743 // the CSR area.
1744 assert(hasFP(MF) && "Re-aligned stack must have frame pointer")((hasFP(MF) && "Re-aligned stack must have frame pointer"
) ? static_cast<void> (0) : __assert_fail ("hasFP(MF) && \"Re-aligned stack must have frame pointer\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1744, __PRETTY_FUNCTION__))
;
1745 UseFP = true;
1746 } else if (hasFP(MF) && !RegInfo->needsStackRealignment(MF)) {
1747 // If the FPOffset is negative and we're producing a signed immediate, we
1748 // have to keep in mind that the available offset range for negative
1749 // offsets is smaller than for positive ones. If an offset is available
1750 // via the FP and the SP, use whichever is closest.
1751 bool FPOffsetFits = !ForSimm || FPOffset >= -256;
1752 PreferFP |= Offset > -FPOffset;
1753
1754 if (MFI.hasVarSizedObjects()) {
1755 // If we have variable sized objects, we can use either FP or BP, as the
1756 // SP offset is unknown. We can use the base pointer if we have one and
1757 // FP is not preferred. If not, we're stuck with using FP.
1758 bool CanUseBP = RegInfo->hasBasePointer(MF);
1759 if (FPOffsetFits && CanUseBP) // Both are ok. Pick the best.
1760 UseFP = PreferFP;
1761 else if (!CanUseBP) { // Can't use BP. Forced to use FP.
1762 assert(!SVEStackSize && "Expected BP to be available")((!SVEStackSize && "Expected BP to be available") ? static_cast
<void> (0) : __assert_fail ("!SVEStackSize && \"Expected BP to be available\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1762, __PRETTY_FUNCTION__))
;
1763 UseFP = true;
1764 }
1765 // else we can use BP and FP, but the offset from FP won't fit.
1766 // That will make us scavenge registers which we can probably avoid by
1767 // using BP. If it won't fit for BP either, we'll scavenge anyway.
1768 } else if (FPOffset >= 0) {
1769 // Use SP or FP, whichever gives us the best chance of the offset
1770 // being in range for direct access. If the FPOffset is positive,
1771 // that'll always be best, as the SP will be even further away.
1772 UseFP = true;
1773 } else if (MF.hasEHFunclets() && !RegInfo->hasBasePointer(MF)) {
1774 // Funclets access the locals contained in the parent's stack frame
1775 // via the frame pointer, so we have to use the FP in the parent
1776 // function.
1777 (void) Subtarget;
1778 assert(((Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv
()) && "Funclets should only be present on Win64") ? static_cast
<void> (0) : __assert_fail ("Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv()) && \"Funclets should only be present on Win64\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1780, __PRETTY_FUNCTION__))
1779 Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv()) &&((Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv
()) && "Funclets should only be present on Win64") ? static_cast
<void> (0) : __assert_fail ("Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv()) && \"Funclets should only be present on Win64\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1780, __PRETTY_FUNCTION__))
1780 "Funclets should only be present on Win64")((Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv
()) && "Funclets should only be present on Win64") ? static_cast
<void> (0) : __assert_fail ("Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv()) && \"Funclets should only be present on Win64\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1780, __PRETTY_FUNCTION__))
;
1781 UseFP = true;
1782 } else {
1783 // We have the choice between FP and (SP or BP).
1784 if (FPOffsetFits && PreferFP) // If FP is the best fit, use it.
1785 UseFP = true;
1786 }
1787 }
1788 }
1789
1790 assert(((isFixed || isCSR) || !RegInfo->needsStackRealignment(MF) || !UseFP) &&((((isFixed || isCSR) || !RegInfo->needsStackRealignment(MF
) || !UseFP) && "In the presence of dynamic stack pointer realignment, "
"non-argument/CSR objects cannot be accessed through the frame pointer"
) ? static_cast<void> (0) : __assert_fail ("((isFixed || isCSR) || !RegInfo->needsStackRealignment(MF) || !UseFP) && \"In the presence of dynamic stack pointer realignment, \" \"non-argument/CSR objects cannot be accessed through the frame pointer\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1792, __PRETTY_FUNCTION__))
1791 "In the presence of dynamic stack pointer realignment, "((((isFixed || isCSR) || !RegInfo->needsStackRealignment(MF
) || !UseFP) && "In the presence of dynamic stack pointer realignment, "
"non-argument/CSR objects cannot be accessed through the frame pointer"
) ? static_cast<void> (0) : __assert_fail ("((isFixed || isCSR) || !RegInfo->needsStackRealignment(MF) || !UseFP) && \"In the presence of dynamic stack pointer realignment, \" \"non-argument/CSR objects cannot be accessed through the frame pointer\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1792, __PRETTY_FUNCTION__))
1792 "non-argument/CSR objects cannot be accessed through the frame pointer")((((isFixed || isCSR) || !RegInfo->needsStackRealignment(MF
) || !UseFP) && "In the presence of dynamic stack pointer realignment, "
"non-argument/CSR objects cannot be accessed through the frame pointer"
) ? static_cast<void> (0) : __assert_fail ("((isFixed || isCSR) || !RegInfo->needsStackRealignment(MF) || !UseFP) && \"In the presence of dynamic stack pointer realignment, \" \"non-argument/CSR objects cannot be accessed through the frame pointer\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1792, __PRETTY_FUNCTION__))
;
1793
1794 if (isSVE) {
1795 int64_t OffsetToSVEArea =
1796 MFI.getStackSize() - AFI->getCalleeSavedStackSize();
1797 StackOffset FPOffset = {ObjectOffset, MVT::nxv1i8};
1798 StackOffset SPOffset = SVEStackSize +
1799 StackOffset(ObjectOffset, MVT::nxv1i8) +
1800 StackOffset(OffsetToSVEArea, MVT::i8);
1801 // Always use the FP for SVE spills if available and beneficial.
1802 if (hasFP(MF) &&
1803 (SPOffset.getBytes() ||
1804 FPOffset.getScalableBytes() < SPOffset.getScalableBytes() ||
1805 RegInfo->needsStackRealignment(MF))) {
1806 FrameReg = RegInfo->getFrameRegister(MF);
1807 return FPOffset;
1808 }
1809
1810 FrameReg = RegInfo->hasBasePointer(MF) ? RegInfo->getBaseRegister()
1811 : (unsigned)AArch64::SP;
1812 return SPOffset;
1813 }
1814
1815 StackOffset ScalableOffset = {};
1816 if (UseFP && !(isFixed || isCSR))
1817 ScalableOffset = -SVEStackSize;
1818 if (!UseFP && (isFixed || isCSR))
1819 ScalableOffset = SVEStackSize;
1820
1821 if (UseFP) {
1822 FrameReg = RegInfo->getFrameRegister(MF);
1823 return StackOffset(FPOffset, MVT::i8) + ScalableOffset;
1824 }
1825
1826 // Use the base pointer if we have one.
1827 if (RegInfo->hasBasePointer(MF))
1828 FrameReg = RegInfo->getBaseRegister();
1829 else {
1830 assert(!MFI.hasVarSizedObjects() &&((!MFI.hasVarSizedObjects() && "Can't use SP when we have var sized objects."
) ? static_cast<void> (0) : __assert_fail ("!MFI.hasVarSizedObjects() && \"Can't use SP when we have var sized objects.\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1831, __PRETTY_FUNCTION__))
1831 "Can't use SP when we have var sized objects.")((!MFI.hasVarSizedObjects() && "Can't use SP when we have var sized objects."
) ? static_cast<void> (0) : __assert_fail ("!MFI.hasVarSizedObjects() && \"Can't use SP when we have var sized objects.\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1831, __PRETTY_FUNCTION__))
;
1832 FrameReg = AArch64::SP;
1833 // If we're using the red zone for this function, the SP won't actually
1834 // be adjusted, so the offsets will be negative. They're also all
1835 // within range of the signed 9-bit immediate instructions.
1836 if (canUseRedZone(MF))
1837 Offset -= AFI->getLocalStackSize();
1838 }
1839
1840 return StackOffset(Offset, MVT::i8) + ScalableOffset;
1841}
1842
1843static unsigned getPrologueDeath(MachineFunction &MF, unsigned Reg) {
1844 // Do not set a kill flag on values that are also marked as live-in. This
1845 // happens with the @llvm-returnaddress intrinsic and with arguments passed in
1846 // callee saved registers.
1847 // Omitting the kill flags is conservatively correct even if the live-in
1848 // is not used after all.
1849 bool IsLiveIn = MF.getRegInfo().isLiveIn(Reg);
1850 return getKillRegState(!IsLiveIn);
1851}
1852
1853static bool produceCompactUnwindFrame(MachineFunction &MF) {
1854 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
1855 AttributeList Attrs = MF.getFunction().getAttributes();
1856 return Subtarget.isTargetMachO() &&
1857 !(Subtarget.getTargetLowering()->supportSwiftError() &&
1858 Attrs.hasAttrSomewhere(Attribute::SwiftError));
1859}
1860
1861static bool invalidateWindowsRegisterPairing(unsigned Reg1, unsigned Reg2,
1862 bool NeedsWinCFI) {
1863 // If we are generating register pairs for a Windows function that requires
1864 // EH support, then pair consecutive registers only. There are no unwind
1865 // opcodes for saves/restores of non-consectuve register pairs.
1866 // The unwind opcodes are save_regp, save_regp_x, save_fregp, save_frepg_x.
1867 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
1868
1869 // TODO: LR can be paired with any register. We don't support this yet in
1870 // the MCLayer. We need to add support for the save_lrpair unwind code.
1871 if (!NeedsWinCFI)
1872 return false;
1873 if (Reg2 == Reg1 + 1)
1874 return false;
1875 return true;
1876}
1877
1878/// Returns true if Reg1 and Reg2 cannot be paired using a ldp/stp instruction.
1879/// WindowsCFI requires that only consecutive registers can be paired.
1880/// LR and FP need to be allocated together when the frame needs to save
1881/// the frame-record. This means any other register pairing with LR is invalid.
1882static bool invalidateRegisterPairing(unsigned Reg1, unsigned Reg2,
1883 bool NeedsWinCFI, bool NeedsFrameRecord) {
1884 if (NeedsWinCFI)
1885 return invalidateWindowsRegisterPairing(Reg1, Reg2, true);
1886
1887 // If we need to store the frame record, don't pair any register
1888 // with LR other than FP.
1889 if (NeedsFrameRecord)
1890 return Reg2 == AArch64::LR;
1891
1892 return false;
1893}
1894
1895namespace {
1896
1897struct RegPairInfo {
1898 unsigned Reg1 = AArch64::NoRegister;
1899 unsigned Reg2 = AArch64::NoRegister;
1900 int FrameIdx;
1901 int Offset;
1902 enum RegType { GPR, FPR64, FPR128, PPR, ZPR } Type;
1903
1904 RegPairInfo() = default;
1905
1906 bool isPaired() const { return Reg2 != AArch64::NoRegister; }
1907
1908 unsigned getScale() const {
1909 switch (Type) {
1910 case PPR:
1911 return 2;
1912 case GPR:
1913 case FPR64:
1914 return 8;
1915 case ZPR:
1916 case FPR128:
1917 return 16;
1918 }
1919 llvm_unreachable("Unsupported type")::llvm::llvm_unreachable_internal("Unsupported type", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1919)
;
1920 }
1921
1922 bool isScalable() const { return Type == PPR || Type == ZPR; }
1923};
1924
1925} // end anonymous namespace
1926
1927static void computeCalleeSaveRegisterPairs(
1928 MachineFunction &MF, const std::vector<CalleeSavedInfo> &CSI,
1929 const TargetRegisterInfo *TRI, SmallVectorImpl<RegPairInfo> &RegPairs,
1930 bool &NeedShadowCallStackProlog, bool NeedsFrameRecord) {
1931
1932 if (CSI.empty())
1933 return;
1934
1935 bool NeedsWinCFI = needsWinCFI(MF);
1936 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
1937 MachineFrameInfo &MFI = MF.getFrameInfo();
1938 CallingConv::ID CC = MF.getFunction().getCallingConv();
1939 unsigned Count = CSI.size();
1940 (void)CC;
1941 // MachO's compact unwind format relies on all registers being stored in
1942 // pairs.
1943 assert((!produceCompactUnwindFrame(MF) ||(((!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost
|| (Count & 1) == 0) && "Odd number of callee-saved regs to spill!"
) ? static_cast<void> (0) : __assert_fail ("(!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost || (Count & 1) == 0) && \"Odd number of callee-saved regs to spill!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1946, __PRETTY_FUNCTION__))
1944 CC == CallingConv::PreserveMost ||(((!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost
|| (Count & 1) == 0) && "Odd number of callee-saved regs to spill!"
) ? static_cast<void> (0) : __assert_fail ("(!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost || (Count & 1) == 0) && \"Odd number of callee-saved regs to spill!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1946, __PRETTY_FUNCTION__))
1945 (Count & 1) == 0) &&(((!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost
|| (Count & 1) == 0) && "Odd number of callee-saved regs to spill!"
) ? static_cast<void> (0) : __assert_fail ("(!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost || (Count & 1) == 0) && \"Odd number of callee-saved regs to spill!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1946, __PRETTY_FUNCTION__))
1946 "Odd number of callee-saved regs to spill!")(((!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost
|| (Count & 1) == 0) && "Odd number of callee-saved regs to spill!"
) ? static_cast<void> (0) : __assert_fail ("(!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost || (Count & 1) == 0) && \"Odd number of callee-saved regs to spill!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1946, __PRETTY_FUNCTION__))
;
1947 int ByteOffset = AFI->getCalleeSavedStackSize();
1948 int ScalableByteOffset = AFI->getSVECalleeSavedStackSize();
1949 // On Linux, we will have either one or zero non-paired register. On Windows
1950 // with CFI, we can have multiple unpaired registers in order to utilize the
1951 // available unwind codes. This flag assures that the alignment fixup is done
1952 // only once, as intened.
1953 bool FixupDone = false;
1954 for (unsigned i = 0; i < Count; ++i) {
1955 RegPairInfo RPI;
1956 RPI.Reg1 = CSI[i].getReg();
1957
1958 if (AArch64::GPR64RegClass.contains(RPI.Reg1))
1959 RPI.Type = RegPairInfo::GPR;
1960 else if (AArch64::FPR64RegClass.contains(RPI.Reg1))
1961 RPI.Type = RegPairInfo::FPR64;
1962 else if (AArch64::FPR128RegClass.contains(RPI.Reg1))
1963 RPI.Type = RegPairInfo::FPR128;
1964 else if (AArch64::ZPRRegClass.contains(RPI.Reg1))
1965 RPI.Type = RegPairInfo::ZPR;
1966 else if (AArch64::PPRRegClass.contains(RPI.Reg1))
1967 RPI.Type = RegPairInfo::PPR;
1968 else
1969 llvm_unreachable("Unsupported register class.")::llvm::llvm_unreachable_internal("Unsupported register class."
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 1969)
;
1970
1971 // Add the next reg to the pair if it is in the same register class.
1972 if (i + 1 < Count) {
1973 unsigned NextReg = CSI[i + 1].getReg();
1974 switch (RPI.Type) {
1975 case RegPairInfo::GPR:
1976 if (AArch64::GPR64RegClass.contains(NextReg) &&
1977 !invalidateRegisterPairing(RPI.Reg1, NextReg, NeedsWinCFI,
1978 NeedsFrameRecord))
1979 RPI.Reg2 = NextReg;
1980 break;
1981 case RegPairInfo::FPR64:
1982 if (AArch64::FPR64RegClass.contains(NextReg) &&
1983 !invalidateWindowsRegisterPairing(RPI.Reg1, NextReg, NeedsWinCFI))
1984 RPI.Reg2 = NextReg;
1985 break;
1986 case RegPairInfo::FPR128:
1987 if (AArch64::FPR128RegClass.contains(NextReg))
1988 RPI.Reg2 = NextReg;
1989 break;
1990 case RegPairInfo::PPR:
1991 case RegPairInfo::ZPR:
1992 break;
1993 }
1994 }
1995
1996 // If either of the registers to be saved is the lr register, it means that
1997 // we also need to save lr in the shadow call stack.
1998 if ((RPI.Reg1 == AArch64::LR || RPI.Reg2 == AArch64::LR) &&
1999 MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack)) {
2000 if (!MF.getSubtarget<AArch64Subtarget>().isXRegisterReserved(18))
2001 report_fatal_error("Must reserve x18 to use shadow call stack");
2002 NeedShadowCallStackProlog = true;
2003 }
2004
2005 // GPRs and FPRs are saved in pairs of 64-bit regs. We expect the CSI
2006 // list to come in sorted by frame index so that we can issue the store
2007 // pair instructions directly. Assert if we see anything otherwise.
2008 //
2009 // The order of the registers in the list is controlled by
2010 // getCalleeSavedRegs(), so they will always be in-order, as well.
2011 assert((!RPI.isPaired() ||(((!RPI.isPaired() || (CSI[i].getFrameIdx() + 1 == CSI[i + 1]
.getFrameIdx())) && "Out of order callee saved regs!"
) ? static_cast<void> (0) : __assert_fail ("(!RPI.isPaired() || (CSI[i].getFrameIdx() + 1 == CSI[i + 1].getFrameIdx())) && \"Out of order callee saved regs!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2013, __PRETTY_FUNCTION__))
2012 (CSI[i].getFrameIdx() + 1 == CSI[i + 1].getFrameIdx())) &&(((!RPI.isPaired() || (CSI[i].getFrameIdx() + 1 == CSI[i + 1]
.getFrameIdx())) && "Out of order callee saved regs!"
) ? static_cast<void> (0) : __assert_fail ("(!RPI.isPaired() || (CSI[i].getFrameIdx() + 1 == CSI[i + 1].getFrameIdx())) && \"Out of order callee saved regs!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2013, __PRETTY_FUNCTION__))
2013 "Out of order callee saved regs!")(((!RPI.isPaired() || (CSI[i].getFrameIdx() + 1 == CSI[i + 1]
.getFrameIdx())) && "Out of order callee saved regs!"
) ? static_cast<void> (0) : __assert_fail ("(!RPI.isPaired() || (CSI[i].getFrameIdx() + 1 == CSI[i + 1].getFrameIdx())) && \"Out of order callee saved regs!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2013, __PRETTY_FUNCTION__))
;
2014
2015 assert((!RPI.isPaired() || !NeedsFrameRecord || RPI.Reg2 != AArch64::FP ||(((!RPI.isPaired() || !NeedsFrameRecord || RPI.Reg2 != AArch64
::FP || RPI.Reg1 == AArch64::LR) && "FrameRecord must be allocated together with LR"
) ? static_cast<void> (0) : __assert_fail ("(!RPI.isPaired() || !NeedsFrameRecord || RPI.Reg2 != AArch64::FP || RPI.Reg1 == AArch64::LR) && \"FrameRecord must be allocated together with LR\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2017, __PRETTY_FUNCTION__))
2016 RPI.Reg1 == AArch64::LR) &&(((!RPI.isPaired() || !NeedsFrameRecord || RPI.Reg2 != AArch64
::FP || RPI.Reg1 == AArch64::LR) && "FrameRecord must be allocated together with LR"
) ? static_cast<void> (0) : __assert_fail ("(!RPI.isPaired() || !NeedsFrameRecord || RPI.Reg2 != AArch64::FP || RPI.Reg1 == AArch64::LR) && \"FrameRecord must be allocated together with LR\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2017, __PRETTY_FUNCTION__))
2017 "FrameRecord must be allocated together with LR")(((!RPI.isPaired() || !NeedsFrameRecord || RPI.Reg2 != AArch64
::FP || RPI.Reg1 == AArch64::LR) && "FrameRecord must be allocated together with LR"
) ? static_cast<void> (0) : __assert_fail ("(!RPI.isPaired() || !NeedsFrameRecord || RPI.Reg2 != AArch64::FP || RPI.Reg1 == AArch64::LR) && \"FrameRecord must be allocated together with LR\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2017, __PRETTY_FUNCTION__))
;
2018
2019 // MachO's compact unwind format relies on all registers being stored in
2020 // adjacent register pairs.
2021 assert((!produceCompactUnwindFrame(MF) ||(((!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost
|| (RPI.isPaired() && ((RPI.Reg1 == AArch64::LR &&
RPI.Reg2 == AArch64::FP) || RPI.Reg1 + 1 == RPI.Reg2))) &&
"Callee-save registers not saved as adjacent register pair!"
) ? static_cast<void> (0) : __assert_fail ("(!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost || (RPI.isPaired() && ((RPI.Reg1 == AArch64::LR && RPI.Reg2 == AArch64::FP) || RPI.Reg1 + 1 == RPI.Reg2))) && \"Callee-save registers not saved as adjacent register pair!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2026, __PRETTY_FUNCTION__))
2022 CC == CallingConv::PreserveMost ||(((!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost
|| (RPI.isPaired() && ((RPI.Reg1 == AArch64::LR &&
RPI.Reg2 == AArch64::FP) || RPI.Reg1 + 1 == RPI.Reg2))) &&
"Callee-save registers not saved as adjacent register pair!"
) ? static_cast<void> (0) : __assert_fail ("(!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost || (RPI.isPaired() && ((RPI.Reg1 == AArch64::LR && RPI.Reg2 == AArch64::FP) || RPI.Reg1 + 1 == RPI.Reg2))) && \"Callee-save registers not saved as adjacent register pair!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2026, __PRETTY_FUNCTION__))
2023 (RPI.isPaired() &&(((!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost
|| (RPI.isPaired() && ((RPI.Reg1 == AArch64::LR &&
RPI.Reg2 == AArch64::FP) || RPI.Reg1 + 1 == RPI.Reg2))) &&
"Callee-save registers not saved as adjacent register pair!"
) ? static_cast<void> (0) : __assert_fail ("(!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost || (RPI.isPaired() && ((RPI.Reg1 == AArch64::LR && RPI.Reg2 == AArch64::FP) || RPI.Reg1 + 1 == RPI.Reg2))) && \"Callee-save registers not saved as adjacent register pair!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2026, __PRETTY_FUNCTION__))
2024 ((RPI.Reg1 == AArch64::LR && RPI.Reg2 == AArch64::FP) ||(((!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost
|| (RPI.isPaired() && ((RPI.Reg1 == AArch64::LR &&
RPI.Reg2 == AArch64::FP) || RPI.Reg1 + 1 == RPI.Reg2))) &&
"Callee-save registers not saved as adjacent register pair!"
) ? static_cast<void> (0) : __assert_fail ("(!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost || (RPI.isPaired() && ((RPI.Reg1 == AArch64::LR && RPI.Reg2 == AArch64::FP) || RPI.Reg1 + 1 == RPI.Reg2))) && \"Callee-save registers not saved as adjacent register pair!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2026, __PRETTY_FUNCTION__))
2025 RPI.Reg1 + 1 == RPI.Reg2))) &&(((!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost
|| (RPI.isPaired() && ((RPI.Reg1 == AArch64::LR &&
RPI.Reg2 == AArch64::FP) || RPI.Reg1 + 1 == RPI.Reg2))) &&
"Callee-save registers not saved as adjacent register pair!"
) ? static_cast<void> (0) : __assert_fail ("(!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost || (RPI.isPaired() && ((RPI.Reg1 == AArch64::LR && RPI.Reg2 == AArch64::FP) || RPI.Reg1 + 1 == RPI.Reg2))) && \"Callee-save registers not saved as adjacent register pair!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2026, __PRETTY_FUNCTION__))
2026 "Callee-save registers not saved as adjacent register pair!")(((!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost
|| (RPI.isPaired() && ((RPI.Reg1 == AArch64::LR &&
RPI.Reg2 == AArch64::FP) || RPI.Reg1 + 1 == RPI.Reg2))) &&
"Callee-save registers not saved as adjacent register pair!"
) ? static_cast<void> (0) : __assert_fail ("(!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost || (RPI.isPaired() && ((RPI.Reg1 == AArch64::LR && RPI.Reg2 == AArch64::FP) || RPI.Reg1 + 1 == RPI.Reg2))) && \"Callee-save registers not saved as adjacent register pair!\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2026, __PRETTY_FUNCTION__))
;
2027
2028 RPI.FrameIdx = CSI[i].getFrameIdx();
2029
2030 int Scale = RPI.getScale();
2031 if (RPI.isScalable())
2032 ScalableByteOffset -= Scale;
2033 else
2034 ByteOffset -= RPI.isPaired() ? 2 * Scale : Scale;
2035
2036 assert(!(RPI.isScalable() && RPI.isPaired()) &&((!(RPI.isScalable() && RPI.isPaired()) && "Paired spill/fill instructions don't exist for SVE vectors"
) ? static_cast<void> (0) : __assert_fail ("!(RPI.isScalable() && RPI.isPaired()) && \"Paired spill/fill instructions don't exist for SVE vectors\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2037, __PRETTY_FUNCTION__))
2037 "Paired spill/fill instructions don't exist for SVE vectors")((!(RPI.isScalable() && RPI.isPaired()) && "Paired spill/fill instructions don't exist for SVE vectors"
) ? static_cast<void> (0) : __assert_fail ("!(RPI.isScalable() && RPI.isPaired()) && \"Paired spill/fill instructions don't exist for SVE vectors\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2037, __PRETTY_FUNCTION__))
;
2038
2039 // Round up size of non-pair to pair size if we need to pad the
2040 // callee-save area to ensure 16-byte alignment.
2041 if (AFI->hasCalleeSaveStackFreeSpace() && !FixupDone &&
2042 !RPI.isScalable() && RPI.Type != RegPairInfo::FPR128 &&
2043 !RPI.isPaired()) {
2044 FixupDone = true;
2045 ByteOffset -= 8;
2046 assert(ByteOffset % 16 == 0)((ByteOffset % 16 == 0) ? static_cast<void> (0) : __assert_fail
("ByteOffset % 16 == 0", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2046, __PRETTY_FUNCTION__))
;
2047 assert(MFI.getObjectAlignment(RPI.FrameIdx) <= 16)((MFI.getObjectAlignment(RPI.FrameIdx) <= 16) ? static_cast
<void> (0) : __assert_fail ("MFI.getObjectAlignment(RPI.FrameIdx) <= 16"
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2047, __PRETTY_FUNCTION__))
;
2048 MFI.setObjectAlignment(RPI.FrameIdx, 16);
2049 }
2050
2051 int Offset = RPI.isScalable() ? ScalableByteOffset : ByteOffset;
2052 assert(Offset % Scale == 0)((Offset % Scale == 0) ? static_cast<void> (0) : __assert_fail
("Offset % Scale == 0", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2052, __PRETTY_FUNCTION__))
;
2053 RPI.Offset = Offset / Scale;
2054
2055 assert(((!RPI.isScalable() && RPI.Offset >= -64 && RPI.Offset <= 63) ||((((!RPI.isScalable() && RPI.Offset >= -64 &&
RPI.Offset <= 63) || (RPI.isScalable() && RPI.Offset
>= -256 && RPI.Offset <= 255)) && "Offset out of bounds for LDP/STP immediate"
) ? static_cast<void> (0) : __assert_fail ("((!RPI.isScalable() && RPI.Offset >= -64 && RPI.Offset <= 63) || (RPI.isScalable() && RPI.Offset >= -256 && RPI.Offset <= 255)) && \"Offset out of bounds for LDP/STP immediate\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2057, __PRETTY_FUNCTION__))
2056 (RPI.isScalable() && RPI.Offset >= -256 && RPI.Offset <= 255)) &&((((!RPI.isScalable() && RPI.Offset >= -64 &&
RPI.Offset <= 63) || (RPI.isScalable() && RPI.Offset
>= -256 && RPI.Offset <= 255)) && "Offset out of bounds for LDP/STP immediate"
) ? static_cast<void> (0) : __assert_fail ("((!RPI.isScalable() && RPI.Offset >= -64 && RPI.Offset <= 63) || (RPI.isScalable() && RPI.Offset >= -256 && RPI.Offset <= 255)) && \"Offset out of bounds for LDP/STP immediate\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2057, __PRETTY_FUNCTION__))
2057 "Offset out of bounds for LDP/STP immediate")((((!RPI.isScalable() && RPI.Offset >= -64 &&
RPI.Offset <= 63) || (RPI.isScalable() && RPI.Offset
>= -256 && RPI.Offset <= 255)) && "Offset out of bounds for LDP/STP immediate"
) ? static_cast<void> (0) : __assert_fail ("((!RPI.isScalable() && RPI.Offset >= -64 && RPI.Offset <= 63) || (RPI.isScalable() && RPI.Offset >= -256 && RPI.Offset <= 255)) && \"Offset out of bounds for LDP/STP immediate\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2057, __PRETTY_FUNCTION__))
;
2058
2059 RegPairs.push_back(RPI);
2060 if (RPI.isPaired())
2061 ++i;
2062 }
2063}
2064
2065bool AArch64FrameLowering::spillCalleeSavedRegisters(
2066 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
2067 const std::vector<CalleeSavedInfo> &CSI,
2068 const TargetRegisterInfo *TRI) const {
2069 MachineFunction &MF = *MBB.getParent();
2070 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
2071 bool NeedsWinCFI = needsWinCFI(MF);
2072 DebugLoc DL;
2073 SmallVector<RegPairInfo, 8> RegPairs;
2074
2075 bool NeedShadowCallStackProlog = false;
2076 computeCalleeSaveRegisterPairs(MF, CSI, TRI, RegPairs,
2077 NeedShadowCallStackProlog, hasFP(MF));
2078 const MachineRegisterInfo &MRI = MF.getRegInfo();
2079
2080 if (NeedShadowCallStackProlog) {
2081 // Shadow call stack prolog: str x30, [x18], #8
2082 BuildMI(MBB, MI, DL, TII.get(AArch64::STRXpost))
2083 .addReg(AArch64::X18, RegState::Define)
2084 .addReg(AArch64::LR)
2085 .addReg(AArch64::X18)
2086 .addImm(8)
2087 .setMIFlag(MachineInstr::FrameSetup);
2088
2089 if (NeedsWinCFI)
2090 BuildMI(MBB, MI, DL, TII.get(AArch64::SEH_Nop))
2091 .setMIFlag(MachineInstr::FrameSetup);
2092
2093 if (!MF.getFunction().hasFnAttribute(Attribute::NoUnwind)) {
2094 // Emit a CFI instruction that causes 8 to be subtracted from the value of
2095 // x18 when unwinding past this frame.
2096 static const char CFIInst[] = {
2097 dwarf::DW_CFA_val_expression,
2098 18, // register
2099 2, // length
2100 static_cast<char>(unsigned(dwarf::DW_OP_breg18)),
2101 static_cast<char>(-8) & 0x7f, // addend (sleb128)
2102 };
2103 unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createEscape(
2104 nullptr, StringRef(CFIInst, sizeof(CFIInst))));
2105 BuildMI(MBB, MI, DL, TII.get(AArch64::CFI_INSTRUCTION))
2106 .addCFIIndex(CFIIndex)
2107 .setMIFlag(MachineInstr::FrameSetup);
2108 }
2109
2110 // This instruction also makes x18 live-in to the entry block.
2111 MBB.addLiveIn(AArch64::X18);
2112 }
2113
2114 for (auto RPII = RegPairs.rbegin(), RPIE = RegPairs.rend(); RPII != RPIE;
2115 ++RPII) {
2116 RegPairInfo RPI = *RPII;
2117 unsigned Reg1 = RPI.Reg1;
2118 unsigned Reg2 = RPI.Reg2;
2119 unsigned StrOpc;
2120
2121 // Issue sequence of spills for cs regs. The first spill may be converted
2122 // to a pre-decrement store later by emitPrologue if the callee-save stack
2123 // area allocation can't be combined with the local stack area allocation.
2124 // For example:
2125 // stp x22, x21, [sp, #0] // addImm(+0)
2126 // stp x20, x19, [sp, #16] // addImm(+2)
2127 // stp fp, lr, [sp, #32] // addImm(+4)
2128 // Rationale: This sequence saves uop updates compared to a sequence of
2129 // pre-increment spills like stp xi,xj,[sp,#-16]!
2130 // Note: Similar rationale and sequence for restores in epilog.
2131 unsigned Size, Align;
2132 switch (RPI.Type) {
2133 case RegPairInfo::GPR:
2134 StrOpc = RPI.isPaired() ? AArch64::STPXi : AArch64::STRXui;
2135 Size = 8;
2136 Align = 8;
2137 break;
2138 case RegPairInfo::FPR64:
2139 StrOpc = RPI.isPaired() ? AArch64::STPDi : AArch64::STRDui;
2140 Size = 8;
2141 Align = 8;
2142 break;
2143 case RegPairInfo::FPR128:
2144 StrOpc = RPI.isPaired() ? AArch64::STPQi : AArch64::STRQui;
2145 Size = 16;
2146 Align = 16;
2147 break;
2148 case RegPairInfo::ZPR:
2149 StrOpc = AArch64::STR_ZXI;
2150 Size = 16;
2151 Align = 16;
2152 break;
2153 case RegPairInfo::PPR:
2154 StrOpc = AArch64::STR_PXI;
2155 Size = 2;
2156 Align = 2;
2157 break;
2158 }
2159 LLVM_DEBUG(dbgs() << "CSR spill: (" << printReg(Reg1, TRI);do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "CSR spill: (" << printReg
(Reg1, TRI); if (RPI.isPaired()) dbgs() << ", " <<
printReg(Reg2, TRI); dbgs() << ") -> fi#(" <<
RPI.FrameIdx; if (RPI.isPaired()) dbgs() << ", " <<
RPI.FrameIdx + 1; dbgs() << ")\n"; } } while (false)
2160 if (RPI.isPaired()) dbgs() << ", " << printReg(Reg2, TRI);do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "CSR spill: (" << printReg
(Reg1, TRI); if (RPI.isPaired()) dbgs() << ", " <<
printReg(Reg2, TRI); dbgs() << ") -> fi#(" <<
RPI.FrameIdx; if (RPI.isPaired()) dbgs() << ", " <<
RPI.FrameIdx + 1; dbgs() << ")\n"; } } while (false)
2161 dbgs() << ") -> fi#(" << RPI.FrameIdx;do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "CSR spill: (" << printReg
(Reg1, TRI); if (RPI.isPaired()) dbgs() << ", " <<
printReg(Reg2, TRI); dbgs() << ") -> fi#(" <<
RPI.FrameIdx; if (RPI.isPaired()) dbgs() << ", " <<
RPI.FrameIdx + 1; dbgs() << ")\n"; } } while (false)
2162 if (RPI.isPaired()) dbgs() << ", " << RPI.FrameIdx + 1;do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "CSR spill: (" << printReg
(Reg1, TRI); if (RPI.isPaired()) dbgs() << ", " <<
printReg(Reg2, TRI); dbgs() << ") -> fi#(" <<
RPI.FrameIdx; if (RPI.isPaired()) dbgs() << ", " <<
RPI.FrameIdx + 1; dbgs() << ")\n"; } } while (false)
2163 dbgs() << ")\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "CSR spill: (" << printReg
(Reg1, TRI); if (RPI.isPaired()) dbgs() << ", " <<
printReg(Reg2, TRI); dbgs() << ") -> fi#(" <<
RPI.FrameIdx; if (RPI.isPaired()) dbgs() << ", " <<
RPI.FrameIdx + 1; dbgs() << ")\n"; } } while (false)
;
2164
2165 assert((!NeedsWinCFI || !(Reg1 == AArch64::LR && Reg2 == AArch64::FP)) &&(((!NeedsWinCFI || !(Reg1 == AArch64::LR && Reg2 == AArch64
::FP)) && "Windows unwdinding requires a consecutive (FP,LR) pair"
) ? static_cast<void> (0) : __assert_fail ("(!NeedsWinCFI || !(Reg1 == AArch64::LR && Reg2 == AArch64::FP)) && \"Windows unwdinding requires a consecutive (FP,LR) pair\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2166, __PRETTY_FUNCTION__))
2166 "Windows unwdinding requires a consecutive (FP,LR) pair")(((!NeedsWinCFI || !(Reg1 == AArch64::LR && Reg2 == AArch64
::FP)) && "Windows unwdinding requires a consecutive (FP,LR) pair"
) ? static_cast<void> (0) : __assert_fail ("(!NeedsWinCFI || !(Reg1 == AArch64::LR && Reg2 == AArch64::FP)) && \"Windows unwdinding requires a consecutive (FP,LR) pair\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2166, __PRETTY_FUNCTION__))
;
2167 // Windows unwind codes require consecutive registers if registers are
2168 // paired. Make the switch here, so that the code below will save (x,x+1)
2169 // and not (x+1,x).
2170 unsigned FrameIdxReg1 = RPI.FrameIdx;
2171 unsigned FrameIdxReg2 = RPI.FrameIdx + 1;
2172 if (NeedsWinCFI && RPI.isPaired()) {
2173 std::swap(Reg1, Reg2);
2174 std::swap(FrameIdxReg1, FrameIdxReg2);
2175 }
2176 MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(StrOpc));
2177 if (!MRI.isReserved(Reg1))
2178 MBB.addLiveIn(Reg1);
2179 if (RPI.isPaired()) {
2180 if (!MRI.isReserved(Reg2))
2181 MBB.addLiveIn(Reg2);
2182 MIB.addReg(Reg2, getPrologueDeath(MF, Reg2));
2183 MIB.addMemOperand(MF.getMachineMemOperand(
2184 MachinePointerInfo::getFixedStack(MF, FrameIdxReg2),
2185 MachineMemOperand::MOStore, Size, Align));
2186 }
2187 MIB.addReg(Reg1, getPrologueDeath(MF, Reg1))
2188 .addReg(AArch64::SP)
2189 .addImm(RPI.Offset) // [sp, #offset*scale],
2190 // where factor*scale is implicit
2191 .setMIFlag(MachineInstr::FrameSetup);
2192 MIB.addMemOperand(MF.getMachineMemOperand(
2193 MachinePointerInfo::getFixedStack(MF,FrameIdxReg1),
2194 MachineMemOperand::MOStore, Size, Align));
2195 if (NeedsWinCFI)
2196 InsertSEH(MIB, TII, MachineInstr::FrameSetup);
2197
2198 // Update the StackIDs of the SVE stack slots.
2199 MachineFrameInfo &MFI = MF.getFrameInfo();
2200 if (RPI.Type == RegPairInfo::ZPR || RPI.Type == RegPairInfo::PPR)
2201 MFI.setStackID(RPI.FrameIdx, TargetStackID::SVEVector);
2202
2203 }
2204 return true;
2205}
2206
2207bool AArch64FrameLowering::restoreCalleeSavedRegisters(
2208 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
2209 std::vector<CalleeSavedInfo> &CSI,
2210 const TargetRegisterInfo *TRI) const {
2211 MachineFunction &MF = *MBB.getParent();
2212 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
2213 DebugLoc DL;
2214 SmallVector<RegPairInfo, 8> RegPairs;
2215 bool NeedsWinCFI = needsWinCFI(MF);
2216
2217 if (MI != MBB.end())
2218 DL = MI->getDebugLoc();
2219
2220 bool NeedShadowCallStackProlog = false;
2221 computeCalleeSaveRegisterPairs(MF, CSI, TRI, RegPairs,
2222 NeedShadowCallStackProlog, hasFP(MF));
2223
2224 auto EmitMI = [&](const RegPairInfo &RPI) {
2225 unsigned Reg1 = RPI.Reg1;
2226 unsigned Reg2 = RPI.Reg2;
2227
2228 // Issue sequence of restores for cs regs. The last restore may be converted
2229 // to a post-increment load later by emitEpilogue if the callee-save stack
2230 // area allocation can't be combined with the local stack area allocation.
2231 // For example:
2232 // ldp fp, lr, [sp, #32] // addImm(+4)
2233 // ldp x20, x19, [sp, #16] // addImm(+2)
2234 // ldp x22, x21, [sp, #0] // addImm(+0)
2235 // Note: see comment in spillCalleeSavedRegisters()
2236 unsigned LdrOpc;
2237 unsigned Size, Align;
2238 switch (RPI.Type) {
2239 case RegPairInfo::GPR:
2240 LdrOpc = RPI.isPaired() ? AArch64::LDPXi : AArch64::LDRXui;
2241 Size = 8;
2242 Align = 8;
2243 break;
2244 case RegPairInfo::FPR64:
2245 LdrOpc = RPI.isPaired() ? AArch64::LDPDi : AArch64::LDRDui;
2246 Size = 8;
2247 Align = 8;
2248 break;
2249 case RegPairInfo::FPR128:
2250 LdrOpc = RPI.isPaired() ? AArch64::LDPQi : AArch64::LDRQui;
2251 Size = 16;
2252 Align = 16;
2253 break;
2254 case RegPairInfo::ZPR:
2255 LdrOpc = AArch64::LDR_ZXI;
2256 Size = 16;
2257 Align = 16;
2258 break;
2259 case RegPairInfo::PPR:
2260 LdrOpc = AArch64::LDR_PXI;
2261 Size = 2;
2262 Align = 2;
2263 break;
2264 }
2265 LLVM_DEBUG(dbgs() << "CSR restore: (" << printReg(Reg1, TRI);do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "CSR restore: (" << printReg
(Reg1, TRI); if (RPI.isPaired()) dbgs() << ", " <<
printReg(Reg2, TRI); dbgs() << ") -> fi#(" <<
RPI.FrameIdx; if (RPI.isPaired()) dbgs() << ", " <<
RPI.FrameIdx + 1; dbgs() << ")\n"; } } while (false)
2266 if (RPI.isPaired()) dbgs() << ", " << printReg(Reg2, TRI);do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "CSR restore: (" << printReg
(Reg1, TRI); if (RPI.isPaired()) dbgs() << ", " <<
printReg(Reg2, TRI); dbgs() << ") -> fi#(" <<
RPI.FrameIdx; if (RPI.isPaired()) dbgs() << ", " <<
RPI.FrameIdx + 1; dbgs() << ")\n"; } } while (false)
2267 dbgs() << ") -> fi#(" << RPI.FrameIdx;do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "CSR restore: (" << printReg
(Reg1, TRI); if (RPI.isPaired()) dbgs() << ", " <<
printReg(Reg2, TRI); dbgs() << ") -> fi#(" <<
RPI.FrameIdx; if (RPI.isPaired()) dbgs() << ", " <<
RPI.FrameIdx + 1; dbgs() << ")\n"; } } while (false)
2268 if (RPI.isPaired()) dbgs() << ", " << RPI.FrameIdx + 1;do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "CSR restore: (" << printReg
(Reg1, TRI); if (RPI.isPaired()) dbgs() << ", " <<
printReg(Reg2, TRI); dbgs() << ") -> fi#(" <<
RPI.FrameIdx; if (RPI.isPaired()) dbgs() << ", " <<
RPI.FrameIdx + 1; dbgs() << ")\n"; } } while (false)
2269 dbgs() << ")\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "CSR restore: (" << printReg
(Reg1, TRI); if (RPI.isPaired()) dbgs() << ", " <<
printReg(Reg2, TRI); dbgs() << ") -> fi#(" <<
RPI.FrameIdx; if (RPI.isPaired()) dbgs() << ", " <<
RPI.FrameIdx + 1; dbgs() << ")\n"; } } while (false)
;
2270
2271 // Windows unwind codes require consecutive registers if registers are
2272 // paired. Make the switch here, so that the code below will save (x,x+1)
2273 // and not (x+1,x).
2274 unsigned FrameIdxReg1 = RPI.FrameIdx;
2275 unsigned FrameIdxReg2 = RPI.FrameIdx + 1;
2276 if (NeedsWinCFI && RPI.isPaired()) {
2277 std::swap(Reg1, Reg2);
2278 std::swap(FrameIdxReg1, FrameIdxReg2);
2279 }
2280 MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(LdrOpc));
2281 if (RPI.isPaired()) {
2282 MIB.addReg(Reg2, getDefRegState(true));
2283 MIB.addMemOperand(MF.getMachineMemOperand(
2284 MachinePointerInfo::getFixedStack(MF, FrameIdxReg2),
2285 MachineMemOperand::MOLoad, Size, Align));
2286 }
2287 MIB.addReg(Reg1, getDefRegState(true))
2288 .addReg(AArch64::SP)
2289 .addImm(RPI.Offset) // [sp, #offset*scale]
2290 // where factor*scale is implicit
2291 .setMIFlag(MachineInstr::FrameDestroy);
2292 MIB.addMemOperand(MF.getMachineMemOperand(
2293 MachinePointerInfo::getFixedStack(MF, FrameIdxReg1),
2294 MachineMemOperand::MOLoad, Size, Align));
2295 if (NeedsWinCFI)
2296 InsertSEH(MIB, TII, MachineInstr::FrameDestroy);
2297 };
2298
2299 // SVE objects are always restored in reverse order.
2300 for (const RegPairInfo &RPI : reverse(RegPairs))
2301 if (RPI.isScalable())
2302 EmitMI(RPI);
2303
2304 if (ReverseCSRRestoreSeq) {
2305 for (const RegPairInfo &RPI : reverse(RegPairs))
2306 if (!RPI.isScalable())
2307 EmitMI(RPI);
2308 } else
2309 for (const RegPairInfo &RPI : RegPairs)
2310 if (!RPI.isScalable())
2311 EmitMI(RPI);
2312
2313 if (NeedShadowCallStackProlog) {
2314 // Shadow call stack epilog: ldr x30, [x18, #-8]!
2315 BuildMI(MBB, MI, DL, TII.get(AArch64::LDRXpre))
2316 .addReg(AArch64::X18, RegState::Define)
2317 .addReg(AArch64::LR, RegState::Define)
2318 .addReg(AArch64::X18)
2319 .addImm(-8)
2320 .setMIFlag(MachineInstr::FrameDestroy);
2321 }
2322
2323 return true;
2324}
2325
2326void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF,
2327 BitVector &SavedRegs,
2328 RegScavenger *RS) const {
2329 // All calls are tail calls in GHC calling conv, and functions have no
2330 // prologue/epilogue.
2331 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
2332 return;
2333
2334 TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
2335 const AArch64RegisterInfo *RegInfo = static_cast<const AArch64RegisterInfo *>(
2336 MF.getSubtarget().getRegisterInfo());
2337 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
2338 unsigned UnspilledCSGPR = AArch64::NoRegister;
2339 unsigned UnspilledCSGPRPaired = AArch64::NoRegister;
2340
2341 MachineFrameInfo &MFI = MF.getFrameInfo();
2342 const MCPhysReg *CSRegs = MF.getRegInfo().getCalleeSavedRegs();
2343
2344 unsigned BasePointerReg = RegInfo->hasBasePointer(MF)
2345 ? RegInfo->getBaseRegister()
2346 : (unsigned)AArch64::NoRegister;
2347
2348 unsigned ExtraCSSpill = 0;
2349 // Figure out which callee-saved registers to save/restore.
2350 for (unsigned i = 0; CSRegs[i]; ++i) {
2351 const unsigned Reg = CSRegs[i];
2352
2353 // Add the base pointer register to SavedRegs if it is callee-save.
2354 if (Reg == BasePointerReg)
2355 SavedRegs.set(Reg);
2356
2357 bool RegUsed = SavedRegs.test(Reg);
2358 unsigned PairedReg = AArch64::NoRegister;
2359 if (AArch64::GPR64RegClass.contains(Reg) ||
2360 AArch64::FPR64RegClass.contains(Reg) ||
2361 AArch64::FPR128RegClass.contains(Reg))
2362 PairedReg = CSRegs[i ^ 1];
2363
2364 if (!RegUsed) {
2365 if (AArch64::GPR64RegClass.contains(Reg) &&
2366 !RegInfo->isReservedReg(MF, Reg)) {
2367 UnspilledCSGPR = Reg;
2368 UnspilledCSGPRPaired = PairedReg;
2369 }
2370 continue;
2371 }
2372
2373 // MachO's compact unwind format relies on all registers being stored in
2374 // pairs.
2375 // FIXME: the usual format is actually better if unwinding isn't needed.
2376 if (produceCompactUnwindFrame(MF) && PairedReg != AArch64::NoRegister &&
2377 !SavedRegs.test(PairedReg)) {
2378 SavedRegs.set(PairedReg);
2379 if (AArch64::GPR64RegClass.contains(PairedReg) &&
2380 !RegInfo->isReservedReg(MF, PairedReg))
2381 ExtraCSSpill = PairedReg;
2382 }
2383 }
2384
2385 // Calculates the callee saved stack size.
2386 unsigned CSStackSize = 0;
2387 unsigned SVECSStackSize = 0;
2388 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
2389 const MachineRegisterInfo &MRI = MF.getRegInfo();
2390 for (unsigned Reg : SavedRegs.set_bits()) {
2391 auto RegSize = TRI->getRegSizeInBits(Reg, MRI) / 8;
2392 if (AArch64::PPRRegClass.contains(Reg) ||
2393 AArch64::ZPRRegClass.contains(Reg))
2394 SVECSStackSize += RegSize;
2395 else
2396 CSStackSize += RegSize;
2397 }
2398
2399 // Save number of saved regs, so we can easily update CSStackSize later.
2400 unsigned NumSavedRegs = SavedRegs.count();
2401
2402 // The frame record needs to be created by saving the appropriate registers
2403 unsigned EstimatedStackSize = MFI.estimateStackSize(MF);
2404 if (hasFP(MF) ||
2405 windowsRequiresStackProbe(MF, EstimatedStackSize + CSStackSize + 16)) {
2406 SavedRegs.set(AArch64::FP);
2407 SavedRegs.set(AArch64::LR);
2408 }
2409
2410 LLVM_DEBUG(dbgs() << "*** determineCalleeSaves\nSaved CSRs:";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "*** determineCalleeSaves\nSaved CSRs:"
; for (unsigned Reg : SavedRegs.set_bits()) dbgs() << ' '
<< printReg(Reg, RegInfo); dbgs() << "\n";; } } while
(false)
2411 for (unsigned Regdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "*** determineCalleeSaves\nSaved CSRs:"
; for (unsigned Reg : SavedRegs.set_bits()) dbgs() << ' '
<< printReg(Reg, RegInfo); dbgs() << "\n";; } } while
(false)
2412 : SavedRegs.set_bits()) dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "*** determineCalleeSaves\nSaved CSRs:"
; for (unsigned Reg : SavedRegs.set_bits()) dbgs() << ' '
<< printReg(Reg, RegInfo); dbgs() << "\n";; } } while
(false)
2413 << ' ' << printReg(Reg, RegInfo);do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "*** determineCalleeSaves\nSaved CSRs:"
; for (unsigned Reg : SavedRegs.set_bits()) dbgs() << ' '
<< printReg(Reg, RegInfo); dbgs() << "\n";; } } while
(false)
2414 dbgs() << "\n";)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "*** determineCalleeSaves\nSaved CSRs:"
; for (unsigned Reg : SavedRegs.set_bits()) dbgs() << ' '
<< printReg(Reg, RegInfo); dbgs() << "\n";; } } while
(false)
;
2415
2416 // If any callee-saved registers are used, the frame cannot be eliminated.
2417 int64_t SVEStackSize =
2418 alignTo(SVECSStackSize + estimateSVEStackObjectOffsets(MFI), 16);
2419 bool CanEliminateFrame = (SavedRegs.count() == 0) && !SVEStackSize;
2420
2421 // The CSR spill slots have not been allocated yet, so estimateStackSize
2422 // won't include them.
2423 unsigned EstimatedStackSizeLimit = estimateRSStackSizeLimit(MF);
2424
2425 // Conservatively always assume BigStack when there are SVE spills.
2426 bool BigStack = SVEStackSize ||
2427 (EstimatedStackSize + CSStackSize) > EstimatedStackSizeLimit;
2428 if (BigStack || !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF))
2429 AFI->setHasStackFrame(true);
2430
2431 // Estimate if we might need to scavenge a register at some point in order
2432 // to materialize a stack offset. If so, either spill one additional
2433 // callee-saved register or reserve a special spill slot to facilitate
2434 // register scavenging. If we already spilled an extra callee-saved register
2435 // above to keep the number of spills even, we don't need to do anything else
2436 // here.
2437 if (BigStack) {
2438 if (!ExtraCSSpill && UnspilledCSGPR != AArch64::NoRegister) {
2439 LLVM_DEBUG(dbgs() << "Spilling " << printReg(UnspilledCSGPR, RegInfo)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "Spilling " << printReg
(UnspilledCSGPR, RegInfo) << " to get a scratch register.\n"
; } } while (false)
2440 << " to get a scratch register.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "Spilling " << printReg
(UnspilledCSGPR, RegInfo) << " to get a scratch register.\n"
; } } while (false)
;
2441 SavedRegs.set(UnspilledCSGPR);
2442 // MachO's compact unwind format relies on all registers being stored in
2443 // pairs, so if we need to spill one extra for BigStack, then we need to
2444 // store the pair.
2445 if (produceCompactUnwindFrame(MF))
2446 SavedRegs.set(UnspilledCSGPRPaired);
2447 ExtraCSSpill = UnspilledCSGPR;
2448 }
2449
2450 // If we didn't find an extra callee-saved register to spill, create
2451 // an emergency spill slot.
2452 if (!ExtraCSSpill || MF.getRegInfo().isPhysRegUsed(ExtraCSSpill)) {
2453 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
2454 const TargetRegisterClass &RC = AArch64::GPR64RegClass;
2455 unsigned Size = TRI->getSpillSize(RC);
2456 unsigned Align = TRI->getSpillAlignment(RC);
2457 int FI = MFI.CreateStackObject(Size, Align, false);
2458 RS->addScavengingFrameIndex(FI);
2459 LLVM_DEBUG(dbgs() << "No available CS registers, allocated fi#" << FIdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "No available CS registers, allocated fi#"
<< FI << " as the emergency spill slot.\n"; } } while
(false)
2460 << " as the emergency spill slot.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "No available CS registers, allocated fi#"
<< FI << " as the emergency spill slot.\n"; } } while
(false)
;
2461 }
2462 }
2463
2464 // Adding the size of additional 64bit GPR saves.
2465 CSStackSize += 8 * (SavedRegs.count() - NumSavedRegs);
2466 unsigned AlignedCSStackSize = alignTo(CSStackSize, 16);
2467 LLVM_DEBUG(dbgs() << "Estimated stack frame size: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "Estimated stack frame size: "
<< EstimatedStackSize + AlignedCSStackSize << " bytes.\n"
; } } while (false)
2468 << EstimatedStackSize + AlignedCSStackSizedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "Estimated stack frame size: "
<< EstimatedStackSize + AlignedCSStackSize << " bytes.\n"
; } } while (false)
2469 << " bytes.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "Estimated stack frame size: "
<< EstimatedStackSize + AlignedCSStackSize << " bytes.\n"
; } } while (false)
;
2470
2471 assert((!MFI.isCalleeSavedInfoValid() ||(((!MFI.isCalleeSavedInfoValid() || AFI->getCalleeSavedStackSize
() == AlignedCSStackSize) && "Should not invalidate callee saved info"
) ? static_cast<void> (0) : __assert_fail ("(!MFI.isCalleeSavedInfoValid() || AFI->getCalleeSavedStackSize() == AlignedCSStackSize) && \"Should not invalidate callee saved info\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2473, __PRETTY_FUNCTION__))
2472 AFI->getCalleeSavedStackSize() == AlignedCSStackSize) &&(((!MFI.isCalleeSavedInfoValid() || AFI->getCalleeSavedStackSize
() == AlignedCSStackSize) && "Should not invalidate callee saved info"
) ? static_cast<void> (0) : __assert_fail ("(!MFI.isCalleeSavedInfoValid() || AFI->getCalleeSavedStackSize() == AlignedCSStackSize) && \"Should not invalidate callee saved info\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2473, __PRETTY_FUNCTION__))
2473 "Should not invalidate callee saved info")(((!MFI.isCalleeSavedInfoValid() || AFI->getCalleeSavedStackSize
() == AlignedCSStackSize) && "Should not invalidate callee saved info"
) ? static_cast<void> (0) : __assert_fail ("(!MFI.isCalleeSavedInfoValid() || AFI->getCalleeSavedStackSize() == AlignedCSStackSize) && \"Should not invalidate callee saved info\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2473, __PRETTY_FUNCTION__))
;
2474
2475 // Round up to register pair alignment to avoid additional SP adjustment
2476 // instructions.
2477 AFI->setCalleeSavedStackSize(AlignedCSStackSize);
2478 AFI->setCalleeSaveStackHasFreeSpace(AlignedCSStackSize != CSStackSize);
2479 AFI->setSVECalleeSavedStackSize(alignTo(SVECSStackSize, 16));
2480}
2481
2482bool AArch64FrameLowering::enableStackSlotScavenging(
2483 const MachineFunction &MF) const {
2484 const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
2485 return AFI->hasCalleeSaveStackFreeSpace();
2486}
2487
2488/// returns true if there are any SVE callee saves.
2489static bool getSVECalleeSaveSlotRange(const MachineFrameInfo &MFI,
2490 int &Min, int &Max) {
2491 if (!MFI.isCalleeSavedInfoValid())
9
Assuming the condition is true
10
Taking true branch
2492 return false;
11
Returning without writing to 'Min'
2493
2494 Min = std::numeric_limits<int>::max();
2495 Max = std::numeric_limits<int>::min();
2496 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
2497 for (auto &CS : CSI) {
2498 if (AArch64::ZPRRegClass.contains(CS.getReg()) ||
2499 AArch64::PPRRegClass.contains(CS.getReg())) {
2500 assert((Max == std::numeric_limits<int>::min() ||(((Max == std::numeric_limits<int>::min() || Max + 1 ==
CS.getFrameIdx()) && "SVE CalleeSaves are not consecutive"
) ? static_cast<void> (0) : __assert_fail ("(Max == std::numeric_limits<int>::min() || Max + 1 == CS.getFrameIdx()) && \"SVE CalleeSaves are not consecutive\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2502, __PRETTY_FUNCTION__))
2501 Max + 1 == CS.getFrameIdx()) &&(((Max == std::numeric_limits<int>::min() || Max + 1 ==
CS.getFrameIdx()) && "SVE CalleeSaves are not consecutive"
) ? static_cast<void> (0) : __assert_fail ("(Max == std::numeric_limits<int>::min() || Max + 1 == CS.getFrameIdx()) && \"SVE CalleeSaves are not consecutive\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2502, __PRETTY_FUNCTION__))
2502 "SVE CalleeSaves are not consecutive")(((Max == std::numeric_limits<int>::min() || Max + 1 ==
CS.getFrameIdx()) && "SVE CalleeSaves are not consecutive"
) ? static_cast<void> (0) : __assert_fail ("(Max == std::numeric_limits<int>::min() || Max + 1 == CS.getFrameIdx()) && \"SVE CalleeSaves are not consecutive\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2502, __PRETTY_FUNCTION__))
;
2503
2504 Min = std::min(Min, CS.getFrameIdx());
2505 Max = std::max(Max, CS.getFrameIdx());
2506 }
2507 }
2508 return Min != std::numeric_limits<int>::max();
2509}
2510
2511// Process all the SVE stack objects and determine offsets for each
2512// object. If AssignOffsets is true, the offsets get assigned.
2513// Fills in the first and last callee-saved frame indices into
2514// Min/MaxCSFrameIndex, respectively.
2515// Returns the size of the stack.
2516static int64_t determineSVEStackObjectOffsets(MachineFrameInfo &MFI,
2517 int &MinCSFrameIndex,
2518 int &MaxCSFrameIndex,
2519 bool AssignOffsets) {
2520 // First process all fixed stack objects.
2521 int64_t Offset = 0;
2522 for (int I = MFI.getObjectIndexBegin(); I != 0; ++I)
6
Assuming 'I' is equal to 0
7
Loop condition is false. Execution continues on line 2530
2523 if (MFI.getStackID(I) == TargetStackID::SVEVector) {
2524 int64_t FixedOffset = -MFI.getObjectOffset(I);
2525 if (FixedOffset > Offset)
2526 Offset = FixedOffset;
2527 }
2528
2529 // Then process all callee saved slots.
2530 if (getSVECalleeSaveSlotRange(MFI, MinCSFrameIndex, MaxCSFrameIndex)) {
8
Calling 'getSVECalleeSaveSlotRange'
12
Returning from 'getSVECalleeSaveSlotRange'
13
Taking false branch
2531 // Make sure to align the last callee save slot.
2532 MFI.setObjectAlignment(MaxCSFrameIndex, 16U);
2533
2534 // Assign offsets to the callee save slots.
2535 for (int I = MinCSFrameIndex; I <= MaxCSFrameIndex; ++I) {
2536 Offset += MFI.getObjectSize(I);
2537 Offset = alignTo(Offset, MFI.getObjectAlignment(I));
2538 if (AssignOffsets) {
2539 LLVM_DEBUG(dbgs() << "alloc FI(" << I << ") at SP[" << Offsetdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "alloc FI(" << I <<
") at SP[" << Offset << "]\n"; } } while (false)
2540 << "]\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "alloc FI(" << I <<
") at SP[" << Offset << "]\n"; } } while (false)
;
2541 MFI.setObjectOffset(I, -Offset);
2542 }
2543 }
2544 }
2545
2546 // Note: We don't take allocatable stack objects into
2547 // account yet, because allocation for those is not yet
2548 // implemented.
2549 return Offset;
14
Returning without writing to 'MinCSFrameIndex'
2550}
2551
2552int64_t AArch64FrameLowering::estimateSVEStackObjectOffsets(
2553 MachineFrameInfo &MFI) const {
2554 int MinCSFrameIndex, MaxCSFrameIndex;
2555 return determineSVEStackObjectOffsets(MFI, MinCSFrameIndex, MaxCSFrameIndex, false);
2556}
2557
2558int64_t AArch64FrameLowering::assignSVEStackObjectOffsets(
2559 MachineFrameInfo &MFI, int &MinCSFrameIndex, int &MaxCSFrameIndex) const {
2560 return determineSVEStackObjectOffsets(MFI, MinCSFrameIndex, MaxCSFrameIndex,
5
Calling 'determineSVEStackObjectOffsets'
15
Returning from 'determineSVEStackObjectOffsets'
16
Returning without writing to 'MinCSFrameIndex'
2561 true);
2562}
2563
2564void AArch64FrameLowering::processFunctionBeforeFrameFinalized(
2565 MachineFunction &MF, RegScavenger *RS) const {
2566 MachineFrameInfo &MFI = MF.getFrameInfo();
2567
2568 assert(getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown &&((getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown
&& "Upwards growing stack unsupported") ? static_cast
<void> (0) : __assert_fail ("getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown && \"Upwards growing stack unsupported\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2569, __PRETTY_FUNCTION__))
1
Assuming the condition is true
2
'?' condition is true
2569 "Upwards growing stack unsupported")((getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown
&& "Upwards growing stack unsupported") ? static_cast
<void> (0) : __assert_fail ("getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown && \"Upwards growing stack unsupported\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2569, __PRETTY_FUNCTION__))
;
2570
2571 int MinCSFrameIndex, MaxCSFrameIndex;
3
'MinCSFrameIndex' declared without an initial value
2572 int64_t SVEStackSize =
2573 assignSVEStackObjectOffsets(MFI, MinCSFrameIndex, MaxCSFrameIndex);
4
Calling 'AArch64FrameLowering::assignSVEStackObjectOffsets'
17
Returning from 'AArch64FrameLowering::assignSVEStackObjectOffsets'
2574
2575 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
2576 AFI->setStackSizeSVE(alignTo(SVEStackSize, 16U));
2577 AFI->setMinMaxSVECSFrameIndex(MinCSFrameIndex, MaxCSFrameIndex);
18
1st function call argument is an uninitialized value
2578
2579 // If this function isn't doing Win64-style C++ EH, we don't need to do
2580 // anything.
2581 if (!MF.hasEHFunclets())
2582 return;
2583 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
2584 WinEHFuncInfo &EHInfo = *MF.getWinEHFuncInfo();
2585
2586 MachineBasicBlock &MBB = MF.front();
2587 auto MBBI = MBB.begin();
2588 while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup))
2589 ++MBBI;
2590
2591 // Create an UnwindHelp object.
2592 int UnwindHelpFI =
2593 MFI.CreateStackObject(/*size*/8, /*alignment*/16, false);
2594 EHInfo.UnwindHelpFrameIdx = UnwindHelpFI;
2595 // We need to store -2 into the UnwindHelp object at the start of the
2596 // function.
2597 DebugLoc DL;
2598 RS->enterBasicBlockEnd(MBB);
2599 RS->backward(std::prev(MBBI));
2600 unsigned DstReg = RS->FindUnusedReg(&AArch64::GPR64commonRegClass);
2601 assert(DstReg && "There must be a free register after frame setup")((DstReg && "There must be a free register after frame setup"
) ? static_cast<void> (0) : __assert_fail ("DstReg && \"There must be a free register after frame setup\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp"
, 2601, __PRETTY_FUNCTION__))
;
2602 BuildMI(MBB, MBBI, DL, TII.get(AArch64::MOVi64imm), DstReg).addImm(-2);
2603 BuildMI(MBB, MBBI, DL, TII.get(AArch64::STURXi))
2604 .addReg(DstReg, getKillRegState(true))
2605 .addFrameIndex(UnwindHelpFI)
2606 .addImm(0);
2607}
2608
2609/// For Win64 AArch64 EH, the offset to the Unwind object is from the SP before
2610/// the update. This is easily retrieved as it is exactly the offset that is set
2611/// in processFunctionBeforeFrameFinalized.
2612int AArch64FrameLowering::getFrameIndexReferencePreferSP(
2613 const MachineFunction &MF, int FI, unsigned &FrameReg,
2614 bool IgnoreSPUpdates) const {
2615 const MachineFrameInfo &MFI = MF.getFrameInfo();
2616 LLVM_DEBUG(dbgs() << "Offset from the SP for " << FI << " is "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "Offset from the SP for " <<
FI << " is " << MFI.getObjectOffset(FI) <<
"\n"; } } while (false)
2617 << MFI.getObjectOffset(FI) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("frame-info")) { dbgs() << "Offset from the SP for " <<
FI << " is " << MFI.getObjectOffset(FI) <<
"\n"; } } while (false)
;
2618 FrameReg = AArch64::SP;
2619 return MFI.getObjectOffset(FI);
2620}
2621
2622/// The parent frame offset (aka dispFrame) is only used on X86_64 to retrieve
2623/// the parent's frame pointer
2624unsigned AArch64FrameLowering::getWinEHParentFrameOffset(
2625 const MachineFunction &MF) const {
2626 return 0;
2627}
2628
2629/// Funclets only need to account for space for the callee saved registers,
2630/// as the locals are accounted for in the parent's stack frame.
2631unsigned AArch64FrameLowering::getWinEHFuncletFrameSize(
2632 const MachineFunction &MF) const {
2633 // This is the size of the pushed CSRs.
2634 unsigned CSSize =
2635 MF.getInfo<AArch64FunctionInfo>()->getCalleeSavedStackSize();
2636 // This is the amount of stack a funclet needs to allocate.
2637 return alignTo(CSSize + MF.getFrameInfo().getMaxCallFrameSize(),
2638 getStackAlignment());
2639}