]> granicus.if.org Git - clang/commitdiff
[XRay] Add -fxray-{always,never}-instrument= flags to clang
authorDean Michael Berris <dberris@google.com>
Thu, 30 Mar 2017 00:29:36 +0000 (00:29 +0000)
committerDean Michael Berris <dberris@google.com>
Thu, 30 Mar 2017 00:29:36 +0000 (00:29 +0000)
Summary:
The -fxray-always-instrument= and -fxray-never-instrument= flags take
filenames that are used to imbue the XRay instrumentation attributes
using a whitelist mechanism (similar to the sanitizer special cases
list). We use the same syntax and semantics as the sanitizer blacklists
files in the implementation.

As implemented, we respect the attributes that are already defined in
the source file (i.e. those that have the
[[clang::xray_{always,never}_instrument]] attributes) before applying
the always/never instrument lists.

Reviewers: rsmith, chandlerc

Subscribers: jfb, mgorny, cfe-commits

Differential Revision: https://reviews.llvm.org/D30388

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@299041 91177308-0d34-0410-b5e6-96231b3b80d8

20 files changed:
include/clang/AST/ASTContext.h
include/clang/Basic/LangOptions.def
include/clang/Basic/LangOptions.h
include/clang/Basic/XRayLists.h [new file with mode: 0644]
include/clang/Driver/Options.td
include/clang/Driver/ToolChain.h
include/clang/Driver/XRayArgs.h [new file with mode: 0644]
lib/AST/ASTContext.cpp
lib/Basic/CMakeLists.txt
lib/Basic/LangOptions.cpp
lib/Basic/XRayLists.cpp [new file with mode: 0644]
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
lib/Driver/CMakeLists.txt
lib/Driver/ToolChain.cpp
lib/Driver/ToolChains/Clang.cpp
lib/Driver/XRayArgs.cpp [new file with mode: 0644]
lib/Frontend/CompilerInvocation.cpp
test/CodeGen/xray-always-instrument.cpp [new file with mode: 0644]

index 5fa515d02db9540c12d370a40da392753dfe2964..d52c07200cec79520e2cea673ab254abbbb27776 100644 (file)
@@ -39,6 +39,7 @@
 #include "clang/Basic/SanitizerBlacklist.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/Specifiers.h"
+#include "clang/Basic/XRayLists.h"
 #include "llvm/ADT/APSInt.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
@@ -475,6 +476,10 @@ private:
   /// entities should not be instrumented.
   std::unique_ptr<SanitizerBlacklist> SanitizerBL;
 
+  /// \breif Function filtering mehcanism to determine whether a given function
+  /// should be imbued with the XRay "always" or "never" attributes.
+  std::unique_ptr<XRayFunctionFilter> XRayFilter;
+
   /// \brief The allocator used to create AST objects.
   ///
   /// AST objects are never destructed; rather, all memory associated with the
@@ -657,6 +662,10 @@ public:
     return *SanitizerBL;
   }
 
