brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.3 KiB · 39e7b42 Raw
261 lines · c
1//===- RemarkUtilHelpers.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// Helpers for remark utilites10//11//===----------------------------------------------------------------------===//12#include "llvm/ADT/StringExtras.h"13#include "llvm/ADT/StringRef.h"14#include "llvm/Remarks/Remark.h"15#include "llvm/Remarks/RemarkFormat.h"16#include "llvm/Remarks/RemarkParser.h"17#include "llvm/Remarks/RemarkSerializer.h"18#include "llvm/Support/CommandLine.h"19#include "llvm/Support/Error.h"20#include "llvm/Support/FileSystem.h"21#include "llvm/Support/MemoryBuffer.h"22#include "llvm/Support/Regex.h"23#include "llvm/Support/StringSaver.h"24#include "llvm/Support/ToolOutputFile.h"25 26// Keep input + output help + names consistent across the various modes via a27// hideous macro.28#define INPUT_OUTPUT_COMMAND_LINE_OPTIONS(SUBOPT)                              \29  static cl::opt<std::string> InputFileName(cl::Positional, cl::init("-"),     \30                                            cl::desc("<input file>"),          \31                                            cl::sub(SUBOPT));                  \32  static cl::opt<std::string> OutputFileName(                                  \33      "o", cl::init("-"), cl::desc("Output"), cl::value_desc("filename"),      \34      cl::sub(SUBOPT));35 36// Keep Input format and names consistent accross the modes via a macro.37#define INPUT_FORMAT_COMMAND_LINE_OPTIONS(SUBOPT)                              \38  static cl::opt<Format> InputFormat(                                          \39      "parser", cl::init(Format::Auto),                                        \40      cl::desc("Input remark format to parse"),                                \41      cl::values(                                                              \42          clEnumValN(Format::Auto, "auto", "Automatic detection (default)"),   \43          clEnumValN(Format::YAML, "yaml", "YAML"),                            \44          clEnumValN(Format::Bitstream, "bitstream", "Bitstream")),            \45      cl::sub(SUBOPT));46 47#define OUTPUT_FORMAT_COMMAND_LINE_OPTIONS(SUBOPT)                             \48  static cl::opt<Format> OutputFormat(                                         \49      "serializer", cl::init(Format::Auto),                                    \50      cl::desc("Output remark format to serialize"),                           \51      cl::values(clEnumValN(Format::Auto, "auto",                              \52                            "Automatic detection based on output file "        \53                            "extension or parser format (default)"),           \54                 clEnumValN(Format::YAML, "yaml", "YAML"),                     \55                 clEnumValN(Format::Bitstream, "bitstream", "Bitstream")),     \56      cl::sub(SUBOPT));57 58#define DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(SUBOPT)                            \59  static cl::opt<bool> UseDebugLoc(                                            \60      "use-debug-loc",                                                         \61      cl::desc(                                                                \62          "Add debug loc information when generating tables for "              \63          "functions. The loc is represented as (path:line number:column "     \64          "number)"),                                                          \65      cl::init(false), cl::sub(SUBOPT));66 67#define REMARK_FILTER_COMMAND_LINE_OPTIONS(SUBOPT)                             \68  static cl::opt<std::string> FunctionOpt(                                     \69      "function", cl::sub(SUBOPT), cl::ValueOptional,                          \70      cl::desc("Optional function name to filter collection by."));            \71  static cl::opt<std::string> FunctionOptRE(                                   \72      "rfunction", cl::sub(SUBOPT), cl::ValueOptional,                         \73      cl::desc("Optional function name to filter collection by "               \74               "(accepts regular expressions)."));                             \75  static cl::opt<std::string> RemarkNameOpt(                                   \76      "remark-name",                                                           \77      cl::desc("Optional remark name to filter collection by."),               \78      cl::ValueOptional, cl::sub(SUBOPT));                                     \79  static cl::opt<std::string> RemarkNameOptRE(                                 \80      "rremark-name",                                                          \81      cl::desc("Optional remark name to filter collection by "                 \82               "(accepts regular expressions)."),                              \83      cl::ValueOptional, cl::sub(SUBOPT));                                     \84  static cl::opt<std::string> PassNameOpt(                                     \85      "pass-name", cl::ValueOptional,                                          \86      cl::desc("Optional remark pass name to filter collection by."),          \87      cl::sub(SUBOPT));                                                        \88  static cl::opt<std::string> PassNameOptRE(                                   \89      "rpass-name", cl::ValueOptional,                                         \90      cl::desc("Optional remark pass name to filter collection "               \91               "by (accepts regular expressions)."),                           \92      cl::sub(SUBOPT));                                                        \93  static cl::opt<Type> RemarkTypeOpt(                                          \94      "remark-type",                                                           \95      cl::desc("Optional remark type to filter collection by."),               \96      cl::values(clEnumValN(Type::Unknown, "unknown", "UNKOWN"),               \97                 clEnumValN(Type::Passed, "passed", "PASSED"),                 \98                 clEnumValN(Type::Missed, "missed", "MISSED"),                 \99                 clEnumValN(Type::Analysis, "analysis", "ANALYSIS"),           \100                 clEnumValN(Type::AnalysisFPCommute, "analysis-fp-commute",    \101                            "ANALYSIS_FP_COMMUTE"),                            \102                 clEnumValN(Type::AnalysisAliasing, "analysis-aliasing",       \103                            "ANALYSIS_ALIASING"),                              \104                 clEnumValN(Type::Failure, "failure", "FAILURE")),             \105      cl::sub(SUBOPT));                                                        \106  static cl::opt<std::string> RemarkFilterArgByOpt(                            \107      "filter-arg-by",                                                         \108      cl::desc("Optional remark arg to filter collection by."),                \109      cl::ValueOptional, cl::sub(SUBOPT));                                     \110  static cl::opt<std::string> RemarkArgFilterOptRE(                            \111      "rfilter-arg-by",                                                        \112      cl::desc("Optional remark arg to filter collection by "                  \113               "(accepts regular expressions)."),                              \114      cl::sub(SUBOPT), cl::ValueOptional);115 116#define REMARK_FILTER_SETUP_FUNC()                                             \117  static Expected<Filters> getRemarkFilters() {                                \118    auto MaybeFunctionFilter =                                                 \119        FilterMatcher::createExactOrRE(FunctionOpt, FunctionOptRE);            \120    if (!MaybeFunctionFilter)                                                  \121      return MaybeFunctionFilter.takeError();                                  \122                                                                               \123    auto MaybeRemarkNameFilter =                                               \124        FilterMatcher::createExactOrRE(RemarkNameOpt, RemarkNameOptRE);        \125    if (!MaybeRemarkNameFilter)                                                \126      return MaybeRemarkNameFilter.takeError();                                \127                                                                               \128    auto MaybePassNameFilter =                                                 \129        FilterMatcher::createExactOrRE(PassNameOpt, PassNameOptRE);            \130    if (!MaybePassNameFilter)                                                  \131      return MaybePassNameFilter.takeError();                                  \132                                                                               \133    auto MaybeRemarkArgFilter = FilterMatcher::createExactOrRE(                \134        RemarkFilterArgByOpt, RemarkArgFilterOptRE);                           \135    if (!MaybeRemarkArgFilter)                                                 \136      return MaybeRemarkArgFilter.takeError();                                 \137                                                                               \138    std::optional<Type> TypeFilter;                                            \139    if (RemarkTypeOpt.getNumOccurrences())                                     \140      TypeFilter = RemarkTypeOpt.getValue();                                   \141                                                                               \142    return Filters{std::move(*MaybeFunctionFilter),                            \143                   std::move(*MaybeRemarkNameFilter),                          \144                   std::move(*MaybePassNameFilter),                            \145                   std::move(*MaybeRemarkArgFilter), TypeFilter};              \146  }147 148namespace llvm {149namespace remarks {150Expected<std::unique_ptr<MemoryBuffer>>151getInputMemoryBuffer(StringRef InputFileName);152Expected<std::unique_ptr<ToolOutputFile>>153getOutputFileWithFlags(StringRef OutputFileName, sys::fs::OpenFlags Flags);154Expected<std::unique_ptr<ToolOutputFile>>155getOutputFileForRemarks(StringRef OutputFileName, Format OutputFormat);156 157/// Choose the serializer format. If \p SelectedFormat is Format::Auto, try to158/// detect the format based on the extension of \p OutputFileName or fall back159/// to \p DefaultFormat.160Format getSerializerFormat(StringRef OutputFileName, Format SelectedFormat,161                           Format DefaultFormat);162 163/// Filter object which can be either a string or a regex to match with the164/// remark properties.165class FilterMatcher {166  Regex FilterRE;167  std::string FilterStr;168  bool IsRegex;169 170  FilterMatcher(StringRef Filter, bool IsRegex)171      : FilterRE(Filter), FilterStr(Filter), IsRegex(IsRegex) {}172 173  static Expected<FilterMatcher> createRE(StringRef Arg, StringRef Value);174 175public:176  static FilterMatcher createExact(StringRef Filter) { return {Filter, false}; }177 178  static Expected<FilterMatcher>179  createRE(const llvm::cl::opt<std::string> &Arg);180 181  static Expected<FilterMatcher> createRE(StringRef Filter,182                                          const cl::list<std::string> &Arg);183 184  static Expected<std::optional<FilterMatcher>>185  createExactOrRE(const llvm::cl::opt<std::string> &ExactArg,186                  const llvm::cl::opt<std::string> &REArg);187 188  static FilterMatcher createAny() { return {".*", true}; }189 190  bool match(StringRef StringToMatch) const {191    if (IsRegex)192      return FilterRE.match(StringToMatch);193    return FilterStr == StringToMatch.trim().str();194  }195};196 197/// Filter out remarks based on remark properties (function, remark name, pass198/// name, argument values and type).199struct Filters {200  std::optional<FilterMatcher> FunctionFilter;201  std::optional<FilterMatcher> RemarkNameFilter;202  std::optional<FilterMatcher> PassNameFilter;203  std::optional<FilterMatcher> ArgFilter;204  std::optional<Type> RemarkTypeFilter;205 206  /// Returns true if \p Remark satisfies all the provided filters.207  bool filterRemark(const Remark &Remark);208};209 210/// Helper to construct Remarks using an API similar to DiagnosticInfo.211/// Once this is more fully featured, consider implementing DiagnosticInfo using212/// RemarkBuilder.213class RemarkBuilder {214  BumpPtrAllocator Alloc;215  UniqueStringSaver Strs;216 217public:218  Remark R;219  struct Argument {220    std::string Key;221    std::string Val;222    std::optional<RemarkLocation> Loc;223    Argument(StringRef Key, StringRef Val,224             std::optional<RemarkLocation> Loc = std::nullopt)225        : Key(Key), Val(Val), Loc(Loc) {}226    Argument(StringRef Key, int Val,227             std::optional<RemarkLocation> Loc = std::nullopt)228        : Key(Key), Val(itostr(Val)), Loc(Loc) {}229  };230 231  RemarkBuilder(Type RemarkType, StringRef PassName, StringRef RemarkName,232                StringRef FunctionName)233      : Strs(Alloc) {234    R.RemarkType = RemarkType;235    R.PassName = Strs.save(PassName);236    R.RemarkName = Strs.save(RemarkName);237    R.FunctionName = Strs.save(FunctionName);238  }239 240  RemarkBuilder &operator<<(Argument &&Arg) {241    auto &RArg = R.Args.emplace_back(Strs.save(Arg.Key), Strs.save(Arg.Val));242    RArg.Loc = Arg.Loc;243    return *this;244  }245 246  RemarkBuilder &operator<<(const char *Str) {247    R.Args.emplace_back("String", Str);248    return *this;249  }250 251  RemarkBuilder &operator<<(StringRef Str) {252    R.Args.emplace_back("String", Strs.save(Str));253    return *this;254  }255};256 257using NV = RemarkBuilder::Argument;258 259} // namespace remarks260} // namespace llvm261