131c2cf11SZain Jaffal //===- RemarkCounter.cpp --------------------------------------------------===// 231c2cf11SZain Jaffal // 331c2cf11SZain Jaffal // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 431c2cf11SZain Jaffal // See https://llvm.org/LICENSE.txt for license information. 531c2cf11SZain Jaffal // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 631c2cf11SZain Jaffal // 731c2cf11SZain Jaffal //===----------------------------------------------------------------------===// 831c2cf11SZain Jaffal // 931c2cf11SZain Jaffal // Generic tool to count remarks based on properties 1031c2cf11SZain Jaffal // 1131c2cf11SZain Jaffal //===----------------------------------------------------------------------===// 1231c2cf11SZain Jaffal 1331c2cf11SZain Jaffal #include "RemarkCounter.h" 1431c2cf11SZain Jaffal #include "RemarkUtilRegistry.h" 1531c2cf11SZain Jaffal #include "llvm/Support/CommandLine.h" 1631c2cf11SZain Jaffal #include "llvm/Support/Regex.h" 1731c2cf11SZain Jaffal 1831c2cf11SZain Jaffal using namespace llvm; 1931c2cf11SZain Jaffal using namespace remarks; 2031c2cf11SZain Jaffal using namespace llvm::remarkutil; 2131c2cf11SZain Jaffal 2231c2cf11SZain Jaffal static cl::SubCommand CountSub("count", 2331c2cf11SZain Jaffal "Collect remarks based on specified criteria."); 2431c2cf11SZain Jaffal 2531c2cf11SZain Jaffal INPUT_FORMAT_COMMAND_LINE_OPTIONS(CountSub) 2631c2cf11SZain Jaffal INPUT_OUTPUT_COMMAND_LINE_OPTIONS(CountSub) 2731c2cf11SZain Jaffal 2831c2cf11SZain Jaffal static cl::list<std::string> 2931c2cf11SZain Jaffal Keys("args", cl::desc("Specify remark argument/s to count by."), 3031c2cf11SZain Jaffal cl::value_desc("arguments"), cl::sub(CountSub), cl::ValueOptional); 3131c2cf11SZain Jaffal static cl::list<std::string> RKeys( 3231c2cf11SZain Jaffal "rargs", 3331c2cf11SZain Jaffal cl::desc( 3431c2cf11SZain Jaffal "Specify remark argument/s to count (accepts regular expressions)."), 3531c2cf11SZain Jaffal cl::value_desc("arguments"), cl::sub(CountSub), cl::ValueOptional); 3631c2cf11SZain Jaffal static cl::opt<std::string> 3731c2cf11SZain Jaffal RemarkNameOpt("remark-name", 3831c2cf11SZain Jaffal cl::desc("Optional remark name to filter collection by."), 3931c2cf11SZain Jaffal cl::ValueOptional, cl::sub(CountSub)); 4031c2cf11SZain Jaffal static cl::opt<std::string> 4131c2cf11SZain Jaffal PassNameOpt("pass-name", cl::ValueOptional, 4231c2cf11SZain Jaffal cl::desc("Optional remark pass name to filter collection by."), 4331c2cf11SZain Jaffal cl::sub(CountSub)); 4431c2cf11SZain Jaffal 4531c2cf11SZain Jaffal static cl::opt<std::string> RemarkFilterArgByOpt( 4631c2cf11SZain Jaffal "filter-arg-by", cl::desc("Optional remark arg to filter collection by."), 4731c2cf11SZain Jaffal cl::ValueOptional, cl::sub(CountSub)); 4831c2cf11SZain Jaffal static cl::opt<std::string> 4931c2cf11SZain Jaffal RemarkNameOptRE("rremark-name", 5031c2cf11SZain Jaffal cl::desc("Optional remark name to filter collection by " 5131c2cf11SZain Jaffal "(accepts regular expressions)."), 5231c2cf11SZain Jaffal cl::ValueOptional, cl::sub(CountSub)); 5331c2cf11SZain Jaffal static cl::opt<std::string> 5431c2cf11SZain Jaffal RemarkArgFilterOptRE("rfilter-arg-by", 5531c2cf11SZain Jaffal cl::desc("Optional remark arg to filter collection by " 5631c2cf11SZain Jaffal "(accepts regular expressions)."), 5731c2cf11SZain Jaffal cl::sub(CountSub), cl::ValueOptional); 5831c2cf11SZain Jaffal static cl::opt<std::string> 5931c2cf11SZain Jaffal PassNameOptRE("rpass-name", cl::ValueOptional, 6031c2cf11SZain Jaffal cl::desc("Optional remark pass name to filter collection " 6131c2cf11SZain Jaffal "by (accepts regular expressions)."), 6231c2cf11SZain Jaffal cl::sub(CountSub)); 6331c2cf11SZain Jaffal static cl::opt<Type> RemarkTypeOpt( 6431c2cf11SZain Jaffal "remark-type", cl::desc("Optional remark type to filter collection by."), 6531c2cf11SZain Jaffal cl::values(clEnumValN(Type::Unknown, "unknown", "UNKOWN"), 6631c2cf11SZain Jaffal clEnumValN(Type::Passed, "passed", "PASSED"), 6731c2cf11SZain Jaffal clEnumValN(Type::Missed, "missed", "MISSED"), 6831c2cf11SZain Jaffal clEnumValN(Type::Analysis, "analysis", "ANALYSIS"), 6931c2cf11SZain Jaffal clEnumValN(Type::AnalysisFPCommute, "analysis-fp-commute", 7031c2cf11SZain Jaffal "ANALYSIS_FP_COMMUTE"), 7131c2cf11SZain Jaffal clEnumValN(Type::AnalysisAliasing, "analysis-aliasing", 7231c2cf11SZain Jaffal "ANALYSIS_ALIASING"), 7331c2cf11SZain Jaffal clEnumValN(Type::Failure, "failure", "FAILURE")), 7431c2cf11SZain Jaffal cl::init(Type::Failure), cl::sub(CountSub)); 7531c2cf11SZain Jaffal static cl::opt<CountBy> CountByOpt( 7631c2cf11SZain Jaffal "count-by", cl::desc("Specify the property to collect remarks by."), 7731c2cf11SZain Jaffal cl::values( 7831c2cf11SZain Jaffal clEnumValN(CountBy::REMARK, "remark-name", 7931c2cf11SZain Jaffal "Counts individual remarks based on how many of the remark " 8031c2cf11SZain Jaffal "exists."), 8131c2cf11SZain Jaffal clEnumValN(CountBy::ARGUMENT, "arg", 8231c2cf11SZain Jaffal "Counts based on the value each specified argument has. The " 8331c2cf11SZain Jaffal "argument has to have a number value to be considered.")), 8431c2cf11SZain Jaffal cl::init(CountBy::REMARK), cl::sub(CountSub)); 8531c2cf11SZain Jaffal static cl::opt<GroupBy> GroupByOpt( 8631c2cf11SZain Jaffal "group-by", cl::desc("Specify the property to group remarks by."), 8731c2cf11SZain Jaffal cl::values( 8831c2cf11SZain Jaffal clEnumValN( 8931c2cf11SZain Jaffal GroupBy::PER_SOURCE, "source", 9031c2cf11SZain Jaffal "Display the count broken down by the filepath of each remark " 9131c2cf11SZain Jaffal "emitted. Requires remarks to have DebugLoc information."), 9231c2cf11SZain Jaffal clEnumValN(GroupBy::PER_FUNCTION, "function", 9331c2cf11SZain Jaffal "Breakdown the count by function name."), 9431c2cf11SZain Jaffal clEnumValN( 9531c2cf11SZain Jaffal GroupBy::PER_FUNCTION_WITH_DEBUG_LOC, "function-with-loc", 9631c2cf11SZain Jaffal "Breakdown the count by function name taking into consideration " 9731c2cf11SZain Jaffal "the filepath info from the DebugLoc of the remark."), 9831c2cf11SZain Jaffal clEnumValN(GroupBy::TOTAL, "total", 9931c2cf11SZain Jaffal "Output the total number corresponding to the count for the " 10031c2cf11SZain Jaffal "provided input file.")), 10131c2cf11SZain Jaffal cl::init(GroupBy::PER_SOURCE), cl::sub(CountSub)); 10231c2cf11SZain Jaffal 10331c2cf11SZain Jaffal /// Look for matching argument with \p Key in \p Remark and return the parsed 10431c2cf11SZain Jaffal /// integer value or 0 if it is has no integer value. 10531c2cf11SZain Jaffal static unsigned getValForKey(StringRef Key, const Remark &Remark) { 10631c2cf11SZain Jaffal auto *RemarkArg = find_if(Remark.Args, [&Key](const Argument &Arg) { 10731c2cf11SZain Jaffal return Arg.Key == Key && Arg.isValInt(); 10831c2cf11SZain Jaffal }); 10931c2cf11SZain Jaffal if (RemarkArg == Remark.Args.end()) 11031c2cf11SZain Jaffal return 0; 11131c2cf11SZain Jaffal return *RemarkArg->getValAsInt(); 11231c2cf11SZain Jaffal } 11331c2cf11SZain Jaffal 11431c2cf11SZain Jaffal Error Filters::regexArgumentsValid() { 11531c2cf11SZain Jaffal if (RemarkNameFilter && RemarkNameFilter->IsRegex) 11631c2cf11SZain Jaffal if (auto E = checkRegex(RemarkNameFilter->FilterRE)) 11731c2cf11SZain Jaffal return E; 11831c2cf11SZain Jaffal if (PassNameFilter && PassNameFilter->IsRegex) 11931c2cf11SZain Jaffal if (auto E = checkRegex(PassNameFilter->FilterRE)) 12031c2cf11SZain Jaffal return E; 12131c2cf11SZain Jaffal if (ArgFilter && ArgFilter->IsRegex) 12231c2cf11SZain Jaffal if (auto E = checkRegex(ArgFilter->FilterRE)) 12331c2cf11SZain Jaffal return E; 12431c2cf11SZain Jaffal return Error::success(); 12531c2cf11SZain Jaffal } 12631c2cf11SZain Jaffal 12731c2cf11SZain Jaffal bool Filters::filterRemark(const Remark &Remark) { 12831c2cf11SZain Jaffal if (RemarkNameFilter && !RemarkNameFilter->match(Remark.RemarkName)) 12931c2cf11SZain Jaffal return false; 13031c2cf11SZain Jaffal if (PassNameFilter && !PassNameFilter->match(Remark.PassName)) 13131c2cf11SZain Jaffal return false; 13231c2cf11SZain Jaffal if (RemarkTypeFilter) 13331c2cf11SZain Jaffal return *RemarkTypeFilter == Remark.RemarkType; 13431c2cf11SZain Jaffal if (ArgFilter) { 13531c2cf11SZain Jaffal if (!any_of(Remark.Args, 13631c2cf11SZain Jaffal [this](Argument Arg) { return ArgFilter->match(Arg.Val); })) 13731c2cf11SZain Jaffal return false; 13831c2cf11SZain Jaffal } 13931c2cf11SZain Jaffal return true; 14031c2cf11SZain Jaffal } 14131c2cf11SZain Jaffal 14231c2cf11SZain Jaffal Error ArgumentCounter::getAllMatchingArgumentsInRemark( 14331c2cf11SZain Jaffal StringRef Buffer, ArrayRef<FilterMatcher> Arguments, Filters &Filter) { 14431c2cf11SZain Jaffal auto MaybeParser = createRemarkParser(InputFormat, Buffer); 14531c2cf11SZain Jaffal if (!MaybeParser) 14631c2cf11SZain Jaffal return MaybeParser.takeError(); 14731c2cf11SZain Jaffal auto &Parser = **MaybeParser; 14831c2cf11SZain Jaffal auto MaybeRemark = Parser.next(); 14931c2cf11SZain Jaffal for (; MaybeRemark; MaybeRemark = Parser.next()) { 15031c2cf11SZain Jaffal auto &Remark = **MaybeRemark; 15131c2cf11SZain Jaffal // Only collect keys from remarks included in the filter. 15231c2cf11SZain Jaffal if (!Filter.filterRemark(Remark)) 15331c2cf11SZain Jaffal continue; 15431c2cf11SZain Jaffal for (auto &Key : Arguments) { 15531c2cf11SZain Jaffal for (Argument Arg : Remark.Args) 15631c2cf11SZain Jaffal if (Key.match(Arg.Key) && Arg.isValInt()) 15731c2cf11SZain Jaffal ArgumentSetIdxMap.insert({Arg.Key, ArgumentSetIdxMap.size()}); 15831c2cf11SZain Jaffal } 15931c2cf11SZain Jaffal } 16031c2cf11SZain Jaffal 16131c2cf11SZain Jaffal auto E = MaybeRemark.takeError(); 16231c2cf11SZain Jaffal if (!E.isA<EndOfFileError>()) 16331c2cf11SZain Jaffal return E; 16431c2cf11SZain Jaffal consumeError(std::move(E)); 16531c2cf11SZain Jaffal return Error::success(); 16631c2cf11SZain Jaffal } 16731c2cf11SZain Jaffal 16831c2cf11SZain Jaffal std::optional<std::string> Counter::getGroupByKey(const Remark &Remark) { 1690603737aSFangrui Song switch (Group) { 17031c2cf11SZain Jaffal case GroupBy::PER_FUNCTION: 17131c2cf11SZain Jaffal return Remark.FunctionName.str(); 17231c2cf11SZain Jaffal case GroupBy::TOTAL: 17331c2cf11SZain Jaffal return "Total"; 17431c2cf11SZain Jaffal case GroupBy::PER_SOURCE: 17531c2cf11SZain Jaffal case GroupBy::PER_FUNCTION_WITH_DEBUG_LOC: 17631c2cf11SZain Jaffal if (!Remark.Loc.has_value()) 17731c2cf11SZain Jaffal return std::nullopt; 17831c2cf11SZain Jaffal 1790603737aSFangrui Song if (Group == GroupBy::PER_FUNCTION_WITH_DEBUG_LOC) 18031c2cf11SZain Jaffal return Remark.Loc->SourceFilePath.str() + ":" + Remark.FunctionName.str(); 18131c2cf11SZain Jaffal return Remark.Loc->SourceFilePath.str(); 18231c2cf11SZain Jaffal } 1834f469450SMartin Storsjö llvm_unreachable("Fully covered switch above!"); 18431c2cf11SZain Jaffal } 18531c2cf11SZain Jaffal 18631c2cf11SZain Jaffal void ArgumentCounter::collect(const Remark &Remark) { 18731c2cf11SZain Jaffal SmallVector<unsigned, 4> Row(ArgumentSetIdxMap.size()); 18831c2cf11SZain Jaffal std::optional<std::string> GroupByKey = getGroupByKey(Remark); 18931c2cf11SZain Jaffal // Early return if we don't have a value 19031c2cf11SZain Jaffal if (!GroupByKey) 19131c2cf11SZain Jaffal return; 19231c2cf11SZain Jaffal auto GroupVal = *GroupByKey; 19331c2cf11SZain Jaffal CountByKeysMap.insert({GroupVal, Row}); 19431c2cf11SZain Jaffal for (auto [Key, Idx] : ArgumentSetIdxMap) { 19531c2cf11SZain Jaffal auto Count = getValForKey(Key, Remark); 19631c2cf11SZain Jaffal CountByKeysMap[GroupVal][Idx] += Count; 19731c2cf11SZain Jaffal } 19831c2cf11SZain Jaffal } 19931c2cf11SZain Jaffal 20031c2cf11SZain Jaffal void RemarkCounter::collect(const Remark &Remark) { 201*1ad3180bSKazu Hirata if (std::optional<std::string> Key = getGroupByKey(Remark)) 202*1ad3180bSKazu Hirata ++CountedByRemarksMap[*Key]; 20331c2cf11SZain Jaffal } 20431c2cf11SZain Jaffal 20531c2cf11SZain Jaffal Error ArgumentCounter::print(StringRef OutputFileName) { 20631c2cf11SZain Jaffal auto MaybeOF = 20731c2cf11SZain Jaffal getOutputFileWithFlags(OutputFileName, sys::fs::OF_TextWithCRLF); 20831c2cf11SZain Jaffal if (!MaybeOF) 20931c2cf11SZain Jaffal return MaybeOF.takeError(); 21031c2cf11SZain Jaffal 21131c2cf11SZain Jaffal auto OF = std::move(*MaybeOF); 2120603737aSFangrui Song OF->os() << groupByToStr(Group) << ","; 21331c2cf11SZain Jaffal unsigned Idx = 0; 21431c2cf11SZain Jaffal for (auto [Key, _] : ArgumentSetIdxMap) { 21531c2cf11SZain Jaffal OF->os() << Key; 21631c2cf11SZain Jaffal if (Idx != ArgumentSetIdxMap.size() - 1) 21731c2cf11SZain Jaffal OF->os() << ","; 21831c2cf11SZain Jaffal Idx++; 21931c2cf11SZain Jaffal } 22031c2cf11SZain Jaffal OF->os() << "\n"; 22131c2cf11SZain Jaffal for (auto [Header, CountVector] : CountByKeysMap) { 22231c2cf11SZain Jaffal OF->os() << Header << ","; 22331c2cf11SZain Jaffal unsigned Idx = 0; 22431c2cf11SZain Jaffal for (auto Count : CountVector) { 22531c2cf11SZain Jaffal OF->os() << Count; 22631c2cf11SZain Jaffal if (Idx != ArgumentSetIdxMap.size() - 1) 22731c2cf11SZain Jaffal OF->os() << ","; 22831c2cf11SZain Jaffal Idx++; 22931c2cf11SZain Jaffal } 23031c2cf11SZain Jaffal OF->os() << "\n"; 23131c2cf11SZain Jaffal } 23231c2cf11SZain Jaffal return Error::success(); 23331c2cf11SZain Jaffal } 23431c2cf11SZain Jaffal 23531c2cf11SZain Jaffal Error RemarkCounter::print(StringRef OutputFileName) { 23631c2cf11SZain Jaffal auto MaybeOF = 23731c2cf11SZain Jaffal getOutputFileWithFlags(OutputFileName, sys::fs::OF_TextWithCRLF); 23831c2cf11SZain Jaffal if (!MaybeOF) 23931c2cf11SZain Jaffal return MaybeOF.takeError(); 24031c2cf11SZain Jaffal 24131c2cf11SZain Jaffal auto OF = std::move(*MaybeOF); 2420603737aSFangrui Song OF->os() << groupByToStr(Group) << "," 24331c2cf11SZain Jaffal << "Count\n"; 24431c2cf11SZain Jaffal for (auto [Key, Count] : CountedByRemarksMap) 24531c2cf11SZain Jaffal OF->os() << Key << "," << Count << "\n"; 24631c2cf11SZain Jaffal OF->keep(); 24731c2cf11SZain Jaffal return Error::success(); 24831c2cf11SZain Jaffal } 24931c2cf11SZain Jaffal 25031c2cf11SZain Jaffal Expected<Filters> getRemarkFilter() { 25131c2cf11SZain Jaffal // Create Filter properties. 25231c2cf11SZain Jaffal std::optional<FilterMatcher> RemarkNameFilter; 25331c2cf11SZain Jaffal std::optional<FilterMatcher> PassNameFilter; 25431c2cf11SZain Jaffal std::optional<FilterMatcher> RemarkArgFilter; 25531c2cf11SZain Jaffal std::optional<Type> RemarkType; 25631c2cf11SZain Jaffal if (!RemarkNameOpt.empty()) 25731c2cf11SZain Jaffal RemarkNameFilter = {RemarkNameOpt, false}; 25831c2cf11SZain Jaffal else if (!RemarkNameOptRE.empty()) 25931c2cf11SZain Jaffal RemarkNameFilter = {RemarkNameOptRE, true}; 26031c2cf11SZain Jaffal if (!PassNameOpt.empty()) 26131c2cf11SZain Jaffal PassNameFilter = {PassNameOpt, false}; 26231c2cf11SZain Jaffal else if (!PassNameOptRE.empty()) 26331c2cf11SZain Jaffal PassNameFilter = {PassNameOptRE, true}; 26431c2cf11SZain Jaffal if (RemarkTypeOpt != Type::Failure) 26531c2cf11SZain Jaffal RemarkType = RemarkTypeOpt; 26631c2cf11SZain Jaffal if (!RemarkFilterArgByOpt.empty()) 26731c2cf11SZain Jaffal RemarkArgFilter = {RemarkFilterArgByOpt, false}; 26831c2cf11SZain Jaffal else if (!RemarkArgFilterOptRE.empty()) 26931c2cf11SZain Jaffal RemarkArgFilter = {RemarkArgFilterOptRE, true}; 27031c2cf11SZain Jaffal // Create RemarkFilter. 27131c2cf11SZain Jaffal return Filters::createRemarkFilter(std::move(RemarkNameFilter), 27231c2cf11SZain Jaffal std::move(PassNameFilter), 27331c2cf11SZain Jaffal std::move(RemarkArgFilter), RemarkType); 27431c2cf11SZain Jaffal } 27531c2cf11SZain Jaffal 27631c2cf11SZain Jaffal Error useCollectRemark(StringRef Buffer, Counter &Counter, Filters &Filter) { 27731c2cf11SZain Jaffal // Create Parser. 27831c2cf11SZain Jaffal auto MaybeParser = createRemarkParser(InputFormat, Buffer); 27931c2cf11SZain Jaffal if (!MaybeParser) 28031c2cf11SZain Jaffal return MaybeParser.takeError(); 28131c2cf11SZain Jaffal auto &Parser = **MaybeParser; 28231c2cf11SZain Jaffal auto MaybeRemark = Parser.next(); 28331c2cf11SZain Jaffal for (; MaybeRemark; MaybeRemark = Parser.next()) { 28431c2cf11SZain Jaffal const Remark &Remark = **MaybeRemark; 28531c2cf11SZain Jaffal if (Filter.filterRemark(Remark)) 28631c2cf11SZain Jaffal Counter.collect(Remark); 28731c2cf11SZain Jaffal } 28831c2cf11SZain Jaffal 28931c2cf11SZain Jaffal if (auto E = Counter.print(OutputFileName)) 29031c2cf11SZain Jaffal return E; 29131c2cf11SZain Jaffal auto E = MaybeRemark.takeError(); 29231c2cf11SZain Jaffal if (!E.isA<EndOfFileError>()) 29331c2cf11SZain Jaffal return E; 29431c2cf11SZain Jaffal consumeError(std::move(E)); 29531c2cf11SZain Jaffal return Error::success(); 29631c2cf11SZain Jaffal } 29731c2cf11SZain Jaffal 29831c2cf11SZain Jaffal static Error collectRemarks() { 29931c2cf11SZain Jaffal // Create a parser for the user-specified input format. 30031c2cf11SZain Jaffal auto MaybeBuf = getInputMemoryBuffer(InputFileName); 30131c2cf11SZain Jaffal if (!MaybeBuf) 30231c2cf11SZain Jaffal return MaybeBuf.takeError(); 30331c2cf11SZain Jaffal StringRef Buffer = (*MaybeBuf)->getBuffer(); 30431c2cf11SZain Jaffal auto MaybeFilter = getRemarkFilter(); 30531c2cf11SZain Jaffal if (!MaybeFilter) 30631c2cf11SZain Jaffal return MaybeFilter.takeError(); 30731c2cf11SZain Jaffal auto &Filter = *MaybeFilter; 30831c2cf11SZain Jaffal if (CountByOpt == CountBy::REMARK) { 30931c2cf11SZain Jaffal RemarkCounter RC(GroupByOpt); 31031c2cf11SZain Jaffal if (auto E = useCollectRemark(Buffer, RC, Filter)) 31131c2cf11SZain Jaffal return E; 31231c2cf11SZain Jaffal } else if (CountByOpt == CountBy::ARGUMENT) { 31331c2cf11SZain Jaffal SmallVector<FilterMatcher, 4> ArgumentsVector; 31431c2cf11SZain Jaffal if (!Keys.empty()) { 31531c2cf11SZain Jaffal for (auto &Key : Keys) 31631c2cf11SZain Jaffal ArgumentsVector.push_back({Key, false}); 31731c2cf11SZain Jaffal } else if (!RKeys.empty()) 31831c2cf11SZain Jaffal for (auto Key : RKeys) 31931c2cf11SZain Jaffal ArgumentsVector.push_back({Key, true}); 32031c2cf11SZain Jaffal else 32131c2cf11SZain Jaffal ArgumentsVector.push_back({".*", true}); 32231c2cf11SZain Jaffal 32331c2cf11SZain Jaffal Expected<ArgumentCounter> AC = ArgumentCounter::createArgumentCounter( 32431c2cf11SZain Jaffal GroupByOpt, ArgumentsVector, Buffer, Filter); 32531c2cf11SZain Jaffal if (!AC) 32631c2cf11SZain Jaffal return AC.takeError(); 32731c2cf11SZain Jaffal if (auto E = useCollectRemark(Buffer, *AC, Filter)) 32831c2cf11SZain Jaffal return E; 32931c2cf11SZain Jaffal } 33031c2cf11SZain Jaffal return Error::success(); 33131c2cf11SZain Jaffal } 33231c2cf11SZain Jaffal 33331c2cf11SZain Jaffal static CommandRegistration CountReg(&CountSub, collectRemarks); 334