Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/tools/llvm-remarkutil/RemarkCounter.h
35230 views
1
//===- RemarkCounter.h ----------------------------------------------------===//
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
// Generic tool to count remarks based on properties
10
//
11
//===----------------------------------------------------------------------===//
12
#ifndef TOOLS_LLVM_REMARKCOUNTER_H
13
#define TOOLS_LLVM_REMARKCOUNTER_H
14
#include "RemarkUtilHelpers.h"
15
#include "llvm/ADT/MapVector.h"
16
#include "llvm/Support/Regex.h"
17
18
namespace llvm {
19
namespace remarks {
20
21
/// Collect remarks by counting the existance of a remark or by looking through
22
/// the keys and summing through the total count.
23
enum class CountBy { REMARK, ARGUMENT };
24
25
/// Summarize the count by either emitting one count for the remark file, or
26
/// grouping the count by source file or by function name.
27
enum class GroupBy {
28
TOTAL,
29
PER_SOURCE,
30
PER_FUNCTION,
31
PER_FUNCTION_WITH_DEBUG_LOC
32
};
33
34
/// Convert \p GroupBy to a std::string.
35
inline std::string groupByToStr(GroupBy GroupBy) {
36
switch (GroupBy) {
37
default:
38
return "Total";
39
case GroupBy::PER_FUNCTION:
40
return "Function";
41
case GroupBy::PER_FUNCTION_WITH_DEBUG_LOC:
42
return "FuctionWithDebugLoc";
43
case GroupBy::PER_SOURCE:
44
return "Source";
45
}
46
}
47
48
/// Filter object which can be either a string or a regex to match with the
49
/// remark properties.
50
struct FilterMatcher {
51
Regex FilterRE;
52
std::string FilterStr;
53
bool IsRegex;
54
FilterMatcher(std::string Filter, bool IsRegex) : IsRegex(IsRegex) {
55
if (IsRegex)
56
FilterRE = Regex(Filter);
57
else
58
FilterStr = Filter;
59
}
60
61
bool match(StringRef StringToMatch) const {
62
if (IsRegex)
63
return FilterRE.match(StringToMatch);
64
return FilterStr == StringToMatch.trim().str();
65
}
66
};
67
68
/// Filter out remarks based on remark properties based on name, pass name,
69
/// argument and type.
70
struct Filters {
71
std::optional<FilterMatcher> RemarkNameFilter;
72
std::optional<FilterMatcher> PassNameFilter;
73
std::optional<FilterMatcher> ArgFilter;
74
std::optional<Type> RemarkTypeFilter;
75
/// Returns a filter object if all the arguments provided are valid regex
76
/// types otherwise return an error.
77
static Expected<Filters>
78
createRemarkFilter(std::optional<FilterMatcher> RemarkNameFilter,
79
std::optional<FilterMatcher> PassNameFilter,
80
std::optional<FilterMatcher> ArgFilter,
81
std::optional<Type> RemarkTypeFilter) {
82
Filters Filter;
83
Filter.RemarkNameFilter = std::move(RemarkNameFilter);
84
Filter.PassNameFilter = std::move(PassNameFilter);
85
Filter.ArgFilter = std::move(ArgFilter);
86
Filter.RemarkTypeFilter = std::move(RemarkTypeFilter);
87
if (auto E = Filter.regexArgumentsValid())
88
return std::move(E);
89
return std::move(Filter);
90
}
91
/// Returns true if \p Remark satisfies all the provided filters.
92
bool filterRemark(const Remark &Remark);
93
94
private:
95
/// Check if arguments can be parsed as valid regex types.
96
Error regexArgumentsValid();
97
};
98
99
/// Convert Regex string error to an error object.
100
inline Error checkRegex(const Regex &Regex) {
101
std::string Error;
102
if (!Regex.isValid(Error))
103
return createStringError(make_error_code(std::errc::invalid_argument),
104
Twine("Regex: ", Error));
105
return Error::success();
106
}
107
108
/// Abstract counter class used to define the general required methods for
109
/// counting a remark.
110
struct Counter {
111
GroupBy Group = GroupBy::TOTAL;
112
Counter() = default;
113
Counter(enum GroupBy GroupBy) : Group(GroupBy) {}
114
/// Obtain the field for collecting remark info based on how we are
115
/// collecting. Remarks are grouped by FunctionName, Source, Source and
116
/// Function or collect by file.
117
std::optional<std::string> getGroupByKey(const Remark &Remark);
118
119
/// Collect count information from \p Remark organized based on \p Group
120
/// property.
121
virtual void collect(const Remark &) = 0;
122
/// Output the final count to the file \p OutputFileName
123
virtual Error print(StringRef OutputFileName) = 0;
124
virtual ~Counter() = default;
125
};
126
127
/// Count remarks based on the provided \p Keys argument and summing up the
128
/// value for each matching key organized by source, function or reporting a
129
/// total for the specified remark file.
130
/// Reporting count grouped by source:
131
///
132
/// | source | key1 | key2 | key3 |
133
/// |---------------|------|------|------|
134
/// | path/to/file1 | 0 | 1 | 3 |
135
/// | path/to/file2 | 1 | 0 | 2 |
136
/// | path/to/file3 | 2 | 3 | 1 |
137
///
138
/// Reporting count grouped by function:
139
///
140
/// | Function | key1 | key2 | key3 |
141
/// |---------------|------|------|------|
142
/// | function1 | 0 | 1 | 3 |
143
/// | function2 | 1 | 0 | 2 |
144
/// | function3 | 2 | 3 | 1 |
145
struct ArgumentCounter : Counter {
146
/// The internal object to keep the count for the remarks. The first argument
147
/// corresponds to the property we are collecting for this can be either a
148
/// source or function. The second argument is a row of integers where each
149
/// item in the row is the count for a specified key.
150
std::map<std::string, SmallVector<unsigned, 4>> CountByKeysMap;
151
/// A set of all the remark argument found in the remark file. The second
152
/// argument is the index of each of those arguments which can be used in
153
/// `CountByKeysMap` to fill count information for that argument.
154
MapVector<StringRef, unsigned> ArgumentSetIdxMap;
155
/// Create an argument counter. If the provided \p Arguments represent a regex
156
/// vector then we need to check that the provided regular expressions are
157
/// valid if not we return an Error.
158
static Expected<ArgumentCounter>
159
createArgumentCounter(GroupBy Group, ArrayRef<FilterMatcher> Arguments,
160
StringRef Buffer, Filters &Filter) {
161
ArgumentCounter AC;
162
AC.Group = Group;
163
for (auto &Arg : Arguments) {
164
if (Arg.IsRegex) {
165
if (auto E = checkRegex(Arg.FilterRE))
166
return std::move(E);
167
}
168
}
169
if (auto E = AC.getAllMatchingArgumentsInRemark(Buffer, Arguments, Filter))
170
return std::move(E);
171
return AC;
172
}
173
174
/// Update the internal count map based on the remark integer arguments that
175
/// correspond the the user specified argument keys to collect for.
176
void collect(const Remark &) override;
177
178
/// Print a CSV table consisting of an index which is specified by \p
179
/// `Group` and can be a function name, source file name or function name
180
/// with the full source path and columns of user specified remark arguments
181
/// to collect the count for.
182
Error print(StringRef OutputFileName) override;
183
184
private:
185
/// collect all the arguments that match the list of \p Arguments provided by
186
/// parsing through \p Buffer of remarks and filling \p ArgumentSetIdxMap
187
/// acting as a row for for all the keys that we are interested in collecting
188
/// information for.
189
Error getAllMatchingArgumentsInRemark(StringRef Buffer,
190
ArrayRef<FilterMatcher> Arguments,
191
Filters &Filter);
192
};
193
194
/// Collect remarks based by counting the existance of individual remarks. The
195
/// reported table will be structured based on the provided \p Group argument
196
/// by reporting count for functions, source or total count for the provided
197
/// remark file.
198
struct RemarkCounter : Counter {
199
std::map<std::string, unsigned> CountedByRemarksMap;
200
RemarkCounter(GroupBy Group) : Counter(Group) {}
201
202
/// Advance the internal map count broken by \p Group when
203
/// seeing \p Remark.
204
void collect(const Remark &) override;
205
206
/// Print a CSV table consisting of an index which is specified by \p
207
/// `Group` and can be a function name, source file name or function name
208
/// with the full source path and a counts column corresponding to the count
209
/// of each individual remark at th index.
210
Error print(StringRef OutputFileName) override;
211
};
212
} // namespace remarks
213
214
} // namespace llvm
215
#endif // TOOLS_LLVM_REMARKCOUNTER_H
216
217