diff options
author | Kazu Hirata <kazu@google.com> | 2024-12-11 09:17:16 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-11 09:17:16 -0800 |
commit | 66edefaee5e87baabe2367cf1dd82ef40cee8c86 (patch) | |
tree | c76c1949b4332311cca83da68502c83b9123c4e0 /llvm | |
parent | 9aa5848d5cb03cd024b1ebb2f8a5225917f63881 (diff) | |
download | llvm-66edefaee5e87baabe2367cf1dd82ef40cee8c86.zip llvm-66edefaee5e87baabe2367cf1dd82ef40cee8c86.tar.gz llvm-66edefaee5e87baabe2367cf1dd82ef40cee8c86.tar.bz2 |
[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.
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/ProfileData/InstrProfReader.h | 1 | ||||
-rw-r--r-- | llvm/include/llvm/ProfileData/MemProf.h | 144 | ||||
-rw-r--r-- | llvm/include/llvm/ProfileData/MemProfYAML.h | 154 | ||||
-rw-r--r-- | llvm/lib/ProfileData/MemProfReader.cpp | 1 | ||||
-rw-r--r-- | llvm/tools/llvm-profdata/llvm-profdata.cpp | 1 | ||||
-rw-r--r-- | llvm/unittests/ProfileData/MemProfTest.cpp | 1 |
6 files changed, 158 insertions, 144 deletions
diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h index 25e13f5..f1010b3 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 ace3c04..ef96b74 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 @@ public: } }; } // 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 0000000..4568385 --- /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 19ae9a7..9dd43d3 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 f34d99e..6b9e234 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 5dc4b0d..456b093 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" |