+  const XRayFunctionFilter &getXRayFilter() const {
+    return *XRayFilter;
+  }
+
   DiagnosticsEngine &getDiagnostics() const;
 
   FullSourceLoc getFullLoc(SourceLocation Loc) const {
index d00aa411de8143a6435b19b6a3fb0dc65e0812f7..1a142b8b746549b7bae6558574d9518ebb62abc9 100644 (file)
@@ -263,6 +263,8 @@ LANGOPT(SanitizeAddressFieldPadding, 2, 0, "controls how aggressive is ASan "
                                            "field padding (0: none, 1:least "
                                            "aggressive, 2: more aggressive)")
 
+LANGOPT(XRayInstrument, 1, 0, "controls whether to do XRay instrumentation")
+
 #undef LANGOPT
 #undef COMPATIBLE_LANGOPT
 #undef BENIGN_LANGOPT
index 16abf9b7bb87575808fb5b500e7131efdfbcb8a3..e684ec1ba947683e519a6dfa6d2046887c73e2f8 100644 (file)
@@ -102,6 +102,16 @@ public:
   /// (files, functions, variables) should not be instrumented.
   std::vector<std::string> SanitizerBlacklistFiles;
 
+  /// \brief Paths to the XRay "always instrument" files specifying which
+  /// objects (files, functions, variables) should be imbued with the XRay
+  /// "always instrument" attribute.
+  std::vector<std::string> XRayAlwaysInstrumentFiles;
+
+  /// \brief Paths to the XRay "never instrument" files specifying which
+  /// objects (files, functions, variables) should be imbued with the XRay
+  /// "never instrument" attribute.
+  std::vector<std::string> XRayNeverInstrumentFiles;
+
   clang::ObjCRuntime ObjCRuntime;
 
   std::string ObjCConstantStringClass;
diff --git a/include/clang/Basic/XRayLists.h b/include/clang/Basic/XRayLists.h
new file mode 100644 (file)
index 0000000..fe53828
--- /dev/null
@@ -0,0 +1,54 @@
+//===--- XRayLists.h - XRay automatic attribution ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// User-provided filters for always/never XRay instrumenting certain functions.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_XRAYLISTS_H
+#define LLVM_CLANG_BASIC_XRAYLISTS_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/SpecialCaseList.h"
+#include <memory>
+
+namespace clang {
+
+class XRayFunctionFilter {
+  std::unique_ptr<llvm::SpecialCaseList> AlwaysInstrument;
+  std::unique_ptr<llvm::SpecialCaseList> NeverInstrument;
+  SourceManager &SM;
+
+public:
+  XRayFunctionFilter(ArrayRef<std::string> AlwaysInstrumentPaths,
+                     ArrayRef<std::string> NeverInstrumentPaths,
+                     SourceManager &SM);
+
+  enum class ImbueAttribute {
+    NONE,
+    ALWAYS,
+    NEVER,
+  };
+
+  ImbueAttribute shouldImbueFunction(StringRef FunctionName) const;
+
+  ImbueAttribute
+  shouldImbueFunctionsInFile(StringRef Filename,
+                             StringRef Category = StringRef()) const;
+
+  ImbueAttribute shouldImbueLocation(SourceLocation Loc,
+                                     StringRef Category = StringRef()) const;
+};
+
+} // namespace clang
+
+#endif
index 06d4a244c1a508377147c0d5a3d913bac5295eab..12b7ca21fc6c98d91794150a054933b5e4f64555 100644 (file)
@@ -962,6 +962,15 @@ def fxray_instruction_threshold_ :
   JoinedOrSeparate<["-"], "fxray-instruction-threshold">,
   Group<f_Group>, Flags<[CC1Option]>;
 
+def fxray_always_instrument :
+  JoinedOrSeparate<["-"], "fxray-always-instrument=">,
+  Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Filename defining the whitelist for imbuing the 'always instrument' XRay attribute.">;
+def fxray_never_instrument :
+  JoinedOrSeparate<["-"], "fxray-never-instrument=">,
+  Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Filename defining the whitelist for imbuing the 'never instrument' XRay attribute.">;
+
 def flat__namespace : Flag<["-"], "flat_namespace">;
 def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>;
 def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
index f8e5fde2cd7400db932face40544ba9495e33078..105d0f338ac6f67beebf7f21ae382a9bba12ccd6 100644 (file)
@@ -44,6 +44,7 @@ namespace driver {
   class RegisterEffectiveTriple;
   class SanitizerArgs;
   class Tool;
+  class XRayArgs;
 
 /// ToolChain - Access to tools for a single platform.
 class ToolChain {
@@ -94,6 +95,7 @@ private:
   Tool *getOffloadBundler() const;
 
   mutable std::unique_ptr<SanitizerArgs> SanitizerArguments;
+  mutable std::unique_ptr<XRayArgs> XRayArguments;
 
   /// The effective clang triple for the current Job.
   mutable llvm::Triple EffectiveTriple;
@@ -177,6 +179,8 @@ public:
 
   const SanitizerArgs& getSanitizerArgs() const;
 
+  const XRayArgs& getXRayArgs() const;
+
   // Returns the Arg * that explicitly turned on/off rtti, or nullptr.
   const llvm::opt::Arg *getRTTIArg() const { return CachedRTTIArg; }
 
diff --git a/include/clang/Driver/XRayArgs.h b/include/clang/Driver/XRayArgs.h
new file mode 100644 (file)
index 0000000..83210d1
--- /dev/null
@@ -0,0 +1,38 @@
+//===--- XRayArgs.h - Arguments for XRay ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_DRIVER_XRAYARGS_H
+#define LLVM_CLANG_DRIVER_XRAYARGS_H
+
+#include "clang/Driver/Types.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+
+namespace clang {
+namespace driver {
+
+class ToolChain;
+
+class XRayArgs {
+  std::vector<std::string> AlwaysInstrumentFiles;
+  std::vector<std::string> NeverInstrumentFiles;
+  std::vector<std::string> ExtraDeps;
+  bool XRayInstrument = false;
+  int InstructionThreshold = 200;
+
+public:
+  /// Parses the XRay arguments from an argument list.
+  XRayArgs(const ToolChain &TC, const llvm::opt::ArgList &Args);
+  void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
+               llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const;
+};
+
+} // namespace driver
+} // namespace clang
+
+#endif // LLVM_CLANG_DRIVER_XRAYARGS_H
index 071537a051cc1d45cd0a28685615bc9fc2ae441f..b4423b00469bd3e41e20e8003a009264e1cadbcd 100644 (file)
@@ -748,6 +748,8 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
       ExternCContext(nullptr), MakeIntegerSeqDecl(nullptr),
       TypePackElementDecl(nullptr), SourceMgr(SM), LangOpts(LOpts),
       SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
+      XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles,
+                                        LangOpts.XRayNeverInstrumentFiles, SM)),
       AddrSpaceMap(nullptr), Target(nullptr), AuxTarget(nullptr),
       PrintingPolicy(LOpts), Idents(idents), Selectors(sels),
       BuiltinInfo(builtins), DeclarationNames(*this), ExternalSource(nullptr),
index 23242ba3f60cfebdfdcc06027986f44773cab98f..2feb31851cfedd64eb196c5987fc4ceeb58be1ed 100644 (file)
@@ -90,6 +90,7 @@ add_clang_library(clangBasic
   VersionTuple.cpp
   VirtualFileSystem.cpp
   Warnings.cpp
+  XRayLists.cpp
   ${version_inc}
   )
 
index ff10a773a97cd4c14c16f6f1ca56c724ace29299..c8a774311efe1fe47054801f639d1c5ff69860ef 100644 (file)
@@ -33,6 +33,8 @@ void LangOptions::resetNonModularOptions() {
   // sanitizer options (this affects __has_feature(address_sanitizer) etc).
   Sanitize.clear();
   SanitizerBlacklistFiles.clear();
+  XRayAlwaysInstrumentFiles.clear();
+  XRayNeverInstrumentFiles.clear();
 
   CurrentModule.clear();
   IsHeaderFile = false;
diff --git a/lib/Basic/XRayLists.cpp b/lib/Basic/XRayLists.cpp
new file mode 100644 (file)
index 0000000..dccf3ba
--- /dev/null
@@ -0,0 +1,53 @@
+//===--- XRayFunctionFilter.cpp - XRay automatic-attribution --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// User-provided filters for always/never XRay instrumenting certain functions.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Basic/XRayLists.h"
+
+using namespace clang;
+
+XRayFunctionFilter::XRayFunctionFilter(
+    ArrayRef<std::string> AlwaysInstrumentPaths,
+    ArrayRef<std::string> NeverInstrumentPaths, SourceManager &SM)
+    : AlwaysInstrument(
+          llvm::SpecialCaseList::createOrDie(AlwaysInstrumentPaths)),
+      NeverInstrument(llvm::SpecialCaseList::createOrDie(NeverInstrumentPaths)),
+      SM(SM) {}
+
+XRayFunctionFilter::ImbueAttribute
+XRayFunctionFilter::shouldImbueFunction(StringRef FunctionName) const {
+  // First apply the always instrument list, than if it isn't an "always" see
+  // whether it's treated as a "never" instrument function.
+  if (AlwaysInstrument->inSection("fun", FunctionName))
+    return ImbueAttribute::ALWAYS;
+  if (NeverInstrument->inSection("fun", FunctionName))
+    return ImbueAttribute::NEVER;
+  return ImbueAttribute::NONE;
+}
+
+XRayFunctionFilter::ImbueAttribute
+XRayFunctionFilter::shouldImbueFunctionsInFile(StringRef Filename,
+                                               StringRef Category) const {
+  if (AlwaysInstrument->inSection("src", Filename, Category))
+    return ImbueAttribute::ALWAYS;
+  if (NeverInstrument->inSection("src", Filename, Category))
+    return ImbueAttribute::NEVER;
+  return ImbueAttribute::NONE;
+}
+
+XRayFunctionFilter::ImbueAttribute
+XRayFunctionFilter::shouldImbueLocation(SourceLocation Loc,
+                                        StringRef Category) const {
+  if (!Loc.isValid())
+    return ImbueAttribute::NONE;
+  return this->shouldImbueFunctionsInFile(SM.getFilename(SM.getFileLoc(Loc)),
+                                          Category);
+}
index 11660b4f41907e116a23da8fa6113fe65df2f4b4..79c0694f90285546f7877635e751dd1dd100a215 100644 (file)
@@ -786,9 +786,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
                       llvm::utostr(LogArgs->getArgumentCount()));
       }
     } else {
-      Fn->addFnAttr(
-          "xray-instruction-threshold",
-          llvm::itostr(CGM.getCodeGenOpts().XRayInstructionThreshold));
+      if (!CGM.imbueXRayAttrs(Fn, Loc))
+        Fn->addFnAttr(
+            "xray-instruction-threshold",
+            llvm::itostr(CGM.getCodeGenOpts().XRayInstructionThreshold));
     }
   }
 
