[llvm] r362160 - [Remarks][NFC] Move the serialization to lib/Remarks

Francis Visoiu Mistrih via llvm-commits llvm-commits at lists.llvm.org
Thu May 30 14:46:00 PDT 2019


Author: thegameg
Date: Thu May 30 14:45:59 2019
New Revision: 362160

URL: http://llvm.org/viewvc/llvm-project?rev=362160&view=rev
Log:
[Remarks][NFC] Move the serialization to lib/Remarks

Separate the remark serialization to YAML from the LLVM Diagnostics.

This adds a new serialization abstraction: remarks::Serializer. It's
completely independent from lib/IR and it provides an easy way to
replace YAML by providing a new remarks::Serializer.

Differential Revision: https://reviews.llvm.org/D62632

Added:
    llvm/trunk/include/llvm/Remarks/RemarkSerializer.h
    llvm/trunk/lib/Remarks/YAMLRemarkSerializer.cpp
Modified:
    llvm/trunk/include/llvm/IR/DiagnosticInfo.h
    llvm/trunk/include/llvm/IR/RemarkStreamer.h
    llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
    llvm/trunk/lib/IR/DiagnosticInfo.cpp
    llvm/trunk/lib/IR/RemarkStreamer.cpp
    llvm/trunk/lib/LTO/LTO.cpp
    llvm/trunk/lib/Remarks/CMakeLists.txt
    llvm/trunk/tools/llc/llc.cpp
    llvm/trunk/tools/opt/opt.cpp

Modified: llvm/trunk/include/llvm/IR/DiagnosticInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DiagnosticInfo.h?rev=362160&r1=362159&r2=362160&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DiagnosticInfo.h (original)
+++ llvm/trunk/include/llvm/IR/DiagnosticInfo.h Thu May 30 14:45:59 2019
@@ -465,12 +465,15 @@ public:
   virtual bool isEnabled() const = 0;
 
   StringRef getPassName() const { return PassName; }
+  StringRef getRemarkName() const { return RemarkName; }
   std::string getMsg() const;
   Optional<uint64_t> getHotness() const { return Hotness; }
   void setHotness(Optional<uint64_t> H) { Hotness = H; }
 
   bool isVerbose() const { return IsVerbose; }
 
+  ArrayRef<Argument> getArgs() const { return Args; }
+
   static bool classof(const DiagnosticInfo *DI) {
     return (DI->getKind() >= DK_FirstRemark &&
             DI->getKind() <= DK_LastRemark) ||
@@ -500,7 +503,7 @@ protected:
   const char *PassName;
 
   /// Textual identifier for the remark (single-word, camel-case). Can be used
-  /// by external tools reading the YAML output file for optimization remarks to
+  /// by external tools reading the output file for optimization remarks to
   /// identify the remark.
   StringRef RemarkName;
 
@@ -518,8 +521,6 @@ protected:
   /// the optimization records and not in the remark printed in the compiler
   /// output.
   int FirstExtraArgIndex = -1;
-
-  friend struct yaml::MappingTraits<DiagnosticInfoOptimizationBase *>;
 };
 
 /// Allow the insertion operator to return the actual remark type rather than a
@@ -1001,12 +1002,6 @@ public:
   void print(DiagnosticPrinter &DP) const override;
 };
 
-namespace yaml {
-template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> {
-  static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag);
-};
-} // namespace yaml
-
 } // end namespace llvm
 
 #endif // LLVM_IR_DIAGNOSTICINFO_H

Modified: llvm/trunk/include/llvm/IR/RemarkStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/RemarkStreamer.h?rev=362160&r1=362159&r2=362160&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/RemarkStreamer.h (original)
+++ llvm/trunk/include/llvm/IR/RemarkStreamer.h Thu May 30 14:45:59 2019
@@ -14,10 +14,9 @@
 #define LLVM_IR_REMARKSTREAMER_H
 
 #include "llvm/IR/DiagnosticInfo.h"
-#include "llvm/Remarks/RemarkStringTable.h"
+#include "llvm/Remarks/RemarkSerializer.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/Regex.h"
-#include "llvm/Support/YAMLTraits.h"
 #include "llvm/Support/raw_ostream.h"
 #include <string>
 #include <vector>
