1195098Sed//===--- ProfileList.h - ProfileList filter ---------------------*- C++ -*-===// 2195098Sed// 3195098Sed// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4195098Sed// See https://llvm.org/LICENSE.txt for license information. 5195098Sed// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6195098Sed// 7195098Sed//===----------------------------------------------------------------------===// 8195098Sed// 9195098Sed// User-provided filters include/exclude profile instrumentation in certain 10195098Sed// functions or files. 11198090Srdivacky// 12198090Srdivacky//===----------------------------------------------------------------------===// 13195098Sed 14198090Srdivacky#include "clang/Basic/ProfileList.h" 15218893Sdim#include "clang/Basic/FileManager.h" 16195340Sed#include "clang/Basic/SourceManager.h" 17198090Srdivacky#include "llvm/Support/SpecialCaseList.h" 18226633Sdim 19226633Sdim#include "llvm/Support/raw_ostream.h" 20226633Sdim#include <optional> 21198090Srdivacky 22195098Sedusing namespace clang; 23226633Sdim 24205407Srdivackynamespace clang { 25202878Srdivacky 26224145Sdimclass ProfileSpecialCaseList : public llvm::SpecialCaseList { 27202878Srdivackypublic: 28198090Srdivacky static std::unique_ptr<ProfileSpecialCaseList> 29198090Srdivacky create(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &VFS, 30198090Srdivacky std::string &Error); 31202878Srdivacky 32234353Sdim static std::unique_ptr<ProfileSpecialCaseList> 33218893Sdim createOrDie(const std::vector<std::string> &Paths, 34195098Sed llvm::vfs::FileSystem &VFS); 35195098Sed 36195098Sed bool isEmpty() const { return Sections.empty(); } 37195098Sed 38198090Srdivacky bool hasPrefix(StringRef Prefix) const { 39224145Sdim for (auto &SectionIter : Sections) 40202878Srdivacky if (SectionIter.Entries.count(Prefix) > 0) 41198090Srdivacky return true; 42224145Sdim return false; 43205407Srdivacky } 44212904Sdim}; 45226633Sdim 46218893Sdimstd::unique_ptr<ProfileSpecialCaseList> 47202878SrdivackyProfileSpecialCaseList::create(const std::vector<std::string> &Paths, 48202878Srdivacky llvm::vfs::FileSystem &VFS, 49203954Srdivacky std::string &Error) { 50203954Srdivacky auto PSCL = std::make_unique<ProfileSpecialCaseList>(); 51203954Srdivacky if (PSCL->createInternal(Paths, VFS, Error)) 52218893Sdim return PSCL; 53221345Sdim return nullptr; 54234353Sdim} 55203954Srdivacky 56221345Sdimstd::unique_ptr<ProfileSpecialCaseList> 57221345SdimProfileSpecialCaseList::createOrDie(const std::vector<std::string> &Paths, 58221345Sdim llvm::vfs::FileSystem &VFS) { 59221345Sdim std::string Error; 60221345Sdim if (auto PSCL = create(Paths, VFS, Error)) 61218893Sdim return PSCL; 62218893Sdim llvm::report_fatal_error(llvm::Twine(Error)); 63223017Sdim} 64234353Sdim 65234353Sdim} 66223017Sdim 67198090SrdivackyProfileList::ProfileList(ArrayRef<std::string> Paths, SourceManager &SM) 68202878Srdivacky : SCL(ProfileSpecialCaseList::createOrDie( 69221345Sdim Paths, SM.getFileManager().getVirtualFileSystem())), 70234353Sdim Empty(SCL->isEmpty()), SM(SM) {} 71218893Sdim 72226633SdimProfileList::~ProfileList() = default; 73218893Sdim 74205218Srdivackystatic StringRef getSectionName(CodeGenOptions::ProfileInstrKind Kind) { 75218893Sdim switch (Kind) { 76218893Sdim case CodeGenOptions::ProfileNone: 77234353Sdim return ""; 78234353Sdim case CodeGenOptions::ProfileClangInstr: 79203954Srdivacky return "clang"; 80203954Srdivacky case CodeGenOptions::ProfileIRInstr: 81203954Srdivacky return "llvm"; 82198090Srdivacky case CodeGenOptions::ProfileCSIRInstr: 83195098Sed return "csllvm"; 84202878Srdivacky } 85202878Srdivacky llvm_unreachable("Unhandled CodeGenOptions::ProfileInstrKind enum"); 86202878Srdivacky} 87202878Srdivacky 88202878SrdivackyProfileList::ExclusionType 89202878SrdivackyProfileList::getDefault(CodeGenOptions::ProfileInstrKind Kind) const { 90202878Srdivacky StringRef Section = getSectionName(Kind); 91202878Srdivacky // Check for "default:<type>" 92202878Srdivacky if (SCL->inSection(Section, "default", "allow")) 93203954Srdivacky return Allow; 94203954Srdivacky if (SCL->inSection(Section, "default", "skip")) 95203954Srdivacky return Skip; 96203954Srdivacky if (SCL->inSection(Section, "default", "forbid")) 97218893Sdim return Forbid; 98206274Srdivacky // If any cases use "fun" or "src", set the default to FORBID. 99206274Srdivacky if (SCL->hasPrefix("fun") || SCL->hasPrefix("src")) 100203954Srdivacky return Forbid; 101202878Srdivacky return Allow; 102202878Srdivacky} 103202878Srdivacky 104202878Srdivackystd::optional<ProfileList::ExclusionType> 105202878SrdivackyProfileList::inSection(StringRef Section, StringRef Prefix, 106203954Srdivacky StringRef Query) const { 107203954Srdivacky if (SCL->inSection(Section, Prefix, Query, "allow")) 108203954Srdivacky return Allow; 109203954Srdivacky if (SCL->inSection(Section, Prefix, Query, "skip")) 110202878Srdivacky return Skip; 111202878Srdivacky if (SCL->inSection(Section, Prefix, Query, "forbid")) 112202878Srdivacky return Forbid; 113202878Srdivacky if (SCL->inSection(Section, Prefix, Query)) 114202878Srdivacky return Allow; 115202878Srdivacky return std::nullopt; 116202878Srdivacky} 117202878Srdivacky 118203954Srdivackystd::optional<ProfileList::ExclusionType> 119202878SrdivackyProfileList::isFunctionExcluded(StringRef FunctionName, 120202878Srdivacky CodeGenOptions::ProfileInstrKind Kind) const { 121202878Srdivacky StringRef Section = getSectionName(Kind); 122202878Srdivacky // Check for "function:<regex>=<case>" 123203954Srdivacky if (auto V = inSection(Section, "function", FunctionName)) 124198090Srdivacky return V; 125198090Srdivacky if (SCL->inSection(Section, "!fun", FunctionName)) 126195098Sed return Forbid; 127218893Sdim if (SCL->inSection(Section, "fun", FunctionName)) 128195098Sed return Allow; 129218893Sdim return std::nullopt; 130218893Sdim} 131218893Sdim 132218893Sdimstd::optional<ProfileList::ExclusionType> 133218893SdimProfileList::isLocationExcluded(SourceLocation Loc, 134218893Sdim CodeGenOptions::ProfileInstrKind Kind) const { 135218893Sdim return isFileExcluded(SM.getFilename(SM.getFileLoc(Loc)), Kind); 136218893Sdim} 137198090Srdivacky 138221345Sdimstd::optional<ProfileList::ExclusionType> 139221345SdimProfileList::isFileExcluded(StringRef FileName, 140202878Srdivacky CodeGenOptions::ProfileInstrKind Kind) const { 141239462Sdim StringRef Section = getSectionName(Kind); 142218893Sdim // Check for "source:<regex>=<case>" 143195098Sed if (auto V = inSection(Section, "source", FileName)) 144198090Srdivacky return V; 145218893Sdim if (SCL->inSection(Section, "!src", FileName)) 146218893Sdim return Forbid; 147218893Sdim if (SCL->inSection(Section, "src", FileName)) 148224145Sdim return Allow; 149224145Sdim return std::nullopt; 150221345Sdim} 151221345Sdim