151 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// Generic tool to count remarks based on properties10//11//===----------------------------------------------------------------------===//12#ifndef TOOLS_LLVM_REMARKCOUNTER_H13#define TOOLS_LLVM_REMARKCOUNTER_H14#include "RemarkUtilHelpers.h"15#include "llvm/ADT/MapVector.h"16#include "llvm/Support/Regex.h"17#include <map>18 19namespace llvm {20namespace remarks {21 22/// Collect remarks by counting the existance of a remark or by looking through23/// the keys and summing through the total count.24enum class CountBy { REMARK, ARGUMENT };25 26/// Summarize the count by either emitting one count for the remark file, or27/// grouping the count by source file or by function name.28enum class GroupBy {29 TOTAL,30 PER_SOURCE,31 PER_FUNCTION,32 PER_FUNCTION_WITH_DEBUG_LOC33};34 35/// Convert \p GroupBy to a std::string.36inline std::string groupByToStr(GroupBy GroupBy) {37 switch (GroupBy) {38 default:39 return "Total";40 case GroupBy::PER_FUNCTION:41 return "Function";42 case GroupBy::PER_FUNCTION_WITH_DEBUG_LOC:43 return "FuctionWithDebugLoc";44 case GroupBy::PER_SOURCE:45 return "Source";46 }47}48 49/// Abstract counter class used to define the general required methods for50/// counting a remark.51struct Counter {52 GroupBy Group = GroupBy::TOTAL;53 Counter() = default;54 Counter(enum GroupBy GroupBy) : Group(GroupBy) {}55 /// Obtain the field for collecting remark info based on how we are56 /// collecting. Remarks are grouped by FunctionName, Source, Source and57 /// Function or collect by file.58 std::optional<std::string> getGroupByKey(const Remark &Remark);59 60 /// Collect count information from \p Remark organized based on \p Group61 /// property.62 virtual void collect(const Remark &) = 0;63 /// Output the final count to the file \p OutputFileName64 virtual Error print(StringRef OutputFileName) = 0;65 virtual ~Counter() = default;66};67 68/// Count remarks based on the provided \p Keys argument and summing up the69/// value for each matching key organized by source, function or reporting a70/// total for the specified remark file.71/// Reporting count grouped by source:72///73/// | source | key1 | key2 | key3 |74/// |---------------|------|------|------|75/// | path/to/file1 | 0 | 1 | 3 |76/// | path/to/file2 | 1 | 0 | 2 |77/// | path/to/file3 | 2 | 3 | 1 |78///79/// Reporting count grouped by function:80///81/// | Function | key1 | key2 | key3 |82/// |---------------|------|------|------|83/// | function1 | 0 | 1 | 3 |84/// | function2 | 1 | 0 | 2 |85/// | function3 | 2 | 3 | 1 |86struct ArgumentCounter : Counter {87 /// The internal object to keep the count for the remarks. The first argument88 /// corresponds to the property we are collecting for this can be either a89 /// source or function. The second argument is a row of integers where each90 /// item in the row is the count for a specified key.91 std::map<std::string, SmallVector<unsigned, 4>> CountByKeysMap;92 /// A set of all the remark argument found in the remark file. The second93 /// argument is the index of each of those arguments which can be used in94 /// `CountByKeysMap` to fill count information for that argument.95 MapVector<StringRef, unsigned> ArgumentSetIdxMap;96 /// Create an argument counter. If the provided \p Arguments represent a regex97 /// vector then we need to check that the provided regular expressions are98 /// valid if not we return an Error.99 static Expected<ArgumentCounter>100 createArgumentCounter(GroupBy Group, ArrayRef<FilterMatcher> Arguments,101 StringRef Buffer, Filters &Filter) {102 ArgumentCounter AC;103 AC.Group = Group;104 if (auto E = AC.getAllMatchingArgumentsInRemark(Buffer, Arguments, Filter))105 return std::move(E);106 return AC;107 }108 109 /// Update the internal count map based on the remark integer arguments that110 /// correspond the the user specified argument keys to collect for.111 void collect(const Remark &) override;112 113 /// Print a CSV table consisting of an index which is specified by \p114 /// `Group` and can be a function name, source file name or function name115 /// with the full source path and columns of user specified remark arguments116 /// to collect the count for.117 Error print(StringRef OutputFileName) override;118 119private:120 /// collect all the arguments that match the list of \p Arguments provided by121 /// parsing through \p Buffer of remarks and filling \p ArgumentSetIdxMap122 /// acting as a row for for all the keys that we are interested in collecting123 /// information for.124 Error getAllMatchingArgumentsInRemark(StringRef Buffer,125 ArrayRef<FilterMatcher> Arguments,126 Filters &Filter);127};128 129/// Collect remarks based by counting the existance of individual remarks. The130/// reported table will be structured based on the provided \p Group argument131/// by reporting count for functions, source or total count for the provided132/// remark file.133struct RemarkCounter : Counter {134 std::map<std::string, unsigned> CountedByRemarksMap;135 RemarkCounter(GroupBy Group) : Counter(Group) {}136 137 /// Advance the internal map count broken by \p Group when138 /// seeing \p Remark.139 void collect(const Remark &) override;140 141 /// Print a CSV table consisting of an index which is specified by \p142 /// `Group` and can be a function name, source file name or function name143 /// with the full source path and a counts column corresponding to the count144 /// of each individual remark at th index.145 Error print(StringRef OutputFileName) override;146};147} // namespace remarks148 149} // namespace llvm150#endif // TOOLS_LLVM_REMARKCOUNTER_H151