[Demangle] Add a few more options to the microsoft demangler
[llvm-complete.git] / lib / IR / RemarkStreamer.cpp
blob0fcc06b961f30364eb8c9f984ecd100ff51b4c1a
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 std::unique_ptr<remarks::RemarkSerializer> RemarkSerializer,
26 Optional<StringRef> FilenameIn)
27 : PassFilter(), RemarkSerializer(std::move(RemarkSerializer)),
28 Filename(FilenameIn ? Optional<std::string>(FilenameIn->str()) : None) {}
30 Error RemarkStreamer::setFilter(StringRef Filter) {
31 Regex R = Regex(Filter);
32 std::string RegexError;
33 if (!R.isValid(RegexError))
34 return createStringError(std::make_error_code(std::errc::invalid_argument),
35 RegexError.data());
36 PassFilter = std::move(R);
37 return Error::success();
40 /// DiagnosticKind -> remarks::Type
41 static remarks::Type toRemarkType(enum DiagnosticKind Kind) {
42 switch (Kind) {
43 default:
44 return remarks::Type::Unknown;
45 case DK_OptimizationRemark:
46 case DK_MachineOptimizationRemark:
47 return remarks::Type::Passed;
48 case DK_OptimizationRemarkMissed:
49 case DK_MachineOptimizationRemarkMissed:
50 return remarks::Type::Missed;
51 case DK_OptimizationRemarkAnalysis:
52 case DK_MachineOptimizationRemarkAnalysis:
53 return remarks::Type::Analysis;
54 case DK_OptimizationRemarkAnalysisFPCommute:
55 return remarks::Type::AnalysisFPCommute;
56 case DK_OptimizationRemarkAnalysisAliasing:
57 return remarks::Type::AnalysisAliasing;
58 case DK_OptimizationFailure:
59 return remarks::Type::Failure;
63 /// DiagnosticLocation -> remarks::RemarkLocation.
64 static Optional<remarks::RemarkLocation>
65 toRemarkLocation(const DiagnosticLocation &DL) {
66 if (!DL.isValid())
67 return None;
68 StringRef File = DL.getRelativePath();
69 unsigned Line = DL.getLine();
70 unsigned Col = DL.getColumn();
71 return remarks::RemarkLocation{File, Line, Col};
74 /// LLVM Diagnostic -> Remark
75 remarks::Remark
76 RemarkStreamer::toRemark(const DiagnosticInfoOptimizationBase &Diag) {
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 for (const DiagnosticInfoOptimizationBase::Argument &Arg : Diag.getArgs()) {
87 R.Args.emplace_back();
88 R.Args.back().Key = Arg.Key;
89 R.Args.back().Val = Arg.Val;
90 R.Args.back().Loc = toRemarkLocation(Arg.Loc);
93 return R;
96 void RemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) {
97 if (Optional<Regex> &Filter = PassFilter)
98 if (!Filter->match(Diag.getPassName()))
99 return;
101 // First, convert the diagnostic to a remark.
102 remarks::Remark R = toRemark(Diag);
103 // Then, emit the remark through the serializer.
104 RemarkSerializer->emit(R);
107 char RemarkSetupFileError::ID = 0;
108 char RemarkSetupPatternError::ID = 0;
109 char RemarkSetupFormatError::ID = 0;
111 Expected<std::unique_ptr<ToolOutputFile>>
112 llvm::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
113 StringRef RemarksPasses, StringRef RemarksFormat,
114 bool RemarksWithHotness,
115 unsigned RemarksHotnessThreshold) {
116 if (RemarksWithHotness)
117 Context.setDiagnosticsHotnessRequested(true);
119 if (RemarksHotnessThreshold)
120 Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
122 if (RemarksFilename.empty())
123 return nullptr;
125 Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
126 if (Error E = Format.takeError())
127 return make_error<RemarkSetupFormatError>(std::move(E));
129 std::error_code EC;
130 auto Flags = *Format == remarks::Format::YAML ? sys::fs::OF_Text
131 : sys::fs::OF_None;
132 auto RemarksFile =
133 std::make_unique<ToolOutputFile>(RemarksFilename, EC, Flags);
134 // We don't use llvm::FileError here because some diagnostics want the file
135 // name separately.
136 if (EC)
137 return make_error<RemarkSetupFileError>(errorCodeToError(EC));
139 Expected<std::unique_ptr<remarks::RemarkSerializer>> RemarkSerializer =
140 remarks::createRemarkSerializer(
141 *Format, remarks::SerializerMode::Separate, RemarksFile->os());
142 if (Error E = RemarkSerializer.takeError())
143 return make_error<RemarkSetupFormatError>(std::move(E));
145 Context.setRemarkStreamer(std::make_unique<RemarkStreamer>(
146 std::move(*RemarkSerializer), RemarksFilename));
148 if (!RemarksPasses.empty())
149 if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses))
150 return make_error<RemarkSetupPatternError>(std::move(E));
152 return std::move(RemarksFile);
155 Error llvm::setupOptimizationRemarks(LLVMContext &Context, raw_ostream &OS,
156 StringRef RemarksPasses,
157 StringRef RemarksFormat,
158 bool RemarksWithHotness,
159 unsigned RemarksHotnessThreshold) {
160 if (RemarksWithHotness)
161 Context.setDiagnosticsHotnessRequested(true);
163 if (RemarksHotnessThreshold)
164 Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
166 Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
167 if (Error E = Format.takeError())
168 return make_error<RemarkSetupFormatError>(std::move(E));
170 Expected<std::unique_ptr<remarks::RemarkSerializer>> RemarkSerializer =
171 remarks::createRemarkSerializer(*Format,
172 remarks::SerializerMode::Separate, OS);
173 if (Error E = RemarkSerializer.takeError())
174 return make_error<RemarkSetupFormatError>(std::move(E));
176 Context.setRemarkStreamer(
177 std::make_unique<RemarkStreamer>(std::move(*RemarkSerializer)));
179 if (!RemarksPasses.empty())
180 if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses))
181 return make_error<RemarkSetupPatternError>(std::move(E));
183 return Error::success();