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