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"
26constexpr char XRayInstrumentOption[] =
"-fxray-instrument";
27constexpr char XRayInstructionThresholdOption[] =
28 "-fxray-instruction-threshold=";
29constexpr const char *
const XRaySupportedModes[] = {
"xray-fdr",
"xray-basic"};
34 const llvm::Triple &Triple = TC.
getTriple();
35 if (!Args.hasFlag(options::OPT_fxray_instrument,
36 options::OPT_fno_xray_instrument,
false))
38 if (Triple.getOS() == llvm::Triple::Linux) {
39 switch (Triple.getArch()) {
40 case llvm::Triple::x86_64:
41 case llvm::Triple::arm:
42 case llvm::Triple::aarch64:
43 case llvm::Triple::hexagon:
44 case llvm::Triple::ppc64le:
45 case llvm::Triple::mips:
46 case llvm::Triple::mipsel:
47 case llvm::Triple::mips64:
48 case llvm::Triple::mips64el:
51 D.
Diag(diag::err_drv_clang_unsupported)
52 << (std::string(XRayInstrumentOption) +
" on " + Triple.str());
54 }
else if (Triple.isOSFreeBSD() || Triple.isOSOpenBSD() ||
55 Triple.isOSNetBSD() || Triple.isMacOSX()) {
56 if (Triple.getArch() != llvm::Triple::x86_64) {
57 D.
Diag(diag::err_drv_clang_unsupported)
58 << (std::string(XRayInstrumentOption) +
" on " + Triple.str());
60 }
else if (Triple.getOS() == llvm::Triple::Fuchsia) {
61 switch (Triple.getArch()) {
62 case llvm::Triple::x86_64:
63 case llvm::Triple::aarch64:
66 D.
Diag(diag::err_drv_clang_unsupported)
67 << (std::string(XRayInstrumentOption) +
" on " + Triple.str());
70 D.
Diag(diag::err_drv_clang_unsupported)
71 << (std::string(XRayInstrumentOption) +
" on " + Triple.str());
76 if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ))
77 D.
Diag(diag::err_drv_argument_not_allowed_with)
78 <<
"-fxray-instrument" << A->getSpelling();
80 XRayInstrument =
true;
82 Args.getLastArg(options::OPT_fxray_instruction_threshold_EQ)) {
83 StringRef S = A->getValue();
84 if (S.getAsInteger(0, InstructionThreshold) || InstructionThreshold < 0)
85 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
92 if (Args.hasFlag(options::OPT_fxray_always_emit_customevents,
93 options::OPT_fno_xray_always_emit_customevents,
false))
94 XRayAlwaysEmitCustomEvents =
true;
96 if (Args.hasFlag(options::OPT_fxray_always_emit_typedevents,
97 options::OPT_fno_xray_always_emit_typedevents,
false))
98 XRayAlwaysEmitTypedEvents =
true;
100 if (!Args.hasFlag(options::OPT_fxray_link_deps,
101 options::OPT_fnoxray_link_deps,
true))
104 if (Args.hasFlag(options::OPT_fxray_ignore_loops,
105 options::OPT_fno_xray_ignore_loops,
false))
106 XRayIgnoreLoops =
true;
108 XRayFunctionIndex = Args.hasFlag(options::OPT_fxray_function_index,
109 options::OPT_fno_xray_function_index,
true);
112 Args.getAllArgValues(options::OPT_fxray_instrumentation_bundle);
116 for (
const auto &B : Bundles) {
118 llvm::SplitString(B, BundleParts,
",");
119 for (
const auto &
P : BundleParts) {
121 auto Valid = llvm::StringSwitch<bool>(
P)
122 .Cases(
"none",
"all",
"function",
"function-entry",
123 "function-exit",
"custom",
true)
127 D.
Diag(clang::diag::err_drv_invalid_value)
128 <<
"-fxray-instrumentation-bundle=" <<
P;
134 InstrumentationBundle.
clear();
138 InstrumentationBundle.
Mask |= Mask;
145 Args.getAllArgValues(options::OPT_fxray_always_instrument)) {
147 AlwaysInstrumentFiles.push_back(
Filename);
154 Args.getAllArgValues(options::OPT_fxray_never_instrument)) {
156 NeverInstrumentFiles.push_back(
Filename);
163 Args.getAllArgValues(options::OPT_fxray_attr_list)) {
172 auto SpecifiedModes = Args.getAllArgValues(options::OPT_fxray_modes);
173 if (SpecifiedModes.empty())
174 llvm::copy(XRaySupportedModes, std::back_inserter(Modes));
176 for (
const auto &Arg : SpecifiedModes) {
179 llvm::SplitString(Arg, ModeParts,
",");
180 for (
const auto &M : ModeParts)
184 llvm::copy(XRaySupportedModes, std::back_inserter(Modes));
186 Modes.push_back(std::string(M));
189 if (
const Arg *A = Args.getLastArg(options::OPT_fxray_function_groups)) {
190 StringRef S = A->getValue();
191 if (S.getAsInteger(0, XRayFunctionGroups) || XRayFunctionGroups < 1)
192 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
196 Args.getLastArg(options::OPT_fxray_selected_function_group)) {
197 StringRef S = A->getValue();
198 if (S.getAsInteger(0, XRaySelectedFunctionGroup) ||
199 XRaySelectedFunctionGroup < 0 ||
200 XRaySelectedFunctionGroup >= XRayFunctionGroups)
201 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
206 Modes.erase(std::unique(Modes.begin(), Modes.end()), Modes.end());
210 ArgStringList &CmdArgs,
types::ID InputType)
const {
214 CmdArgs.push_back(XRayInstrumentOption);
216 if (XRayAlwaysEmitCustomEvents)
217 CmdArgs.push_back(
"-fxray-always-emit-customevents");
219 if (XRayAlwaysEmitTypedEvents)
220 CmdArgs.push_back(
"-fxray-always-emit-typedevents");
223 CmdArgs.push_back(
"-fxray-ignore-loops");
225 if (!XRayFunctionIndex)
226 CmdArgs.push_back(
"-fno-xray-function-index");
228 if (XRayFunctionGroups > 1) {
229 CmdArgs.push_back(Args.MakeArgString(Twine(
"-fxray-function-groups=") +
230 Twine(XRayFunctionGroups)));
233 if (XRaySelectedFunctionGroup != 0) {
235 Args.MakeArgString(Twine(
"-fxray-selected-function-group=") +
236 Twine(XRaySelectedFunctionGroup)));
239 CmdArgs.push_back(Args.MakeArgString(Twine(XRayInstructionThresholdOption) +
240 Twine(InstructionThreshold)));
242 for (
const auto &Always : AlwaysInstrumentFiles) {
244 AlwaysInstrumentOpt += Always;
245 CmdArgs.push_back(Args.MakeArgString(AlwaysInstrumentOpt));
248 for (
const auto &
Never : NeverInstrumentFiles) {
250 NeverInstrumentOpt +=
Never;
251 CmdArgs.push_back(Args.MakeArgString(NeverInstrumentOpt));
254 for (
const auto &AttrFile : AttrListFiles) {
256 AttrListFileOpt += AttrFile;
257 CmdArgs.push_back(Args.MakeArgString(AttrListFileOpt));
260 for (
const auto &Dep : ExtraDeps) {
263 CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt));
266 for (
const auto &Mode : Modes) {
269 CmdArgs.push_back(Args.MakeArgString(ModeOpt));
273 if (InstrumentationBundle.
full()) {
275 }
else if (InstrumentationBundle.
empty()) {
280 Bundle +=
"function";
282 Bundle +=
"function-entry";
284 Bundle +=
"function-exit";
291 CmdArgs.push_back(Args.MakeArgString(Bundle));
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
DiagnosticBuilder Diag(unsigned DiagID) const
llvm::vfs::FileSystem & getVFS() const
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
for(unsigned I=0, E=TL.getNumArgs();I !=E;++I)
XRayInstrMask parseXRayInstrValue(StringRef Value)
Parses a command line argument into a mask.
void clear(XRayInstrMask K=XRayInstrKind::All)
bool has(XRayInstrMask K) const