index 89ee7fc74c391845cbc176b870b5c912fecc2e92..035165cdb9e0c53a03fc2126c51fb998ea474617 100644 (file)
@@ -1489,6 +1489,30 @@ bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV,
   return false;
 }
 
+bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc,
+                                   StringRef Category) const {
+  if (!LangOpts.XRayInstrument)
+    return false;
+  const auto &XRayFilter = getContext().getXRayFilter();
+  using ImbueAttr = XRayFunctionFilter::ImbueAttribute;
+  auto Attr = XRayFunctionFilter::ImbueAttribute::NONE;
+  if (Loc.isValid())
+    Attr = XRayFilter.shouldImbueLocation(Loc, Category);
+  if (Attr == ImbueAttr::NONE)
+    Attr = XRayFilter.shouldImbueFunction(Fn->getName());
+  switch (Attr) {
+  case ImbueAttr::NONE:
+    return false;
+  case ImbueAttr::ALWAYS:
+    Fn->addFnAttr("function-instrument", "xray-always");
+    break;
+  case ImbueAttr::NEVER:
+    Fn->addFnAttr("function-instrument", "xray-never");
+    break;
+  }
+  return true;
+}
+
 bool CodeGenModule::MustBeEmitted(const ValueDecl *Global) {
   // Never defer when EmitAllDecls is specified.
   if (LangOpts.EmitAllDecls)
index 5c9dd965e85ab45374d5f7c24d840fdfbfcc3932..ce8c58224c5398075006f8a881057c04be3a39e2 100644 (file)
@@ -28,6 +28,7 @@
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/Module.h"
 #include "clang/Basic/SanitizerBlacklist.h"
+#include "clang/Basic/XRayLists.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
@@ -1125,6 +1126,12 @@ public:
                               QualType Ty,
                               StringRef Category = StringRef()) const;
 
