17531a503SFrancis Visoiu Mistrih //===- llvm/IR/LLVMRemarkStreamer.cpp - Remark Streamer -*- C++ ---------*-===//
27531a503SFrancis Visoiu Mistrih //
37531a503SFrancis Visoiu Mistrih // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47531a503SFrancis Visoiu Mistrih // See https://llvm.org/LICENSE.txt for license information.
57531a503SFrancis Visoiu Mistrih // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67531a503SFrancis Visoiu Mistrih //
77531a503SFrancis Visoiu Mistrih //===----------------------------------------------------------------------===//
87531a503SFrancis Visoiu Mistrih //
97531a503SFrancis Visoiu Mistrih // This file contains the implementation of the conversion between IR
107531a503SFrancis Visoiu Mistrih // Diagnostics and serializable remarks::Remark objects.
117531a503SFrancis Visoiu Mistrih //
127531a503SFrancis Visoiu Mistrih //===----------------------------------------------------------------------===//
137531a503SFrancis Visoiu Mistrih
147531a503SFrancis Visoiu Mistrih #include "llvm/IR/LLVMRemarkStreamer.h"
157531a503SFrancis Visoiu Mistrih #include "llvm/IR/DiagnosticInfo.h"
167531a503SFrancis Visoiu Mistrih #include "llvm/IR/Function.h"
177531a503SFrancis Visoiu Mistrih #include "llvm/IR/GlobalValue.h"
18*e188aae4Sserge-sans-paille #include "llvm/Remarks/RemarkStreamer.h"
19af450eabSReid Kleckner #include "llvm/Support/FileSystem.h"
20*e188aae4Sserge-sans-paille #include "llvm/Support/ToolOutputFile.h"
217531a503SFrancis Visoiu Mistrih
227531a503SFrancis Visoiu Mistrih using namespace llvm;
237531a503SFrancis Visoiu Mistrih
247531a503SFrancis Visoiu Mistrih /// DiagnosticKind -> remarks::Type
toRemarkType(enum DiagnosticKind Kind)257531a503SFrancis Visoiu Mistrih static remarks::Type toRemarkType(enum DiagnosticKind Kind) {
267531a503SFrancis Visoiu Mistrih switch (Kind) {
277531a503SFrancis Visoiu Mistrih default:
287531a503SFrancis Visoiu Mistrih return remarks::Type::Unknown;
297531a503SFrancis Visoiu Mistrih case DK_OptimizationRemark:
307531a503SFrancis Visoiu Mistrih case DK_MachineOptimizationRemark:
317531a503SFrancis Visoiu Mistrih return remarks::Type::Passed;
327531a503SFrancis Visoiu Mistrih case DK_OptimizationRemarkMissed:
337531a503SFrancis Visoiu Mistrih case DK_MachineOptimizationRemarkMissed:
347531a503SFrancis Visoiu Mistrih return remarks::Type::Missed;
357531a503SFrancis Visoiu Mistrih case DK_OptimizationRemarkAnalysis:
367531a503SFrancis Visoiu Mistrih case DK_MachineOptimizationRemarkAnalysis:
377531a503SFrancis Visoiu Mistrih return remarks::Type::Analysis;
387531a503SFrancis Visoiu Mistrih case DK_OptimizationRemarkAnalysisFPCommute:
397531a503SFrancis Visoiu Mistrih return remarks::Type::AnalysisFPCommute;
407531a503SFrancis Visoiu Mistrih case DK_OptimizationRemarkAnalysisAliasing:
417531a503SFrancis Visoiu Mistrih return remarks::Type::AnalysisAliasing;
427531a503SFrancis Visoiu Mistrih case DK_OptimizationFailure:
437531a503SFrancis Visoiu Mistrih return remarks::Type::Failure;
447531a503SFrancis Visoiu Mistrih }
457531a503SFrancis Visoiu Mistrih }
467531a503SFrancis Visoiu Mistrih
477531a503SFrancis Visoiu Mistrih /// DiagnosticLocation -> remarks::RemarkLocation.
487531a503SFrancis Visoiu Mistrih static Optional<remarks::RemarkLocation>
toRemarkLocation(const DiagnosticLocation & DL)497531a503SFrancis Visoiu Mistrih toRemarkLocation(const DiagnosticLocation &DL) {
507531a503SFrancis Visoiu Mistrih if (!DL.isValid())
517531a503SFrancis Visoiu Mistrih return None;
527531a503SFrancis Visoiu Mistrih StringRef File = DL.getRelativePath();
537531a503SFrancis Visoiu Mistrih unsigned Line = DL.getLine();
547531a503SFrancis Visoiu Mistrih unsigned Col = DL.getColumn();
557531a503SFrancis Visoiu Mistrih return remarks::RemarkLocation{File, Line, Col};
567531a503SFrancis Visoiu Mistrih }
577531a503SFrancis Visoiu Mistrih
587531a503SFrancis Visoiu Mistrih /// LLVM Diagnostic -> Remark
597531a503SFrancis Visoiu Mistrih remarks::Remark
toRemark(const DiagnosticInfoOptimizationBase & Diag) const607531a503SFrancis Visoiu Mistrih LLVMRemarkStreamer::toRemark(const DiagnosticInfoOptimizationBase &Diag) const {
617531a503SFrancis Visoiu Mistrih remarks::Remark R; // The result.
627531a503SFrancis Visoiu Mistrih R.RemarkType = toRemarkType(static_cast<DiagnosticKind>(Diag.getKind()));
637531a503SFrancis Visoiu Mistrih R.PassName = Diag.getPassName();
647531a503SFrancis Visoiu Mistrih R.RemarkName = Diag.getRemarkName();
657531a503SFrancis Visoiu Mistrih R.FunctionName =
667531a503SFrancis Visoiu Mistrih GlobalValue::dropLLVMManglingEscape(Diag.getFunction().getName());
677531a503SFrancis Visoiu Mistrih R.Loc = toRemarkLocation(Diag.getLocation());
687531a503SFrancis Visoiu Mistrih R.Hotness = Diag.getHotness();
697531a503SFrancis Visoiu Mistrih
707531a503SFrancis Visoiu Mistrih for (const DiagnosticInfoOptimizationBase::Argument &Arg : Diag.getArgs()) {
717531a503SFrancis Visoiu Mistrih R.Args.emplace_back();
727531a503SFrancis Visoiu Mistrih R.Args.back().Key = Arg.Key;
737531a503SFrancis Visoiu Mistrih R.Args.back().Val = Arg.Val;
747531a503SFrancis Visoiu Mistrih R.Args.back().Loc = toRemarkLocation(Arg.Loc);
757531a503SFrancis Visoiu Mistrih }
767531a503SFrancis Visoiu Mistrih
777531a503SFrancis Visoiu Mistrih return R;
787531a503SFrancis Visoiu Mistrih }
797531a503SFrancis Visoiu Mistrih
emit(const DiagnosticInfoOptimizationBase & Diag)807531a503SFrancis Visoiu Mistrih void LLVMRemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) {
817531a503SFrancis Visoiu Mistrih if (!RS.matchesFilter(Diag.getPassName()))
827531a503SFrancis Visoiu Mistrih return;
837531a503SFrancis Visoiu Mistrih
847531a503SFrancis Visoiu Mistrih // First, convert the diagnostic to a remark.
857531a503SFrancis Visoiu Mistrih remarks::Remark R = toRemark(Diag);
867531a503SFrancis Visoiu Mistrih // Then, emit the remark through the serializer.
877531a503SFrancis Visoiu Mistrih RS.getSerializer().emit(R);
887531a503SFrancis Visoiu Mistrih }
897531a503SFrancis Visoiu Mistrih
907531a503SFrancis Visoiu Mistrih char LLVMRemarkSetupFileError::ID = 0;
917531a503SFrancis Visoiu Mistrih char LLVMRemarkSetupPatternError::ID = 0;
927531a503SFrancis Visoiu Mistrih char LLVMRemarkSetupFormatError::ID = 0;
937531a503SFrancis Visoiu Mistrih
setupLLVMOptimizationRemarks(LLVMContext & Context,StringRef RemarksFilename,StringRef RemarksPasses,StringRef RemarksFormat,bool RemarksWithHotness,Optional<uint64_t> RemarksHotnessThreshold)947531a503SFrancis Visoiu Mistrih Expected<std::unique_ptr<ToolOutputFile>> llvm::setupLLVMOptimizationRemarks(
957531a503SFrancis Visoiu Mistrih LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses,
967531a503SFrancis Visoiu Mistrih StringRef RemarksFormat, bool RemarksWithHotness,
973acda917SWei Wang Optional<uint64_t> RemarksHotnessThreshold) {
987531a503SFrancis Visoiu Mistrih if (RemarksWithHotness)
997531a503SFrancis Visoiu Mistrih Context.setDiagnosticsHotnessRequested(true);
1007531a503SFrancis Visoiu Mistrih
1017531a503SFrancis Visoiu Mistrih Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
1027531a503SFrancis Visoiu Mistrih
1037531a503SFrancis Visoiu Mistrih if (RemarksFilename.empty())
1047531a503SFrancis Visoiu Mistrih return nullptr;
1057531a503SFrancis Visoiu Mistrih
1067531a503SFrancis Visoiu Mistrih Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
1077531a503SFrancis Visoiu Mistrih if (Error E = Format.takeError())
1087531a503SFrancis Visoiu Mistrih return make_error<LLVMRemarkSetupFormatError>(std::move(E));
1097531a503SFrancis Visoiu Mistrih
1107531a503SFrancis Visoiu Mistrih std::error_code EC;
11182b3e28eSAbhina Sreeskantharajan auto Flags = *Format == remarks::Format::YAML ? sys::fs::OF_TextWithCRLF
1127531a503SFrancis Visoiu Mistrih : sys::fs::OF_None;
1137531a503SFrancis Visoiu Mistrih auto RemarksFile =
1147531a503SFrancis Visoiu Mistrih std::make_unique<ToolOutputFile>(RemarksFilename, EC, Flags);
1157531a503SFrancis Visoiu Mistrih // We don't use llvm::FileError here because some diagnostics want the file
1167531a503SFrancis Visoiu Mistrih // name separately.
1177531a503SFrancis Visoiu Mistrih if (EC)
1187531a503SFrancis Visoiu Mistrih return make_error<LLVMRemarkSetupFileError>(errorCodeToError(EC));
1197531a503SFrancis Visoiu Mistrih
1207531a503SFrancis Visoiu Mistrih Expected<std::unique_ptr<remarks::RemarkSerializer>> RemarkSerializer =
1217531a503SFrancis Visoiu Mistrih remarks::createRemarkSerializer(
1227531a503SFrancis Visoiu Mistrih *Format, remarks::SerializerMode::Separate, RemarksFile->os());
1237531a503SFrancis Visoiu Mistrih if (Error E = RemarkSerializer.takeError())
1247531a503SFrancis Visoiu Mistrih return make_error<LLVMRemarkSetupFormatError>(std::move(E));
1257531a503SFrancis Visoiu Mistrih
1267531a503SFrancis Visoiu Mistrih // Create the main remark streamer.
1277531a503SFrancis Visoiu Mistrih Context.setMainRemarkStreamer(std::make_unique<remarks::RemarkStreamer>(
1287531a503SFrancis Visoiu Mistrih std::move(*RemarkSerializer), RemarksFilename));
1297531a503SFrancis Visoiu Mistrih
1307531a503SFrancis Visoiu Mistrih // Create LLVM's optimization remarks streamer.
1317531a503SFrancis Visoiu Mistrih Context.setLLVMRemarkStreamer(
1327531a503SFrancis Visoiu Mistrih std::make_unique<LLVMRemarkStreamer>(*Context.getMainRemarkStreamer()));
1337531a503SFrancis Visoiu Mistrih
1347531a503SFrancis Visoiu Mistrih if (!RemarksPasses.empty())
1357531a503SFrancis Visoiu Mistrih if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses))
1367531a503SFrancis Visoiu Mistrih return make_error<LLVMRemarkSetupPatternError>(std::move(E));
1377531a503SFrancis Visoiu Mistrih
138c55cf4afSBill Wendling return std::move(RemarksFile);
1397531a503SFrancis Visoiu Mistrih }
1407531a503SFrancis Visoiu Mistrih
setupLLVMOptimizationRemarks(LLVMContext & Context,raw_ostream & OS,StringRef RemarksPasses,StringRef RemarksFormat,bool RemarksWithHotness,Optional<uint64_t> RemarksHotnessThreshold)1413acda917SWei Wang Error llvm::setupLLVMOptimizationRemarks(
1423acda917SWei Wang LLVMContext &Context, raw_ostream &OS, StringRef RemarksPasses,
1433acda917SWei Wang StringRef RemarksFormat, bool RemarksWithHotness,
1443acda917SWei Wang Optional<uint64_t> RemarksHotnessThreshold) {
1457531a503SFrancis Visoiu Mistrih if (RemarksWithHotness)
1467531a503SFrancis Visoiu Mistrih Context.setDiagnosticsHotnessRequested(true);
1477531a503SFrancis Visoiu Mistrih
1487531a503SFrancis Visoiu Mistrih Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
1497531a503SFrancis Visoiu Mistrih
1507531a503SFrancis Visoiu Mistrih Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
1517531a503SFrancis Visoiu Mistrih if (Error E = Format.takeError())
1527531a503SFrancis Visoiu Mistrih return make_error<LLVMRemarkSetupFormatError>(std::move(E));
1537531a503SFrancis Visoiu Mistrih
1547531a503SFrancis Visoiu Mistrih Expected<std::unique_ptr<remarks::RemarkSerializer>> RemarkSerializer =
1557531a503SFrancis Visoiu Mistrih remarks::createRemarkSerializer(*Format,
1567531a503SFrancis Visoiu Mistrih remarks::SerializerMode::Separate, OS);
1577531a503SFrancis Visoiu Mistrih if (Error E = RemarkSerializer.takeError())
1587531a503SFrancis Visoiu Mistrih return make_error<LLVMRemarkSetupFormatError>(std::move(E));
1597531a503SFrancis Visoiu Mistrih
1607531a503SFrancis Visoiu Mistrih // Create the main remark streamer.
1617531a503SFrancis Visoiu Mistrih Context.setMainRemarkStreamer(
1627531a503SFrancis Visoiu Mistrih std::make_unique<remarks::RemarkStreamer>(std::move(*RemarkSerializer)));
1637531a503SFrancis Visoiu Mistrih
1647531a503SFrancis Visoiu Mistrih // Create LLVM's optimization remarks streamer.
1657531a503SFrancis Visoiu Mistrih Context.setLLVMRemarkStreamer(
1667531a503SFrancis Visoiu Mistrih std::make_unique<LLVMRemarkStreamer>(*Context.getMainRemarkStreamer()));
1677531a503SFrancis Visoiu Mistrih
1687531a503SFrancis Visoiu Mistrih if (!RemarksPasses.empty())
1697531a503SFrancis Visoiu Mistrih if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses))
1707531a503SFrancis Visoiu Mistrih return make_error<LLVMRemarkSetupPatternError>(std::move(E));
1717531a503SFrancis Visoiu Mistrih
1727531a503SFrancis Visoiu Mistrih return Error::success();
1737531a503SFrancis Visoiu Mistrih }
174