diff --git a/llvm/include/llvm/ProfileData/MemProf.h b/llvm/include/llvm/ProfileData/MemProf.h index 6ffead4f13aeb..fe017913f6de2 100644 --- a/llvm/include/llvm/ProfileData/MemProf.h +++ b/llvm/include/llvm/ProfileData/MemProf.h @@ -12,6 +12,7 @@ #include "llvm/Support/Endian.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/HashBuilder.h" +#include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" #include @@ -1145,6 +1146,95 @@ template class CallStackRadixTreeBuilder { } }; } // namespace memprof + +namespace yaml { +template <> struct MappingTraits { + 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("Inline", 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, GlobalValue::GUID>); + static_assert(std::is_same_v, + std::unique_ptr>); + static_assert( + std::is_same_v, uint32_t>); + static_assert(std::is_same_v, uint32_t>); + static_assert( + std::is_same_v, bool>); + + // MSVC issues unused variable warnings despite the uses in static_assert + // above. + (void)Function; + (void)SymbolName; + (void)LineOffset; + (void)Column; + (void)IsInlineFrame; + } +}; + +template <> struct CustomMappingTraits { + 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 + // 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(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 &VI) { + llvm_unreachable("To be implemented"); + } +}; + +template <> struct MappingTraits { + 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 { + 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 { + 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) +LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::AllocationInfo) +LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::GUIDMemProfRecordPair) + #endif // LLVM_PROFILEDATA_MEMPROF_H_ diff --git a/llvm/lib/ProfileData/MemProfReader.cpp b/llvm/lib/ProfileData/MemProfReader.cpp index 1b8a9d3b7cb1d..fdb8e596b0dd3 100644 --- a/llvm/lib/ProfileData/MemProfReader.cpp +++ b/llvm/lib/ProfileData/MemProfReader.cpp @@ -41,97 +41,6 @@ #define DEBUG_TYPE "memprof" -namespace llvm { -namespace yaml { -template <> struct MappingTraits { - 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("Inline", 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, GlobalValue::GUID>); - static_assert(std::is_same_v, - std::unique_ptr>); - static_assert( - std::is_same_v, uint32_t>); - static_assert(std::is_same_v, uint32_t>); - static_assert( - std::is_same_v, bool>); - - // MSVC issues unused variable warnings despite the uses in static_assert - // above. - (void)Function; - (void)SymbolName; - (void)LineOffset; - (void)Column; - (void)IsInlineFrame; - } -}; - -template <> struct CustomMappingTraits { - 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 - // 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(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 &VI) { - llvm_unreachable("To be implemented"); - } -}; - -template <> struct MappingTraits { - 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 { - 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 { - 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) -LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::AllocationInfo) -LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::GUIDMemProfRecordPair) - namespace llvm { namespace memprof { namespace {