Skip to content

Commit 66edefa

Browse files
[memprof] Move YAML support to MemProfYAML.h (NFC) (#119515)
The YAML support is increasing in size, so this patch moves it to a separate file.
1 parent 9aa5848 commit 66edefa

File tree

6 files changed

+158
-144
lines changed

6 files changed

+158
-144
lines changed

llvm/include/llvm/ProfileData/InstrProfReader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/ProfileData/InstrProf.h"
2222
#include "llvm/ProfileData/InstrProfCorrelator.h"
2323
#include "llvm/ProfileData/MemProf.h"
24+
#include "llvm/ProfileData/MemProfYAML.h"
2425
#include "llvm/Support/Endian.h"
2526
#include "llvm/Support/Error.h"
2627
#include "llvm/Support/LineIterator.h"

llvm/include/llvm/ProfileData/MemProf.h

Lines changed: 0 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@
1111
#include "llvm/Support/BLAKE3.h"
1212
#include "llvm/Support/Endian.h"
1313
#include "llvm/Support/EndianStream.h"
14-
#include "llvm/Support/Format.h"
1514
#include "llvm/Support/HashBuilder.h"
16-
#include "llvm/Support/YAMLTraits.h"
1715
#include "llvm/Support/raw_ostream.h"
1816

1917
#include <bitset>
@@ -492,23 +490,6 @@ struct MemProfRecord {
492490
}
493491
};
494492

