Coverage Report

Created: 2024-01-17 10:31

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