+  /// Imbue XRay attributes to a function, applying the always/never attribute
+  /// lists in the process. Returns true if we did imbue attributes this way,
+  /// false otherwise.
+  bool imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc,
+                      StringRef Category = StringRef()) const;
+
   SanitizerMetadata *getSanitizerMetadata() {
     return SanitizerMD.get();
   }
index 0d7a99766b86955aabacc04fbb5fa445edebe516..43d6aa8f99b8e7e096ca587510ad17e06f97e35f 100644 (file)
@@ -58,6 +58,7 @@ add_clang_library(clangDriver
   ToolChains/WebAssembly.cpp
   ToolChains/XCore.cpp
   Types.cpp
+  XRayArgs.cpp
 
   DEPENDS
   ClangDriverOptions
index f9dafb547533237f3e2bf6190a049b4bf7e9af90..4f82503276f4bda8d1585ada6c6a24ff36d1a073 100644 (file)
@@ -19,6 +19,7 @@
 #include "clang/Driver/DriverDiagnostic.h"
 #include "clang/Driver/Options.h"
 #include "clang/Driver/SanitizerArgs.h"
+#include "clang/Driver/XRayArgs.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
@@ -100,6 +101,12 @@ const SanitizerArgs& ToolChain::getSanitizerArgs() const {
   return *SanitizerArguments.get();
 }
 
+const XRayArgs& ToolChain::getXRayArgs() const {
+  if (!XRayArguments.get())
+    XRayArguments.reset(new XRayArgs(*this, Args));
+  return *XRayArguments.get();
+}
+
 namespace {
 struct DriverSuffix {
   const char *Suffix;
index 0511004b41b646d50aeb62043c8d0060a189b955..f8eeeb4eef69f5e6fc77631aa379320c4caa7ee1 100644 (file)
@@ -27,6 +27,7 @@
 #include "clang/Driver/DriverDiagnostic.h"
 #include "clang/Driver/Options.h"
 #include "clang/Driver/SanitizerArgs.h"
+#include "clang/Driver/XRayArgs.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/CodeGen.h"
@@ -2818,37 +2819,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
 
   Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
 
-  if (Args.hasFlag(options::OPT_fxray_instrument,
-                   options::OPT_fnoxray_instrument, false)) {
-    const char *const XRayInstrumentOption = "-fxray-instrument";
-    if (Triple.getOS() == llvm::Triple::Linux)
-      switch (Triple.getArch()) {
-      case llvm::Triple::x86_64:
-      case llvm::Triple::arm:
-      case llvm::Triple::aarch64:
-      case llvm::Triple::ppc64le:
-      case llvm::Triple::mips:
-      case llvm::Triple::mipsel:
-      case llvm::Triple::mips64:
-      case llvm::Triple::mips64el:
-        // Supported.
-        break;
-      default:
-        D.Diag(diag::err_drv_clang_unsupported)
-            << (std::string(XRayInstrumentOption) + " on " + Triple.str());
-      }
-    else
-      D.Diag(diag::err_drv_clang_unsupported)
-          << (std::string(XRayInstrumentOption) + " on non-Linux target OS");
-    CmdArgs.push_back(XRayInstrumentOption);
-    if (const Arg *A =
-            Args.getLastArg(options::OPT_fxray_instruction_threshold_,
-                            options::OPT_fxray_instruction_threshold_EQ)) {
-      CmdArgs.push_back("-fxray-instruction-threshold");
-      CmdArgs.push_back(A->getValue());
-    }
-  }
-
   addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs);
 
   // Add runtime flag for PS4 when PGO or Coverage are enabled.
@@ -3238,6 +3208,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();
   Sanitize.addArgs(getToolChain(), Args, CmdArgs, InputType);
 
+  const XRayArgs &XRay = getToolChain().getXRayArgs();
+  XRay.addArgs(getToolChain(), Args, CmdArgs, InputType);
+
   if (getToolChain().SupportsProfiling())
     Args.AddLastArg(CmdArgs, options::OPT_pg);
 
diff --git a/lib/Driver/XRayArgs.cpp b/lib/Driver/XRayArgs.cpp
new file mode 100644 (file)
index 0000000..59a35f1
--- /dev/null
@@ -0,0 +1,113 @@
+//===--- XRayArgs.cpp - Arguments for XRay --------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Driver/XRayArgs.h"
+#include "ToolChains/CommonArgs.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/SpecialCaseList.h"
+
+using namespace clang;
+using namespace clang::driver;
+using namespace llvm::opt;
+
+namespace {
+constexpr char XRayInstrumentOption[] = "-fxray-instrument";
+constexpr char XRayInstructionThresholdOption[] =
+    "-fxray-instruction-threshold=";
+constexpr char XRayAlwaysInstrumentOption[] = "-fxray-always-instrument=";
+constexpr char XRayNeverInstrumentOption[] = "-fxray-never-instrument=";
+} // namespace
+
+XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
+  const Driver &D = TC.getDriver();
+  const llvm::Triple &Triple = TC.getTriple();
+  if (Args.hasFlag(options::OPT_fxray_instrument,
+                   options::OPT_fnoxray_instrument, false)) {
+    if (Triple.getOS() == llvm::Triple::Linux)
+      switch (Triple.getArch()) {
+      case llvm::Triple::x86_64:
+      case llvm::Triple::arm:
+      case llvm::Triple::aarch64:
+      case llvm::Triple::ppc64le:
+      case llvm::Triple::mips:
+      case llvm::Triple::mipsel:
+      case llvm::Triple::mips64:
+      case llvm::Triple::mips64el:
+        break;
+      default:
+        D.Diag(diag::err_drv_clang_unsupported)
+            << (std::string(XRayInstrumentOption) + " on " + Triple.str());
+      }
+    else
+      D.Diag(diag::err_drv_clang_unsupported)
+          << (std::string(XRayInstrumentOption) + " on non-Linux target OS");
+    XRayInstrument = true;
+    if (const Arg *A =
+            Args.getLastArg(options::OPT_fxray_instruction_threshold_,
+                            options::OPT_fxray_instruction_threshold_EQ)) {
+      StringRef S = A->getValue();
+      if (S.getAsInteger(0, InstructionThreshold) || InstructionThreshold < 0)
+        D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
+    }
+
+    // Validate the always/never attribute files. We also make sure that they
+    // are treated as actual dependencies.
+    for (const auto &Filename :
+         Args.getAllArgValues(options::OPT_fxray_always_instrument)) {
+      if (llvm::sys::fs::exists(Filename)) {
+        AlwaysInstrumentFiles.push_back(Filename);
+        ExtraDeps.push_back(Filename);
+      } else
+        D.Diag(clang::diag::err_drv_no_such_file) << Filename;
+    }
+
+    for (const auto &Filename :
+         Args.getAllArgValues(options::OPT_fxray_never_instrument)) {
+      if (llvm::sys::fs::exists(Filename)) {
+        NeverInstrumentFiles.push_back(Filename);
+        ExtraDeps.push_back(Filename);
+      } else
+        D.Diag(clang::diag::err_drv_no_such_file) << Filename;
+    }
+  }
+}
+
+void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args,
+                       ArgStringList &CmdArgs, types::ID InputType) const {
+  if (!XRayInstrument)
+    return;
+
+  CmdArgs.push_back(XRayInstrumentOption);
+  CmdArgs.push_back(Args.MakeArgString(XRayInstructionThresholdOption +
+                                       std::to_string(InstructionThreshold)));
+
+  for (const auto &Always : AlwaysInstrumentFiles) {
+    SmallString<64> AlwaysInstrumentOpt(XRayAlwaysInstrumentOption);
+    AlwaysInstrumentOpt += Always;
+    CmdArgs.push_back(Args.MakeArgString(AlwaysInstrumentOpt));
+  }
+
+  for (const auto &Never : NeverInstrumentFiles) {
+    SmallString<64> NeverInstrumentOpt(XRayNeverInstrumentOption);
+    NeverInstrumentOpt += Never;
+    CmdArgs.push_back(Args.MakeArgString(NeverInstrumentOpt));
+  }
+
+  for (const auto &Dep : ExtraDeps) {
+    SmallString<64> ExtraDepOpt("-fdepfile-entry=");
+    ExtraDepOpt += Dep;
+    CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt));
+  }
+}
index 0c1d6d0d8543e9622ad9eb33f6c062c9d615c25a..bea29e2de7c395b9922bcbf03a954517b2b1cc1a 100644 (file)
@@ -2307,6 +2307,14 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
   Opts.SanitizeAddressFieldPadding =
       getLastArgIntValue(Args, OPT_fsanitize_address_field_padding, 0, Diags);
   Opts.SanitizerBlacklistFiles = Args.getAllArgValues(OPT_fsanitize_blacklist);
