1 //===--- ProfileList.h - ProfileList filter ---------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // User-provided filters include/exclude profile instrumentation in certain
10 // functions or files.
12 //===----------------------------------------------------------------------===//
14 #include "clang/Basic/ProfileList.h"
15 #include "clang/Basic/FileManager.h"
16 #include "clang/Basic/SourceManager.h"
17 #include "llvm/Support/SpecialCaseList.h"
19 #include "llvm/Support/raw_ostream.h"
22 using namespace clang
;
26 class ProfileSpecialCaseList
: public llvm::SpecialCaseList
{
28 static std::unique_ptr
<ProfileSpecialCaseList
>
29 create(const std::vector
<std::string
> &Paths
, llvm::vfs::FileSystem
&VFS
,
32 static std::unique_ptr
<ProfileSpecialCaseList
>
33 createOrDie(const std::vector
<std::string
> &Paths
,
34 llvm::vfs::FileSystem
&VFS
);
36 bool isEmpty() const { return Sections
.empty(); }
38 bool hasPrefix(StringRef Prefix
) const {
39 for (auto &SectionIter
: Sections
)
40 if (SectionIter
.Entries
.count(Prefix
) > 0)
46 std::unique_ptr
<ProfileSpecialCaseList
>
47 ProfileSpecialCaseList::create(const std::vector
<std::string
> &Paths
,
48 llvm::vfs::FileSystem
&VFS
,
50 auto PSCL
= std::make_unique
<ProfileSpecialCaseList
>();
51 if (PSCL
->createInternal(Paths
, VFS
, Error
))
56 std::unique_ptr
<ProfileSpecialCaseList
>
57 ProfileSpecialCaseList::createOrDie(const std::vector
<std::string
> &Paths
,
58 llvm::vfs::FileSystem
&VFS
) {
60 if (auto PSCL
= create(Paths
, VFS
, Error
))
62 llvm::report_fatal_error(llvm::Twine(Error
));
67 ProfileList::ProfileList(ArrayRef
<std::string
> Paths
, SourceManager
&SM
)
68 : SCL(ProfileSpecialCaseList::createOrDie(
69 Paths
, SM
.getFileManager().getVirtualFileSystem())),
70 Empty(SCL
->isEmpty()), SM(SM
) {}
72 ProfileList::~ProfileList() = default;
74 static StringRef
getSectionName(CodeGenOptions::ProfileInstrKind Kind
) {
76 case CodeGenOptions::ProfileNone
:
78 case CodeGenOptions::ProfileClangInstr
:
80 case CodeGenOptions::ProfileIRInstr
:
82 case CodeGenOptions::ProfileCSIRInstr
:
85 llvm_unreachable("Unhandled CodeGenOptions::ProfileInstrKind enum");
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"))
94 if (SCL
->inSection(Section
, "default", "skip"))
96 if (SCL
->inSection(Section
, "default", "forbid"))
98 // If any cases use "fun" or "src", set the default to FORBID.
99 if (SCL
->hasPrefix("fun") || SCL
->hasPrefix("src"))
104 std::optional
<ProfileList::ExclusionType
>
105 ProfileList::inSection(StringRef Section
, StringRef Prefix
,
106 StringRef Query
) const {
107 if (SCL
->inSection(Section
, Prefix
, Query
, "allow"))
109 if (SCL
->inSection(Section
, Prefix
, Query
, "skip"))
111 if (SCL
->inSection(Section
, Prefix
, Query
, "forbid"))
113 if (SCL
->inSection(Section
, Prefix
, Query
))
118 std::optional
<ProfileList::ExclusionType
>
119 ProfileList::isFunctionExcluded(StringRef FunctionName
,
120 CodeGenOptions::ProfileInstrKind Kind
) const {
121 StringRef Section
= getSectionName(Kind
);
122 // Check for "function:<regex>=<case>"
123 if (auto V
= inSection(Section
, "function", FunctionName
))
125 if (SCL
->inSection(Section
, "!fun", FunctionName
))
127 if (SCL
->inSection(Section
, "fun", FunctionName
))
132 std::optional
<ProfileList::ExclusionType
>
133 ProfileList::isLocationExcluded(SourceLocation Loc
,
134 CodeGenOptions::ProfileInstrKind Kind
) const {
135 return isFileExcluded(SM
.getFilename(SM
.getFileLoc(Loc
)), Kind
);
138 std::optional
<ProfileList::ExclusionType
>
139 ProfileList::isFileExcluded(StringRef FileName
,
140 CodeGenOptions::ProfileInstrKind Kind
) const {
141 StringRef Section
= getSectionName(Kind
);
142 // Check for "source:<regex>=<case>"
143 if (auto V
= inSection(Section
, "source", FileName
))
145 if (SCL
->inSection(Section
, "!src", FileName
))
147 if (SCL
->inSection(Section
, "src", FileName
))