@@ -27,33 +26,36 @@ namespace llvm {
 class RemarkStreamer {
   /// The filename that the remark diagnostics are emitted to.
   const std::string Filename;
-  /// The open raw_ostream that the remark diagnostics are emitted to.
-  raw_ostream &OS;
   /// The regex used to filter remarks based on the passes that emit them.
   Optional<Regex> PassFilter;
+  /// The object used to serialize the remarks to a specific format.
+  std::unique_ptr<remarks::Serializer> Serializer;
 
-  /// The YAML streamer.
-  yaml::Output YAMLOutput;
-
-  /// The string table containing all the unique strings used in the output.
-  /// The table will be serialized in a section to be consumed after the
-  /// compilation.
-  remarks::StringTable StrTab;
+  /// Temporary buffer for converting diagnostics into remark objects. This is
+  /// used for the remark arguments that are converted from a vector of
+  /// diagnostic arguments to a vector of remark arguments.
+  SmallVector<remarks::Argument, 8> TmpArgs;
+  /// Convert diagnostics into remark objects. The result uses \p TmpArgs as a
+  /// temporary buffer for the remark arguments, and relies on all the strings
+  /// to be kept in memory until the next call to `toRemark`.
+  /// The lifetime of the members of the result is bound to the lifetime of both
+  /// the remark streamer and the LLVM diagnostics.
+  remarks::Remark toRemark(const DiagnosticInfoOptimizationBase &Diag);
 
 public:
-  RemarkStreamer(StringRef Filename, raw_ostream& OS);
+  RemarkStreamer(StringRef Filename,
+                 std::unique_ptr<remarks::Serializer> Serializer);
   /// Return the filename that the remark diagnostics are emitted to.
   StringRef getFilename() const { return Filename; }
   /// Return stream that the remark diagnostics are emitted to.
-  raw_ostream &getStream() { return OS; }
+  raw_ostream &getStream() { return Serializer->OS; }
+  /// Return the serializer used for this stream.
+  remarks::Serializer &getSerializer() { return *Serializer; }
   /// Set a pass filter based on a regex \p Filter.
   /// Returns an error if the regex is invalid.
   Error setFilter(StringRef Filter);
   /// Emit a diagnostic through the streamer.
   void emit(const DiagnosticInfoOptimizationBase &Diag);
-  /// The string table used during emission.
-  remarks::StringTable &getStringTable() { return StrTab; }
-  const remarks::StringTable &getStringTable() const { return StrTab; }
 };
 } // end namespace llvm
 

Added: llvm/trunk/include/llvm/Remarks/RemarkSerializer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Remarks/RemarkSerializer.h?rev=362160&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Remarks/RemarkSerializer.h (added)
+++ llvm/trunk/include/llvm/Remarks/RemarkSerializer.h Thu May 30 14:45:59 2019
@@ -0,0 +1,68 @@
+//===-- RemarkSerializer.h - Remark serialization interface -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides an interface for serializing remarks to different formats.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_REMARKS_REMARK_SERIALIZER_H
+#define LLVM_REMARKS_REMARK_SERIALIZER_H
+
+#include "llvm/Remarks/Remark.h"
+#include "llvm/Remarks/RemarkStringTable.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+namespace remarks {
+
+/// This is the base class for a remark serializer.
+/// It includes support for using a string table while emitting.
+struct Serializer {
+  /// The open raw_ostream that the remark diagnostics are emitted to.
+  raw_ostream &OS;
+  /// The string table containing all the unique strings used in the output.
+  /// The table can be serialized to be consumed after the compilation.
+  Optional<StringTable> StrTab;
+
+  Serializer(raw_ostream &OS) : OS(OS), StrTab() {}
+
+  /// This is just an interface.
+  virtual ~Serializer() = default;
+  virtual void emit(const Remark &Remark) = 0;
+};
+
+/// Wether the serializer should use a string table while emitting.
+enum class UseStringTable { No, Yes };
+
+/// Serialize the remarks to YAML. One remark entry looks like this:
+/// --- !<TYPE>
+/// Pass:            <PASSNAME>
+/// Name:            <REMARKNAME>
+/// DebugLoc:        { File: <SOURCEFILENAME>, Line: <SOURCELINE>,
+///                    Column: <SOURCECOLUMN> }
+/// Function:        <FUNCTIONNAME>
+/// Args:
+///   - <KEY>: <VALUE>
+///     DebugLoc:        { File: <FILE>, Line: <LINE>, Column: <COL> }
+/// ...
+struct YAMLSerializer : public Serializer {
+  /// The YAML streamer.
+  yaml::Output YAMLOutput;
+
+  YAMLSerializer(raw_ostream &OS,
+                 UseStringTable UseStringTable = UseStringTable::No);
+
+  /// Emit a remark to the stream.
+  void emit(const Remark &Remark) override;
+};
+
+} // end namespace remarks
+} // end namespace llvm
+
+#endif /* LLVM_REMARKS_REMARK_SERIALIZER_H */

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=362160&r1=362159&r2=362160&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Thu May 30 14:45:59 2019
@@ -100,6 +100,7 @@
 #include "llvm/MC/SectionKind.h"
 #include "llvm/Pass.h"
 #include "llvm/Remarks/Remark.h"
