clang: lib/Driver/XRayArgs.cpp Source File (original) (raw)
1
2
3
4
5
6
7
13#include "llvm/ADT/StringExtras.h"
14#include "llvm/ADT/StringSwitch.h"
15#include "llvm/Support/SpecialCaseList.h"
16#include "llvm/Support/VirtualFileSystem.h"
17
18using namespace clang;
21
23
26 const llvm::Triple &Triple = TC.getTriple();
27 if (!Args.hasFlag(options::OPT_fxray_instrument,
28 options::OPT_fno_xray_instrument, false))
29 return;
30 XRayInstrument = Args.getLastArg(options::OPT_fxray_instrument);
31 if (Triple.isMacOSX()) {
32 switch (Triple.getArch()) {
33 case llvm::Triple::aarch64:
34 case llvm::Triple::x86_64:
35 break;
36 default:
37 D.Diag(diag::err_drv_unsupported_opt_for_target)
38 << XRayInstrument->getSpelling() << Triple.str();
39 break;
40 }
41 } else if (Triple.isOSBinFormatELF()) {
42 switch (Triple.getArch()) {
43 case llvm::Triple::x86_64:
44 case llvm::Triple::arm:
45 case llvm::Triple::aarch64:
46 case llvm::Triple::hexagon:
47 case llvm::Triple::ppc64le:
48 case llvm::Triple::loongarch64:
49 case llvm::Triple::mips:
50 case llvm::Triple::mipsel:
51 case llvm::Triple::mips64:
52 case llvm::Triple::mips64el:
53 case llvm::Triple::systemz:
54 case llvm::Triple::riscv32:
55 case llvm::Triple::riscv64:
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 if (Args.hasFlag(options::OPT_fxray_shared, options::OPT_fno_xray_shared,
67 false)) {
68 XRayShared = true;
69
70
71 switch (Triple.getArch()) {
72 case llvm::Triple::aarch64:
73 case llvm::Triple::x86_64:
74 break;
75 default:
76 D.Diag(diag::err_drv_unsupported_opt_for_target)
77 << "-fxray-shared" << Triple.str();
78 }
79
81 if (!PICLvl) {
82 D.Diag(diag::err_opt_not_valid_without_opt) << "-fxray-shared"
83 << "-fPIC";
84 }
85 }
86
87
88
89 if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ))
90 D.Diag(diag::err_drv_argument_not_allowed_with)
91 << XRayInstrument->getSpelling() << A->getSpelling();
92
93 if (!Args.hasFlag(options::OPT_fxray_link_deps,
94 options::OPT_fno_xray_link_deps, true))
95 XRayRT = false;
96
97 auto Bundles =
98 Args.getAllArgValues(options::OPT_fxray_instrumentation_bundle);
99 if (Bundles.empty())
101 else
102 for (const auto &B : Bundles) {
104 llvm::SplitString(B, BundleParts, ",");
105 for (const auto &P : BundleParts) {
106
107 auto Valid = llvm::StringSwitch(P)
108 .Cases("none", "all", "function", "function-entry",
109 "function-exit", "custom", true)
110 .Default(false);
111
112 if (!Valid) {
113 D.Diag(clang::diag::err_drv_invalid_value)
114 << "-fxray-instrumentation-bundle=" << P;
115 continue;
116 }
117
120 InstrumentationBundle.clear();
121 break;
122 }
123
124 InstrumentationBundle.Mask |= Mask;
125 }
126 }
127
128
129
131 Args.getAllArgValues(options::OPT_fxray_always_instrument)) {
132 if (D.getVFS().exists(Filename)) {
133 AlwaysInstrumentFiles.push_back(Filename);
134 ExtraDeps.push_back(Filename);
135 } else
136 D.Diag(clang::diag::err_drv_no_such_file) << Filename;
137 }
138
140 Args.getAllArgValues(options::OPT_fxray_never_instrument)) {
141 if (D.getVFS().exists(Filename)) {
142 NeverInstrumentFiles.push_back(Filename);
143 ExtraDeps.push_back(Filename);
144 } else
145 D.Diag(clang::diag::err_drv_no_such_file) << Filename;
146 }
147
149 Args.getAllArgValues(options::OPT_fxray_attr_list)) {
150 if (D.getVFS().exists(Filename)) {
151 AttrListFiles.push_back(Filename);
152 ExtraDeps.push_back(Filename);
153 } else
154 D.Diag(clang::diag::err_drv_no_such_file) << Filename;
155 }
156
157
158 auto SpecifiedModes = Args.getAllArgValues(options::OPT_fxray_modes);
159 if (SpecifiedModes.empty())
161 else
162 for (const auto &Arg : SpecifiedModes) {
163
165 llvm::SplitString(Arg, ModeParts, ",");
166 for (const auto &M : ModeParts)
167 if (M == "none")
168 Modes.clear();
169 else if (M == "all")
171 else
172 Modes.push_back(std::string(M));
173 }
174
175
176 llvm::sort(Modes);
177 Modes.erase(std::unique(Modes.begin(), Modes.end()), Modes.end());
178}
179
181 ArgStringList &CmdArgs, types::ID InputType) const {
182 if (!XRayInstrument)
183 return;
185 XRayInstrument->render(Args, CmdArgs);
186
187
188
189
190
191 Args.addOptInFlag(CmdArgs, options::OPT_fxray_always_emit_customevents,
192 options::OPT_fno_xray_always_emit_customevents);
193
194 Args.addOptInFlag(CmdArgs, options::OPT_fxray_always_emit_typedevents,
195 options::OPT_fno_xray_always_emit_typedevents);
196 Args.addOptInFlag(CmdArgs, options::OPT_fxray_ignore_loops,
197 options::OPT_fno_xray_ignore_loops);
198 Args.addOptOutFlag(CmdArgs, options::OPT_fxray_function_index,
199 options::OPT_fno_xray_function_index);
200
201 if (XRayShared)
202 Args.addOptInFlag(CmdArgs, options::OPT_fxray_shared,
203 options::OPT_fno_xray_shared);
204
205 if (const Arg *A =
206 Args.getLastArg(options::OPT_fxray_instruction_threshold_EQ)) {
208 StringRef S = A->getValue();
209 if (S.getAsInteger(0, Value) || Value < 0)
210 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
211 else
212 A->render(Args, CmdArgs);
213 }
214
215 int XRayFunctionGroups = 1;
216 int XRaySelectedFunctionGroup = 0;
217 if (const Arg *A = Args.getLastArg(options::OPT_fxray_function_groups)) {
218 StringRef S = A->getValue();
219 if (S.getAsInteger(0, XRayFunctionGroups) || XRayFunctionGroups < 1)
220 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
221 if (XRayFunctionGroups > 1)
222 A->render(Args, CmdArgs);
223 }
224 if (const Arg *A =
225 Args.getLastArg(options::OPT_fxray_selected_function_group)) {
226 StringRef S = A->getValue();
227 if (S.getAsInteger(0, XRaySelectedFunctionGroup) ||
228 XRaySelectedFunctionGroup < 0 ||
229 XRaySelectedFunctionGroup >= XRayFunctionGroups)
230 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
231 if (XRaySelectedFunctionGroup != 0)
232 A->render(Args, CmdArgs);
233 }
234
235 for (const auto &Always : AlwaysInstrumentFiles) {
236 SmallString<64> AlwaysInstrumentOpt("-fxray-always-instrument=");
237 AlwaysInstrumentOpt += Always;
238 CmdArgs.push_back(Args.MakeArgString(AlwaysInstrumentOpt));
239 }
240
241 for (const auto &Never : NeverInstrumentFiles) {
242 SmallString<64> NeverInstrumentOpt("-fxray-never-instrument=");
243 NeverInstrumentOpt += Never;
244 CmdArgs.push_back(Args.MakeArgString(NeverInstrumentOpt));
245 }
246
247 for (const auto &AttrFile : AttrListFiles) {
249 AttrListFileOpt += AttrFile;
250 CmdArgs.push_back(Args.MakeArgString(AttrListFileOpt));
251 }
252
253 for (const auto &Dep : ExtraDeps) {
255 ExtraDepOpt += Dep;
256 CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt));
257 }
258
259 for (const auto &Mode : Modes) {
261 ModeOpt += Mode;
262 CmdArgs.push_back(Args.MakeArgString(ModeOpt));
263 }
264
265 SmallString<64> Bundle("-fxray-instrumentation-bundle=");
266 if (InstrumentationBundle.full()) {
267 Bundle += "all";
268 } else if (InstrumentationBundle.empty()) {
269 Bundle += "none";
270 } else {
273 Bundle += "function";
275 Bundle += "function-entry";
277 Bundle += "function-exit";
278
280 Bundle += "custom";
282 Bundle += "typed";
283 }
284 CmdArgs.push_back(Args.MakeArgString(Bundle));
285}
constexpr const char * XRaySupportedModes[]
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const
XRayArgs(const ToolChain &TC, const llvm::opt::ArgList &Args)
Parses the XRay arguments from an argument list.
constexpr XRayInstrMask Typed
constexpr XRayInstrMask FunctionExit
constexpr XRayInstrMask None
constexpr XRayInstrMask FunctionEntry
constexpr XRayInstrMask All
constexpr XRayInstrMask Custom
The JSON file list parser is used to communicate input to InstallAPI.
XRayInstrMask parseXRayInstrValue(StringRef Value)
Parses a command line argument into a mask.
void clear(XRayInstrMask K=XRayInstrKind::All)
bool has(XRayInstrMask K) const