LLVMRemarkStreamer.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. //===- llvm/IR/LLVMRemarkStreamer.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 conversion between IR
  10. // Diagnostics and serializable remarks::Remark objects.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/IR/LLVMRemarkStreamer.h"
  14. #include "llvm/IR/DiagnosticInfo.h"
  15. #include "llvm/IR/Function.h"
  16. #include "llvm/IR/GlobalValue.h"
  17. #include "llvm/Remarks/RemarkStreamer.h"
  18. #include "llvm/Support/FileSystem.h"
  19. #include "llvm/Support/ToolOutputFile.h"
  20. using namespace llvm;
  21. /// DiagnosticKind -> remarks::Type
  22. static remarks::Type toRemarkType(enum DiagnosticKind Kind) {
  23. switch (Kind) {
  24. default:
  25. return remarks::Type::Unknown;
  26. case DK_OptimizationRemark:
  27. case DK_MachineOptimizationRemark:
  28. return remarks::Type::Passed;
  29. case DK_OptimizationRemarkMissed:
  30. case DK_MachineOptimizationRemarkMissed:
  31. return remarks::Type::Missed;
  32. case DK_OptimizationRemarkAnalysis:
  33. case DK_MachineOptimizationRemarkAnalysis:
  34. return remarks::Type::Analysis;
  35. case DK_OptimizationRemarkAnalysisFPCommute:
  36. return remarks::Type::AnalysisFPCommute;
  37. case DK_OptimizationRemarkAnalysisAliasing:
  38. return remarks::Type::AnalysisAliasing;
  39. case DK_OptimizationFailure:
  40. return remarks::Type::Failure;
  41. }
  42. }
  43. /// DiagnosticLocation -> remarks::RemarkLocation.
  44. static Optional<remarks::RemarkLocation>
  45. toRemarkLocation(const DiagnosticLocation &DL) {
  46. if (!DL.isValid())
  47. return None;
  48. StringRef File = DL.getRelativePath();
  49. unsigned Line = DL.getLine();
  50. unsigned Col = DL.getColumn();
  51. return remarks::RemarkLocation{File, Line, Col};
  52. }
  53. /// LLVM Diagnostic -> Remark
  54. remarks::Remark
  55. LLVMRemarkStreamer::toRemark(const DiagnosticInfoOptimizationBase &Diag) const {
  56. remarks::Remark R; // The result.
  57. R.RemarkType = toRemarkType(static_cast<DiagnosticKind>(Diag.getKind()));
  58. R.PassName = Diag.getPassName();
  59. R.RemarkName = Diag.getRemarkName();
  60. R.FunctionName =
  61. GlobalValue::dropLLVMManglingEscape(Diag.getFunction().getName());
  62. R.Loc = toRemarkLocation(Diag.getLocation());
  63. R.Hotness = Diag.getHotness();
  64. for (const DiagnosticInfoOptimizationBase::Argument &Arg : Diag.getArgs()) {
  65. R.Args.emplace_back();
  66. R.Args.back().Key = Arg.Key;
  67. R.Args.back().Val = Arg.Val;
  68. R.Args.back().Loc = toRemarkLocation(Arg.Loc);
  69. }
  70. return R;
  71. }
  72. void LLVMRemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) {
  73. if (!RS.matchesFilter(Diag.getPassName()))
  74. return;
  75. // First, convert the diagnostic to a remark.
  76. remarks::Remark R = toRemark(Diag);
  77. // Then, emit the remark through the serializer.
  78. RS.getSerializer().emit(R);
  79. }
  80. char LLVMRemarkSetupFileError::ID = 0;
  81. char LLVMRemarkSetupPatternError::ID = 0;
  82. char LLVMRemarkSetupFormatError::ID = 0;
  83. Expected<std::unique_ptr<ToolOutputFile>> llvm::setupLLVMOptimizationRemarks(
  84. LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses,
  85. StringRef RemarksFormat, bool RemarksWithHotness,
  86. Optional<uint64_t> RemarksHotnessThreshold) {
  87. if (RemarksWithHotness)
  88. Context.setDiagnosticsHotnessRequested(true);
  89. Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
  90. if (RemarksFilename.empty())
  91. return nullptr;
  92. Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
  93. if (Error E = Format.takeError())
  94. return make_error<LLVMRemarkSetupFormatError>(std::move(E));
  95. std::error_code EC;
  96. auto Flags = *Format == remarks::Format::YAML ? sys::fs::OF_TextWithCRLF
  97. : sys::fs::OF_None;
  98. auto RemarksFile =
  99. std::make_unique<ToolOutputFile>(RemarksFilename, EC, Flags);
  100. // We don't use llvm::FileError here because some diagnostics want the file
  101. // name separately.
  102. if (EC)
  103. return make_error<LLVMRemarkSetupFileError>(errorCodeToError(EC));
  104. Expected<std::unique_ptr<remarks::RemarkSerializer>> RemarkSerializer =
  105. remarks::createRemarkSerializer(
  106. *Format, remarks::SerializerMode::Separate, RemarksFile->os());
  107. if (Error E = RemarkSerializer.takeError())
  108. return make_error<LLVMRemarkSetupFormatError>(std::move(E));
  109. // Create the main remark streamer.
  110. Context.setMainRemarkStreamer(std::make_unique<remarks::RemarkStreamer>(
  111. std::move(*RemarkSerializer), RemarksFilename));
  112. // Create LLVM's optimization remarks streamer.
  113. Context.setLLVMRemarkStreamer(
  114. std::make_unique<LLVMRemarkStreamer>(*Context.getMainRemarkStreamer()));
  115. if (!RemarksPasses.empty())
  116. if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses))
  117. return make_error<LLVMRemarkSetupPatternError>(std::move(E));
  118. return std::move(RemarksFile);
  119. }
  120. Error llvm::setupLLVMOptimizationRemarks(
  121. LLVMContext &Context, raw_ostream &OS, StringRef RemarksPasses,
  122. StringRef RemarksFormat, bool RemarksWithHotness,
  123. Optional<uint64_t> RemarksHotnessThreshold) {
  124. if (RemarksWithHotness)
  125. Context.setDiagnosticsHotnessRequested(true);
  126. Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
  127. Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
  128. if (Error E = Format.takeError())
  129. return make_error<LLVMRemarkSetupFormatError>(std::move(E));
  130. Expected<std::unique_ptr<remarks::RemarkSerializer>> RemarkSerializer =
  131. remarks::createRemarkSerializer(*Format,
  132. remarks::SerializerMode::Separate, OS);
  133. if (Error E = RemarkSerializer.takeError())
  134. return make_error<LLVMRemarkSetupFormatError>(std::move(E));
  135. // Create the main remark streamer.
  136. Context.setMainRemarkStreamer(
  137. std::make_unique<remarks::RemarkStreamer>(std::move(*RemarkSerializer)));
  138. // Create LLVM's optimization remarks streamer.
  139. Context.setLLVMRemarkStreamer(
  140. std::make_unique<LLVMRemarkStreamer>(*Context.getMainRemarkStreamer()));
  141. if (!RemarksPasses.empty())
  142. if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses))
  143. return make_error<LLVMRemarkSetupPatternError>(std::move(E));
  144. return Error::success();
  145. }