Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
35294 views
1
//=- AArch64MachineFunctionInfo.cpp - AArch64 Machine Function Info ---------=//
2
3
//
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
7
//
8
//===----------------------------------------------------------------------===//
9
///
10
/// \file
11
/// This file implements AArch64-specific per-machine-function
12
/// information.
13
///
14
//===----------------------------------------------------------------------===//
15
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"
23
24
using namespace llvm;
25
26
yaml::AArch64FunctionInfo::AArch64FunctionInfo(
27
const llvm::AArch64FunctionInfo &MFI)
28
: HasRedZone(MFI.hasRedZone()) {}
29
30
void yaml::AArch64FunctionInfo::mappingImpl(yaml::IO &YamlIO) {
31
MappingTraits<AArch64FunctionInfo>::mapping(YamlIO, *this);
32
}
33
34
void AArch64FunctionInfo::initializeBaseYamlFields(
35
const yaml::AArch64FunctionInfo &YamlMFI) {
36
if (YamlMFI.HasRedZone)
37
HasRedZone = YamlMFI.HasRedZone;
38
}
39
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};
48
49
StringRef Scope = F.getFnAttribute("sign-return-address").getValueAsString();
50
if (Scope == "none")
51
return {false, false};
52
53
if (Scope == "all")
54
return {true, true};
55
56
assert(Scope == "non-leaf");
57
return {true, false};
58
}
59
60
static bool ShouldSignWithBKey(const Function &F, const AArch64Subtarget &STI) {
61
if (F.hasFnAttribute("ptrauth-returns"))
62
return true;
63
if (!F.hasFnAttribute("sign-return-address-key")) {
64
if (STI.getTargetTriple().isOSWindows())
65
return true;
66
return false;
67
}
68
69
const StringRef Key =
70
F.getFnAttribute("sign-return-address-key").getValueAsString();
71
assert(Key == "a_key" || Key == "b_key");
72
return Key == "b_key";
73
}
74
75
AArch64FunctionInfo::AArch64FunctionInfo(const Function &F,
76
const AArch64Subtarget *STI) {
77
// If we already know that the function doesn't have a redzone, set
78
// HasRedZone here.
79
if (F.hasFnAttribute(Attribute::NoRedZone))
80
HasRedZone = false;
81
std::tie(SignReturnAddress, SignReturnAddressAll) = GetSignReturnAddress(F);
82
SignWithBKey = ShouldSignWithBKey(F, *STI);
83
// TODO: skip functions that have no instrumented allocas for optimization
84
IsMTETagged = F.hasFnAttribute(Attribute::SanitizeMemTag);
85
86
// BTI/PAuthLR are set on the function attribute.
87
BranchTargetEnforcement = F.hasFnAttribute("branch-target-enforcement");
88
BranchProtectionPAuthLR = F.hasFnAttribute("branch-protection-pauth-lr");
89
90
// The default stack probe size is 4096 if the function has no
91
// stack-probe-size attribute. This is a safe default because it is the
92
// smallest possible guard page size.
93
uint64_t ProbeSize = 4096;
94
if (F.hasFnAttribute("stack-probe-size"))
95
ProbeSize = F.getFnAttributeAsParsedInteger("stack-probe-size");
96
else if (const auto *PS = mdconst::extract_or_null<ConstantInt>(
97
F.getParent()->getModuleFlag("stack-probe-size")))
98
ProbeSize = PS->getZExtValue();
99
assert(int64_t(ProbeSize) > 0 && "Invalid stack probe size");
100
101
if (STI->isTargetWindows()) {
102
if (!F.hasFnAttribute("no-stack-arg-probe"))
103
StackProbeSize = ProbeSize;
104
} else {
105
// Round down to the stack alignment.
106
uint64_t StackAlign =
107
STI->getFrameLowering()->getTransientStackAlign().value();
108
ProbeSize = std::max(StackAlign, ProbeSize & ~(StackAlign - 1U));
109
StringRef ProbeKind;
110
if (F.hasFnAttribute("probe-stack"))
111
ProbeKind = F.getFnAttribute("probe-stack").getValueAsString();
112
else if (const auto *PS = dyn_cast_or_null<MDString>(
113
F.getParent()->getModuleFlag("probe-stack")))
114
ProbeKind = PS->getString();
115
if (ProbeKind.size()) {
116
if (ProbeKind != "inline-asm")
117
report_fatal_error("Unsupported stack probing method");
118
StackProbeSize = ProbeSize;
119
}
120
}
121
}
122
123
MachineFunctionInfo *AArch64FunctionInfo::clone(
124
BumpPtrAllocator &Allocator, MachineFunction &DestMF,
125
const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
126
const {
127
return DestMF.cloneInfo<AArch64FunctionInfo>(*this);
128
}
129
130
bool AArch64FunctionInfo::shouldSignReturnAddress(bool SpillsLR) const {
131
if (!SignReturnAddress)
132
return false;
133
if (SignReturnAddressAll)
134
return true;
135
return SpillsLR;
136
}
137
138
static bool isLRSpilled(const MachineFunction &MF) {
139
return llvm::any_of(
140
MF.getFrameInfo().getCalleeSavedInfo(),
141
[](const auto &Info) { return Info.getReg() == AArch64::LR; });
142
}
143
144
bool AArch64FunctionInfo::shouldSignReturnAddress(
145
const MachineFunction &MF) const {
146
return shouldSignReturnAddress(isLRSpilled(MF));
147
}
148
149
bool AArch64FunctionInfo::needsShadowCallStackPrologueEpilogue(
150
MachineFunction &MF) const {
151
if (!(isLRSpilled(MF) &&
152
MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack)))
153
return false;
154
155
if (!MF.getSubtarget<AArch64Subtarget>().isXRegisterReserved(18))
156
report_fatal_error("Must reserve x18 to use shadow call stack");
157
158
return true;
159
}
160
161
bool AArch64FunctionInfo::needsDwarfUnwindInfo(
162
const MachineFunction &MF) const {
163
if (!NeedsDwarfUnwindInfo)
164
NeedsDwarfUnwindInfo = MF.needsFrameMoves() &&
165
!MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
166
167
return *NeedsDwarfUnwindInfo;
168
}
169
170
bool AArch64FunctionInfo::needsAsyncDwarfUnwindInfo(
171
const MachineFunction &MF) const {
172
if (!NeedsAsyncDwarfUnwindInfo) {
173
const Function &F = MF.getFunction();
174
const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
175
// The check got "minsize" is because epilogue unwind info is not emitted
176
// (yet) for homogeneous epilogues, outlined functions, and functions
177
// outlined from.
178
NeedsAsyncDwarfUnwindInfo =
179
needsDwarfUnwindInfo(MF) &&
180
((F.getUWTableKind() == UWTableKind::Async && !F.hasMinSize()) ||
181
AFI->hasStreamingModeChanges());
182
}
183
return *NeedsAsyncDwarfUnwindInfo;
184
}
185
186