--- /dev/null
+//===--- XRayInstr.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// \brief Defines the clang::XRayInstrKind enum.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_XRAYINSTR_H
+#define LLVM_CLANG_BASIC_XRAYINSTR_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MathExtras.h"
+#include <cassert>
+#include <cstdint>
+
+namespace clang {
+
+using XRayInstrMask = uint32_t;
+
+namespace XRayInstrKind {
+
+// TODO: Auto-generate these as we add more instrumentation kinds.
+enum XRayInstrOrdinal : XRayInstrMask {
+ XRIO_Function,
+ XRIO_Custom,
+ XRIO_Count
+};
+
+constexpr XRayInstrMask None = 0;
+constexpr XRayInstrMask Function = 1U << XRIO_Function;
+constexpr XRayInstrMask Custom = 1U << XRIO_Custom;
+constexpr XRayInstrMask All = Function | Custom;
+
+} // namespace XRayInstrKind
+
+struct XRayInstrSet {
+ bool has(XRayInstrMask K) const {
+ assert(llvm::isPowerOf2_32(K));
+ return Mask & K;
+ }
+
+ bool hasOneOf(XRayInstrMask K) const { return Mask & K; }
+
+ void set(XRayInstrMask K, bool Value) {
+ assert(llvm::isPowerOf2_32(K));
+ Mask = Value ? (Mask | K) : (Mask & ~K);
+ }
+
+ void clear(XRayInstrMask K = XRayInstrKind::All) { Mask &= ~K; }
+
+ bool empty() const { return Mask == 0; }
+
+ XRayInstrMask Mask = 0;
+};
+
+XRayInstrMask parseXRayInstrValue(StringRef Value);
+
+} // namespace clang
+
+#endif // LLVM_CLANG_BASIC_XRAYINSTR_H
def fnoxray_link_deps : Flag<["-"], "fnoxray-link-deps">, Group<f_Group>,
Flags<[CC1Option]>;
+def fxray_instrumentation_bundle :
+ JoinedOrSeparate<["-"], "fxray-instrumentation-bundle=">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Select which XRay instrumentation points to emit. Options: all, none, function, custom. Default is 'all'.">;
+
def ffine_grained_bitfield_accesses : Flag<["-"],
"ffine-grained-bitfield-accesses">, Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Use separate accesses for bitfields with legal widths and alignments.">;
#ifndef LLVM_CLANG_DRIVER_XRAYARGS_H
#define LLVM_CLANG_DRIVER_XRAYARGS_H
+#include "clang/Basic/XRayInstr.h"
#include "clang/Driver/Types.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
std::vector<std::string> AttrListFiles;
std::vector<std::string> ExtraDeps;
std::vector<std::string> Modes;
+ XRayInstrSet InstrumentationBundle;
bool XRayInstrument = false;
int InstructionThreshold = 200;
bool XRayAlwaysEmitCustomEvents = false;
bool needsXRayRt() const { return XRayInstrument && XRayRT; }
llvm::ArrayRef<std::string> modeList() const { return Modes; }
-
+ XRayInstrSet instrumentationBundle() const { return InstrumentationBundle; }
};
} // namespace driver
#include "clang/Basic/DebugInfoOptions.h"
#include "clang/Basic/Sanitizers.h"
+#include "clang/Basic/XRayInstr.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Regex.h"
#include "llvm/Target/TargetOptions.h"
/// registers.
std::string PreferVectorWidth;
+ /// Set of XRay instrumentation kinds to emit.
+ XRayInstrSet XRayInstrumentationBundle;
+
public:
// Define accessors/mutators for code generation options of enumeration type.
#define CODEGENOPT(Name, Bits, Default)
VersionTuple.cpp
VirtualFileSystem.cpp
Warnings.cpp
+ XRayInstr.cpp
XRayLists.cpp
${version_inc}
)
--- /dev/null
+//===--- XRayInstr.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is part of XRay, a function call instrumentation system.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/XRayInstr.h"
+#include "llvm/ADT/StringSwitch.h"
+
+namespace clang {
+
+XRayInstrMask parseXRayInstrValue(StringRef Value) {
+ XRayInstrMask ParsedKind = llvm::StringSwitch<XRayInstrMask>(Value)
+ .Case("all", XRayInstrKind::All)
+ .Case("custom", XRayInstrKind::Custom)
+ .Case("function", XRayInstrKind::Function)
+ .Case("none", XRayInstrKind::None)
+ .Default(XRayInstrKind::None);
+ return ParsedKind;
+}
+
+} // namespace clang
case Builtin::BI__xray_customevent: {
if (!ShouldXRayInstrumentFunction())
return RValue::getIgnored();
+
+ if (!CGM.getCodeGenOpts().XRayInstrumentationBundle.has(
+ XRayInstrKind::Custom))
+ return RValue::getIgnored();
+
if (const auto *XRayAttr = CurFuncDecl->getAttr<XRayInstrumentAttr>())
if (XRayAttr->neverXRayInstrument() && !AlwaysEmitXRayCustomEvents())
return RValue::getIgnored();
/// AlwaysEmitXRayCustomEvents - Return true if we should emit IR for calls to
/// the __xray_customevent(...) builin calls, when doing XRay instrumentation.
bool CodeGenFunction::AlwaysEmitXRayCustomEvents() const {
- return CGM.getCodeGenOpts().XRayAlwaysEmitCustomEvents;
+ return CGM.getCodeGenOpts().XRayInstrumentFunctions &&
+ (CGM.getCodeGenOpts().XRayAlwaysEmitCustomEvents ||
+ CGM.getCodeGenOpts().XRayInstrumentationBundle.Mask ==
+ XRayInstrKind::Custom);
}
llvm::Constant *
}
// Apply xray attributes to the function (as a string, for now)
- bool InstrumentXray = ShouldXRayInstrumentFunction();
+ bool InstrumentXray = ShouldXRayInstrumentFunction() &&
+ CGM.getCodeGenOpts().XRayInstrumentationBundle.has(
+ XRayInstrKind::Function);
if (D && InstrumentXray) {
if (const auto *XRayAttr = D->getAttr<XRayInstrumentAttr>()) {
if (XRayAttr->alwaysXRayInstrument())
StringRef Category) const {
if (!LangOpts.XRayInstrument)
return false;
+
const auto &XRayFilter = getContext().getXRayFilter();
using ImbueAttr = XRayFunctionFilter::ImbueAttribute;
- auto Attr = XRayFunctionFilter::ImbueAttribute::NONE;
+ auto Attr = ImbueAttr::NONE;
if (Loc.isValid())
Attr = XRayFilter.shouldImbueLocation(Loc, Category);
if (Attr == ImbueAttr::NONE)
}
} else {
D.Diag(diag::err_drv_clang_unsupported)
- << (std::string(XRayInstrumentOption) +
- " on non-supported target OS");
+ << (std::string(XRayInstrumentOption) + " on " + Triple.str());
}
XRayInstrument = true;
if (const Arg *A =
options::OPT_fnoxray_link_deps, true))
XRayRT = false;
+ auto Bundles =
+ Args.getAllArgValues(options::OPT_fxray_instrumentation_bundle);
+ if (Bundles.empty())
+ InstrumentationBundle.Mask = XRayInstrKind::All;
+ else
+ for (const auto &B : Bundles) {
+ llvm::SmallVector<StringRef, 2> BundleParts;
+ llvm::SplitString(B, BundleParts, ",");
+ for (const auto &P : BundleParts) {
+ // TODO: Automate the generation of the string case table.
+ auto Valid = llvm::StringSwitch<bool>(P)
+ .Cases("none", "all", "function", "custom", true)
+ .Default(false);
+
+ if (!Valid) {
+ D.Diag(clang::diag::err_drv_invalid_value)
+ << "-fxray-instrumentation-bundle=" << P;
+ continue;
+ }
+
+ auto Mask = parseXRayInstrValue(P);
+ if (Mask == XRayInstrKind::None) {
+ InstrumentationBundle.clear();
+ break;
+ }
+
+ InstrumentationBundle.Mask |= Mask;
+ }
+ }
+
// Validate the always/never attribute files. We also make sure that they
// are treated as actual dependencies.
for (const auto &Filename :
CmdArgs.push_back(Args.MakeArgString(NeverInstrumentOpt));
}
- for (const auto& AttrFile : AttrListFiles) {
+ for (const auto &AttrFile : AttrListFiles) {
SmallString<64> AttrListFileOpt("-fxray-attr-list=");
AttrListFileOpt += AttrFile;
CmdArgs.push_back(Args.MakeArgString(AttrListFileOpt));
#include "clang/Basic/VersionTuple.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Basic/Visibility.h"
+#include "clang/Basic/XRayInstr.h"
#include "clang/Config/config.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Regex.h"
+#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetOptions.h"
-#include "llvm/Support/ScopedPrinter.h"
#include <algorithm>
#include <atomic>
#include <cassert>
}
}
+static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle,
+ ArgList &Args, DiagnosticsEngine &D,
+ XRayInstrSet &S) {
+ llvm::SmallVector<StringRef, 2> BundleParts;
+ llvm::SplitString(Bundle, BundleParts, ",");
+ for (const auto B : BundleParts) {
+ auto Mask = parseXRayInstrValue(B);
+ if (Mask == XRayInstrKind::None)
+ if (B != "none")
+ D.Report(diag::err_drv_invalid_value) << FlagName << Bundle;
+ else
+ S.Mask = Mask;
+ else if (Mask == XRayInstrKind::All)
+ S.Mask = Mask;
+ else
+ S.set(Mask, true);
+ }
+}
+
// Set the profile kind for fprofile-instrument.
static void setPGOInstrumentor(CodeGenOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags) {
Args.hasArg(OPT_finstrument_functions_after_inlining);
Opts.InstrumentFunctionEntryBare =
Args.hasArg(OPT_finstrument_function_entry_bare);
- Opts.XRayInstrumentFunctions = Args.hasArg(OPT_fxray_instrument);
+
+ Opts.XRayInstrumentFunctions =
+ Args.hasArg(OPT_fxray_instrument);
Opts.XRayAlwaysEmitCustomEvents =
Args.hasArg(OPT_fxray_always_emit_customevents);
Opts.XRayInstructionThreshold =
getLastArgIntValue(Args, OPT_fxray_instruction_threshold_EQ, 200, Diags);
+
+ auto XRayInstrBundles =
+ Args.getAllArgValues(OPT_fxray_instrumentation_bundle);
+ if (XRayInstrBundles.empty())
+ Opts.XRayInstrumentationBundle.Mask = XRayInstrKind::All;
+ else
+ for (const auto &A : XRayInstrBundles)
+ parseXRayInstrumentationBundle("-fxray-instrumentation-bundle=", A, Args,
+ Diags, Opts.XRayInstrumentationBundle);
+
Opts.InstrumentForProfiling = Args.hasArg(OPT_pg);
Opts.CallFEntry = Args.hasArg(OPT_mfentry);
Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info);
--- /dev/null
+// RUN: %clang_cc1 -fxray-instrument -fxray-instrumentation-bundle=none -x c++ \
+// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK,NOFUNCTION,NOCUSTOM %s
+// RUN: %clang_cc1 -fxray-instrument \
+// RUN: -fxray-instrumentation-bundle=function -x c++ \
+// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,NOCUSTOM %s
+// RUN: %clang_cc1 -fxray-instrument \
+// RUN: -fxray-instrumentation-bundle=custom -x c++ \
+// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK,NOFUNCTION,CUSTOM %s
+// RUN: %clang_cc1 -fxray-instrument \
+// RUN: -fxray-instrumentation-bundle=function,custom -x c++ \
+// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,CUSTOM %s
+// RUN: %clang_cc1 -fxray-instrument \
+// RUN: -fxray-instrumentation-bundle=function \
+// RUN: -fxray-instrumentation-bundle=custom -x c++ \
+// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,CUSTOM %s
+
+// CHECK: define void @_Z16alwaysInstrumentv() #[[ALWAYSATTR:[0-9]+]] {
+[[clang::xray_always_instrument]] void alwaysInstrument() {
+ static constexpr char kPhase[] = "always";
+ __xray_customevent(kPhase, 6);
+ // CUSTOM: call void @llvm.xray.customevent(i8*{{.*}}, i32 6)
+ // NOCUSTOM-NOT: call void @llvm.xray.customevent(i8*{{.*}}, i32 6)
+}
+
+// FUNCTION: attributes #[[ALWAYSATTR]] = {{.*}} "function-instrument"="xray-always" {{.*}}
+// NOFUNCTION-NOT: attributes #[[ALWAYSATTR]] = {{.*}} "function-instrument"="xray-always" {{.*}}