xref: /openbsd-src/gnu/llvm/clang/lib/Basic/ProfileList.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1a9ac8606Spatrick //===--- ProfileList.h - ProfileList filter ---------------------*- C++ -*-===//
2a9ac8606Spatrick //
3a9ac8606Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a9ac8606Spatrick // See https://llvm.org/LICENSE.txt for license information.
5a9ac8606Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a9ac8606Spatrick //
7a9ac8606Spatrick //===----------------------------------------------------------------------===//
8a9ac8606Spatrick //
9a9ac8606Spatrick // User-provided filters include/exclude profile instrumentation in certain
10a9ac8606Spatrick // functions or files.
11a9ac8606Spatrick //
12a9ac8606Spatrick //===----------------------------------------------------------------------===//
13a9ac8606Spatrick 
14a9ac8606Spatrick #include "clang/Basic/ProfileList.h"
15a9ac8606Spatrick #include "clang/Basic/FileManager.h"
16a9ac8606Spatrick #include "clang/Basic/SourceManager.h"
17a9ac8606Spatrick #include "llvm/Support/SpecialCaseList.h"
18a9ac8606Spatrick 
19a9ac8606Spatrick #include "llvm/Support/raw_ostream.h"
20*12c85518Srobert #include <optional>
21a9ac8606Spatrick 
22a9ac8606Spatrick using namespace clang;
23a9ac8606Spatrick 
24a9ac8606Spatrick namespace clang {
25a9ac8606Spatrick 
26a9ac8606Spatrick class ProfileSpecialCaseList : public llvm::SpecialCaseList {
27a9ac8606Spatrick public:
28a9ac8606Spatrick   static std::unique_ptr<ProfileSpecialCaseList>
29a9ac8606Spatrick   create(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &VFS,
30a9ac8606Spatrick          std::string &Error);
31a9ac8606Spatrick 
32a9ac8606Spatrick   static std::unique_ptr<ProfileSpecialCaseList>
33a9ac8606Spatrick   createOrDie(const std::vector<std::string> &Paths,
34a9ac8606Spatrick               llvm::vfs::FileSystem &VFS);
35a9ac8606Spatrick 
isEmpty() const36a9ac8606Spatrick   bool isEmpty() const { return Sections.empty(); }
37a9ac8606Spatrick 
hasPrefix(StringRef Prefix) const38a9ac8606Spatrick   bool hasPrefix(StringRef Prefix) const {
39a9ac8606Spatrick     for (auto &SectionIter : Sections)
40a9ac8606Spatrick       if (SectionIter.Entries.count(Prefix) > 0)
41a9ac8606Spatrick         return true;
42a9ac8606Spatrick     return false;
43a9ac8606Spatrick   }
44a9ac8606Spatrick };
45a9ac8606Spatrick 
46a9ac8606Spatrick std::unique_ptr<ProfileSpecialCaseList>
create(const std::vector<std::string> & Paths,llvm::vfs::FileSystem & VFS,std::string & Error)47a9ac8606Spatrick ProfileSpecialCaseList::create(const std::vector<std::string> &Paths,
48a9ac8606Spatrick                                llvm::vfs::FileSystem &VFS,
49a9ac8606Spatrick                                std::string &Error) {
50a9ac8606Spatrick   auto PSCL = std::make_unique<ProfileSpecialCaseList>();
51a9ac8606Spatrick   if (PSCL->createInternal(Paths, VFS, Error))
52a9ac8606Spatrick     return PSCL;
53a9ac8606Spatrick   return nullptr;
54a9ac8606Spatrick }
55a9ac8606Spatrick 
56a9ac8606Spatrick std::unique_ptr<ProfileSpecialCaseList>
createOrDie(const std::vector<std::string> & Paths,llvm::vfs::FileSystem & VFS)57a9ac8606Spatrick ProfileSpecialCaseList::createOrDie(const std::vector<std::string> &Paths,
58a9ac8606Spatrick                                     llvm::vfs::FileSystem &VFS) {
59a9ac8606Spatrick   std::string Error;
60a9ac8606Spatrick   if (auto PSCL = create(Paths, VFS, Error))
61a9ac8606Spatrick     return PSCL;
62*12c85518Srobert   llvm::report_fatal_error(llvm::Twine(Error));
63a9ac8606Spatrick }
64a9ac8606Spatrick 
65a9ac8606Spatrick }
66a9ac8606Spatrick 
ProfileList(ArrayRef<std::string> Paths,SourceManager & SM)67a9ac8606Spatrick ProfileList::ProfileList(ArrayRef<std::string> Paths, SourceManager &SM)
68a9ac8606Spatrick     : SCL(ProfileSpecialCaseList::createOrDie(
69a9ac8606Spatrick           Paths, SM.getFileManager().getVirtualFileSystem())),
70*12c85518Srobert       Empty(SCL->isEmpty()), SM(SM) {}
71a9ac8606Spatrick 
72a9ac8606Spatrick ProfileList::~ProfileList() = default;
73a9ac8606Spatrick 
getSectionName(CodeGenOptions::ProfileInstrKind Kind)74a9ac8606Spatrick static StringRef getSectionName(CodeGenOptions::ProfileInstrKind Kind) {
75a9ac8606Spatrick   switch (Kind) {
76a9ac8606Spatrick   case CodeGenOptions::ProfileNone:
77a9ac8606Spatrick     return "";
78a9ac8606Spatrick   case CodeGenOptions::ProfileClangInstr:
79a9ac8606Spatrick     return "clang";
80a9ac8606Spatrick   case CodeGenOptions::ProfileIRInstr:
81a9ac8606Spatrick     return "llvm";
82a9ac8606Spatrick   case CodeGenOptions::ProfileCSIRInstr:
83a9ac8606Spatrick     return "csllvm";
84a9ac8606Spatrick   }
85a9ac8606Spatrick   llvm_unreachable("Unhandled CodeGenOptions::ProfileInstrKind enum");
86a9ac8606Spatrick }
87a9ac8606Spatrick 
88*12c85518Srobert ProfileList::ExclusionType
getDefault(CodeGenOptions::ProfileInstrKind Kind) const89*12c85518Srobert ProfileList::getDefault(CodeGenOptions::ProfileInstrKind Kind) const {
90*12c85518Srobert   StringRef Section = getSectionName(Kind);
91*12c85518Srobert   // Check for "default:<type>"
92*12c85518Srobert   if (SCL->inSection(Section, "default", "allow"))
93*12c85518Srobert     return Allow;
94*12c85518Srobert   if (SCL->inSection(Section, "default", "skip"))
95*12c85518Srobert     return Skip;
96*12c85518Srobert   if (SCL->inSection(Section, "default", "forbid"))
97*12c85518Srobert     return Forbid;
98*12c85518Srobert   // If any cases use "fun" or "src", set the default to FORBID.
99*12c85518Srobert   if (SCL->hasPrefix("fun") || SCL->hasPrefix("src"))
100*12c85518Srobert     return Forbid;
101*12c85518Srobert   return Allow;
102*12c85518Srobert }
103*12c85518Srobert 
104*12c85518Srobert std::optional<ProfileList::ExclusionType>
inSection(StringRef Section,StringRef Prefix,StringRef Query) const105*12c85518Srobert ProfileList::inSection(StringRef Section, StringRef Prefix,
106*12c85518Srobert                        StringRef Query) const {
107*12c85518Srobert   if (SCL->inSection(Section, Prefix, Query, "allow"))
108*12c85518Srobert     return Allow;
109*12c85518Srobert   if (SCL->inSection(Section, Prefix, Query, "skip"))
110*12c85518Srobert     return Skip;
111*12c85518Srobert   if (SCL->inSection(Section, Prefix, Query, "forbid"))
112*12c85518Srobert     return Forbid;
113*12c85518Srobert   if (SCL->inSection(Section, Prefix, Query))
114*12c85518Srobert     return Allow;
115*12c85518Srobert   return std::nullopt;
116*12c85518Srobert }
117*12c85518Srobert 
118*12c85518Srobert std::optional<ProfileList::ExclusionType>
isFunctionExcluded(StringRef FunctionName,CodeGenOptions::ProfileInstrKind Kind) const119a9ac8606Spatrick ProfileList::isFunctionExcluded(StringRef FunctionName,
120a9ac8606Spatrick                                 CodeGenOptions::ProfileInstrKind Kind) const {
121a9ac8606Spatrick   StringRef Section = getSectionName(Kind);
122*12c85518Srobert   // Check for "function:<regex>=<case>"
123*12c85518Srobert   if (auto V = inSection(Section, "function", FunctionName))
124*12c85518Srobert     return V;
125a9ac8606Spatrick   if (SCL->inSection(Section, "!fun", FunctionName))
126*12c85518Srobert     return Forbid;
127a9ac8606Spatrick   if (SCL->inSection(Section, "fun", FunctionName))
128*12c85518Srobert     return Allow;
129*12c85518Srobert   return std::nullopt;
130a9ac8606Spatrick }
131a9ac8606Spatrick 
132*12c85518Srobert std::optional<ProfileList::ExclusionType>
isLocationExcluded(SourceLocation Loc,CodeGenOptions::ProfileInstrKind Kind) const133a9ac8606Spatrick ProfileList::isLocationExcluded(SourceLocation Loc,
134a9ac8606Spatrick                                 CodeGenOptions::ProfileInstrKind Kind) const {
135a9ac8606Spatrick   return isFileExcluded(SM.getFilename(SM.getFileLoc(Loc)), Kind);
136a9ac8606Spatrick }
137a9ac8606Spatrick 
138*12c85518Srobert std::optional<ProfileList::ExclusionType>
isFileExcluded(StringRef FileName,CodeGenOptions::ProfileInstrKind Kind) const139a9ac8606Spatrick ProfileList::isFileExcluded(StringRef FileName,
140a9ac8606Spatrick                             CodeGenOptions::ProfileInstrKind Kind) const {
141a9ac8606Spatrick   StringRef Section = getSectionName(Kind);
142*12c85518Srobert   // Check for "source:<regex>=<case>"
143*12c85518Srobert   if (auto V = inSection(Section, "source", FileName))
144*12c85518Srobert     return V;
145a9ac8606Spatrick   if (SCL->inSection(Section, "!src", FileName))
146*12c85518Srobert     return Forbid;
147a9ac8606Spatrick   if (SCL->inSection(Section, "src", FileName))
148*12c85518Srobert     return Allow;
149*12c85518Srobert   return std::nullopt;
150a9ac8606Spatrick }
151