[llvm] [memprof] Move YAML support to MemProfYAML.h (NFC) (PR #119515)

Kazu Hirata via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 10 23:04:25 PST 2024


https://github.com/kazutakahirata created https://github.com/llvm/llvm-project/pull/119515

The YAML support is increasing in size, so this patch moves it to a
separate file.


>From b759270100596e41be9f66d51add4c5e63487e4b Mon Sep 17 00:00:00 2001
From: Kazu Hirata <kazu at google.com>
Date: Tue, 10 Dec 2024 22:39:58 -0800
Subject: [PATCH] [memprof] Move YAML support to MemProfYAML.h (NFC)

The YAML support is increasing in size, so this patch moves it to a
separate file.
---
 .../llvm/ProfileData/InstrProfReader.h        |   1 +
 llvm/include/llvm/ProfileData/MemProf.h       | 144 ----------------
 llvm/include/llvm/ProfileData/MemProfYAML.h   | 154 ++++++++++++++++++
 llvm/lib/ProfileData/MemProfReader.cpp        |   1 +
 llvm/tools/llvm-profdata/llvm-profdata.cpp    |   1 +
 llvm/unittests/ProfileData/MemProfTest.cpp    |   1 +
 6 files changed, 158 insertions(+), 144 deletions(-)
 create mode 100644 llvm/include/llvm/ProfileData/MemProfYAML.h

diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h
index 25e13f575296dd..f1010b312ee569 100644
--- a/llvm/include/llvm/ProfileData/InstrProfReader.h
+++ b/llvm/include/llvm/ProfileData/InstrProfReader.h
@@ -21,6 +21,7 @@
 #include "llvm/ProfileData/InstrProf.h"
 #include "llvm/ProfileData/InstrProfCorrelator.h"
 #include "llvm/ProfileData/MemProf.h"
+#include "llvm/ProfileData/MemProfYAML.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/LineIterator.h"
diff --git a/llvm/include/llvm/ProfileData/MemProf.h b/llvm/include/llvm/ProfileData/MemProf.h
index ace3c044d8c277..ef96b74c9d400c 100644
--- a/llvm/include/llvm/ProfileData/MemProf.h
+++ b/llvm/include/llvm/ProfileData/MemProf.h
@@ -11,9 +11,7 @@
 #include "llvm/Support/BLAKE3.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/EndianStream.h"
-#include "llvm/Support/Format.h"
 #include "llvm/Support/HashBuilder.h"
-#include "llvm/Support/YAMLTraits.h"
 #include "llvm/Support/raw_ostream.h"
 
 #include <bitset>
@@ -492,23 +490,6 @@ struct MemProfRecord {
   }
 };
 
-// A "typedef" for GUID.  See ScalarTraits<memprof::GUIDHex64> for how a GUID is
-// serialized and deserialized in YAML.
-LLVM_YAML_STRONG_TYPEDEF(uint64_t, GUIDHex64)
-
-// Helper struct for AllMemProfData.  In YAML, we treat the GUID and the fields
-// within MemProfRecord at the same level as if the GUID were part of
-// MemProfRecord.
-struct GUIDMemProfRecordPair {
-  GUIDHex64 GUID;
-  MemProfRecord Record;
-};
-
-// The top-level data structure, only used with YAML for now.
-struct AllMemProfData {
-  std::vector<GUIDMemProfRecordPair> HeapProfileRecords;
-};
-
 // Reads a memprof schema from a buffer. All entries in the buffer are
 // interpreted as uint64_t. The first entry in the buffer denotes the number of
 // ids in the schema. Subsequent entries are integers which map to memprof::Meta
@@ -1169,131 +1150,6 @@ template <typename FrameIdTy> class CallStackRadixTreeBuilder {
   }
 };
 } // namespace memprof