495-
// A "typedef" for GUID. See ScalarTraits<memprof::GUIDHex64> for how a GUID is
496-
// serialized and deserialized in YAML.
497-
LLVM_YAML_STRONG_TYPEDEF(uint64_t, GUIDHex64)
498-
499-
// Helper struct for AllMemProfData. In YAML, we treat the GUID and the fields
500-
// within MemProfRecord at the same level as if the GUID were part of
501-
// MemProfRecord.
502-
struct GUIDMemProfRecordPair {
503-
GUIDHex64 GUID;
504-
MemProfRecord Record;
505-
};
506-
507-
// The top-level data structure, only used with YAML for now.
508-
struct AllMemProfData {
509-
std::vector<GUIDMemProfRecordPair> HeapProfileRecords;
510-
};
511-
512493
// Reads a memprof schema from a buffer. All entries in the buffer are
513494
// interpreted as uint64_t. The first entry in the buffer denotes the number of
514495
// ids in the schema. Subsequent entries are integers which map to memprof::Meta
@@ -1169,131 +1150,6 @@ template <typename FrameIdTy> class CallStackRadixTreeBuilder {
11691150
}
11701151
};
11711152
} // namespace memprof
1172-
1173-
namespace yaml {
1174-
template <> struct ScalarTraits<memprof::GUIDHex64> {
1175-
static void output(const memprof::GUIDHex64 &Val, void *, raw_ostream &Out) {
1176-
// Print GUID as a 16-digit hexadecimal number.
1177-
Out << format("0x%016" PRIx64, (uint64_t)Val);
1178-
}
1179-
static StringRef input(StringRef Scalar, void *, memprof::GUIDHex64 &Val) {
1180-
// Reject decimal GUIDs.
1181-
if (all_of(Scalar, [](char C) { return std::isdigit(C); }))
1182-
return "use a hexadecimal GUID or a function instead";
1183-
1184-
uint64_t Num;
1185-
if (Scalar.starts_with_insensitive("0x")) {
1186-
// Accept hexadecimal numbers starting with 0x or 0X.
1187-
if (Scalar.getAsInteger(0, Num))
1188-
return "invalid hex64 number";
1189-
Val = Num;
1190-
} else {
1191-
// Otherwise, treat the input as a string containing a function name.
1192-
Val = memprof::IndexedMemProfRecord::getGUID(Scalar);
1193-
}
1194-
return StringRef();
1195-
}
1196-
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1197-
};
1198-
1199-
template <> struct MappingTraits<memprof::Frame> {
1200-
static void mapping(IO &Io, memprof::Frame &F) {
1201-
Io.mapRequired("Function", F.Function);
1202-
Io.mapRequired("LineOffset", F.LineOffset);
1203-
Io.mapRequired("Column", F.Column);
1204-
Io.mapRequired("IsInlineFrame", F.IsInlineFrame);
1205-
1206-
// Assert that the definition of Frame matches what we expect. The
1207-
// structured bindings below detect changes to the number of fields.
1208-
// static_assert checks the type of each field.
1209-
const auto &[Function, SymbolName, LineOffset, Column, IsInlineFrame] = F;
1210-
static_assert(
1211-
std::is_same_v<remove_cvref_t<decltype(Function)>, GlobalValue::GUID>);
1212-
static_assert(std::is_same_v<remove_cvref_t<decltype(SymbolName)>,
1213-
std::unique_ptr<std::string>>);
1214-
static_assert(
1215-
std::is_same_v<remove_cvref_t<decltype(LineOffset)>, uint32_t>);
1216-
static_assert(std::is_same_v<remove_cvref_t<decltype(Column)>, uint32_t>);
1217-
static_assert(
1218-
std::is_same_v<remove_cvref_t<decltype(IsInlineFrame)>, bool>);
1219-
1220-
// MSVC issues unused variable warnings despite the uses in static_assert
1221-
// above.
1222-
(void)Function;
1223-
(void)SymbolName;
1224-
(void)LineOffset;
1225-
(void)Column;
1226-
(void)IsInlineFrame;
1227-
}
1228-
1229-
// Request the inline notation for brevity:
1230-
// { Function: 123, LineOffset: 11, Column: 10; IsInlineFrame: true }
1231-
static const bool flow = true;
1232-
};
1233-
1234-
template <> struct CustomMappingTraits<memprof::PortableMemInfoBlock> {
1235-
static void inputOne(IO &Io, StringRef KeyStr,
1236-
memprof::PortableMemInfoBlock &MIB) {
1237-
// PortableMemInfoBlock keeps track of the set of fields that actually have
1238-
// values. We update the set here as we receive a key-value pair from the
1239-
// YAML document.
1240-
//
1241-
// We set MIB.Name via a temporary variable because ScalarTraits<uintptr_t>
1242-
// isn't available on macOS.
1243-
#define MIBEntryDef(NameTag, Name, Type) \
1244-
if (KeyStr == #Name) { \
1245-
uint64_t Value; \
1246-
Io.mapRequired(KeyStr.str().c_str(), Value); \
1247-
MIB.Name = static_cast<Type>(Value); \
1248-
MIB.Schema.set(llvm::to_underlying(memprof::Meta::Name)); \
1249-
return; \
1250-
}
1251-
#include "llvm/ProfileData/MIBEntryDef.inc"
1252-
#undef MIBEntryDef
1253-
Io.setError("Key is not a valid validation event");
1254-
}
1255-
1256-
static void output(IO &Io, memprof::PortableMemInfoBlock &MIB) {
1257-
auto Schema = MIB.getSchema();
1258-
#define MIBEntryDef(NameTag, Name, Type) \
1259-
if (Schema.test(llvm::to_underlying(memprof::Meta::Name))) { \
1260-
uint64_t Value = MIB.Name; \
1261-
Io.mapRequired(#Name, Value); \
1262-
}
1263-
#include "llvm/ProfileData/MIBEntryDef.inc"
1264-
#undef MIBEntryDef
1265-
}
1266-
};
1267-
1268-
template <> struct MappingTraits<memprof::AllocationInfo> {
1269-
static void mapping(IO &Io, memprof::AllocationInfo &AI) {
1270-
Io.mapRequired("Callstack", AI.CallStack);
1271-
Io.mapRequired("MemInfoBlock", AI.Info);
1272-
}
1273-
};
1274-
1275-
// In YAML, we use GUIDMemProfRecordPair instead of MemProfRecord so that we can
1276-
// treat the GUID and the fields within MemProfRecord at the same level as if
1277-
// the GUID were part of MemProfRecord.
1278-
template <> struct MappingTraits<memprof::GUIDMemProfRecordPair> {
1279-
static void mapping(IO &Io, memprof::GUIDMemProfRecordPair &Pair) {
1280-
Io.mapRequired("GUID", Pair.GUID);
1281-
Io.mapRequired("AllocSites", Pair.Record.AllocSites);
1282-
Io.mapRequired("CallSites", Pair.Record.CallSites);
1283-
}
1284-
};
1285-
1286-
template <> struct MappingTraits<memprof::AllMemProfData> {
1287-
static void mapping(IO &Io, memprof::AllMemProfData &Data) {
1288-
Io.mapRequired("HeapProfileRecords", Data.HeapProfileRecords);
1289-
}
1290-
};
1291-
} // namespace yaml
12921153
} // namespace llvm
12931154

