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;
26 constexpr
char XRayInstrumentOption[] =
"-fxray-instrument";
27 constexpr
char XRayInstructionThresholdOption[] =
28 "-fxray-instruction-threshold=";
29 constexpr
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_,
83 options::OPT_fxray_instruction_threshold_EQ)) {
84 StringRef S = A->getValue();
85 if (S.getAsInteger(0, InstructionThreshold) || InstructionThreshold < 0)
86 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
93 if (Args.hasFlag(options::OPT_fxray_always_emit_customevents,
94 options::OPT_fno_xray_always_emit_customevents,
false))
95 XRayAlwaysEmitCustomEvents =
true;
97 if (Args.hasFlag(options::OPT_fxray_always_emit_typedevents,
98 options::OPT_fno_xray_always_emit_typedevents,
false))
99 XRayAlwaysEmitTypedEvents =
true;
101 if (!Args.hasFlag(options::OPT_fxray_link_deps,
102 options::OPT_fnoxray_link_deps,
true))
105 if (Args.hasFlag(options::OPT_fxray_ignore_loops,
106 options::OPT_fno_xray_ignore_loops,
false))
107 XRayIgnoreLoops =
true;
109 XRayFunctionIndex = Args.hasFlag(options::OPT_fxray_function_index,
110 options::OPT_fno_xray_function_index,
true);
113 Args.getAllArgValues(options::OPT_fxray_instrumentation_bundle);
117 for (
const auto &B : Bundles) {
119 llvm::SplitString(B, BundleParts,
",");
120 for (
const auto &
P : BundleParts) {
122 auto Valid = llvm::StringSwitch<bool>(
P)
123 .Cases(
"none",
"all",
"function",
"function-entry",
124 "function-exit",
"custom",
true)
128 D.
Diag(clang::diag::err_drv_invalid_value)
129 <<
"-fxray-instrumentation-bundle=" <<
P;
135 InstrumentationBundle.clear();
139 InstrumentationBundle.Mask |= Mask;
146 Args.getAllArgValues(options::OPT_fxray_always_instrument)) {
148 AlwaysInstrumentFiles.push_back(
Filename);
155 Args.getAllArgValues(options::OPT_fxray_never_instrument)) {
157 NeverInstrumentFiles.push_back(
Filename);
164 Args.getAllArgValues(options::OPT_fxray_attr_list)) {
173 auto SpecifiedModes = Args.getAllArgValues(options::OPT_fxray_modes);
174 if (SpecifiedModes.empty())
175 llvm::copy(XRaySupportedModes, std::back_inserter(Modes));
177 for (
const auto &Arg : SpecifiedModes) {
180 llvm::SplitString(Arg, ModeParts,
",");
181 for (
const auto &M : ModeParts)
185 llvm::copy(XRaySupportedModes, std::back_inserter(Modes));
190 if (
const Arg *A = Args.getLastArg(options::OPT_fxray_function_groups)) {
191 StringRef S = A->getValue();
192 if (S.getAsInteger(0, XRayFunctionGroups) || XRayFunctionGroups < 1)
193 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
197 Args.getLastArg(options::OPT_fxray_selected_function_group)) {
198 StringRef S = A->getValue();
199 if (S.getAsInteger(0, XRaySelectedFunctionGroup) ||
200 XRaySelectedFunctionGroup < 0 ||
201 XRaySelectedFunctionGroup >= XRayFunctionGroups)
202 D.
Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
207 Modes.erase(std::unique(Modes.begin(), Modes.end()), Modes.end());
211 ArgStringList &CmdArgs,
types::ID InputType)
const {
215 CmdArgs.push_back(XRayInstrumentOption);
217 if (XRayAlwaysEmitCustomEvents)
218 CmdArgs.push_back(
"-fxray-always-emit-customevents");
220 if (XRayAlwaysEmitTypedEvents)
221 CmdArgs.push_back(
"-fxray-always-emit-typedevents");
224 CmdArgs.push_back(
"-fxray-ignore-loops");
226 if (!XRayFunctionIndex)
227 CmdArgs.push_back(
"-fno-xray-function-index");
229 if (XRayFunctionGroups > 1) {
230 CmdArgs.push_back(Args.MakeArgString(Twine(
"-fxray-function-groups=") +
231 Twine(XRayFunctionGroups)));
234 if (XRaySelectedFunctionGroup != 0) {
236 Args.MakeArgString(Twine(
"-fxray-selected-function-group=") +
237 Twine(XRaySelectedFunctionGroup)));
240 CmdArgs.push_back(Args.MakeArgString(Twine(XRayInstructionThresholdOption) +
241 Twine(InstructionThreshold)));
243 for (
const auto &Always : AlwaysInstrumentFiles) {
245 AlwaysInstrumentOpt += Always;
246 CmdArgs.push_back(Args.MakeArgString(AlwaysInstrumentOpt));
249 for (
const auto &
Never : NeverInstrumentFiles) {
251 NeverInstrumentOpt +=
Never;
252 CmdArgs.push_back(Args.MakeArgString(NeverInstrumentOpt));
255 for (
const auto &AttrFile : AttrListFiles) {
257 AttrListFileOpt += AttrFile;
258 CmdArgs.push_back(Args.MakeArgString(AttrListFileOpt));
261 for (
const auto &Dep : ExtraDeps) {
264 CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt));
267 for (
const auto &Mode : Modes) {
270 CmdArgs.push_back(Args.MakeArgString(ModeOpt));
274 if (InstrumentationBundle.full()) {
276 }
else if (InstrumentationBundle.empty()) {
281 Bundle +=
"function";
283 Bundle +=
"function-entry";
285 Bundle +=
"function-exit";
292 CmdArgs.push_back(Args.MakeArgString(Bundle));