[DFAJumpThreading] Remove incoming StartBlock from all phis when unfolding select...
[llvm-project.git] / clang / lib / Driver / XRayArgs.cpp
blob8c5134e2501358c268c8886d7d645f9cda6fcbc2
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"
21 using namespace clang;
22 using namespace clang::driver;
23 using namespace llvm::opt;
25 constexpr const char *XRaySupportedModes[] = {"xray-fdr", "xray-basic"};
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;
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();
61 } else {
62 D.Diag(diag::err_drv_unsupported_opt_for_target)
63 << XRayInstrument->getSpelling() << Triple.str();
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();
72 if (!Args.hasFlag(options::OPT_fxray_link_deps,
73 options::OPT_fno_xray_link_deps, true))
74 XRayRT = false;
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);
91 if (!Valid) {
92 D.Diag(clang::diag::err_drv_invalid_value)
93 << "-fxray-instrumentation-bundle=" << P;
94 continue;
97 auto Mask = parseXRayInstrValue(P);
98 if (Mask == XRayInstrKind::None) {
99 InstrumentationBundle.clear();
100 break;
103 InstrumentationBundle.Mask |= Mask;
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;
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;
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;
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));
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());
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);
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);
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);
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);
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);
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);
210 for (const auto &Always : AlwaysInstrumentFiles) {
211 SmallString<64> AlwaysInstrumentOpt("-fxray-always-instrument=");
212 AlwaysInstrumentOpt += Always;
213 CmdArgs.push_back(Args.MakeArgString(AlwaysInstrumentOpt));
216 for (const auto &Never : NeverInstrumentFiles) {
217 SmallString<64> NeverInstrumentOpt("-fxray-never-instrument=");
218 NeverInstrumentOpt += Never;
219 CmdArgs.push_back(Args.MakeArgString(NeverInstrumentOpt));
222 for (const auto &AttrFile : AttrListFiles) {
223 SmallString<64> AttrListFileOpt("-fxray-attr-list=");
224 AttrListFileOpt += AttrFile;
225 CmdArgs.push_back(Args.MakeArgString(AttrListFileOpt));
228 for (const auto &Dep : ExtraDeps) {
229 SmallString<64> ExtraDepOpt("-fdepfile-entry=");
230 ExtraDepOpt += Dep;
231 CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt));
234 for (const auto &Mode : Modes) {
235 SmallString<64> ModeOpt("-fxray-modes=");
236 ModeOpt += Mode;
237 CmdArgs.push_back(Args.MakeArgString(ModeOpt));
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";
254 if (InstrumentationBundle.has(XRayInstrKind::Custom))
255 Bundle += "custom";
256 if (InstrumentationBundle.has(XRayInstrKind::Typed))
257 Bundle += "typed";
259 CmdArgs.push_back(Args.MakeArgString(Bundle));