1294-
LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::Frame)
1295-
LLVM_YAML_IS_SEQUENCE_VECTOR(std::vector<memprof::Frame>)
1296-
LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::AllocationInfo)
1297-
LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::GUIDMemProfRecordPair)
1298-
12991155
#endif // LLVM_PROFILEDATA_MEMPROF_H_
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#ifndef LLVM_PROFILEDATA_MEMPROFYAML_H_
2+
#define LLVM_PROFILEDATA_MEMPROFYAML_H_
3+
4+
#include "llvm/ProfileData/MemProf.h"
5+
#include "llvm/Support/Format.h"
6+
#include "llvm/Support/YAMLTraits.h"
7+
8+
namespace llvm {
9+
namespace memprof {
10+
// A "typedef" for GUID. See ScalarTraits<memprof::GUIDHex64> for how a GUID is
11+
// serialized and deserialized in YAML.
12+
LLVM_YAML_STRONG_TYPEDEF(uint64_t, GUIDHex64)
13+
14+
// Helper struct for AllMemProfData. In YAML, we treat the GUID and the fields
15+
// within MemProfRecord at the same level as if the GUID were part of
16+
// MemProfRecord.
17+
struct GUIDMemProfRecordPair {
18+
GUIDHex64 GUID;
19+
MemProfRecord Record;
20+
};
21+
22+
// The top-level data structure, only used with YAML for now.
23+
struct AllMemProfData {
24+
std::vector<GUIDMemProfRecordPair> HeapProfileRecords;
25+
};
26+
} // namespace memprof
27+
28+
namespace yaml {
29+
template <> struct ScalarTraits<memprof::GUIDHex64> {
30+
static void output(const memprof::GUIDHex64 &Val, void *, raw_ostream &Out) {
31+
// Print GUID as a 16-digit hexadecimal number.
32+
Out << format("0x%016" PRIx64, (uint64_t)Val);
33+
}
34+
static StringRef input(StringRef Scalar, void *, memprof::GUIDHex64 &Val) {
35+
// Reject decimal GUIDs.
36+
if (all_of(Scalar, [](char C) { return std::isdigit(C); }))
37+
return "use a hexadecimal GUID or a function instead";
38+
39+
uint64_t Num;
40+
if (Scalar.starts_with_insensitive("0x")) {
41+
// Accept hexadecimal numbers starting with 0x or 0X.
42+
if (Scalar.getAsInteger(0, Num))
43+
return "invalid hex64 number";
44+
Val = Num;
45+
} else {
46+
// Otherwise, treat the input as a string containing a function name.
47+
Val = memprof::IndexedMemProfRecord::getGUID(Scalar);
48+
}
49+
return StringRef();
50+
}
51+
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
52+
};
53+
54+
template <> struct MappingTraits<memprof::Frame> {
55+
static void mapping(IO &Io, memprof::Frame &F) {
56+
Io.mapRequired("Function", F.Function);
57+
Io.mapRequired("LineOffset", F.LineOffset);
58+
Io.mapRequired("Column", F.Column);
59+
Io.mapRequired("IsInlineFrame", F.IsInlineFrame);
60+
61+
// Assert that the definition of Frame matches what we expect. The
62+
// structured bindings below detect changes to the number of fields.
63+
// static_assert checks the type of each field.
64+
const auto &[Function, SymbolName, LineOffset, Column, IsInlineFrame] = F;
65+
static_assert(
66+
std::is_same_v<remove_cvref_t<decltype(Function)>, GlobalValue::GUID>);
67+
static_assert(std::is_same_v<remove_cvref_t<decltype(SymbolName)>,
68+
std::unique_ptr<std::string>>);
69+
static_assert(
70+
std::is_same_v<remove_cvref_t<decltype(LineOffset)>, uint32_t>);
71+
static_assert(std::is_same_v<remove_cvref_t<decltype(Column)>, uint32_t>);
72+
static_assert(
73+
std::is_same_v<remove_cvref_t<decltype(IsInlineFrame)>, bool>);
74+
75+
// MSVC issues unused variable warnings despite the uses in static_assert
76+
// above.
77+
(void)Function;
78+
(void)SymbolName;
79+
(void)LineOffset;
80+
(void)Column;
81+
(void)IsInlineFrame;
82+
}
83+
84+
// Request the inline notation for brevity:
85+
// { Function: 123, LineOffset: 11, Column: 10; IsInlineFrame: true }
86+
static const bool flow = true;
87+
};
88+
89+
template <> struct CustomMappingTraits<memprof::PortableMemInfoBlock> {
90+
static void inputOne(IO &Io, StringRef KeyStr,
91+
memprof::PortableMemInfoBlock &MIB) {
92+
// PortableMemInfoBlock keeps track of the set of fields that actually have
93+
// values. We update the set here as we receive a key-value pair from the
94+
// YAML document.
95+
//
96+
// We set MIB.Name via a temporary variable because ScalarTraits<uintptr_t>
97+
// isn't available on macOS.
98+
#define MIBEntryDef(NameTag, Name, Type) \
99+
if (KeyStr == #Name) { \
100+
uint64_t Value; \
101+
Io.mapRequired(KeyStr.str().c_str(), Value); \
102+
MIB.Name = static_cast<Type>(Value); \
103+
MIB.Schema.set(llvm::to_underlying(memprof::Meta::Name)); \
104+
return; \
105+
}
106+
#include "llvm/ProfileData/MIBEntryDef.inc"
107+
#undef MIBEntryDef
108+
Io.setError("Key is not a valid validation event");
109+
}
110+
111+
static void output(IO &Io, memprof::PortableMemInfoBlock &MIB) {
112+
auto Schema = MIB.getSchema();
113+
#define MIBEntryDef(NameTag, Name, Type) \
114+
if (Schema.test(llvm::to_underlying(memprof::Meta::Name))) { \
115+
uint64_t Value = MIB.Name; \
116+
Io.mapRequired(#Name, Value); \
117+
}
118+
#include "llvm/ProfileData/MIBEntryDef.inc"
119+
#undef MIBEntryDef
120+
}
121+
};
122+
123+
template <> struct MappingTraits<memprof::AllocationInfo> {
124+
static void mapping(IO &Io, memprof::AllocationInfo &AI) {
125+
Io.mapRequired("Callstack", AI.CallStack);
126+
Io.mapRequired("MemInfoBlock", AI.Info);
127+
}
128+
};
129+
130+
// In YAML, we use GUIDMemProfRecordPair instead of MemProfRecord so that we can
131+
// treat the GUID and the fields within MemProfRecord at the same level as if
132+
// the GUID were part of MemProfRecord.
133+
template <> struct MappingTraits<memprof::GUIDMemProfRecordPair> {
134+
static void mapping(IO &Io, memprof::GUIDMemProfRecordPair &Pair) {
135+
Io.mapRequired("GUID", Pair.GUID);
136+
Io.mapRequired("AllocSites", Pair.Record.AllocSites);
137+
Io.mapRequired("CallSites", Pair.Record.CallSites);
138+
}
139+
};
140+
141+
template <> struct MappingTraits<memprof::AllMemProfData> {
142+
static void mapping(IO &Io, memprof::AllMemProfData &Data) {
143+
Io.mapRequired("HeapProfileRecords", Data.HeapProfileRecords);
144+
}
145+
};
146+
} // namespace yaml
147+
} // namespace llvm
148+
149+
LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::Frame)
150+
LLVM_YAML_IS_SEQUENCE_VECTOR(std::vector<memprof::Frame>)
151+
LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::AllocationInfo)
152+
LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::GUIDMemProfRecordPair)
153+
154+
#endif // LLVM_PROFILEDATA_MEMPROFYAML_H_

