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