|
12 | 12 | #include "llvm/Support/Endian.h"
|
13 | 13 | #include "llvm/Support/EndianStream.h"
|
14 | 14 | #include "llvm/Support/HashBuilder.h"
|
| 15 | +#include "llvm/Support/YAMLTraits.h" |
15 | 16 | #include "llvm/Support/raw_ostream.h"
|
16 | 17 |
|
17 | 18 | #include <bitset>
|
@@ -1145,6 +1146,95 @@ template <typename FrameIdTy> class CallStackRadixTreeBuilder {
|
1145 | 1146 | }
|
1146 | 1147 | };
|
1147 | 1148 | } // namespace memprof
|
| 1149 | + |
| 1150 | +namespace yaml { |
| 1151 | +template <> struct MappingTraits<memprof::Frame> { |
| 1152 | + static void mapping(IO &Io, memprof::Frame &F) { |
| 1153 | + Io.mapRequired("Function", F.Function); |
| 1154 | + Io.mapRequired("LineOffset", F.LineOffset); |
| 1155 | + Io.mapRequired("Column", F.Column); |
| 1156 | + Io.mapRequired("Inline", F.IsInlineFrame); |
| 1157 | + |
| 1158 | + // Assert that the definition of Frame matches what we expect. The |
| 1159 | + // structured bindings below detect changes to the number of fields. |
| 1160 | + // static_assert checks the type of each field. |
| 1161 | + const auto &[Function, SymbolName, LineOffset, Column, IsInlineFrame] = F; |
| 1162 | + static_assert( |
| 1163 | + std::is_same_v<remove_cvref_t<decltype(Function)>, GlobalValue::GUID>); |
| 1164 | + static_assert(std::is_same_v<remove_cvref_t<decltype(SymbolName)>, |
| 1165 | + std::unique_ptr<std::string>>); |
| 1166 | + static_assert( |
| 1167 | + std::is_same_v<remove_cvref_t<decltype(LineOffset)>, uint32_t>); |
| 1168 | + static_assert(std::is_same_v<remove_cvref_t<decltype(Column)>, uint32_t>); |
| 1169 | + static_assert( |
| 1170 | + std::is_same_v<remove_cvref_t<decltype(IsInlineFrame)>, bool>); |
| 1171 | + |
| 1172 | + // MSVC issues unused variable warnings despite the uses in static_assert |
| 1173 | + // above. |
| 1174 | + (void)Function; |
| 1175 | + (void)SymbolName; |
| 1176 | + (void)LineOffset; |
| 1177 | + (void)Column; |
| 1178 | + (void)IsInlineFrame; |
| 1179 | + } |
| 1180 | +}; |
| 1181 | + |
| 1182 | +template <> struct CustomMappingTraits<memprof::PortableMemInfoBlock> { |
| 1183 | + static void inputOne(IO &Io, StringRef KeyStr, |
| 1184 | + memprof::PortableMemInfoBlock &MIB) { |
| 1185 | + // PortableMemInfoBlock keeps track of the set of fields that actually have |
| 1186 | + // values. We update the set here as we receive a key-value pair from the |
| 1187 | + // YAML document. |
| 1188 | + // |
| 1189 | + // We set MIB.Name via a temporary variable because ScalarTraits<uintptr_t> |
| 1190 | + // isn't available on macOS. |
| 1191 | +#define MIBEntryDef(NameTag, Name, Type) \ |
| 1192 | + if (KeyStr == #Name) { \ |
| 1193 | + uint64_t Value; \ |
| 1194 | + Io.mapRequired(KeyStr.str().c_str(), Value); \ |
| 1195 | + MIB.Name = static_cast<Type>(Value); \ |
| 1196 | + MIB.Schema.set(llvm::to_underlying(memprof::Meta::Name)); \ |
| 1197 | + return; \ |
| 1198 | + } |
| 1199 | +#include "llvm/ProfileData/MIBEntryDef.inc" |
| 1200 | +#undef MIBEntryDef |
| 1201 | + Io.setError("Key is not a valid validation event"); |
| 1202 | + } |
| 1203 | + |
| 1204 | + static void output(IO &Io, memprof::PortableMemInfoBlock &VI) { |
| 1205 | + llvm_unreachable("To be implemented"); |
| 1206 | + } |
| 1207 | +}; |
| 1208 | + |
| 1209 | +template <> struct MappingTraits<memprof::AllocationInfo> { |
| 1210 | + static void mapping(IO &Io, memprof::AllocationInfo &AI) { |
| 1211 | + Io.mapRequired("Callstack", AI.CallStack); |
| 1212 | + Io.mapRequired("MemInfoBlock", AI.Info); |
| 1213 | + } |
| 1214 | +}; |
| 1215 | + |
| 1216 | +// In YAML, we use GUIDMemProfRecordPair instead of MemProfRecord so that we can |
| 1217 | +// treat the GUID and the fields within MemProfRecord at the same level as if |
| 1218 | +// the GUID were part of MemProfRecord. |
| 1219 | +template <> struct MappingTraits<memprof::GUIDMemProfRecordPair> { |
| 1220 | + static void mapping(IO &Io, memprof::GUIDMemProfRecordPair &Pair) { |
| 1221 | + Io.mapRequired("GUID", Pair.GUID); |
| 1222 | + Io.mapRequired("AllocSites", Pair.Record.AllocSites); |
| 1223 | + Io.mapRequired("CallSites", Pair.Record.CallSites); |
| 1224 | + } |
| 1225 | +}; |
| 1226 | + |
| 1227 | +template <> struct MappingTraits<memprof::AllMemProfData> { |
| 1228 | + static void mapping(IO &Io, memprof::AllMemProfData &Data) { |
| 1229 | + Io.mapRequired("HeapProfileRecords", Data.HeapProfileRecords); |
| 1230 | + } |
| 1231 | +}; |
| 1232 | +} // namespace yaml |
1148 | 1233 | } // namespace llvm
|
1149 | 1234 |
|
| 1235 | +LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::Frame) |
| 1236 | +LLVM_YAML_IS_SEQUENCE_VECTOR(std::vector<memprof::Frame>) |
| 1237 | +LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::AllocationInfo) |
| 1238 | +LLVM_YAML_IS_SEQUENCE_VECTOR(memprof::GUIDMemProfRecordPair) |
| 1239 | + |
1150 | 1240 | #endif // LLVM_PROFILEDATA_MEMPROF_H_
|
0 commit comments