+#include "llvm/Remarks/RemarkStringTable.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compiler.h"
@@ -1347,6 +1348,7 @@ void AsmPrinter::emitRemarksSection(Modu
   RemarkStreamer *RS = M.getContext().getRemarkStreamer();
   if (!RS)
     return;
+  const remarks::Serializer &Serializer = RS->getSerializer();
 
   // Switch to the right section: .remarks/__remarks.
   MCSection *RemarksSection =
@@ -1368,23 +1370,27 @@ void AsmPrinter::emitRemarksSection(Modu
   // Note: we need to use the streamer here to emit it in the section. We can't
   // just use the serialize function with a raw_ostream because of the way
   // MCStreamers work.
-  const remarks::StringTable &StrTab = RS->getStringTable();
-  std::vector<StringRef> StrTabStrings = StrTab.serialize();
-  uint64_t StrTabSize = StrTab.SerializedSize;
+  uint64_t StrTabSize =
+      Serializer.StrTab ? Serializer.StrTab->SerializedSize : 0;
   // Emit the total size of the string table (the size itself excluded):
   // little-endian uint64_t.
   // The total size is located after the version number.
+  // Note: even if no string table is used, emit 0.
   std::array<char, 8> StrTabSizeBuf;
   support::endian::write64le(StrTabSizeBuf.data(), StrTabSize);
   OutStreamer->EmitBinaryData(
       StringRef(StrTabSizeBuf.data(), StrTabSizeBuf.size()));
-  // Emit a list of null-terminated strings.
-  // Note: the order is important here: the ID used in the remarks corresponds
-  // to the position of the string in the section.
-  for (StringRef Str : StrTabStrings) {
-    OutStreamer->EmitBytes(Str);
-    // Explicitly emit a '\0'.
-    OutStreamer->EmitIntValue(/*Value=*/0, /*Size=*/1);
+
+  if (const Optional<remarks::StringTable> &StrTab = Serializer.StrTab) {
+    std::vector<StringRef> StrTabStrings = StrTab->serialize();
+    // Emit a list of null-terminated strings.
+    // Note: the order is important here: the ID used in the remarks corresponds
+    // to the position of the string in the section.
+    for (StringRef Str : StrTabStrings) {
+      OutStreamer->EmitBytes(Str);
+      // Explicitly emit a '\0'.
+      OutStreamer->EmitIntValue(/*Value=*/0, /*Size=*/1);
+    }
   }
 
   // Emit the null-terminated absolute path to the remark file.

Modified: llvm/trunk/lib/IR/DiagnosticInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DiagnosticInfo.cpp?rev=362160&r1=362159&r2=362160&view=diff
==============================================================================
--- llvm/trunk/lib/IR/DiagnosticInfo.cpp (original)
+++ llvm/trunk/lib/IR/DiagnosticInfo.cpp Thu May 30 14:45:59 2019
@@ -43,8 +43,6 @@
 
 using namespace llvm;
 
-cl::opt<bool> UseStringTable("remarks-yaml-string-table", cl::init(false));
-
 int llvm::getNextAvailablePluginDiagnosticKind() {
   static std::atomic<int> PluginKindID(DK_FirstPluginKind);
   return ++PluginKindID;
@@ -374,138 +372,3 @@ std::string DiagnosticInfoOptimizationBa
 
 void OptimizationRemarkAnalysisFPCommute::anchor() {}
 void OptimizationRemarkAnalysisAliasing::anchor() {}
-
-template <typename T>
-static void mapRemarkHeader(
-    yaml::IO &io, T PassName, T RemarkName, DiagnosticLocation DL,
-    T FunctionName, Optional<uint64_t> Hotness,
-    SmallVectorImpl<DiagnosticInfoOptimizationBase::Argument> &Args) {
-  io.mapRequired("Pass", PassName);
-  io.mapRequired("Name", RemarkName);
-  if (!io.outputting() || DL.isValid())
-    io.mapOptional("DebugLoc", DL);
-  io.mapRequired("Function", FunctionName);
-  io.mapOptional("Hotness", Hotness);
-  io.mapOptional("Args", Args);
-}
-
-namespace llvm {
-namespace yaml {
-
-void MappingTraits<DiagnosticInfoOptimizationBase *>::mapping(
-    IO &io, DiagnosticInfoOptimizationBase *&OptDiag) {
-  assert(io.outputting() && "input not yet implemented");
-
-  if (io.mapTag("!Passed",
-                (OptDiag->getKind() == DK_OptimizationRemark ||
-                 OptDiag->getKind() == DK_MachineOptimizationRemark)))
-    ;
-  else if (io.mapTag(
-               "!Missed",
-               (OptDiag->getKind() == DK_OptimizationRemarkMissed ||
-                OptDiag->getKind() == DK_MachineOptimizationRemarkMissed)))
-    ;
-  else if (io.mapTag(
-               "!Analysis",
-               (OptDiag->getKind() == DK_OptimizationRemarkAnalysis ||
-                OptDiag->getKind() == DK_MachineOptimizationRemarkAnalysis)))
-    ;
-  else if (io.mapTag("!AnalysisFPCommute",
-                     OptDiag->getKind() ==
-                         DK_OptimizationRemarkAnalysisFPCommute))
-    ;
-  else if (io.mapTag("!AnalysisAliasing",
-                     OptDiag->getKind() ==
-                         DK_OptimizationRemarkAnalysisAliasing))
-    ;
-  else if (io.mapTag("!Failure", OptDiag->getKind() == DK_OptimizationFailure))
-    ;
-  else
-    llvm_unreachable("Unknown remark type");
-
-  // These are read-only for now.
-  DiagnosticLocation DL = OptDiag->getLocation();
-  StringRef FN =
-      GlobalValue::dropLLVMManglingEscape(OptDiag->getFunction().getName());
-
-  StringRef PassName(OptDiag->PassName);
-  if (UseStringTable) {
-    remarks::StringTable &StrTab =
-        reinterpret_cast<RemarkStreamer *>(io.getContext())->getStringTable();
-    unsigned PassID = StrTab.add(PassName).first;
-    unsigned NameID = StrTab.add(OptDiag->RemarkName).first;
-    unsigned FunctionID = StrTab.add(FN).first;
-    mapRemarkHeader(io, PassID, NameID, DL, FunctionID, OptDiag->Hotness,
-                    OptDiag->Args);
-  } else {
-    mapRemarkHeader(io, PassName, OptDiag->RemarkName, DL, FN, OptDiag->Hotness,
-                    OptDiag->Args);
-  }
-}
-
-template <> struct MappingTraits<DiagnosticLocation> {
-  static void mapping(IO &io, DiagnosticLocation &DL) {
-    assert(io.outputting() && "input not yet implemented");
-
-    StringRef File = DL.getRelativePath();
-    unsigned Line = DL.getLine();
-    unsigned Col = DL.getColumn();
-
-    if (UseStringTable) {
-      remarks::StringTable &StrTab =
-          reinterpret_cast<RemarkStreamer *>(io.getContext())->getStringTable();
-      unsigned FileID = StrTab.add(File).first;
-      io.mapRequired("File", FileID);
-    } else {
-      io.mapRequired("File", File);
-    }
-
-    io.mapRequired("Line", Line);
-    io.mapRequired("Column", Col);
-  }
-
-  static const bool flow = true;
-};
-
-/// Helper struct for multiline string block literals. Use this type to preserve
-/// newlines in strings.
-struct StringBlockVal {
-  StringRef Value;
-  StringBlockVal(const std::string &Value) : Value(Value) {}
-};
-
-template <> struct BlockScalarTraits<StringBlockVal> {
-  static void output(const StringBlockVal &S, void *Ctx, raw_ostream &OS) {
-    return ScalarTraits<StringRef>::output(S.Value, Ctx, OS);
-  }
-
-  static StringRef input(StringRef Scalar, void *Ctx, StringBlockVal &S) {
-    return ScalarTraits<StringRef>::input(Scalar, Ctx, S.Value);
-  }
-};
-
-// Implement this as a mapping for now to get proper quotation for the value.
-template <> struct MappingTraits<DiagnosticInfoOptimizationBase::Argument> {
-  static void mapping(IO &io, DiagnosticInfoOptimizationBase::Argument &A) {
-    assert(io.outputting() && "input not yet implemented");
-
-    if (UseStringTable) {
-      remarks::StringTable &StrTab =
-          reinterpret_cast<RemarkStreamer *>(io.getContext())->getStringTable();
-      auto ValueID = StrTab.add(A.Val).first;
-      io.mapRequired(A.Key.data(), ValueID);
-    } else if (StringRef(A.Val).count('\n') > 1) {
-      StringBlockVal S(A.Val);
-      io.mapRequired(A.Key.data(), S);
-    } else {
-      io.mapRequired(A.Key.data(), A.Val);
-    }
-    if (A.Loc.isValid())
-      io.mapOptional("DebugLoc", A.Loc);
-  }
-};
-
-} // end namespace yaml
-} // end namespace llvm
-
-LLVM_YAML_IS_SEQUENCE_VECTOR(DiagnosticInfoOptimizationBase::Argument)

Modified: llvm/trunk/lib/IR/RemarkStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/RemarkStreamer.cpp?rev=362160&r1=362159&r2=362160&view=diff
==============================================================================
--- llvm/trunk/lib/IR/RemarkStreamer.cpp (original)
+++ llvm/trunk/lib/IR/RemarkStreamer.cpp Thu May 30 14:45:59 2019
@@ -12,12 +12,15 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/IR/RemarkStreamer.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalValue.h"
 
 using namespace llvm;
 
-RemarkStreamer::RemarkStreamer(StringRef Filename, raw_ostream &OS)
-    : Filename(Filename), OS(OS),
-      YAMLOutput(OS, reinterpret_cast<void *>(this)), StrTab() {
+RemarkStreamer::RemarkStreamer(StringRef Filename,
+                               std::unique_ptr<remarks::Serializer> Serializer)
+    : Filename(Filename), PassFilter(), Serializer(std::move(Serializer)) {
   assert(!Filename.empty() && "This needs to be a real filename.");
 }
 
@@ -31,12 +34,75 @@ Error RemarkStreamer::setFilter(StringRe
   return Error::success();
 }
 
+/// DiagnosticKind -> remarks::Type
+static remarks::Type toRemarkType(enum DiagnosticKind Kind) {
+  switch (Kind) {
+  default:
+    return remarks::Type::Unknown;
+  case DK_OptimizationRemark:
+  case DK_MachineOptimizationRemark:
+    return remarks::Type::Passed;
+  case DK_OptimizationRemarkMissed:
+  case DK_MachineOptimizationRemarkMissed:
+    return remarks::Type::Missed;
+  case DK_OptimizationRemarkAnalysis:
+  case DK_MachineOptimizationRemarkAnalysis:
+    return remarks::Type::Analysis;
+  case DK_OptimizationRemarkAnalysisFPCommute:
+    return remarks::Type::AnalysisFPCommute;
+  case DK_OptimizationRemarkAnalysisAliasing:
+    return remarks::Type::AnalysisAliasing;
+  case DK_OptimizationFailure:
+    return remarks::Type::Failure;
+  }
+}
+
+/// DiagnosticLocation -> remarks::RemarkLocation.
+static Optional<remarks::RemarkLocation>
+toRemarkLocation(const DiagnosticLocation &DL) {
+  if (!DL.isValid())
+    return None;
+  StringRef File = DL.getRelativePath();
+  unsigned Line = DL.getLine();
+  unsigned Col = DL.getColumn();
+  return remarks::RemarkLocation{File, Line, Col};
+}
+
+/// LLVM Diagnostic -> Remark
+remarks::Remark
+RemarkStreamer::toRemark(const DiagnosticInfoOptimizationBase &Diag) {
+  // Re-use the buffer.
+  TmpArgs.clear();
+
+  remarks::Remark R; // The result.
+  R.RemarkType = toRemarkType(static_cast<DiagnosticKind>(Diag.getKind()));
+  R.PassName = Diag.getPassName();
+  R.RemarkName = Diag.getRemarkName();
+  R.FunctionName =
+      GlobalValue::dropLLVMManglingEscape(Diag.getFunction().getName());
+  R.Loc = toRemarkLocation(Diag.getLocation());
+  R.Hotness = Diag.getHotness();
+
+  // Use TmpArgs to build the list of arguments and re-use the memory allocated
+  // from previous remark conversions.
+  for (const DiagnosticInfoOptimizationBase::Argument &Arg : Diag.getArgs()) {
+    TmpArgs.emplace_back();
+    TmpArgs.back().Key = Arg.Key;
+    TmpArgs.back().Val = Arg.Val;
+    TmpArgs.back().Loc = toRemarkLocation(Arg.Loc);
+  }
+  R.Args = TmpArgs; // This is valid until the next call to this function.
+
+  return R;
+}
+
 void RemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) {
   if (Optional<Regex> &Filter = PassFilter)
     if (!Filter->match(Diag.getPassName()))
       return;
 
-  DiagnosticInfoOptimizationBase *DiagPtr =
-      const_cast<DiagnosticInfoOptimizationBase *>(&Diag);
-  YAMLOutput << DiagPtr;
+  // First, convert the diagnostic to a remark.
+  remarks::Remark R = toRemark(Diag);
+  // Then, emit the remark through the serializer.
+  Serializer->emit(R);
 }

Modified: llvm/trunk/lib/LTO/LTO.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTO.cpp?rev=362160&r1=362159&r2=362160&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/LTO.cpp (original)
+++ llvm/trunk/lib/LTO/LTO.cpp Thu May 30 14:45:59 2019
@@ -1356,8 +1356,9 @@ lto::setupOptimizationRemarks(LLVMContex
       llvm::make_unique<ToolOutputFile>(Filename, EC, sys::fs::F_None);
   if (EC)
     return errorCodeToError(EC);
-  Context.setRemarkStreamer(
-      llvm::make_unique<RemarkStreamer>(Filename, DiagnosticFile->os()));
+  Context.setRemarkStreamer(llvm::make_unique<RemarkStreamer>(
+      Filename,
+      llvm::make_unique<remarks::YAMLSerializer>(DiagnosticFile->os())));
 
   if (!LTORemarksPasses.empty())
     if (Error E = Context.getRemarkStreamer()->setFilter(LTORemarksPasses))

Modified: llvm/trunk/lib/Remarks/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Remarks/CMakeLists.txt?rev=362160&r1=362159&r2=362160&view=diff
==============================================================================
--- llvm/trunk/lib/Remarks/CMakeLists.txt (original)
+++ llvm/trunk/lib/Remarks/CMakeLists.txt Thu May 30 14:45:59 2019
@@ -3,4 +3,5 @@ add_llvm_library(LLVMRemarks
   RemarkParser.cpp
   RemarkStringTable.cpp
   YAMLRemarkParser.cpp
+  YAMLRemarkSerializer.cpp
 )

Added: llvm/trunk/lib/Remarks/YAMLRemarkSerializer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Remarks/YAMLRemarkSerializer.cpp?rev=362160&view=auto
==============================================================================
--- llvm/trunk/lib/Remarks/YAMLRemarkSerializer.cpp (added)
+++ llvm/trunk/lib/Remarks/YAMLRemarkSerializer.cpp Thu May 30 14:45:59 2019
@@ -0,0 +1,166 @@
+//===- YAMLRemarkSerializer.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the implementation of the YAML remark serializer using
+// LLVM's YAMLTraits.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Remarks/RemarkSerializer.h"
+#include "llvm/Support/CommandLine.h"
+
+using namespace llvm;
+using namespace llvm::remarks;
+
+cl::opt<bool> RemarksYAMLStringTable("remarks-yaml-string-table",
+                                     cl::init(false));
+
+// Use the same keys whether we use a string table or not (respectively, T is an
+// unsigned or a StringRef).
+template <typename T>
+static void mapRemarkHeader(yaml::IO &io, T PassName, T RemarkName,
+                            Optional<RemarkLocation> RL, T FunctionName,
+                            Optional<uint64_t> Hotness,
+                            ArrayRef<Argument> Args) {
+  io.mapRequired("Pass", PassName);
+  io.mapRequired("Name", RemarkName);
+  io.mapOptional("DebugLoc", RL);
+  io.mapRequired("Function", FunctionName);
+  io.mapOptional("Hotness", Hotness);
+  io.mapOptional("Args", Args);
+}
+
+namespace llvm {
+namespace yaml {
+
+template <> struct MappingTraits<remarks::Remark *> {
+  static void mapping(IO &io, remarks::Remark *&Remark) {
+    assert(io.outputting() && "input not yet implemented");
+
+    if (io.mapTag("!Passed", (Remark->RemarkType == Type::Passed)))
+      ;
+    else if (io.mapTag("!Missed", (Remark->RemarkType == Type::Missed)))
+      ;
+    else if (io.mapTag("!Analysis", (Remark->RemarkType == Type::Analysis)))
+      ;
+    else if (io.mapTag("!AnalysisFPCommute",
+                       (Remark->RemarkType == Type::AnalysisFPCommute)))
+      ;
+    else if (io.mapTag("!AnalysisAliasing",
+                       (Remark->RemarkType == Type::AnalysisAliasing)))
+      ;
+    else if (io.mapTag("!Failure", (Remark->RemarkType == Type::Failure)))
+      ;
+    else
+      llvm_unreachable("Unknown remark type");
+
+    if (Optional<StringTable> &StrTab =
+            reinterpret_cast<YAMLSerializer *>(io.getContext())->StrTab) {
+      unsigned PassID = StrTab->add(Remark->PassName).first;
+      unsigned NameID = StrTab->add(Remark->RemarkName).first;
+      unsigned FunctionID = StrTab->add(Remark->FunctionName).first;
+      mapRemarkHeader(io, PassID, NameID, Remark->Loc, FunctionID,
+                      Remark->Hotness, Remark->Args);
+    } else {
+      mapRemarkHeader(io, Remark->PassName, Remark->RemarkName, Remark->Loc,
+                      Remark->FunctionName, Remark->Hotness, Remark->Args);
+    }
+  }
+};
+
+template <> struct MappingTraits<RemarkLocation> {
+  static void mapping(IO &io, RemarkLocation &RL) {
+    assert(io.outputting() && "input not yet implemented");
+
+    StringRef File = RL.SourceFilePath;
+    unsigned Line = RL.SourceLine;
+    unsigned Col = RL.SourceColumn;
+
+    if (Optional<StringTable> &StrTab =
+            reinterpret_cast<YAMLSerializer *>(io.getContext())->StrTab) {
+      unsigned FileID = StrTab->add(File).first;
+      io.mapRequired("File", FileID);
+    } else {
+      io.mapRequired("File", File);
+    }
+
+    io.mapRequired("Line", Line);
+    io.mapRequired("Column", Col);
+  }
+
+  static const bool flow = true;
+};
+
+/// Helper struct for multiline string block literals. Use this type to preserve
+/// newlines in strings.
+struct StringBlockVal {
+  StringRef Value;
+  StringBlockVal(const std::string &Value) : Value(Value) {}
+};
+
+template <> struct BlockScalarTraits<StringBlockVal> {
+  static void output(const StringBlockVal &S, void *Ctx, raw_ostream &OS) {
+    return ScalarTraits<StringRef>::output(S.Value, Ctx, OS);
+  }
+
+  static StringRef input(StringRef Scalar, void *Ctx, StringBlockVal &S) {
+    return ScalarTraits<StringRef>::input(Scalar, Ctx, S.Value);
+  }
+};
+
+/// ArrayRef is not really compatible with the YAMLTraits. Everything should be
+/// immutable in an ArrayRef, while the SequenceTraits expect a mutable version
+/// for inputting, but we're only using the outputting capabilities here.
+/// This is a hack, but still nicer than having to manually call the YAMLIO
+/// internal methods.
+/// Keep this in this file so that it doesn't get misused from YAMLTraits.h.
+template <typename T> struct SequenceTraits<ArrayRef<T>> {
+  static size_t size(IO &io, ArrayRef<T> &seq) { return seq.size(); }
+  static Argument &element(IO &io, ArrayRef<T> &seq, size_t index) {
+    assert(io.outputting() && "input not yet implemented");
+    // The assert above should make this "safer" to satisfy the YAMLTraits.
+    return const_cast<T &>(seq[index]);
+  }
+};
+
+/// Implement this as a mapping for now to get proper quotation for the value.
+template <> struct MappingTraits<Argument> {
+  static void mapping(IO &io, Argument &A) {
+    assert(io.outputting() && "input not yet implemented");
+
+    if (Optional<StringTable> &StrTab =
+            reinterpret_cast<YAMLSerializer *>(io.getContext())->StrTab) {
+      auto ValueID = StrTab->add(A.Val).first;
+      io.mapRequired(A.Key.data(), ValueID);
+    } else if (StringRef(A.Val).count('\n') > 1) {
+      StringBlockVal S(A.Val);
+      io.mapRequired(A.Key.data(), S);
+    } else {
+      io.mapRequired(A.Key.data(), A.Val);
+    }
+    io.mapOptional("DebugLoc", A.Loc);
+  }
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(Argument)
+
+YAMLSerializer::YAMLSerializer(raw_ostream &OS, UseStringTable UseStringTable)
+    : Serializer(OS), YAMLOutput(OS, reinterpret_cast<void *>(this)) {
+  if (UseStringTable == UseStringTable::Yes || RemarksYAMLStringTable)
+    StrTab.emplace();
+}
+
+void YAMLSerializer::emit(const Remark &Remark) {
+  // Again, YAMLTraits expect a non-const object for inputting, but we're not
+  // using that here.
+  auto R = const_cast<remarks::Remark *>(&Remark);
+  YAMLOutput << R;
+}

Modified: llvm/trunk/tools/llc/llc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llc/llc.cpp?rev=362160&r1=362159&r2=362160&view=diff
==============================================================================
--- llvm/trunk/tools/llc/llc.cpp (original)
+++ llvm/trunk/tools/llc/llc.cpp Thu May 30 14:45:59 2019
@@ -340,8 +340,9 @@ int main(int argc, char **argv) {
       WithColor::error(errs(), argv[0]) << EC.message() << '\n';
       return 1;
     }
-    Context.setRemarkStreamer(
-        llvm::make_unique<RemarkStreamer>(RemarksFilename, YamlFile->os()));
+    Context.setRemarkStreamer(llvm::make_unique<RemarkStreamer>(
+        RemarksFilename,
+        llvm::make_unique<remarks::YAMLSerializer>(YamlFile->os())));
 
     if (!RemarksPasses.empty())
       if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses)) {

Modified: llvm/trunk/tools/opt/opt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/opt.cpp?rev=362160&r1=362159&r2=362160&view=diff
==============================================================================
--- llvm/trunk/tools/opt/opt.cpp (original)
+++ llvm/trunk/tools/opt/opt.cpp Thu May 30 14:45:59 2019
@@ -563,7 +563,8 @@ int main(int argc, char **argv) {
       return 1;
     }
     Context.setRemarkStreamer(llvm::make_unique<RemarkStreamer>(
-        RemarksFilename, OptRemarkFile->os()));
+        RemarksFilename,
+        llvm::make_unique<remarks::YAMLSerializer>(OptRemarkFile->os())));
 
     if (!RemarksPasses.empty())
       if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses)) {




More information about the llvm-commits mailing list