1 //===- llvm/IR/RemarkStreamer.cpp - Remark Streamer -*- C++ -------------*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains the implementation of the remark outputting as part of
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/RemarkFormat.h"
22 RemarkStreamer::RemarkStreamer(StringRef Filename,
23 std::unique_ptr<remarks::Serializer> Serializer)
24 : Filename(Filename), PassFilter(), Serializer(std::move(Serializer)) {
25 assert(!Filename.empty() && "This needs to be a real filename.");
28 Error RemarkStreamer::setFilter(StringRef Filter) {
29 Regex R = Regex(Filter);
30 std::string RegexError;
31 if (!R.isValid(RegexError))
32 return createStringError(std::make_error_code(std::errc::invalid_argument),
34 PassFilter = std::move(R);
35 return Error::success();
38 /// DiagnosticKind -> remarks::Type
39 static remarks::Type toRemarkType(enum DiagnosticKind Kind) {
42 return remarks::Type::Unknown;
43 case DK_OptimizationRemark:
44 case DK_MachineOptimizationRemark:
45 return remarks::Type::Passed;
46 case DK_OptimizationRemarkMissed:
47 case DK_MachineOptimizationRemarkMissed:
48 return remarks::Type::Missed;
49 case DK_OptimizationRemarkAnalysis:
50 case DK_MachineOptimizationRemarkAnalysis:
51 return remarks::Type::Analysis;
52 case DK_OptimizationRemarkAnalysisFPCommute:
53 return remarks::Type::AnalysisFPCommute;
54 case DK_OptimizationRemarkAnalysisAliasing:
55 return remarks::Type::AnalysisAliasing;
56 case DK_OptimizationFailure:
57 return remarks::Type::Failure;
61 /// DiagnosticLocation -> remarks::RemarkLocation.
62 static Optional<remarks::RemarkLocation>
63 toRemarkLocation(const DiagnosticLocation &DL) {
66 StringRef File = DL.getRelativePath();
67 unsigned Line = DL.getLine();
68 unsigned Col = DL.getColumn();
69 return remarks::RemarkLocation{File, Line, Col};
72 /// LLVM Diagnostic -> Remark
74 RemarkStreamer::toRemark(const DiagnosticInfoOptimizationBase &Diag) {
75 remarks::Remark R; // The result.
76 R.RemarkType = toRemarkType(static_cast<DiagnosticKind>(Diag.getKind()));
77 R.PassName = Diag.getPassName();
78 R.RemarkName = Diag.getRemarkName();
80 GlobalValue::dropLLVMManglingEscape(Diag.getFunction().getName());
81 R.Loc = toRemarkLocation(Diag.getLocation());
82 R.Hotness = Diag.getHotness();
84 for (const DiagnosticInfoOptimizationBase::Argument &Arg : Diag.getArgs()) {
85 R.Args.emplace_back();
86 R.Args.back().Key = Arg.Key;
87 R.Args.back().Val = Arg.Val;
88 R.Args.back().Loc = toRemarkLocation(Arg.Loc);
94 void RemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) {
95 if (Optional<Regex> &Filter = PassFilter)
96 if (!Filter->match(Diag.getPassName()))
99 // First, convert the diagnostic to a remark.
100 remarks::Remark R = toRemark(Diag);
101 // Then, emit the remark through the serializer.
105 char RemarkSetupFileError::ID = 0;
106 char RemarkSetupPatternError::ID = 0;
107 char RemarkSetupFormatError::ID = 0;
109 static std::unique_ptr<remarks::Serializer>
110 formatToSerializer(remarks::Format RemarksFormat, raw_ostream &OS) {
111 switch (RemarksFormat) {
113 llvm_unreachable("Unknown remark serializer format.");
115 case remarks::Format::YAML:
116 return llvm::make_unique<remarks::YAMLSerializer>(OS);
120 Expected<std::unique_ptr<ToolOutputFile>>
121 llvm::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
122 StringRef RemarksPasses, StringRef RemarksFormat,
123 bool RemarksWithHotness,
124 unsigned RemarksHotnessThreshold) {
125 if (RemarksWithHotness)
126 Context.setDiagnosticsHotnessRequested(true);
128 if (RemarksHotnessThreshold)
129 Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
131 if (RemarksFilename.empty())
136 llvm::make_unique<ToolOutputFile>(RemarksFilename, EC, sys::fs::F_None);
137 // We don't use llvm::FileError here because some diagnostics want the file
140 return make_error<RemarkSetupFileError>(errorCodeToError(EC));
142 Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
143 if (Error E = Format.takeError())
144 return make_error<RemarkSetupFormatError>(std::move(E));
146 Context.setRemarkStreamer(llvm::make_unique<RemarkStreamer>(
147 RemarksFilename, formatToSerializer(*Format, RemarksFile->os())));
149 if (!RemarksPasses.empty())
150 if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses))
151 return make_error<RemarkSetupPatternError>(std::move(E));
153 return std::move(RemarksFile);