llvm/lib/ProfileData/MemProfReader.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "llvm/ProfileData/MemProf.h"
3333
#include "llvm/ProfileData/MemProfData.inc"
3434
#include "llvm/ProfileData/MemProfReader.h"
35+
#include "llvm/ProfileData/MemProfYAML.h"
3536
#include "llvm/ProfileData/SampleProf.h"
3637
#include "llvm/Support/Debug.h"
3738
#include "llvm/Support/Endian.h"

llvm/tools/llvm-profdata/llvm-profdata.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/ProfileData/InstrProfWriter.h"
2222
#include "llvm/ProfileData/MemProf.h"
2323
#include "llvm/ProfileData/MemProfReader.h"
24+
#include "llvm/ProfileData/MemProfYAML.h"
2425
#include "llvm/ProfileData/ProfileCommon.h"
2526
#include "llvm/ProfileData/SampleProfReader.h"
2627
#include "llvm/ProfileData/SampleProfWriter.h"

llvm/unittests/ProfileData/MemProfTest.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "llvm/Object/ObjectFile.h"
1717
#include "llvm/ProfileData/MemProfData.inc"
1818
#include "llvm/ProfileData/MemProfReader.h"
19+
#include "llvm/ProfileData/MemProfYAML.h"
1920
#include "llvm/Support/raw_ostream.h"
2021
#include "gmock/gmock.h"
2122
#include "gtest/gtest.h"

0 commit comments

Comments
 (0)