xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-remarkutil/RemarkCounter.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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.
groupByToStr(GroupBy GroupBy)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 out remarks based on remark properties based on name, pass name,
49 /// argument and type.
50 struct Filters {
51   std::optional<FilterMatcher> RemarkNameFilter;
52   std::optional<FilterMatcher> PassNameFilter;
53   std::optional<FilterMatcher> ArgFilter;
54   std::optional<Type> RemarkTypeFilter;
55 
56   /// Returns true if \p Remark satisfies all the provided filters.
57   bool filterRemark(const Remark &Remark);
58 };
59 
60 /// Abstract counter class used to define the general required methods for
61 /// counting a remark.
62 struct Counter {
63   GroupBy Group = GroupBy::TOTAL;
64   Counter() = default;
CounterCounter65   Counter(enum GroupBy GroupBy) : Group(GroupBy) {}
66   /// Obtain the field for collecting remark info based on how we are
67   /// collecting. Remarks are grouped by FunctionName, Source, Source and
68   /// Function or collect by file.
69   std::optional<std::string> getGroupByKey(const Remark &Remark);
70 
71   /// Collect count information from \p Remark organized based on \p Group
72   /// property.
73   virtual void collect(const Remark &) = 0;
74   /// Output the final count to the file \p OutputFileName
75   virtual Error print(StringRef OutputFileName) = 0;
76   virtual ~Counter() = default;
77 };
78 
79 /// Count remarks based on the provided \p Keys argument and summing up the
80 /// value for each matching key organized by source, function or reporting a
81 /// total for the specified remark file.
82 /// Reporting count grouped by source:
83 ///
84 ///  | source        | key1 | key2 | key3 |
85 ///  |---------------|------|------|------|
86 ///  | path/to/file1 | 0    | 1    | 3    |
87 ///  | path/to/file2 | 1    | 0    | 2    |
88 ///  | path/to/file3 | 2    | 3    | 1    |
89 ///
90 /// Reporting count grouped by function:
91 ///
92 ///  | Function      | key1 | key2 | key3 |
93 ///  |---------------|------|------|------|
94 ///  | function1     | 0    | 1    | 3    |
95 ///  | function2     | 1    | 0    | 2    |
96 ///  | function3     | 2    | 3    | 1    |
97 struct ArgumentCounter : Counter {
98   /// The internal object to keep the count for the remarks. The first argument
99   /// corresponds to the property we are collecting for this can be either a
100   /// source or function. The second argument is a row of integers where each
101   /// item in the row is the count for a specified key.
102   std::map<std::string, SmallVector<unsigned, 4>> CountByKeysMap;
103   /// A set of all the remark argument found in the remark file. The second
104   /// argument is the index of each of those arguments which can be used in
105   /// `CountByKeysMap` to fill count information for that argument.
106   MapVector<StringRef, unsigned> ArgumentSetIdxMap;
107   /// Create an argument counter. If the provided \p Arguments represent a regex
108   /// vector then we need to check that the provided regular expressions are
109   /// valid if not we return an Error.
110   static Expected<ArgumentCounter>
createArgumentCounterArgumentCounter111   createArgumentCounter(GroupBy Group, ArrayRef<FilterMatcher> Arguments,
112                         StringRef Buffer, Filters &Filter) {
113     ArgumentCounter AC;
114     AC.Group = Group;
115     if (auto E = AC.getAllMatchingArgumentsInRemark(Buffer, Arguments, Filter))
116       return std::move(E);
117     return AC;
118   }
119 
120   /// Update the internal count map based on the remark integer arguments that
121   /// correspond the the user specified argument keys to collect for.
122   void collect(const Remark &) override;
123 
124   /// Print a CSV table consisting of an index which is specified by \p
125   /// `Group` and can be a function name, source file name or function name
126   /// with the full source path and columns of user specified remark arguments
127   /// to collect the count for.
128   Error print(StringRef OutputFileName) override;
129 
130 private:
131   /// collect all the arguments that match the list of \p Arguments provided by
132   /// parsing through \p Buffer of remarks and filling \p ArgumentSetIdxMap
133   /// acting as a row for for all the keys that we are interested in collecting
134   /// information for.
135   Error getAllMatchingArgumentsInRemark(StringRef Buffer,
136                                         ArrayRef<FilterMatcher> Arguments,
137                                         Filters &Filter);
138 };
139 
140 /// Collect remarks based by counting the existance of individual remarks. The
141 /// reported table will be structured based on the provided \p Group argument
142 /// by reporting count for functions, source or total count for the provided
143 /// remark file.
144 struct RemarkCounter : Counter {
145   std::map<std::string, unsigned> CountedByRemarksMap;
RemarkCounterRemarkCounter146   RemarkCounter(GroupBy Group) : Counter(Group) {}
147 
148   /// Advance the internal map count broken by \p Group when
149   /// seeing \p Remark.
150   void collect(const Remark &) override;
151 
152   /// Print a CSV table consisting of an index which is specified by \p
153   /// `Group` and can be a function name, source file name or function name
154   /// with the full source path and a counts column corresponding to the count
155   /// of each individual remark at th index.
156   Error print(StringRef OutputFileName) override;
157 };
158 } // namespace remarks
159 
160 } // namespace llvm
161 #endif // TOOLS_LLVM_REMARKCOUNTER_H
162