[ARM] MVE integer min and max
[llvm-complete.git] / lib / IR / RemarkStreamer.cpp
blob2c3bc8406e55ef4f0a3862f48b0e0a03749f022d
1 //===- llvm/IR/RemarkStreamer.cpp - Remark Streamer -*- C++ -------------*-===//
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 // This file contains the implementation of the remark outputting as part of
10 // LLVMContext.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/IR/RemarkStreamer.h"
15 #include "llvm/IR/DiagnosticInfo.h"
16 #include "llvm/IR/Function.h"
17 #include "llvm/IR/GlobalValue.h"
19 using namespace llvm;
21 RemarkStreamer::RemarkStreamer(StringRef Filename,
22 std::unique_ptr<remarks::Serializer> Serializer)
23 : Filename(Filename), PassFilter(), Serializer(std::move(Serializer)) {
24 assert(!Filename.empty() && "This needs to be a real filename.");
27 Error RemarkStreamer::setFilter(StringRef Filter) {
28 Regex R = Regex(Filter);
29 std::string RegexError;
30 if (!R.isValid(RegexError))
31 return createStringError(std::make_error_code(std::errc::invalid_argument),
32 RegexError.data());
33 PassFilter = std::move(R);
34 return Error::success();
37 /// DiagnosticKind -> remarks::Type
38 static remarks::Type toRemarkType(enum DiagnosticKind Kind) {
39 switch (Kind) {
40 default:
41 return remarks::Type::Unknown;
42 case DK_OptimizationRemark:
43 case DK_MachineOptimizationRemark:
44 return remarks::Type::Passed;
45 case DK_OptimizationRemarkMissed:
46 case DK_MachineOptimizationRemarkMissed:
47 return remarks::Type::Missed;
48 case DK_OptimizationRemarkAnalysis:
49 case DK_MachineOptimizationRemarkAnalysis:
50 return remarks::Type::Analysis;
51 case DK_OptimizationRemarkAnalysisFPCommute:
52 return remarks::Type::AnalysisFPCommute;
53 case DK_OptimizationRemarkAnalysisAliasing:
54 return remarks::Type::AnalysisAliasing;
55 case DK_OptimizationFailure:
56 return remarks::Type::Failure;
60 /// DiagnosticLocation -> remarks::RemarkLocation.
61 static Optional<remarks::RemarkLocation>
62 toRemarkLocation(const DiagnosticLocation &DL) {
63 if (!DL.isValid())
64 return None;
65 StringRef File = DL.getRelativePath();
66 unsigned Line = DL.getLine();
67 unsigned Col = DL.getColumn();
68 return remarks::RemarkLocation{File, Line, Col};
71 /// LLVM Diagnostic -> Remark
72 remarks::Remark
73 RemarkStreamer::toRemark(const DiagnosticInfoOptimizationBase &Diag) {
74 // Re-use the buffer.
75 TmpArgs.clear();
77 remarks::Remark R; // The result.
78 R.RemarkType = toRemarkType(static_cast<DiagnosticKind>(Diag.getKind()));
79 R.PassName = Diag.getPassName();
80 R.RemarkName = Diag.getRemarkName();
81 R.FunctionName =
82 GlobalValue::dropLLVMManglingEscape(Diag.getFunction().getName());
83 R.Loc = toRemarkLocation(Diag.getLocation());
84 R.Hotness = Diag.getHotness();
86 // Use TmpArgs to build the list of arguments and re-use the memory allocated
87 // from previous remark conversions.
88 for (const DiagnosticInfoOptimizationBase::Argument &Arg : Diag.getArgs()) {
89 TmpArgs.emplace_back();
90 TmpArgs.back().Key = Arg.Key;
91 TmpArgs.back().Val = Arg.Val;
92 TmpArgs.back().Loc = toRemarkLocation(Arg.Loc);
94 R.Args = TmpArgs; // This is valid until the next call to this function.
96 return R;
99 void RemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) {
100 if (Optional<Regex> &Filter = PassFilter)
101 if (!Filter->match(Diag.getPassName()))
102 return;
104 // First, convert the diagnostic to a remark.
105 remarks::Remark R = toRemark(Diag);
106 // Then, emit the remark through the serializer.
107 Serializer->emit(R);
110 char RemarkSetupFileError::ID = 0;
111 char RemarkSetupPatternError::ID = 0;
112 char RemarkSetupFormatError::ID = 0;
114 static std::unique_ptr<remarks::Serializer>
115 formatToSerializer(RemarksSerializerFormat RemarksFormat, raw_ostream &OS) {
116 switch (RemarksFormat) {
117 default:
118 llvm_unreachable("Unknown remark serializer format.");
119 return nullptr;
120 case RemarksSerializerFormat::YAML:
121 return llvm::make_unique<remarks::YAMLSerializer>(OS);
125 Expected<RemarksSerializerFormat>
126 llvm::parseSerializerFormat(StringRef StrFormat) {
127 auto Format = StringSwitch<RemarksSerializerFormat>(StrFormat)
128 .Cases("", "yaml", RemarksSerializerFormat::YAML)
129 .Default(RemarksSerializerFormat::Unknown);
131 if (Format == RemarksSerializerFormat::Unknown)
132 return createStringError(std::make_error_code(std::errc::invalid_argument),
133 "Unknown remark serializer format: '%s'",
134 StrFormat.data());
136 return Format;
139 Expected<std::unique_ptr<ToolOutputFile>>
140 llvm::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
141 StringRef RemarksPasses, StringRef RemarksFormat,
142 bool RemarksWithHotness,
143 unsigned RemarksHotnessThreshold) {
144 if (RemarksWithHotness)
145 Context.setDiagnosticsHotnessRequested(true);
147 if (RemarksHotnessThreshold)
148 Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
150 if (RemarksFilename.empty())
151 return nullptr;
153 std::error_code EC;
154 auto RemarksFile =
155 llvm::make_unique<ToolOutputFile>(RemarksFilename, EC, sys::fs::F_None);
156 // We don't use llvm::FileError here because some diagnostics want the file
157 // name separately.
158 if (EC)
159 return make_error<RemarkSetupFileError>(errorCodeToError(EC));
161 Expected<RemarksSerializerFormat> Format =
162 parseSerializerFormat(RemarksFormat);
163 if (Error E = Format.takeError())
164 return make_error<RemarkSetupFormatError>(std::move(E));
166 Context.setRemarkStreamer(llvm::make_unique<RemarkStreamer>(
167 RemarksFilename, formatToSerializer(*Format, RemarksFile->os())));
169 if (!RemarksPasses.empty())
170 if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses))
171 return make_error<RemarkSetupPatternError>(std::move(E));
173 return std::move(RemarksFile);