1//===- RemarkUtilHelpers.cpp ----------------------------------------------===//
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// Helpers for remark utilites
10//
11//===----------------------------------------------------------------------===//
12#include "RemarkUtilHelpers.h"
13
14namespace llvm {
15namespace remarks {
16/// \returns A MemoryBuffer for the input file on success, and an Error
17/// otherwise.
18Expected<std::unique_ptr<MemoryBuffer>>
19getInputMemoryBuffer(StringRef InputFileName) {
20 auto MaybeBuf = MemoryBuffer::getFileOrSTDIN(Filename: InputFileName);
21 if (auto ErrorCode = MaybeBuf.getError())
22 return createStringError(EC: ErrorCode,
23 S: Twine("Cannot open file '" + InputFileName +
24 "': " + ErrorCode.message()));
25 return std::move(*MaybeBuf);
26}
27
28/// \returns A ToolOutputFile which can be used for outputting the results of
29/// some tool mode.
30/// \p OutputFileName is the desired destination.
31/// \p Flags controls whether or not the file is opened for writing in text
32/// mode, as a binary, etc. See sys::fs::OpenFlags for more detail.
33Expected<std::unique_ptr<ToolOutputFile>>
34getOutputFileWithFlags(StringRef OutputFileName, sys::fs::OpenFlags Flags) {
35 if (OutputFileName == "")
36 OutputFileName = "-";
37 std::error_code ErrorCode;
38 auto OF = std::make_unique<ToolOutputFile>(args&: OutputFileName, args&: ErrorCode, args&: Flags);
39 if (ErrorCode)
40 return errorCodeToError(EC: ErrorCode);
41 return std::move(OF);
42}
43
44/// \returns A ToolOutputFile which can be used for writing remarks on success,
45/// and an Error otherwise.
46/// \p OutputFileName is the desired destination.
47/// \p OutputFormat
48Expected<std::unique_ptr<ToolOutputFile>>
49getOutputFileForRemarks(StringRef OutputFileName, Format OutputFormat) {
50 assert((OutputFormat == Format::YAML || OutputFormat == Format::Bitstream) &&
51 "Expected one of YAML or Bitstream!");
52 return getOutputFileWithFlags(OutputFileName, Flags: OutputFormat == Format::YAML
53 ? sys::fs::OF_TextWithCRLF
54 : sys::fs::OF_None);
55}
56
57Format getSerializerFormat(StringRef OutputFileName, Format SelectedFormat,
58 Format DefaultFormat) {
59 if (SelectedFormat != Format::Auto)
60 return SelectedFormat;
61 SelectedFormat = DefaultFormat;
62 if (OutputFileName.empty() || OutputFileName == "-" ||
63 OutputFileName.ends_with_insensitive(Suffix: ".yaml") ||
64 OutputFileName.ends_with_insensitive(Suffix: ".yml"))
65 SelectedFormat = Format::YAML;
66 if (OutputFileName.ends_with_insensitive(Suffix: ".bitstream"))
67 SelectedFormat = Format::Bitstream;
68 return SelectedFormat;
69}
70
71Expected<FilterMatcher>
72FilterMatcher::createRE(const llvm::cl::opt<std::string> &Arg) {
73 return createRE(Arg: Arg.ArgStr, Value: Arg);
74}
75
76Expected<FilterMatcher>
77FilterMatcher::createRE(StringRef Filter, const cl::list<std::string> &Arg) {
78 return createRE(Arg: Arg.ArgStr, Value: Filter);
79}
80
81Expected<FilterMatcher> FilterMatcher::createRE(StringRef Arg,
82 StringRef Value) {
83 FilterMatcher FM(Value, true);
84 std::string Error;
85 if (!FM.FilterRE.isValid(Error))
86 return createStringError(EC: make_error_code(e: std::errc::invalid_argument),
87 S: "invalid argument '--" + Arg + "=" + Value +
88 "': " + Error);
89 return std::move(FM);
90}
91
92Expected<std::optional<FilterMatcher>>
93FilterMatcher::createExactOrRE(const llvm::cl::opt<std::string> &ExactArg,
94 const llvm::cl::opt<std::string> &REArg) {
95 if (!ExactArg.empty() && !REArg.empty())
96 return createStringError(EC: make_error_code(e: std::errc::invalid_argument),
97 S: "conflicting arguments: --" + ExactArg.ArgStr +
98 " and --" + REArg.ArgStr);
99
100 if (!ExactArg.empty())
101 return createExact(Filter: ExactArg);
102
103 if (!REArg.empty())
104 return createRE(Arg: REArg);
105
106 return std::nullopt;
107}
108
109bool Filters::filterRemark(const Remark &Remark) {
110 if (FunctionFilter && !FunctionFilter->match(StringToMatch: Remark.FunctionName))
111 return false;
112 if (RemarkNameFilter && !RemarkNameFilter->match(StringToMatch: Remark.RemarkName))
113 return false;
114 if (PassNameFilter && !PassNameFilter->match(StringToMatch: Remark.PassName))
115 return false;
116 if (RemarkTypeFilter)
117 return *RemarkTypeFilter == Remark.RemarkType;
118 if (ArgFilter) {
119 if (!any_of(Range: Remark.Args,
120 P: [this](Argument Arg) { return ArgFilter->match(StringToMatch: Arg.Val); }))
121 return false;
122 }
123 return true;
124}
125
126} // namespace remarks
127} // namespace llvm
128