1*e8d8bef9SDimitry Andric //===--- ProfileList.h - ProfileList filter ---------------------*- C++ -*-===// 2*e8d8bef9SDimitry Andric // 3*e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*e8d8bef9SDimitry Andric // 7*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8*e8d8bef9SDimitry Andric // 9*e8d8bef9SDimitry Andric // User-provided filters include/exclude profile instrumentation in certain 10*e8d8bef9SDimitry Andric // functions or files. 11*e8d8bef9SDimitry Andric // 12*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 13*e8d8bef9SDimitry Andric 14*e8d8bef9SDimitry Andric #include "clang/Basic/ProfileList.h" 15*e8d8bef9SDimitry Andric #include "clang/Basic/FileManager.h" 16*e8d8bef9SDimitry Andric #include "clang/Basic/SourceManager.h" 17*e8d8bef9SDimitry Andric #include "llvm/Support/SpecialCaseList.h" 18*e8d8bef9SDimitry Andric 19*e8d8bef9SDimitry Andric #include "llvm/Support/raw_ostream.h" 20*e8d8bef9SDimitry Andric 21*e8d8bef9SDimitry Andric using namespace clang; 22*e8d8bef9SDimitry Andric 23*e8d8bef9SDimitry Andric namespace clang { 24*e8d8bef9SDimitry Andric 25*e8d8bef9SDimitry Andric class ProfileSpecialCaseList : public llvm::SpecialCaseList { 26*e8d8bef9SDimitry Andric public: 27*e8d8bef9SDimitry Andric static std::unique_ptr<ProfileSpecialCaseList> 28*e8d8bef9SDimitry Andric create(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &VFS, 29*e8d8bef9SDimitry Andric std::string &Error); 30*e8d8bef9SDimitry Andric 31*e8d8bef9SDimitry Andric static std::unique_ptr<ProfileSpecialCaseList> 32*e8d8bef9SDimitry Andric createOrDie(const std::vector<std::string> &Paths, 33*e8d8bef9SDimitry Andric llvm::vfs::FileSystem &VFS); 34*e8d8bef9SDimitry Andric 35*e8d8bef9SDimitry Andric bool isEmpty() const { return Sections.empty(); } 36*e8d8bef9SDimitry Andric 37*e8d8bef9SDimitry Andric bool hasPrefix(StringRef Prefix) const { 38*e8d8bef9SDimitry Andric for (auto &SectionIter : Sections) 39*e8d8bef9SDimitry Andric if (SectionIter.Entries.count(Prefix) > 0) 40*e8d8bef9SDimitry Andric return true; 41*e8d8bef9SDimitry Andric return false; 42*e8d8bef9SDimitry Andric } 43*e8d8bef9SDimitry Andric }; 44*e8d8bef9SDimitry Andric 45*e8d8bef9SDimitry Andric std::unique_ptr<ProfileSpecialCaseList> 46*e8d8bef9SDimitry Andric ProfileSpecialCaseList::create(const std::vector<std::string> &Paths, 47*e8d8bef9SDimitry Andric llvm::vfs::FileSystem &VFS, 48*e8d8bef9SDimitry Andric std::string &Error) { 49*e8d8bef9SDimitry Andric auto PSCL = std::make_unique<ProfileSpecialCaseList>(); 50*e8d8bef9SDimitry Andric if (PSCL->createInternal(Paths, VFS, Error)) 51*e8d8bef9SDimitry Andric return PSCL; 52*e8d8bef9SDimitry Andric return nullptr; 53*e8d8bef9SDimitry Andric } 54*e8d8bef9SDimitry Andric 55*e8d8bef9SDimitry Andric std::unique_ptr<ProfileSpecialCaseList> 56*e8d8bef9SDimitry Andric ProfileSpecialCaseList::createOrDie(const std::vector<std::string> &Paths, 57*e8d8bef9SDimitry Andric llvm::vfs::FileSystem &VFS) { 58*e8d8bef9SDimitry Andric std::string Error; 59*e8d8bef9SDimitry Andric if (auto PSCL = create(Paths, VFS, Error)) 60*e8d8bef9SDimitry Andric return PSCL; 61*e8d8bef9SDimitry Andric llvm::report_fatal_error(Error); 62*e8d8bef9SDimitry Andric } 63*e8d8bef9SDimitry Andric 64*e8d8bef9SDimitry Andric } 65*e8d8bef9SDimitry Andric 66*e8d8bef9SDimitry Andric ProfileList::ProfileList(ArrayRef<std::string> Paths, SourceManager &SM) 67*e8d8bef9SDimitry Andric : SCL(ProfileSpecialCaseList::createOrDie( 68*e8d8bef9SDimitry Andric Paths, SM.getFileManager().getVirtualFileSystem())), 69*e8d8bef9SDimitry Andric Empty(SCL->isEmpty()), 70*e8d8bef9SDimitry Andric Default(SCL->hasPrefix("fun") || SCL->hasPrefix("src")), SM(SM) {} 71*e8d8bef9SDimitry Andric 72*e8d8bef9SDimitry Andric ProfileList::~ProfileList() = default; 73*e8d8bef9SDimitry Andric 74*e8d8bef9SDimitry Andric static StringRef getSectionName(CodeGenOptions::ProfileInstrKind Kind) { 75*e8d8bef9SDimitry Andric switch (Kind) { 76*e8d8bef9SDimitry Andric case CodeGenOptions::ProfileNone: 77*e8d8bef9SDimitry Andric return ""; 78*e8d8bef9SDimitry Andric case CodeGenOptions::ProfileClangInstr: 79*e8d8bef9SDimitry Andric return "clang"; 80*e8d8bef9SDimitry Andric case CodeGenOptions::ProfileIRInstr: 81*e8d8bef9SDimitry Andric return "llvm"; 82*e8d8bef9SDimitry Andric case CodeGenOptions::ProfileCSIRInstr: 83*e8d8bef9SDimitry Andric return "csllvm"; 84*e8d8bef9SDimitry Andric } 85*e8d8bef9SDimitry Andric } 86*e8d8bef9SDimitry Andric 87*e8d8bef9SDimitry Andric llvm::Optional<bool> 88*e8d8bef9SDimitry Andric ProfileList::isFunctionExcluded(StringRef FunctionName, 89*e8d8bef9SDimitry Andric CodeGenOptions::ProfileInstrKind Kind) const { 90*e8d8bef9SDimitry Andric StringRef Section = getSectionName(Kind); 91*e8d8bef9SDimitry Andric if (SCL->inSection(Section, "!fun", FunctionName)) 92*e8d8bef9SDimitry Andric return true; 93*e8d8bef9SDimitry Andric if (SCL->inSection(Section, "fun", FunctionName)) 94*e8d8bef9SDimitry Andric return false; 95*e8d8bef9SDimitry Andric return None; 96*e8d8bef9SDimitry Andric } 97*e8d8bef9SDimitry Andric 98*e8d8bef9SDimitry Andric llvm::Optional<bool> 99*e8d8bef9SDimitry Andric ProfileList::isLocationExcluded(SourceLocation Loc, 100*e8d8bef9SDimitry Andric CodeGenOptions::ProfileInstrKind Kind) const { 101*e8d8bef9SDimitry Andric return isFileExcluded(SM.getFilename(SM.getFileLoc(Loc)), Kind); 102*e8d8bef9SDimitry Andric } 103*e8d8bef9SDimitry Andric 104*e8d8bef9SDimitry Andric llvm::Optional<bool> 105*e8d8bef9SDimitry Andric ProfileList::isFileExcluded(StringRef FileName, 106*e8d8bef9SDimitry Andric CodeGenOptions::ProfileInstrKind Kind) const { 107*e8d8bef9SDimitry Andric StringRef Section = getSectionName(Kind); 108*e8d8bef9SDimitry Andric if (SCL->inSection(Section, "!src", FileName)) 109*e8d8bef9SDimitry Andric return true; 110*e8d8bef9SDimitry Andric if (SCL->inSection(Section, "src", FileName)) 111*e8d8bef9SDimitry Andric return false; 112*e8d8bef9SDimitry Andric return None; 113*e8d8bef9SDimitry Andric } 114