1 //=- AArch64MachineFunctionInfo.cpp - AArch64 Machine Function Info ---------=//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
11 /// This file implements AArch64-specific per-machine-function
14 //===----------------------------------------------------------------------===//
16 #include "AArch64MachineFunctionInfo.h"
17 #include "AArch64InstrInfo.h"
18 #include "AArch64Subtarget.h"
19 #include "llvm/IR/Constants.h"
20 #include "llvm/IR/Metadata.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/MC/MCAsmInfo.h"
26 yaml::AArch64FunctionInfo::AArch64FunctionInfo(
27 const llvm::AArch64FunctionInfo
&MFI
)
28 : HasRedZone(MFI
.hasRedZone()) {}
30 void yaml::AArch64FunctionInfo::mappingImpl(yaml::IO
&YamlIO
) {
31 MappingTraits
<AArch64FunctionInfo
>::mapping(YamlIO
, *this);
34 void AArch64FunctionInfo::initializeBaseYamlFields(
35 const yaml::AArch64FunctionInfo
&YamlMFI
) {
36 if (YamlMFI
.HasRedZone
)
37 HasRedZone
= YamlMFI
.HasRedZone
;
40 static std::pair
<bool, bool> GetSignReturnAddress(const Function
&F
) {
41 if (F
.hasFnAttribute("ptrauth-returns"))
42 return {true, false}; // non-leaf
43 // The function should be signed in the following situations:
44 // - sign-return-address=all
45 // - sign-return-address=non-leaf and the functions spills the LR
46 if (!F
.hasFnAttribute("sign-return-address"))
47 return {false, false};
49 StringRef Scope
= F
.getFnAttribute("sign-return-address").getValueAsString();
51 return {false, false};
56 assert(Scope
== "non-leaf");
60 static bool ShouldSignWithBKey(const Function
&F
, const AArch64Subtarget
&STI
) {
61 if (F
.hasFnAttribute("ptrauth-returns"))
63 if (!F
.hasFnAttribute("sign-return-address-key")) {
64 if (STI
.getTargetTriple().isOSWindows())
70 F
.getFnAttribute("sign-return-address-key").getValueAsString();
71 assert(Key
== "a_key" || Key
== "b_key");
72 return Key
== "b_key";
75 static bool hasELFSignedGOTHelper(const Function
&F
,
76 const AArch64Subtarget
*STI
) {
77 if (!Triple(STI
->getTargetTriple()).isOSBinFormatELF())
79 const Module
*M
= F
.getParent();
80 const auto *Flag
= mdconst::extract_or_null
<ConstantInt
>(
81 M
->getModuleFlag("ptrauth-elf-got"));
82 if (Flag
&& Flag
->getZExtValue() == 1)
87 AArch64FunctionInfo::AArch64FunctionInfo(const Function
&F
,
88 const AArch64Subtarget
*STI
) {
89 // If we already know that the function doesn't have a redzone, set
91 if (F
.hasFnAttribute(Attribute::NoRedZone
))
93 std::tie(SignReturnAddress
, SignReturnAddressAll
) = GetSignReturnAddress(F
);
94 SignWithBKey
= ShouldSignWithBKey(F
, *STI
);
95 HasELFSignedGOT
= hasELFSignedGOTHelper(F
, STI
);
96 // TODO: skip functions that have no instrumented allocas for optimization
97 IsMTETagged
= F
.hasFnAttribute(Attribute::SanitizeMemTag
);
99 // BTI/PAuthLR are set on the function attribute.
100 BranchTargetEnforcement
= F
.hasFnAttribute("branch-target-enforcement");
101 BranchProtectionPAuthLR
= F
.hasFnAttribute("branch-protection-pauth-lr");
103 // The default stack probe size is 4096 if the function has no
104 // stack-probe-size attribute. This is a safe default because it is the
105 // smallest possible guard page size.
106 uint64_t ProbeSize
= 4096;
107 if (F
.hasFnAttribute("stack-probe-size"))
108 ProbeSize
= F
.getFnAttributeAsParsedInteger("stack-probe-size");
109 else if (const auto *PS
= mdconst::extract_or_null
<ConstantInt
>(
110 F
.getParent()->getModuleFlag("stack-probe-size")))
111 ProbeSize
= PS
->getZExtValue();
112 assert(int64_t(ProbeSize
) > 0 && "Invalid stack probe size");
114 if (STI
->isTargetWindows()) {
115 if (!F
.hasFnAttribute("no-stack-arg-probe"))
116 StackProbeSize
= ProbeSize
;
118 // Round down to the stack alignment.
119 uint64_t StackAlign
=
120 STI
->getFrameLowering()->getTransientStackAlign().value();
121 ProbeSize
= std::max(StackAlign
, ProbeSize
& ~(StackAlign
- 1U));
123 if (F
.hasFnAttribute("probe-stack"))
124 ProbeKind
= F
.getFnAttribute("probe-stack").getValueAsString();
125 else if (const auto *PS
= dyn_cast_or_null
<MDString
>(
126 F
.getParent()->getModuleFlag("probe-stack")))
127 ProbeKind
= PS
->getString();
128 if (ProbeKind
.size()) {
129 if (ProbeKind
!= "inline-asm")
130 report_fatal_error("Unsupported stack probing method");
131 StackProbeSize
= ProbeSize
;
136 MachineFunctionInfo
*AArch64FunctionInfo::clone(
137 BumpPtrAllocator
&Allocator
, MachineFunction
&DestMF
,
138 const DenseMap
<MachineBasicBlock
*, MachineBasicBlock
*> &Src2DstMBB
)
140 return DestMF
.cloneInfo
<AArch64FunctionInfo
>(*this);
143 bool AArch64FunctionInfo::shouldSignReturnAddress(bool SpillsLR
) const {
144 if (!SignReturnAddress
)
146 if (SignReturnAddressAll
)
151 static bool isLRSpilled(const MachineFunction
&MF
) {
153 MF
.getFrameInfo().getCalleeSavedInfo(),
154 [](const auto &Info
) { return Info
.getReg() == AArch64::LR
; });
157 bool AArch64FunctionInfo::shouldSignReturnAddress(
158 const MachineFunction
&MF
) const {
159 return shouldSignReturnAddress(isLRSpilled(MF
));
162 bool AArch64FunctionInfo::needsShadowCallStackPrologueEpilogue(
163 MachineFunction
&MF
) const {
164 if (!(isLRSpilled(MF
) &&
165 MF
.getFunction().hasFnAttribute(Attribute::ShadowCallStack
)))
168 if (!MF
.getSubtarget
<AArch64Subtarget
>().isXRegisterReserved(18))
169 report_fatal_error("Must reserve x18 to use shadow call stack");
174 bool AArch64FunctionInfo::needsDwarfUnwindInfo(
175 const MachineFunction
&MF
) const {
176 if (!NeedsDwarfUnwindInfo
)
177 NeedsDwarfUnwindInfo
= MF
.needsFrameMoves() &&
178 !MF
.getTarget().getMCAsmInfo()->usesWindowsCFI();
180 return *NeedsDwarfUnwindInfo
;
183 bool AArch64FunctionInfo::needsAsyncDwarfUnwindInfo(
184 const MachineFunction
&MF
) const {
185 if (!NeedsAsyncDwarfUnwindInfo
) {
186 const Function
&F
= MF
.getFunction();
187 const AArch64FunctionInfo
*AFI
= MF
.getInfo
<AArch64FunctionInfo
>();
188 // The check got "minsize" is because epilogue unwind info is not emitted
189 // (yet) for homogeneous epilogues, outlined functions, and functions
191 NeedsAsyncDwarfUnwindInfo
=
192 needsDwarfUnwindInfo(MF
) &&
193 ((F
.getUWTableKind() == UWTableKind::Async
&& !F
.hasMinSize()) ||
194 AFI
->hasStreamingModeChanges());
196 return *NeedsAsyncDwarfUnwindInfo
;