ProfileList.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. //===--- ProfileList.h - ProfileList filter ---------------------*- C++ -*-===//
  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. //
  9. // User-provided filters include/exclude profile instrumentation in certain
  10. // functions or files.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/Basic/ProfileList.h"
  14. #include "clang/Basic/FileManager.h"
  15. #include "clang/Basic/SourceManager.h"
  16. #include "llvm/Support/SpecialCaseList.h"
  17. #include "llvm/Support/raw_ostream.h"
  18. #include <optional>
  19. using namespace clang;
  20. namespace clang {
  21. class ProfileSpecialCaseList : public llvm::SpecialCaseList {
  22. public:
  23. static std::unique_ptr<ProfileSpecialCaseList>
  24. create(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &VFS,
  25. std::string &Error);
  26. static std::unique_ptr<ProfileSpecialCaseList>
  27. createOrDie(const std::vector<std::string> &Paths,
  28. llvm::vfs::FileSystem &VFS);
  29. bool isEmpty() const { return Sections.empty(); }
  30. bool hasPrefix(StringRef Prefix) const {
  31. for (auto &SectionIter : Sections)
  32. if (SectionIter.Entries.count(Prefix) > 0)
  33. return true;
  34. return false;
  35. }
  36. };
  37. std::unique_ptr<ProfileSpecialCaseList>
  38. ProfileSpecialCaseList::create(const std::vector<std::string> &Paths,
  39. llvm::vfs::FileSystem &VFS,
  40. std::string &Error) {
  41. auto PSCL = std::make_unique<ProfileSpecialCaseList>();
  42. if (PSCL->createInternal(Paths, VFS, Error))
  43. return PSCL;
  44. return nullptr;
  45. }
  46. std::unique_ptr<ProfileSpecialCaseList>
  47. ProfileSpecialCaseList::createOrDie(const std::vector<std::string> &Paths,
  48. llvm::vfs::FileSystem &VFS) {
  49. std::string Error;
  50. if (auto PSCL = create(Paths, VFS, Error))
  51. return PSCL;
  52. llvm::report_fatal_error(llvm::Twine(Error));
  53. }
  54. }
  55. ProfileList::ProfileList(ArrayRef<std::string> Paths, SourceManager &SM)
  56. : SCL(ProfileSpecialCaseList::createOrDie(
  57. Paths, SM.getFileManager().getVirtualFileSystem())),
  58. Empty(SCL->isEmpty()), SM(SM) {}
  59. ProfileList::~ProfileList() = default;
  60. static StringRef getSectionName(CodeGenOptions::ProfileInstrKind Kind) {
  61. switch (Kind) {
  62. case CodeGenOptions::ProfileNone:
  63. return "";
  64. case CodeGenOptions::ProfileClangInstr:
  65. return "clang";
  66. case CodeGenOptions::ProfileIRInstr:
  67. return "llvm";
  68. case CodeGenOptions::ProfileCSIRInstr:
  69. return "csllvm";
  70. }
  71. llvm_unreachable("Unhandled CodeGenOptions::ProfileInstrKind enum");
  72. }
  73. ProfileList::ExclusionType
  74. ProfileList::getDefault(CodeGenOptions::ProfileInstrKind Kind) const {
  75. StringRef Section = getSectionName(Kind);
  76. // Check for "default:<type>"
  77. if (SCL->inSection(Section, "default", "allow"))
  78. return Allow;
  79. if (SCL->inSection(Section, "default", "skip"))
  80. return Skip;
  81. if (SCL->inSection(Section, "default", "forbid"))
  82. return Forbid;
  83. // If any cases use "fun" or "src", set the default to FORBID.
  84. if (SCL->hasPrefix("fun") || SCL->hasPrefix("src"))
  85. return Forbid;
  86. return Allow;
  87. }
  88. std::optional<ProfileList::ExclusionType>
  89. ProfileList::inSection(StringRef Section, StringRef Prefix,
  90. StringRef Query) const {
  91. if (SCL->inSection(Section, Prefix, Query, "allow"))
  92. return Allow;
  93. if (SCL->inSection(Section, Prefix, Query, "skip"))
  94. return Skip;
  95. if (SCL->inSection(Section, Prefix, Query, "forbid"))
  96. return Forbid;
  97. if (SCL->inSection(Section, Prefix, Query))
  98. return Allow;
  99. return std::nullopt;
  100. }
  101. std::optional<ProfileList::ExclusionType>
  102. ProfileList::isFunctionExcluded(StringRef FunctionName,
  103. CodeGenOptions::ProfileInstrKind Kind) const {
  104. StringRef Section = getSectionName(Kind);
  105. // Check for "function:<regex>=<case>"
  106. if (auto V = inSection(Section, "function", FunctionName))
  107. return V;
  108. if (SCL->inSection(Section, "!fun", FunctionName))
  109. return Forbid;
  110. if (SCL->inSection(Section, "fun", FunctionName))
  111. return Allow;
  112. return std::nullopt;
  113. }
  114. std::optional<ProfileList::ExclusionType>
  115. ProfileList::isLocationExcluded(SourceLocation Loc,
  116. CodeGenOptions::ProfileInstrKind Kind) const {
  117. return isFileExcluded(SM.getFilename(SM.getFileLoc(Loc)), Kind);
  118. }
  119. std::optional<ProfileList::ExclusionType>
  120. ProfileList::isFileExcluded(StringRef FileName,
  121. CodeGenOptions::ProfileInstrKind Kind) const {
  122. StringRef Section = getSectionName(Kind);
  123. // Check for "source:<regex>=<case>"
  124. if (auto V = inSection(Section, "source", FileName))
  125. return V;
  126. if (SCL->inSection(Section, "!src", FileName))
  127. return Forbid;
  128. if (SCL->inSection(Section, "src", FileName))
  129. return Allow;
  130. return std::nullopt;
  131. }