[llvm-objdump] - Remove one overload of reportError. NFCI.
[llvm-complete.git] / lib / IR / RemarkStreamer.cpp
blob73387ecbac1a75a08b429a903f4c92ba82254e34
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"
18 #include "llvm/Remarks/BitstreamRemarkSerializer.h"
19 #include "llvm/Remarks/RemarkFormat.h"
20 #include "llvm/Remarks/RemarkSerializer.h"
22 using namespace llvm;
24 RemarkStreamer::RemarkStreamer(
25 StringRef Filename,
26 std::unique_ptr<remarks::RemarkSerializer> RemarkSerializer)
27 : Filename(Filename), PassFilter(),
28 RemarkSerializer(std::move(RemarkSerializer)) {
29 assert(!Filename.empty() && "This needs to be a real filename.");
32 Error RemarkStreamer::setFilter(StringRef Filter) {
33 Regex R = Regex(Filter);
34 std::string RegexError;
35 if (!R.isValid(RegexError))
36 return createStringError(std::make_error_code(std::errc::invalid_argument),
37 RegexError.data());
38 PassFilter = std::move(R);
39 return Error::success();
42 /// DiagnosticKind -> remarks::Type
43 static remarks::Type toRemarkType(enum DiagnosticKind Kind) {
44 switch (Kind) {
45 default:
46 return remarks::Type::Unknown;
47 case DK_OptimizationRemark:
48 case DK_MachineOptimizationRemark:
49 return remarks::Type::Passed;
50 case DK_OptimizationRemarkMissed:
51 case DK_MachineOptimizationRemarkMissed:
52 return remarks::Type::Missed;
53 case DK_OptimizationRemarkAnalysis:
54 case DK_MachineOptimizationRemarkAnalysis:
55 return remarks::Type::Analysis;
56 case DK_OptimizationRemarkAnalysisFPCommute:
57 return remarks::Type::AnalysisFPCommute;
58 case DK_OptimizationRemarkAnalysisAliasing:
59 return remarks::Type::AnalysisAliasing;
60 case DK_OptimizationFailure:
61 return remarks::Type::Failure;
65 /// DiagnosticLocation -> remarks::RemarkLocation.
66 static Optional<remarks::RemarkLocation>
67 toRemarkLocation(const DiagnosticLocation &DL) {
68 if (!DL.isValid())
69 return None;
70 StringRef File = DL.getRelativePath();
71 unsigned Line = DL.getLine();
72 unsigned Col = DL.getColumn();
73 return remarks::RemarkLocation{File, Line, Col};
76 /// LLVM Diagnostic -> Remark
77 remarks::Remark
78 RemarkStreamer::toRemark(const DiagnosticInfoOptimizationBase &Diag) {
79 remarks::Remark R; // The result.
80 R.RemarkType = toRemarkType(static_cast<DiagnosticKind>(Diag.getKind()));
81 R.PassName = Diag.getPassName();
82 R.RemarkName = Diag.getRemarkName();
83 R.FunctionName =
84 GlobalValue::dropLLVMManglingEscape(Diag.getFunction().getName());
85 R.Loc = toRemarkLocation(Diag.getLocation());
86 R.Hotness = Diag.getHotness();
88 for (const DiagnosticInfoOptimizationBase::Argument &Arg : Diag.getArgs()) {
89 R.Args.emplace_back();
90 R.Args.back().Key = Arg.Key;
91 R.Args.back().Val = Arg.Val;
92 R.Args.back().Loc = toRemarkLocation(Arg.Loc);
95 return R;
98 void RemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) {
99 if (Optional<Regex> &Filter = PassFilter)
100 if (!Filter->match(Diag.getPassName()))
101 return;
103 // First, convert the diagnostic to a remark.
104 remarks::Remark R = toRemark(Diag);
105 // Then, emit the remark through the serializer.
106 RemarkSerializer->emit(R);
109 char RemarkSetupFileError::ID = 0;
110 char RemarkSetupPatternError::ID = 0;
111 char RemarkSetupFormatError::ID = 0;
113 Expected<std::unique_ptr<ToolOutputFile>>
114 llvm::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
115 StringRef RemarksPasses, StringRef RemarksFormat,
116 bool RemarksWithHotness,
117 unsigned RemarksHotnessThreshold) {
118 if (RemarksWithHotness)
119 Context.setDiagnosticsHotnessRequested(true);
121 if (RemarksHotnessThreshold)
122 Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
124 if (RemarksFilename.empty())
125 return nullptr;
127 std::error_code EC;
128 auto RemarksFile =
129 std::make_unique<ToolOutputFile>(RemarksFilename, EC, sys::fs::OF_None);
130 // We don't use llvm::FileError here because some diagnostics want the file
131 // name separately.
132 if (EC)
133 return make_error<RemarkSetupFileError>(errorCodeToError(EC));
135 Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
136 if (Error E = Format.takeError())
137 return make_error<RemarkSetupFormatError>(std::move(E));
139 Expected<std::unique_ptr<remarks::RemarkSerializer>> RemarkSerializer =
140 remarks::createRemarkSerializer(*Format, remarks::SerializerMode::Separate, RemarksFile->os());
141 if (Error E = RemarkSerializer.takeError())
142 return make_error<RemarkSetupFormatError>(std::move(E));
144 Context.setRemarkStreamer(std::make_unique<RemarkStreamer>(
145 RemarksFilename, std::move(*RemarkSerializer)));
147 if (!RemarksPasses.empty())
148 if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses))
149 return make_error<RemarkSetupPatternError>(std::move(E));
151 return std::move(RemarksFile);