xref: /freebsd-src/contrib/llvm-project/llvm/lib/IR/LLVMRemarkStreamer.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
15ffd83dbSDimitry Andric //===- llvm/IR/LLVMRemarkStreamer.cpp - Remark Streamer -*- C++ ---------*-===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric //
95ffd83dbSDimitry Andric // This file contains the implementation of the conversion between IR
105ffd83dbSDimitry Andric // Diagnostics and serializable remarks::Remark objects.
115ffd83dbSDimitry Andric //
125ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
135ffd83dbSDimitry Andric 
145ffd83dbSDimitry Andric #include "llvm/IR/LLVMRemarkStreamer.h"
155ffd83dbSDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
165ffd83dbSDimitry Andric #include "llvm/IR/Function.h"
175ffd83dbSDimitry Andric #include "llvm/IR/GlobalValue.h"
185ffd83dbSDimitry Andric #include "llvm/Support/FileSystem.h"
195ffd83dbSDimitry Andric 
205ffd83dbSDimitry Andric using namespace llvm;
215ffd83dbSDimitry Andric 
225ffd83dbSDimitry Andric /// DiagnosticKind -> remarks::Type
235ffd83dbSDimitry Andric static remarks::Type toRemarkType(enum DiagnosticKind Kind) {
245ffd83dbSDimitry Andric   switch (Kind) {
255ffd83dbSDimitry Andric   default:
265ffd83dbSDimitry Andric     return remarks::Type::Unknown;
275ffd83dbSDimitry Andric   case DK_OptimizationRemark:
285ffd83dbSDimitry Andric   case DK_MachineOptimizationRemark:
295ffd83dbSDimitry Andric     return remarks::Type::Passed;
305ffd83dbSDimitry Andric   case DK_OptimizationRemarkMissed:
315ffd83dbSDimitry Andric   case DK_MachineOptimizationRemarkMissed:
325ffd83dbSDimitry Andric     return remarks::Type::Missed;
335ffd83dbSDimitry Andric   case DK_OptimizationRemarkAnalysis:
345ffd83dbSDimitry Andric   case DK_MachineOptimizationRemarkAnalysis:
355ffd83dbSDimitry Andric     return remarks::Type::Analysis;
365ffd83dbSDimitry Andric   case DK_OptimizationRemarkAnalysisFPCommute:
375ffd83dbSDimitry Andric     return remarks::Type::AnalysisFPCommute;
385ffd83dbSDimitry Andric   case DK_OptimizationRemarkAnalysisAliasing:
395ffd83dbSDimitry Andric     return remarks::Type::AnalysisAliasing;
405ffd83dbSDimitry Andric   case DK_OptimizationFailure:
415ffd83dbSDimitry Andric     return remarks::Type::Failure;
425ffd83dbSDimitry Andric   }
435ffd83dbSDimitry Andric }
445ffd83dbSDimitry Andric 
455ffd83dbSDimitry Andric /// DiagnosticLocation -> remarks::RemarkLocation.
465ffd83dbSDimitry Andric static Optional<remarks::RemarkLocation>
475ffd83dbSDimitry Andric toRemarkLocation(const DiagnosticLocation &DL) {
485ffd83dbSDimitry Andric   if (!DL.isValid())
495ffd83dbSDimitry Andric     return None;
505ffd83dbSDimitry Andric   StringRef File = DL.getRelativePath();
515ffd83dbSDimitry Andric   unsigned Line = DL.getLine();
525ffd83dbSDimitry Andric   unsigned Col = DL.getColumn();
535ffd83dbSDimitry Andric   return remarks::RemarkLocation{File, Line, Col};
545ffd83dbSDimitry Andric }
555ffd83dbSDimitry Andric 
565ffd83dbSDimitry Andric /// LLVM Diagnostic -> Remark
575ffd83dbSDimitry Andric remarks::Remark
585ffd83dbSDimitry Andric LLVMRemarkStreamer::toRemark(const DiagnosticInfoOptimizationBase &Diag) const {
595ffd83dbSDimitry Andric   remarks::Remark R; // The result.
605ffd83dbSDimitry Andric   R.RemarkType = toRemarkType(static_cast<DiagnosticKind>(Diag.getKind()));
615ffd83dbSDimitry Andric   R.PassName = Diag.getPassName();
625ffd83dbSDimitry Andric   R.RemarkName = Diag.getRemarkName();
635ffd83dbSDimitry Andric   R.FunctionName =
645ffd83dbSDimitry Andric       GlobalValue::dropLLVMManglingEscape(Diag.getFunction().getName());
655ffd83dbSDimitry Andric   R.Loc = toRemarkLocation(Diag.getLocation());
665ffd83dbSDimitry Andric   R.Hotness = Diag.getHotness();
675ffd83dbSDimitry Andric 
685ffd83dbSDimitry Andric   for (const DiagnosticInfoOptimizationBase::Argument &Arg : Diag.getArgs()) {
695ffd83dbSDimitry Andric     R.Args.emplace_back();
705ffd83dbSDimitry Andric     R.Args.back().Key = Arg.Key;
715ffd83dbSDimitry Andric     R.Args.back().Val = Arg.Val;
725ffd83dbSDimitry Andric     R.Args.back().Loc = toRemarkLocation(Arg.Loc);
735ffd83dbSDimitry Andric   }
745ffd83dbSDimitry Andric 
755ffd83dbSDimitry Andric   return R;
765ffd83dbSDimitry Andric }
775ffd83dbSDimitry Andric 
785ffd83dbSDimitry Andric void LLVMRemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) {
795ffd83dbSDimitry Andric   if (!RS.matchesFilter(Diag.getPassName()))
805ffd83dbSDimitry Andric       return;
815ffd83dbSDimitry Andric 
825ffd83dbSDimitry Andric   // First, convert the diagnostic to a remark.
835ffd83dbSDimitry Andric   remarks::Remark R = toRemark(Diag);
845ffd83dbSDimitry Andric   // Then, emit the remark through the serializer.
855ffd83dbSDimitry Andric   RS.getSerializer().emit(R);
865ffd83dbSDimitry Andric }
875ffd83dbSDimitry Andric 
885ffd83dbSDimitry Andric char LLVMRemarkSetupFileError::ID = 0;
895ffd83dbSDimitry Andric char LLVMRemarkSetupPatternError::ID = 0;
905ffd83dbSDimitry Andric char LLVMRemarkSetupFormatError::ID = 0;
915ffd83dbSDimitry Andric 
925ffd83dbSDimitry Andric Expected<std::unique_ptr<ToolOutputFile>> llvm::setupLLVMOptimizationRemarks(
935ffd83dbSDimitry Andric     LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses,
945ffd83dbSDimitry Andric     StringRef RemarksFormat, bool RemarksWithHotness,
95*e8d8bef9SDimitry Andric     Optional<uint64_t> RemarksHotnessThreshold) {
965ffd83dbSDimitry Andric   if (RemarksWithHotness)
975ffd83dbSDimitry Andric     Context.setDiagnosticsHotnessRequested(true);
985ffd83dbSDimitry Andric 
995ffd83dbSDimitry Andric   Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
1005ffd83dbSDimitry Andric 
1015ffd83dbSDimitry Andric   if (RemarksFilename.empty())
1025ffd83dbSDimitry Andric     return nullptr;
1035ffd83dbSDimitry Andric 
1045ffd83dbSDimitry Andric   Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
1055ffd83dbSDimitry Andric   if (Error E = Format.takeError())
1065ffd83dbSDimitry Andric     return make_error<LLVMRemarkSetupFormatError>(std::move(E));
1075ffd83dbSDimitry Andric 
1085ffd83dbSDimitry Andric   std::error_code EC;
1095ffd83dbSDimitry Andric   auto Flags = *Format == remarks::Format::YAML ? sys::fs::OF_Text
1105ffd83dbSDimitry Andric                                                 : sys::fs::OF_None;
1115ffd83dbSDimitry Andric   auto RemarksFile =
1125ffd83dbSDimitry Andric       std::make_unique<ToolOutputFile>(RemarksFilename, EC, Flags);
1135ffd83dbSDimitry Andric   // We don't use llvm::FileError here because some diagnostics want the file
1145ffd83dbSDimitry Andric   // name separately.
1155ffd83dbSDimitry Andric   if (EC)
1165ffd83dbSDimitry Andric     return make_error<LLVMRemarkSetupFileError>(errorCodeToError(EC));
1175ffd83dbSDimitry Andric 
1185ffd83dbSDimitry Andric   Expected<std::unique_ptr<remarks::RemarkSerializer>> RemarkSerializer =
1195ffd83dbSDimitry Andric       remarks::createRemarkSerializer(
1205ffd83dbSDimitry Andric           *Format, remarks::SerializerMode::Separate, RemarksFile->os());
1215ffd83dbSDimitry Andric   if (Error E = RemarkSerializer.takeError())
1225ffd83dbSDimitry Andric     return make_error<LLVMRemarkSetupFormatError>(std::move(E));
1235ffd83dbSDimitry Andric 
1245ffd83dbSDimitry Andric   // Create the main remark streamer.
1255ffd83dbSDimitry Andric   Context.setMainRemarkStreamer(std::make_unique<remarks::RemarkStreamer>(
1265ffd83dbSDimitry Andric       std::move(*RemarkSerializer), RemarksFilename));
1275ffd83dbSDimitry Andric 
1285ffd83dbSDimitry Andric   // Create LLVM's optimization remarks streamer.
1295ffd83dbSDimitry Andric   Context.setLLVMRemarkStreamer(
1305ffd83dbSDimitry Andric       std::make_unique<LLVMRemarkStreamer>(*Context.getMainRemarkStreamer()));
1315ffd83dbSDimitry Andric 
1325ffd83dbSDimitry Andric   if (!RemarksPasses.empty())
1335ffd83dbSDimitry Andric     if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses))
1345ffd83dbSDimitry Andric       return make_error<LLVMRemarkSetupPatternError>(std::move(E));
1355ffd83dbSDimitry Andric 
1365ffd83dbSDimitry Andric   return std::move(RemarksFile);
1375ffd83dbSDimitry Andric }
1385ffd83dbSDimitry Andric 
139*e8d8bef9SDimitry Andric Error llvm::setupLLVMOptimizationRemarks(
140*e8d8bef9SDimitry Andric     LLVMContext &Context, raw_ostream &OS, StringRef RemarksPasses,
141*e8d8bef9SDimitry Andric     StringRef RemarksFormat, bool RemarksWithHotness,
142*e8d8bef9SDimitry Andric     Optional<uint64_t> RemarksHotnessThreshold) {
1435ffd83dbSDimitry Andric   if (RemarksWithHotness)
1445ffd83dbSDimitry Andric     Context.setDiagnosticsHotnessRequested(true);
1455ffd83dbSDimitry Andric 
1465ffd83dbSDimitry Andric   Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
1475ffd83dbSDimitry Andric 
1485ffd83dbSDimitry Andric   Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
1495ffd83dbSDimitry Andric   if (Error E = Format.takeError())
1505ffd83dbSDimitry Andric     return make_error<LLVMRemarkSetupFormatError>(std::move(E));
1515ffd83dbSDimitry Andric 
1525ffd83dbSDimitry Andric   Expected<std::unique_ptr<remarks::RemarkSerializer>> RemarkSerializer =
1535ffd83dbSDimitry Andric       remarks::createRemarkSerializer(*Format,
1545ffd83dbSDimitry Andric                                       remarks::SerializerMode::Separate, OS);
1555ffd83dbSDimitry Andric   if (Error E = RemarkSerializer.takeError())
1565ffd83dbSDimitry Andric     return make_error<LLVMRemarkSetupFormatError>(std::move(E));
1575ffd83dbSDimitry Andric 
1585ffd83dbSDimitry Andric   // Create the main remark streamer.
1595ffd83dbSDimitry Andric   Context.setMainRemarkStreamer(
1605ffd83dbSDimitry Andric       std::make_unique<remarks::RemarkStreamer>(std::move(*RemarkSerializer)));
1615ffd83dbSDimitry Andric 
1625ffd83dbSDimitry Andric   // Create LLVM's optimization remarks streamer.
1635ffd83dbSDimitry Andric   Context.setLLVMRemarkStreamer(
1645ffd83dbSDimitry Andric       std::make_unique<LLVMRemarkStreamer>(*Context.getMainRemarkStreamer()));
1655ffd83dbSDimitry Andric 
1665ffd83dbSDimitry Andric   if (!RemarksPasses.empty())
1675ffd83dbSDimitry Andric     if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses))
1685ffd83dbSDimitry Andric       return make_error<LLVMRemarkSetupPatternError>(std::move(E));
1695ffd83dbSDimitry Andric 
1705ffd83dbSDimitry Andric   return Error::success();
1715ffd83dbSDimitry Andric }
172