-
-namespace yaml {
-template <> struct ScalarTraits<memprof::GUIDHex64> {
-  static void output(const memprof::GUIDHex64 &Val, void *, raw_ostream &Out) {
-    // Print GUID as a 16-digit hexadecimal number.
-    Out << format("0x%016" PRIx64, (uint64_t)Val);
-  }
-  static StringRef input(StringRef Scalar, void *, memprof::GUIDHex64 &Val) {
-    // Reject decimal GUIDs.
-    if (all_of(Scalar, [](char C) { return std::isdigit(C); }))
-      return "use a hexadecimal GUID or a function instead";
-
-    uint64_t Num;
-    if (Scalar.starts_with_insensitive("0x")) {
-      // Accept hexadecimal numbers starting with 0x or 0X.
-      if (Scalar.getAsInteger(0, Num))
-        return "invalid hex64 number";
-      Val = Num;
-    } else {
-      // Otherwise, treat the input as a string containing a function name.
-      Val = memprof::IndexedMemProfRecord::getGUID(Scalar);
-    }
-    return StringRef();
-  }
-  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
-};
-
-template <> struct MappingTraits<memprof::Frame> {
-  static void mapping(IO &Io, memprof::Frame &F) {
-    Io.mapRequired("Function", F.Function);
-    Io.mapRequired("LineOffset", F.LineOffset);
-    Io.mapRequired("Column", F.Column);
-    Io.mapRequired("IsInlineFrame", F.IsInlineFrame);
-
-    // Assert that the definition of Frame matches what we expect.  The
-    // structured bindings below detect changes to the number of fields.
-    // static_assert checks the type of each field.
-    const auto &[Function, SymbolName, LineOffset, Column, IsInlineFrame] = F;
-    static_assert(
-        std::is_same_v<remove_cvref_t<decltype(Function)>, GlobalValue::GUID>);
-    static_assert(std::is_same_v<remove_cvref_t<decltype(SymbolName)>,
-                                 std::unique_ptr<std::string>>);
-    static_assert(
-        std::is_same_v<remove_cvref_t<decltype(LineOffset)>, uint32_t>);
-    static_assert(std::is_same_v<remove_cvref_t<decltype(Column)>, uint32_t>);
-    static_assert(
-        std::is_same_v<remove_cvref_t<decltype(IsInlineFrame)>, bool>);
-
-    // MSVC issues unused variable warnings despite the uses in static_assert
-    // above.
-    (void)Function;
-    (void)SymbolName;
-    (void)LineOffset;
-    (void)Column;
-    (void)IsInlineFrame;
-  }
-
-  // Request the inline notation for brevity:
-  //   { Function: 123, LineOffset: 11, Column: 10; IsInlineFrame: true }
-  static const bool flow = true;
-};
-
-template <> struct CustomMappingTraits<memprof::PortableMemInfoBlock> {
-  static void inputOne(IO &Io, StringRef KeyStr,
-                       memprof::PortableMemInfoBlock &MIB) {
-    // PortableMemInfoBlock keeps track of the set of fields that actually have
-    // values.  We update the set here as we receive a key-value pair from the
-    // YAML document.
-    //
-    // We set MIB.Name via a temporary variable because ScalarTraits<uintptr_t>
-    // isn't available on macOS.
-#define MIBEntryDef(NameTag, Name, Type)                                       \
-  if (KeyStr == #Name) {                                                       \
-    uint64_t Value;                                                            \
-    Io.mapRequired(KeyStr.str().c_str(), Value);                               \
-    MIB.Name = static_cast<Type>(Value);                                       \
-    MIB.Schema.set(llvm::to_underlying(memprof::Meta::Name));                  \
-    return;                                                                    \
-  }
-#include "llvm/ProfileData/MIBEntryDef.inc"
-#undef MIBEntryDef
-    Io.setError("Key is not a valid validation event");
-  }
-
-  static void output(IO &Io, memprof::PortableMemInfoBlock &MIB) {
-    auto Schema = MIB.getSchema();
-#define MIBEntryDef(NameTag, Name, Type)                                       \
-  if (Schema.test(llvm::to_underlying(memprof::Meta::Name))) {                 \
-    uint64_t Value = MIB.Name;                                                 \
-    Io.mapRequired(#Name, Value);                                              \
-  }
-#include "llvm/ProfileData/MIBEntryDef.inc"
-#undef MIBEntryDef
-  }
-};
-
-template <> struct MappingTraits<memprof::AllocationInfo> {
-  static void mapping(IO &Io, memprof::AllocationInfo &AI) {
-    Io.mapRequired("Callstack", AI.CallStack);
-    Io.mapRequired("MemInfoBlock", AI.Info);
-  }
-};
-
-// In YAML, we use GUIDMemProfRecordPair instead of MemProfRecord so that we can
-// treat the GUID and the fields within MemProfRecord at the same level as if
-// the GUID were part of MemProfRecord.
-template <> struct MappingTraits<memprof::GUIDMemProfRecordPair> {
-  static void mapping(IO &Io, memprof::GUIDMemProfRecordPair &Pair) {
-    Io.mapRequired("GUID", Pair.GUID);
-    Io.mapRequired("AllocSites", Pair.Record.AllocSites);
-    Io.mapRequired("CallSites", Pair.Record.CallSites);
-  }
-};
-
-template <> struct MappingTraits<memprof::AllMemProfData> {
-  static void mapping(IO &Io, memprof::AllMemProfData &Data) {
-    Io.mapRequired("HeapProfileRecords", Data.HeapProfileRecords);
-  }
-};
-} // namespace yaml
 } // namespace llvm
 
-LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::Frame)
-LLVM_YAML_IS_SEQUENCE_VECTOR(std::vector<memprof::Frame>)
-LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::AllocationInfo)
-LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::GUIDMemProfRecordPair)
-
 #endif // LLVM_PROFILEDATA_MEMPROF_H_
diff --git a/llvm/include/llvm/ProfileData/MemProfYAML.h b/llvm/include/llvm/ProfileData/MemProfYAML.h
new file mode 100644
index 00000000000000..4568385fc6f71f
--- /dev/null
+++ b/llvm/include/llvm/ProfileData/MemProfYAML.h
@@ -0,0 +1,154 @@
+#ifndef LLVM_PROFILEDATA_MEMPROFYAML_H_
+#define LLVM_PROFILEDATA_MEMPROFYAML_H_
+
+#include "llvm/ProfileData/MemProf.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/YAMLTraits.h"
+
+namespace llvm {
+namespace memprof {
+// A "typedef" for GUID.  See ScalarTraits<memprof::GUIDHex64> for how a GUID is
+// serialized and deserialized in YAML.
+LLVM_YAML_STRONG_TYPEDEF(uint64_t, GUIDHex64)
+
+// Helper struct for AllMemProfData.  In YAML, we treat the GUID and the fields
+// within MemProfRecord at the same level as if the GUID were part of
+// MemProfRecord.
+struct GUIDMemProfRecordPair {
+  GUIDHex64 GUID;
+  MemProfRecord Record;
+};
+
+// The top-level data structure, only used with YAML for now.
+struct AllMemProfData {
+  std::vector<GUIDMemProfRecordPair> HeapProfileRecords;
+};
+} // namespace memprof
+
+namespace yaml {
+template <> struct ScalarTraits<memprof::GUIDHex64> {
+  static void output(const memprof::GUIDHex64 &Val, void *, raw_ostream &Out) {
+    // Print GUID as a 16-digit hexadecimal number.
+    Out << format("0x%016" PRIx64, (uint64_t)Val);
+  }
+  static StringRef input(StringRef Scalar, void *, memprof::GUIDHex64 &Val) {
+    // Reject decimal GUIDs.
+    if (all_of(Scalar, [](char C) { return std::isdigit(C); }))
+      return "use a hexadecimal GUID or a function instead";
+
+    uint64_t Num;
+    if (Scalar.starts_with_insensitive("0x")) {
+      // Accept hexadecimal numbers starting with 0x or 0X.
+      if (Scalar.getAsInteger(0, Num))
+        return "invalid hex64 number";
+      Val = Num;
+    } else {
+      // Otherwise, treat the input as a string containing a function name.
+      Val = memprof::IndexedMemProfRecord::getGUID(Scalar);
+    }
+    return StringRef();
+  }
+  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template <> struct MappingTraits<memprof::Frame> {
+  static void mapping(IO &Io, memprof::Frame &F) {
+    Io.mapRequired("Function", F.Function);
+    Io.mapRequired("LineOffset", F.LineOffset);
+    Io.mapRequired("Column", F.Column);
+    Io.mapRequired("IsInlineFrame", F.IsInlineFrame);
+
+    // Assert that the definition of Frame matches what we expect.  The
+    // structured bindings below detect changes to the number of fields.
+    // static_assert checks the type of each field.
+    const auto &[Function, SymbolName, LineOffset, Column, IsInlineFrame] = F;
+    static_assert(
+        std::is_same_v<remove_cvref_t<decltype(Function)>, GlobalValue::GUID>);
+    static_assert(std::is_same_v<remove_cvref_t<decltype(SymbolName)>,
+                                 std::unique_ptr<std::string>>);
+    static_assert(
+        std::is_same_v<remove_cvref_t<decltype(LineOffset)>, uint32_t>);
+    static_assert(std::is_same_v<remove_cvref_t<decltype(Column)>, uint32_t>);
+    static_assert(
+        std::is_same_v<remove_cvref_t<decltype(IsInlineFrame)>, bool>);
+
+    // MSVC issues unused variable warnings despite the uses in static_assert
+    // above.
+    (void)Function;
+    (void)SymbolName;
+    (void)LineOffset;
+    (void)Column;
+    (void)IsInlineFrame;
+  }
+
+  // Request the inline notation for brevity:
+  //   { Function: 123, LineOffset: 11, Column: 10; IsInlineFrame: true }
+  static const bool flow = true;
+};
+
+template <> struct CustomMappingTraits<memprof::PortableMemInfoBlock> {
+  static void inputOne(IO &Io, StringRef KeyStr,
+                       memprof::PortableMemInfoBlock &MIB) {
+    // PortableMemInfoBlock keeps track of the set of fields that actually have
+    // values.  We update the set here as we receive a key-value pair from the
+    // YAML document.
+    //
+    // We set MIB.Name via a temporary variable because ScalarTraits<uintptr_t>
+    // isn't available on macOS.
+#define MIBEntryDef(NameTag, Name, Type)                                       \
+  if (KeyStr == #Name) {                                                       \
+    uint64_t Value;                                                            \
+    Io.mapRequired(KeyStr.str().c_str(), Value);                               \
+    MIB.Name = static_cast<Type>(Value);                                       \
+    MIB.Schema.set(llvm::to_underlying(memprof::Meta::Name));                  \
+    return;                                                                    \
+  }
+#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+    Io.setError("Key is not a valid validation event");
+  }
+
+  static void output(IO &Io, memprof::PortableMemInfoBlock &MIB) {
+    auto Schema = MIB.getSchema();
+#define MIBEntryDef(NameTag, Name, Type)                                       \
+  if (Schema.test(llvm::to_underlying(memprof::Meta::Name))) {                 \
+    uint64_t Value = MIB.Name;                                                 \
+    Io.mapRequired(#Name, Value);                                              \
+  }
+#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+  }
+};
+
+template <> struct MappingTraits<memprof::AllocationInfo> {
+  static void mapping(IO &Io, memprof::AllocationInfo &AI) {
+    Io.mapRequired("Callstack", AI.CallStack);
+    Io.mapRequired("MemInfoBlock", AI.Info);
+  }
+};
+
+// In YAML, we use GUIDMemProfRecordPair instead of MemProfRecord so that we can
+// treat the GUID and the fields within MemProfRecord at the same level as if
+// the GUID were part of MemProfRecord.
+template <> struct MappingTraits<memprof::GUIDMemProfRecordPair> {
+  static void mapping(IO &Io, memprof::GUIDMemProfRecordPair &Pair) {
+    Io.mapRequired("GUID", Pair.GUID);
+    Io.mapRequired("AllocSites", Pair.Record.AllocSites);
+    Io.mapRequired("CallSites", Pair.Record.CallSites);
+  }
+};
+
+template <> struct MappingTraits<memprof::AllMemProfData> {
+  static void mapping(IO &Io, memprof::AllMemProfData &Data) {
+    Io.mapRequired("HeapProfileRecords", Data.HeapProfileRecords);
+  }
+};
+} // namespace yaml
+} // namespace llvm
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::Frame)
+LLVM_YAML_IS_SEQUENCE_VECTOR(std::vector<memprof::Frame>)
+LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::AllocationInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::GUIDMemProfRecordPair)
+
+#endif // LLVM_PROFILEDATA_MEMPROFYAML_H_
diff --git a/llvm/lib/ProfileData/MemProfReader.cpp b/llvm/lib/ProfileData/MemProfReader.cpp
index 19ae9a79ea519e..9dd43d34f2a0bb 100644
--- a/llvm/lib/ProfileData/MemProfReader.cpp
+++ b/llvm/lib/ProfileData/MemProfReader.cpp
@@ -32,6 +32,7 @@
 #include "llvm/ProfileData/MemProf.h"
 #include "llvm/ProfileData/MemProfData.inc"
 #include "llvm/ProfileData/MemProfReader.h"
+#include "llvm/ProfileData/MemProfYAML.h"
 #include "llvm/ProfileData/SampleProf.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Endian.h"
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index f34d99e10f3163..6b9e2349899a44 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -21,6 +21,7 @@
 #include "llvm/ProfileData/InstrProfWriter.h"
 #include "llvm/ProfileData/MemProf.h"
 #include "llvm/ProfileData/MemProfReader.h"
+#include "llvm/ProfileData/MemProfYAML.h"
 #include "llvm/ProfileData/ProfileCommon.h"
 #include "llvm/ProfileData/SampleProfReader.h"
 #include "llvm/ProfileData/SampleProfWriter.h"
diff --git a/llvm/unittests/ProfileData/MemProfTest.cpp b/llvm/unittests/ProfileData/MemProfTest.cpp
index 5886d3e2bcf842..db2cf1b4c23658 100644
--- a/llvm/unittests/ProfileData/MemProfTest.cpp
+++ b/llvm/unittests/ProfileData/MemProfTest.cpp
@@ -16,6 +16,7 @@
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/ProfileData/MemProfData.inc"
 #include "llvm/ProfileData/MemProfReader.h"
+#include "llvm/ProfileData/MemProfYAML.h"
 #include "llvm/Support/raw_ostream.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"



More information about the llvm-commits mailing list