+
+  // -fxray-{always,never}-instrument= filenames.
+  Opts.XRayInstrument =
+      Args.hasFlag(OPT_fxray_instrument, OPT_fnoxray_instrument, false);
+  Opts.XRayAlwaysInstrumentFiles =
+      Args.getAllArgValues(OPT_fxray_always_instrument);
+  Opts.XRayNeverInstrumentFiles =
+      Args.getAllArgValues(OPT_fxray_never_instrument);
 }
 
 static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
diff --git a/test/CodeGen/xray-always-instrument.cpp b/test/CodeGen/xray-always-instrument.cpp
new file mode 100644 (file)
index 0000000..60d8595
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: echo "fun:*foo*" > %t.always-instrument
+// RUN: echo "src:*xray-always-instrument.cpp" >> %t.always-instrument
+// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 -fxray-always-instrument=%t.always-instrument -emit-llvm -o - %s -triple x86_64-unknown-linux-gnu | FileCheck %s
+
+void foo() {}
+
+[[clang::xray_never_instrument]] void bar() {}
+
+void baz() {}
+
+// CHECK: define void @_Z3foov() #[[ALWAYSATTR:[0-9]+]] {
+// CHECK: define void @_Z3barv() #[[NEVERATTR:[0-9]+]] {
+// CHECK: define void @_Z3bazv() #[[ALWAYSATTR:[0-9]+]] {
+// CHECK: attributes #[[ALWAYSATTR]] = {{.*}} "function-instrument"="xray-always" {{.*}}
+// CHECK: attributes #[[NEVERATTR]] = {{.*}} "function-instrument"="xray-never" {{.*}}