1bb9eb198SPetr Hosek //===--- ProfileList.h - ProfileList filter ---------------------*- C++ -*-===//
2bb9eb198SPetr Hosek //
3bb9eb198SPetr Hosek // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bb9eb198SPetr Hosek // See https://llvm.org/LICENSE.txt for license information.
5bb9eb198SPetr Hosek // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bb9eb198SPetr Hosek //
7bb9eb198SPetr Hosek //===----------------------------------------------------------------------===//
8bb9eb198SPetr Hosek //
9bb9eb198SPetr Hosek // User-provided filters include/exclude profile instrumentation in certain
10bb9eb198SPetr Hosek // functions or files.
11bb9eb198SPetr Hosek //
12bb9eb198SPetr Hosek //===----------------------------------------------------------------------===//
13bb9eb198SPetr Hosek
14bb9eb198SPetr Hosek #include "clang/Basic/ProfileList.h"
15bb9eb198SPetr Hosek #include "clang/Basic/FileManager.h"
16bb9eb198SPetr Hosek #include "clang/Basic/SourceManager.h"
17bb9eb198SPetr Hosek #include "llvm/Support/SpecialCaseList.h"
18bb9eb198SPetr Hosek
19bb9eb198SPetr Hosek #include "llvm/Support/raw_ostream.h"
20a1580d7bSKazu Hirata #include <optional>
21bb9eb198SPetr Hosek
22bb9eb198SPetr Hosek using namespace clang;
23bb9eb198SPetr Hosek
24bb9eb198SPetr Hosek namespace clang {
25bb9eb198SPetr Hosek
26bb9eb198SPetr Hosek class ProfileSpecialCaseList : public llvm::SpecialCaseList {
27bb9eb198SPetr Hosek public:
28bb9eb198SPetr Hosek static std::unique_ptr<ProfileSpecialCaseList>
29bb9eb198SPetr Hosek create(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &VFS,
30bb9eb198SPetr Hosek std::string &Error);
31bb9eb198SPetr Hosek
32bb9eb198SPetr Hosek static std::unique_ptr<ProfileSpecialCaseList>
33bb9eb198SPetr Hosek createOrDie(const std::vector<std::string> &Paths,
34bb9eb198SPetr Hosek llvm::vfs::FileSystem &VFS);
35bb9eb198SPetr Hosek
isEmpty() const36bb9eb198SPetr Hosek bool isEmpty() const { return Sections.empty(); }
37bb9eb198SPetr Hosek
hasPrefix(StringRef Prefix) const38bb9eb198SPetr Hosek bool hasPrefix(StringRef Prefix) const {
39*8eb34700SEllis Hoag for (const auto &It : Sections)
40*8eb34700SEllis Hoag if (It.second.Entries.count(Prefix) > 0)
41bb9eb198SPetr Hosek return true;
42bb9eb198SPetr Hosek return false;
43bb9eb198SPetr Hosek }
44bb9eb198SPetr Hosek };
45bb9eb198SPetr Hosek
46bb9eb198SPetr Hosek std::unique_ptr<ProfileSpecialCaseList>
create(const std::vector<std::string> & Paths,llvm::vfs::FileSystem & VFS,std::string & Error)47bb9eb198SPetr Hosek ProfileSpecialCaseList::create(const std::vector<std::string> &Paths,
48bb9eb198SPetr Hosek llvm::vfs::FileSystem &VFS,
49bb9eb198SPetr Hosek std::string &Error) {
50bb9eb198SPetr Hosek auto PSCL = std::make_unique<ProfileSpecialCaseList>();
51bb9eb198SPetr Hosek if (PSCL->createInternal(Paths, VFS, Error))
52bb9eb198SPetr Hosek return PSCL;
53bb9eb198SPetr Hosek return nullptr;
54bb9eb198SPetr Hosek }
55bb9eb198SPetr Hosek
56bb9eb198SPetr Hosek std::unique_ptr<ProfileSpecialCaseList>
createOrDie(const std::vector<std::string> & Paths,llvm::vfs::FileSystem & VFS)57bb9eb198SPetr Hosek ProfileSpecialCaseList::createOrDie(const std::vector<std::string> &Paths,
58bb9eb198SPetr Hosek llvm::vfs::FileSystem &VFS) {
59bb9eb198SPetr Hosek std::string Error;
60bb9eb198SPetr Hosek if (auto PSCL = create(Paths, VFS, Error))
61bb9eb198SPetr Hosek return PSCL;
62b9b90bb5SSimon Pilgrim llvm::report_fatal_error(llvm::Twine(Error));
63bb9eb198SPetr Hosek }
64bb9eb198SPetr Hosek
65bb9eb198SPetr Hosek }
66bb9eb198SPetr Hosek
ProfileList(ArrayRef<std::string> Paths,SourceManager & SM)67bb9eb198SPetr Hosek ProfileList::ProfileList(ArrayRef<std::string> Paths, SourceManager &SM)
68bb9eb198SPetr Hosek : SCL(ProfileSpecialCaseList::createOrDie(
69bb9eb198SPetr Hosek Paths, SM.getFileManager().getVirtualFileSystem())),
706f4c3c0fSEllis Hoag Empty(SCL->isEmpty()), SM(SM) {}
71bb9eb198SPetr Hosek
72bb9eb198SPetr Hosek ProfileList::~ProfileList() = default;
73bb9eb198SPetr Hosek
getSectionName(CodeGenOptions::ProfileInstrKind Kind)74bb9eb198SPetr Hosek static StringRef getSectionName(CodeGenOptions::ProfileInstrKind Kind) {
75bb9eb198SPetr Hosek switch (Kind) {
76bb9eb198SPetr Hosek case CodeGenOptions::ProfileNone:
77bb9eb198SPetr Hosek return "";
78bb9eb198SPetr Hosek case CodeGenOptions::ProfileClangInstr:
79bb9eb198SPetr Hosek return "clang";
80bb9eb198SPetr Hosek case CodeGenOptions::ProfileIRInstr:
81bb9eb198SPetr Hosek return "llvm";
82bb9eb198SPetr Hosek case CodeGenOptions::ProfileCSIRInstr:
83bb9eb198SPetr Hosek return "csllvm";
84bb9eb198SPetr Hosek }
85da83b869SSimon Pilgrim llvm_unreachable("Unhandled CodeGenOptions::ProfileInstrKind enum");
86bb9eb198SPetr Hosek }
87bb9eb198SPetr Hosek
886f4c3c0fSEllis Hoag ProfileList::ExclusionType
getDefault(CodeGenOptions::ProfileInstrKind Kind) const896f4c3c0fSEllis Hoag ProfileList::getDefault(CodeGenOptions::ProfileInstrKind Kind) const {
90b692312cSEllis Hoag StringRef Section = getSectionName(Kind);
916f4c3c0fSEllis Hoag // Check for "default:<type>"
926f4c3c0fSEllis Hoag if (SCL->inSection(Section, "default", "allow"))
936f4c3c0fSEllis Hoag return Allow;
946f4c3c0fSEllis Hoag if (SCL->inSection(Section, "default", "skip"))
956f4c3c0fSEllis Hoag return Skip;
966f4c3c0fSEllis Hoag if (SCL->inSection(Section, "default", "forbid"))
976f4c3c0fSEllis Hoag return Forbid;
986f4c3c0fSEllis Hoag // If any cases use "fun" or "src", set the default to FORBID.
996f4c3c0fSEllis Hoag if (SCL->hasPrefix("fun") || SCL->hasPrefix("src"))
1006f4c3c0fSEllis Hoag return Forbid;
1016f4c3c0fSEllis Hoag return Allow;
1026f4c3c0fSEllis Hoag }
1036f4c3c0fSEllis Hoag
1046ad0788cSKazu Hirata std::optional<ProfileList::ExclusionType>
inSection(StringRef Section,StringRef Prefix,StringRef Query) const1056f4c3c0fSEllis Hoag ProfileList::inSection(StringRef Section, StringRef Prefix,
1066f4c3c0fSEllis Hoag StringRef Query) const {
1076f4c3c0fSEllis Hoag if (SCL->inSection(Section, Prefix, Query, "allow"))
1086f4c3c0fSEllis Hoag return Allow;
1096f4c3c0fSEllis Hoag if (SCL->inSection(Section, Prefix, Query, "skip"))
1106f4c3c0fSEllis Hoag return Skip;
1116f4c3c0fSEllis Hoag if (SCL->inSection(Section, Prefix, Query, "forbid"))
1126f4c3c0fSEllis Hoag return Forbid;
1136f4c3c0fSEllis Hoag if (SCL->inSection(Section, Prefix, Query))
1146f4c3c0fSEllis Hoag return Allow;
115eeee3feeSKazu Hirata return std::nullopt;
116b692312cSEllis Hoag }
117b692312cSEllis Hoag
1186ad0788cSKazu Hirata std::optional<ProfileList::ExclusionType>
isFunctionExcluded(StringRef FunctionName,CodeGenOptions::ProfileInstrKind Kind) const1196f4c3c0fSEllis Hoag ProfileList::isFunctionExcluded(StringRef FunctionName,
1206f4c3c0fSEllis Hoag CodeGenOptions::ProfileInstrKind Kind) const {
1216f4c3c0fSEllis Hoag StringRef Section = getSectionName(Kind);
1226f4c3c0fSEllis Hoag // Check for "function:<regex>=<case>"
1236f4c3c0fSEllis Hoag if (auto V = inSection(Section, "function", FunctionName))
1246f4c3c0fSEllis Hoag return V;
1256f4c3c0fSEllis Hoag if (SCL->inSection(Section, "!fun", FunctionName))
1266f4c3c0fSEllis Hoag return Forbid;
1276f4c3c0fSEllis Hoag if (SCL->inSection(Section, "fun", FunctionName))
1286f4c3c0fSEllis Hoag return Allow;
129eeee3feeSKazu Hirata return std::nullopt;
1306f4c3c0fSEllis Hoag }
1316f4c3c0fSEllis Hoag
1326ad0788cSKazu Hirata std::optional<ProfileList::ExclusionType>
isLocationExcluded(SourceLocation Loc,CodeGenOptions::ProfileInstrKind Kind) const133bb9eb198SPetr Hosek ProfileList::isLocationExcluded(SourceLocation Loc,
134bb9eb198SPetr Hosek CodeGenOptions::ProfileInstrKind Kind) const {
135bb9eb198SPetr Hosek return isFileExcluded(SM.getFilename(SM.getFileLoc(Loc)), Kind);
136bb9eb198SPetr Hosek }
137bb9eb198SPetr Hosek
1386ad0788cSKazu Hirata std::optional<ProfileList::ExclusionType>
isFileExcluded(StringRef FileName,CodeGenOptions::ProfileInstrKind Kind) const139bb9eb198SPetr Hosek ProfileList::isFileExcluded(StringRef FileName,
140bb9eb198SPetr Hosek CodeGenOptions::ProfileInstrKind Kind) const {
141bb9eb198SPetr Hosek StringRef Section = getSectionName(Kind);
1426f4c3c0fSEllis Hoag // Check for "source:<regex>=<case>"
1436f4c3c0fSEllis Hoag if (auto V = inSection(Section, "source", FileName))
1446f4c3c0fSEllis Hoag return V;
145bb9eb198SPetr Hosek if (SCL->inSection(Section, "!src", FileName))
1466f4c3c0fSEllis Hoag return Forbid;
147bb9eb198SPetr Hosek if (SCL->inSection(Section, "src", FileName))
1486f4c3c0fSEllis Hoag return Allow;
149eeee3feeSKazu Hirata return std::nullopt;
150bb9eb198SPetr Hosek }
151