Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Driver/XRayArgs.cpp
35233 views
1
//===--- XRayArgs.cpp - Arguments for XRay --------------------------------===//
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
#include "clang/Driver/XRayArgs.h"
9
#include "ToolChains/CommonArgs.h"
10
#include "clang/Driver/Driver.h"
11
#include "clang/Driver/DriverDiagnostic.h"
12
#include "clang/Driver/Options.h"
13
#include "clang/Driver/ToolChain.h"
14
#include "llvm/ADT/StringExtras.h"
15
#include "llvm/ADT/StringSwitch.h"
16
#include "llvm/Support/Path.h"
17
#include "llvm/Support/ScopedPrinter.h"
18
#include "llvm/Support/SpecialCaseList.h"
19
#include "llvm/Support/VirtualFileSystem.h"
20
21
using namespace clang;
22
using namespace clang::driver;
23
using namespace llvm::opt;
24
25
constexpr const char *XRaySupportedModes[] = {"xray-fdr", "xray-basic"};
26
27
XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
28
const Driver &D = TC.getDriver();
29
const llvm::Triple &Triple = TC.getTriple();
30
if (!Args.hasFlag(options::OPT_fxray_instrument,
31
options::OPT_fno_xray_instrument, false))
32
return;
33
XRayInstrument = Args.getLastArg(options::OPT_fxray_instrument);
34
if (Triple.isMacOSX()) {
35
switch (Triple.getArch()) {
36
case llvm::Triple::aarch64:
37
case llvm::Triple::x86_64:
38
break;
39
default:
40
D.Diag(diag::err_drv_unsupported_opt_for_target)
41
<< XRayInstrument->getSpelling() << Triple.str();
42
break;
43
}
44
} else if (Triple.isOSBinFormatELF()) {
45
switch (Triple.getArch()) {
46
case llvm::Triple::x86_64:
47
case llvm::Triple::arm:
48
case llvm::Triple::aarch64:
49
case llvm::Triple::hexagon:
50
case llvm::Triple::ppc64le:
51
case llvm::Triple::loongarch64:
52
case llvm::Triple::mips:
53
case llvm::Triple::mipsel:
54
case llvm::Triple::mips64:
55
case llvm::Triple::mips64el:
56
break;
57
default:
58
D.Diag(diag::err_drv_unsupported_opt_for_target)
59
<< XRayInstrument->getSpelling() << Triple.str();
60
}
61
} else {
62
D.Diag(diag::err_drv_unsupported_opt_for_target)
63
<< XRayInstrument->getSpelling() << Triple.str();
64
}
65
66
// Both XRay and -fpatchable-function-entry use
67
// TargetOpcode::PATCHABLE_FUNCTION_ENTER.
68
if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ))
69
D.Diag(diag::err_drv_argument_not_allowed_with)
70
<< XRayInstrument->getSpelling() << A->getSpelling();
71
72
if (!Args.hasFlag(options::OPT_fxray_link_deps,
73
options::OPT_fno_xray_link_deps, true))
74
XRayRT = false;
75
76
auto Bundles =
77
Args.getAllArgValues(options::OPT_fxray_instrumentation_bundle);
78
if (Bundles.empty())
79
InstrumentationBundle.Mask = XRayInstrKind::All;
80
else
81
for (const auto &B : Bundles) {
82
llvm::SmallVector<StringRef, 2> BundleParts;
83
llvm::SplitString(B, BundleParts, ",");
84
for (const auto &P : BundleParts) {
85
// TODO: Automate the generation of the string case table.
86
auto Valid = llvm::StringSwitch<bool>(P)
87
.Cases("none", "all", "function", "function-entry",
88
"function-exit", "custom", true)
89
.Default(false);
90
91
if (!Valid) {
92
D.Diag(clang::diag::err_drv_invalid_value)
93
<< "-fxray-instrumentation-bundle=" << P;
94
continue;
95
}
96
97
auto Mask = parseXRayInstrValue(P);
98
if (Mask == XRayInstrKind::None) {
99
InstrumentationBundle.clear();
100
break;
101
}
102
103
InstrumentationBundle.Mask |= Mask;
104
}
105
}
106
107
// Validate the always/never attribute files. We also make sure that they
108
// are treated as actual dependencies.
109
for (const auto &Filename :
110
Args.getAllArgValues(options::OPT_fxray_always_instrument)) {
111
if (D.getVFS().exists(Filename)) {
112
AlwaysInstrumentFiles.push_back(Filename);
113
ExtraDeps.push_back(Filename);
114
} else
115
D.Diag(clang::diag::err_drv_no_such_file) << Filename;
116
}
117
118
for (const auto &Filename :
119
Args.getAllArgValues(options::OPT_fxray_never_instrument)) {
120
if (D.getVFS().exists(Filename)) {
121
NeverInstrumentFiles.push_back(Filename);
122
ExtraDeps.push_back(Filename);
123
} else
124
D.Diag(clang::diag::err_drv_no_such_file) << Filename;
125
}
126
127
for (const auto &Filename :
128
Args.getAllArgValues(options::OPT_fxray_attr_list)) {
129
if (D.getVFS().exists(Filename)) {
130
AttrListFiles.push_back(Filename);
131
ExtraDeps.push_back(Filename);
132
} else
133
D.Diag(clang::diag::err_drv_no_such_file) << Filename;
134
}
135
136
// Get the list of modes we want to support.
137
auto SpecifiedModes = Args.getAllArgValues(options::OPT_fxray_modes);
138
if (SpecifiedModes.empty())
139
llvm::copy(XRaySupportedModes, std::back_inserter(Modes));
140
else
141
for (const auto &Arg : SpecifiedModes) {
142
// Parse CSV values for -fxray-modes=...
143
llvm::SmallVector<StringRef, 2> ModeParts;
144
llvm::SplitString(Arg, ModeParts, ",");
145
for (const auto &M : ModeParts)
146
if (M == "none")
147
Modes.clear();
148
else if (M == "all")
149
llvm::copy(XRaySupportedModes, std::back_inserter(Modes));
150
else
151
Modes.push_back(std::string(M));
152
}
153
154
// Then we want to sort and unique the modes we've collected.
155
llvm::sort(Modes);
156
Modes.erase(std::unique(Modes.begin(), Modes.end()), Modes.end());
157
}
158
159
void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args,
160
ArgStringList &CmdArgs, types::ID InputType) const {
161
if (!XRayInstrument)
162
return;
163
const Driver &D = TC.getDriver();
164
XRayInstrument->render(Args, CmdArgs);
165
166
// By default, the back-end will not emit the lowering for XRay customevent
167
// calls if the function is not instrumented. In the future we will change
168
// this default to be the reverse, but in the meantime we're going to
169
// introduce the new functionality behind a flag.
170
Args.addOptInFlag(CmdArgs, options::OPT_fxray_always_emit_customevents,
171
options::OPT_fno_xray_always_emit_customevents);
172
173
Args.addOptInFlag(CmdArgs, options::OPT_fxray_always_emit_typedevents,
174
options::OPT_fno_xray_always_emit_typedevents);
175
Args.addOptInFlag(CmdArgs, options::OPT_fxray_ignore_loops,
176
options::OPT_fno_xray_ignore_loops);
177
Args.addOptOutFlag(CmdArgs, options::OPT_fxray_function_index,
178
options::OPT_fno_xray_function_index);
179
180
if (const Arg *A =
181
Args.getLastArg(options::OPT_fxray_instruction_threshold_EQ)) {
182
int Value;
183
StringRef S = A->getValue();
184
if (S.getAsInteger(0, Value) || Value < 0)
185
D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
186
else
187
A->render(Args, CmdArgs);
188
}
189
190
int XRayFunctionGroups = 1;
191
int XRaySelectedFunctionGroup = 0;
192
if (const Arg *A = Args.getLastArg(options::OPT_fxray_function_groups)) {
193
StringRef S = A->getValue();
194
if (S.getAsInteger(0, XRayFunctionGroups) || XRayFunctionGroups < 1)
195
D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
196
if (XRayFunctionGroups > 1)
197
A->render(Args, CmdArgs);
198
}
199
if (const Arg *A =
200
Args.getLastArg(options::OPT_fxray_selected_function_group)) {
201
StringRef S = A->getValue();
202
if (S.getAsInteger(0, XRaySelectedFunctionGroup) ||
203
XRaySelectedFunctionGroup < 0 ||
204
XRaySelectedFunctionGroup >= XRayFunctionGroups)
205
D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
206
if (XRaySelectedFunctionGroup != 0)
207
A->render(Args, CmdArgs);
208
}
209
210
for (const auto &Always : AlwaysInstrumentFiles) {
211
SmallString<64> AlwaysInstrumentOpt("-fxray-always-instrument=");
212
AlwaysInstrumentOpt += Always;
213
CmdArgs.push_back(Args.MakeArgString(AlwaysInstrumentOpt));
214
}
215
216
for (const auto &Never : NeverInstrumentFiles) {
217
SmallString<64> NeverInstrumentOpt("-fxray-never-instrument=");
218
NeverInstrumentOpt += Never;
219
CmdArgs.push_back(Args.MakeArgString(NeverInstrumentOpt));
220
}
221
222
for (const auto &AttrFile : AttrListFiles) {
223
SmallString<64> AttrListFileOpt("-fxray-attr-list=");
224
AttrListFileOpt += AttrFile;
225
CmdArgs.push_back(Args.MakeArgString(AttrListFileOpt));
226
}
227
228
for (const auto &Dep : ExtraDeps) {
229
SmallString<64> ExtraDepOpt("-fdepfile-entry=");
230
ExtraDepOpt += Dep;
231
CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt));
232
}
233
234
for (const auto &Mode : Modes) {
235
SmallString<64> ModeOpt("-fxray-modes=");
236
ModeOpt += Mode;
237
CmdArgs.push_back(Args.MakeArgString(ModeOpt));
238
}
239
240
SmallString<64> Bundle("-fxray-instrumentation-bundle=");
241
if (InstrumentationBundle.full()) {
242
Bundle += "all";
243
} else if (InstrumentationBundle.empty()) {
244
Bundle += "none";
245
} else {
246
if (InstrumentationBundle.has(XRayInstrKind::FunctionEntry) &&
247
InstrumentationBundle.has(XRayInstrKind::FunctionExit))
248
Bundle += "function";
249
else if (InstrumentationBundle.has(XRayInstrKind::FunctionEntry))
250
Bundle += "function-entry";
251
else if (InstrumentationBundle.has(XRayInstrKind::FunctionExit))
252
Bundle += "function-exit";
253
254
if (InstrumentationBundle.has(XRayInstrKind::Custom))
255
Bundle += "custom";
256
if (InstrumentationBundle.has(XRayInstrKind::Typed))
257
Bundle += "typed";
258
}
259
CmdArgs.push_back(Args.MakeArgString(Bundle));
260
}
261
262