151 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// User-provided filters include/exclude profile instrumentation in certain10// 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 <optional>20 21using namespace clang;22 23namespace clang {24 25class ProfileSpecialCaseList : public llvm::SpecialCaseList {26public:27 static std::unique_ptr<ProfileSpecialCaseList>28 create(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &VFS,29 std::string &Error);30 31 static std::unique_ptr<ProfileSpecialCaseList>32 createOrDie(const std::vector<std::string> &Paths,33 llvm::vfs::FileSystem &VFS);34 35 bool isEmpty() const { return sections().empty(); }36 37 bool hasPrefix(StringRef Prefix) const {38 for (const auto &It : sections())39 if (It.hasPrefix(Prefix))40 return true;41 return false;42 }43};44 45std::unique_ptr<ProfileSpecialCaseList>46ProfileSpecialCaseList::create(const std::vector<std::string> &Paths,47 llvm::vfs::FileSystem &VFS, std::string &Error) {48 auto PSCL = std::make_unique<ProfileSpecialCaseList>();49 if (PSCL->createInternal(Paths, VFS, Error))50 return PSCL;51 return nullptr;52}53 54std::unique_ptr<ProfileSpecialCaseList>55ProfileSpecialCaseList::createOrDie(const std::vector<std::string> &Paths,56 llvm::vfs::FileSystem &VFS) {57 std::string Error;58 if (auto PSCL = create(Paths, VFS, Error))59 return PSCL;60 llvm::report_fatal_error(llvm::Twine(Error));61}62 63} // namespace clang64 65ProfileList::ProfileList(ArrayRef<std::string> Paths, SourceManager &SM)66 : SCL(ProfileSpecialCaseList::createOrDie(67 Paths, SM.getFileManager().getVirtualFileSystem())),68 Empty(SCL->isEmpty()), SM(SM) {}69 70ProfileList::~ProfileList() = default;71 72static StringRef getSectionName(llvm::driver::ProfileInstrKind Kind) {73 switch (Kind) {74 case llvm::driver::ProfileInstrKind::ProfileNone:75 return "";76 case llvm::driver::ProfileInstrKind::ProfileClangInstr:77 return "clang";78 case llvm::driver::ProfileInstrKind::ProfileIRInstr:79 return "llvm";80 case llvm::driver::ProfileInstrKind::ProfileCSIRInstr:81 return "csllvm";82 case llvm::driver::ProfileInstrKind::ProfileIRSampleColdCov:83 return "sample-coldcov";84 }85 llvm_unreachable("Unhandled llvm::driver::ProfileInstrKind enum");86}87 88ProfileList::ExclusionType89ProfileList::getDefault(llvm::driver::ProfileInstrKind Kind) const {90 StringRef Section = getSectionName(Kind);91 // Check for "default:<type>"92 if (SCL->inSection(Section, "default", "allow"))93 return Allow;94 if (SCL->inSection(Section, "default", "skip"))95 return Skip;96 if (SCL->inSection(Section, "default", "forbid"))97 return Forbid;98 // If any cases use "fun" or "src", set the default to FORBID.99 if (SCL->hasPrefix("fun") || SCL->hasPrefix("src"))100 return Forbid;101 return Allow;102}103 104std::optional<ProfileList::ExclusionType>105ProfileList::inSection(StringRef Section, StringRef Prefix,106 StringRef Query) const {107 if (SCL->inSection(Section, Prefix, Query, "allow"))108 return Allow;109 if (SCL->inSection(Section, Prefix, Query, "skip"))110 return Skip;111 if (SCL->inSection(Section, Prefix, Query, "forbid"))112 return Forbid;113 if (SCL->inSection(Section, Prefix, Query))114 return Allow;115 return std::nullopt;116}117 118std::optional<ProfileList::ExclusionType>119ProfileList::isFunctionExcluded(StringRef FunctionName,120 llvm::driver::ProfileInstrKind Kind) const {121 StringRef Section = getSectionName(Kind);122 // Check for "function:<regex>=<case>"123 if (auto V = inSection(Section, "function", FunctionName))124 return V;125 if (SCL->inSection(Section, "!fun", FunctionName))126 return Forbid;127 if (SCL->inSection(Section, "fun", FunctionName))128 return Allow;129 return std::nullopt;130}131 132std::optional<ProfileList::ExclusionType>133ProfileList::isLocationExcluded(SourceLocation Loc,134 llvm::driver::ProfileInstrKind Kind) const {135 return isFileExcluded(SM.getFilename(SM.getFileLoc(Loc)), Kind);136}137 138std::optional<ProfileList::ExclusionType>139ProfileList::isFileExcluded(StringRef FileName,140 llvm::driver::ProfileInstrKind Kind) const {141 StringRef Section = getSectionName(Kind);142 // Check for "source:<regex>=<case>"143 if (auto V = inSection(Section, "source", FileName))144 return V;145 if (SCL->inSection(Section, "!src", FileName))146 return Forbid;147 if (SCL->inSection(Section, "src", FileName))148 return Allow;149 return std::nullopt;150}151