1 //===- CodeViewYAMLSymbols.cpp - CodeView YAMLIO Symbol implementation ----===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines classes for handling the YAML representation of CodeView
11 // Debug Info.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
19 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
20 #include "llvm/DebugInfo/CodeView/EnumTables.h"
21 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
22 #include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
23 
24 using namespace llvm;
25 using namespace llvm::codeview;
26 using namespace llvm::CodeViewYAML;
27 using namespace llvm::CodeViewYAML::detail;
28 using namespace llvm::yaml;
29 
30 LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
31 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex)
32 
33 // We only need to declare these, the definitions are in CodeViewYAMLTypes.cpp
34 LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, false)
35 LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, false)
36 
37 LLVM_YAML_DECLARE_ENUM_TRAITS(SymbolKind)
38 LLVM_YAML_DECLARE_ENUM_TRAITS(FrameCookieKind)
39 
40 LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym2Flags)
41 LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym3Flags)
42 LLVM_YAML_DECLARE_BITSET_TRAITS(ExportFlags)
43 LLVM_YAML_DECLARE_BITSET_TRAITS(PublicSymFlags)
44 LLVM_YAML_DECLARE_BITSET_TRAITS(LocalSymFlags)
45 LLVM_YAML_DECLARE_BITSET_TRAITS(ProcSymFlags)
46 LLVM_YAML_DECLARE_BITSET_TRAITS(FrameProcedureOptions)
47 LLVM_YAML_DECLARE_ENUM_TRAITS(CPUType)
48 LLVM_YAML_DECLARE_ENUM_TRAITS(RegisterId)
49 LLVM_YAML_DECLARE_ENUM_TRAITS(TrampolineType)
50 LLVM_YAML_DECLARE_ENUM_TRAITS(ThunkOrdinal)
51 
52 LLVM_YAML_STRONG_TYPEDEF(llvm::StringRef, TypeName)
53 
54 LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeName, true)
55 
56 StringRef ScalarTraits<TypeName>::input(StringRef S, void *V, TypeName &T) {
57   return ScalarTraits<StringRef>::input(S, V, T.value);
58 }
59 void ScalarTraits<TypeName>::output(const TypeName &T, void *V,
60                                     llvm::raw_ostream &R) {
61   ScalarTraits<StringRef>::output(T.value, V, R);
62 }
63 
64 void ScalarEnumerationTraits<SymbolKind>::enumeration(IO &io,
65                                                       SymbolKind &Value) {
66   auto SymbolNames = getSymbolTypeNames();
67   for (const auto &E : SymbolNames)
68     io.enumCase(Value, E.Name.str().c_str(), E.Value);
69 }
70 
71 void ScalarBitSetTraits<CompileSym2Flags>::bitset(IO &io,
72                                                   CompileSym2Flags &Flags) {
73   auto FlagNames = getCompileSym2FlagNames();
74   for (const auto &E : FlagNames) {
75     io.bitSetCase(Flags, E.Name.str().c_str(),
76                   static_cast<CompileSym2Flags>(E.Value));
77   }
78 }
79 
80 void ScalarBitSetTraits<CompileSym3Flags>::bitset(IO &io,
81                                                   CompileSym3Flags &Flags) {
82   auto FlagNames = getCompileSym3FlagNames();
83   for (const auto &E : FlagNames) {
84     io.bitSetCase(Flags, E.Name.str().c_str(),
85                   static_cast<CompileSym3Flags>(E.Value));
86   }
87 }
88 
89 void ScalarBitSetTraits<ExportFlags>::bitset(IO &io, ExportFlags &Flags) {
90   auto FlagNames = getExportSymFlagNames();
91   for (const auto &E : FlagNames) {
92     io.bitSetCase(Flags, E.Name.str().c_str(),
93                   static_cast<ExportFlags>(E.Value));
94   }
95 }
96 
97 void ScalarBitSetTraits<PublicSymFlags>::bitset(IO &io, PublicSymFlags &Flags) {
98   auto FlagNames = getProcSymFlagNames();
99   for (const auto &E : FlagNames) {
100     io.bitSetCase(Flags, E.Name.str().c_str(),
101                   static_cast<PublicSymFlags>(E.Value));
102   }
103 }
104 
105 void ScalarBitSetTraits<LocalSymFlags>::bitset(IO &io, LocalSymFlags &Flags) {
106   auto FlagNames = getLocalFlagNames();
107   for (const auto &E : FlagNames) {
108     io.bitSetCase(Flags, E.Name.str().c_str(),
109                   static_cast<LocalSymFlags>(E.Value));
110   }
111 }
112 
113 void ScalarBitSetTraits<ProcSymFlags>::bitset(IO &io, ProcSymFlags &Flags) {
114   auto FlagNames = getProcSymFlagNames();
115   for (const auto &E : FlagNames) {
116     io.bitSetCase(Flags, E.Name.str().c_str(),
117                   static_cast<ProcSymFlags>(E.Value));
118   }
119 }
120 
121 void ScalarBitSetTraits<FrameProcedureOptions>::bitset(
122     IO &io, FrameProcedureOptions &Flags) {
123   auto FlagNames = getFrameProcSymFlagNames();
124   for (const auto &E : FlagNames) {
125     io.bitSetCase(Flags, E.Name.str().c_str(),
126                   static_cast<FrameProcedureOptions>(E.Value));
127   }
128 }
129 
130 void ScalarEnumerationTraits<CPUType>::enumeration(IO &io, CPUType &Cpu) {
131   auto CpuNames = getCPUTypeNames();
132   for (const auto &E : CpuNames) {
133     io.enumCase(Cpu, E.Name.str().c_str(), static_cast<CPUType>(E.Value));
134   }
135 }
136 
137 void ScalarEnumerationTraits<RegisterId>::enumeration(IO &io, RegisterId &Reg) {
138   auto RegNames = getRegisterNames();
139   for (const auto &E : RegNames) {
140     io.enumCase(Reg, E.Name.str().c_str(), static_cast<RegisterId>(E.Value));
141   }
142   io.enumFallback<Hex16>(Reg);
143 }
144 
145 void ScalarEnumerationTraits<TrampolineType>::enumeration(
146     IO &io, TrampolineType &Tramp) {
147   auto TrampNames = getTrampolineNames();
148   for (const auto &E : TrampNames) {
149     io.enumCase(Tramp, E.Name.str().c_str(),
150                 static_cast<TrampolineType>(E.Value));
151   }
152 }
153 
154 void ScalarEnumerationTraits<ThunkOrdinal>::enumeration(IO &io,
155                                                         ThunkOrdinal &Ord) {
156   auto ThunkNames = getThunkOrdinalNames();
157   for (const auto &E : ThunkNames) {
158     io.enumCase(Ord, E.Name.str().c_str(), static_cast<ThunkOrdinal>(E.Value));
159   }
160 }
161 
162 void ScalarEnumerationTraits<FrameCookieKind>::enumeration(
163     IO &io, FrameCookieKind &FC) {
164   auto ThunkNames = getFrameCookieKindNames();
165   for (const auto &E : ThunkNames) {
166     io.enumCase(FC, E.Name.str().c_str(),
167                 static_cast<FrameCookieKind>(E.Value));
168   }
169 }
170 
171 namespace llvm {
172 namespace CodeViewYAML {
173 namespace detail {
174 
175 struct SymbolRecordBase {
176   codeview::SymbolKind Kind;
177   explicit SymbolRecordBase(codeview::SymbolKind K) : Kind(K) {}
178 
179   virtual ~SymbolRecordBase() {}
180   virtual void map(yaml::IO &io) = 0;
181   virtual codeview::CVSymbol
182   toCodeViewSymbol(BumpPtrAllocator &Allocator,
183                    CodeViewContainer Container) const = 0;
184   virtual Error fromCodeViewSymbol(codeview::CVSymbol Type) = 0;
185 };
186 
187 template <typename T> struct SymbolRecordImpl : public SymbolRecordBase {
188   explicit SymbolRecordImpl(codeview::SymbolKind K)
189       : SymbolRecordBase(K), Symbol(static_cast<SymbolRecordKind>(K)) {}
190 
191   void map(yaml::IO &io) override;
192 
193   codeview::CVSymbol
194   toCodeViewSymbol(BumpPtrAllocator &Allocator,
195                    CodeViewContainer Container) const override {
196     return SymbolSerializer::writeOneSymbol(Symbol, Allocator, Container);
197   }
198   Error fromCodeViewSymbol(codeview::CVSymbol CVS) override {
199     return SymbolDeserializer::deserializeAs<T>(CVS, Symbol);
200   }
201 
202   mutable T Symbol;
203 };
204 
205 struct UnknownSymbolRecord : public SymbolRecordBase {
206   explicit UnknownSymbolRecord(codeview::SymbolKind K) : SymbolRecordBase(K) {}
207 
208   void map(yaml::IO &io) override;
209 
210   CVSymbol toCodeViewSymbol(BumpPtrAllocator &Allocator,
211                             CodeViewContainer Container) const override {
212     RecordPrefix Prefix;
213     uint32_t TotalLen = sizeof(RecordPrefix) + Data.size();
214     Prefix.RecordKind = Kind;
215     Prefix.RecordLen = TotalLen - 2;
216     uint8_t *Buffer = Allocator.Allocate<uint8_t>(TotalLen);
217     ::memcpy(Buffer, &Prefix, sizeof(RecordPrefix));
218     ::memcpy(Buffer + sizeof(RecordPrefix), Data.data(), Data.size());
219     return CVSymbol(Kind, ArrayRef<uint8_t>(Buffer, TotalLen));
220   }
221   Error fromCodeViewSymbol(CVSymbol CVS) override {
222     this->Kind = CVS.kind();
223     Data = CVS.RecordData.drop_front(sizeof(RecordPrefix));
224     return Error::success();
225   }
226 
227   std::vector<uint8_t> Data;
228 };
229 
230 template <> void SymbolRecordImpl<ScopeEndSym>::map(IO &IO) {}
231 
232 void UnknownSymbolRecord::map(yaml::IO &io) {
233   yaml::BinaryRef Binary;
234   if (io.outputting())
235     Binary = yaml::BinaryRef(Data);
236   io.mapRequired("Data", Binary);
237   if (!io.outputting()) {
238     std::string Str;
239     raw_string_ostream OS(Str);
240     Binary.writeAsBinary(OS);
241     OS.flush();
242     Data.assign(Str.begin(), Str.end());
243   }
244 }
245 
246 template <> void SymbolRecordImpl<Thunk32Sym>::map(IO &IO) {
247   IO.mapRequired("Parent", Symbol.Parent);
248   IO.mapRequired("End", Symbol.End);
249   IO.mapRequired("Next", Symbol.Next);
250   IO.mapRequired("Off", Symbol.Offset);
251   IO.mapRequired("Seg", Symbol.Segment);
252   IO.mapRequired("Len", Symbol.Length);
253   IO.mapRequired("Ordinal", Symbol.Thunk);
254 }
255 
256 template <> void SymbolRecordImpl<TrampolineSym>::map(IO &IO) {
257   IO.mapRequired("Type", Symbol.Type);
258   IO.mapRequired("Size", Symbol.Size);
259   IO.mapRequired("ThunkOff", Symbol.ThunkOffset);
260   IO.mapRequired("TargetOff", Symbol.TargetOffset);
261   IO.mapRequired("ThunkSection", Symbol.ThunkSection);
262   IO.mapRequired("TargetSection", Symbol.TargetSection);
263 }
264 
265 template <> void SymbolRecordImpl<SectionSym>::map(IO &IO) {
266   IO.mapRequired("SectionNumber", Symbol.SectionNumber);
267   IO.mapRequired("Alignment", Symbol.Alignment);
268   IO.mapRequired("Rva", Symbol.Rva);
269   IO.mapRequired("Length", Symbol.Length);
270   IO.mapRequired("Characteristics", Symbol.Characteristics);
271   IO.mapRequired("Name", Symbol.Name);
272 }
273 
274 template <> void SymbolRecordImpl<CoffGroupSym>::map(IO &IO) {
275   IO.mapRequired("Size", Symbol.Size);
276   IO.mapRequired("Characteristics", Symbol.Characteristics);
277   IO.mapRequired("Offset", Symbol.Offset);
278   IO.mapRequired("Segment", Symbol.Segment);
279   IO.mapRequired("Name", Symbol.Name);
280 }
281 
282 template <> void SymbolRecordImpl<ExportSym>::map(IO &IO) {
283   IO.mapRequired("Ordinal", Symbol.Ordinal);
284   IO.mapRequired("Flags", Symbol.Flags);
285   IO.mapRequired("Name", Symbol.Name);
286 }
287 
288 template <> void SymbolRecordImpl<ProcSym>::map(IO &IO) {
289   IO.mapOptional("PtrParent", Symbol.Parent, 0U);
290   IO.mapOptional("PtrEnd", Symbol.End, 0U);
291   IO.mapOptional("PtrNext", Symbol.Next, 0U);
292   IO.mapRequired("CodeSize", Symbol.CodeSize);
293   IO.mapRequired("DbgStart", Symbol.DbgStart);
294   IO.mapRequired("DbgEnd", Symbol.DbgEnd);
295   IO.mapRequired("FunctionType", Symbol.FunctionType);
296   IO.mapOptional("Offset", Symbol.CodeOffset, 0U);
297   IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
298   IO.mapRequired("Flags", Symbol.Flags);
299   IO.mapRequired("DisplayName", Symbol.Name);
300 }
301 
302 template <> void SymbolRecordImpl<RegisterSym>::map(IO &IO) {
303   IO.mapRequired("Type", Symbol.Index);
304   IO.mapRequired("Seg", Symbol.Register);
305   IO.mapRequired("Name", Symbol.Name);
306 }
307 
308 template <> void SymbolRecordImpl<PublicSym32>::map(IO &IO) {
309   IO.mapRequired("Flags", Symbol.Flags);
310   IO.mapOptional("Offset", Symbol.Offset, 0U);
311   IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
312   IO.mapRequired("Name", Symbol.Name);
313 }
314 
315 template <> void SymbolRecordImpl<ProcRefSym>::map(IO &IO) {
316   IO.mapRequired("SumName", Symbol.SumName);
317   IO.mapRequired("SymOffset", Symbol.SymOffset);
318   IO.mapRequired("Mod", Symbol.Module);
319   IO.mapRequired("Name", Symbol.Name);
320 }
321 
322 template <> void SymbolRecordImpl<EnvBlockSym>::map(IO &IO) {
323   IO.mapRequired("Entries", Symbol.Fields);
324 }
325 
326 template <> void SymbolRecordImpl<InlineSiteSym>::map(IO &IO) {
327   IO.mapOptional("PtrParent", Symbol.Parent, 0U);
328   IO.mapOptional("PtrEnd", Symbol.End, 0U);
329   IO.mapRequired("Inlinee", Symbol.Inlinee);
330   // TODO: The binary annotations
331 }
332 
333 template <> void SymbolRecordImpl<LocalSym>::map(IO &IO) {
334   IO.mapRequired("Type", Symbol.Type);
335   IO.mapRequired("Flags", Symbol.Flags);
336 
337   IO.mapRequired("VarName", Symbol.Name);
338 }
339 
340 template <> void SymbolRecordImpl<DefRangeSym>::map(IO &IO) {
341   // TODO: Print the subfields
342 }
343 
344 template <> void SymbolRecordImpl<DefRangeSubfieldSym>::map(IO &IO) {
345   // TODO: Print the subfields
346 }
347 
348 template <> void SymbolRecordImpl<DefRangeRegisterSym>::map(IO &IO) {
349   // TODO: Print the subfields
350 }
351 
352 template <> void SymbolRecordImpl<DefRangeFramePointerRelSym>::map(IO &IO) {
353   // TODO: Print the subfields
354 }
355 
356 template <> void SymbolRecordImpl<DefRangeSubfieldRegisterSym>::map(IO &IO) {
357   // TODO: Print the subfields
358 }
359 
360 template <>
361 void SymbolRecordImpl<DefRangeFramePointerRelFullScopeSym>::map(IO &IO) {
362   // TODO: Print the subfields
363 }
364 
365 template <> void SymbolRecordImpl<DefRangeRegisterRelSym>::map(IO &IO) {
366   // TODO: Print the subfields
367 }
368 
369 template <> void SymbolRecordImpl<BlockSym>::map(IO &IO) {
370   IO.mapOptional("PtrParent", Symbol.Parent, 0U);
371   IO.mapOptional("PtrEnd", Symbol.End, 0U);
372   IO.mapRequired("CodeSize", Symbol.CodeSize);
373   IO.mapOptional("Offset", Symbol.CodeOffset, 0U);
374   IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
375   IO.mapRequired("BlockName", Symbol.Name);
376 }
377 
378 template <> void SymbolRecordImpl<LabelSym>::map(IO &IO) {
379   IO.mapOptional("Offset", Symbol.CodeOffset, 0U);
380   IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
381   IO.mapRequired("Flags", Symbol.Flags);
382   IO.mapRequired("Flags", Symbol.Flags);
383   IO.mapRequired("DisplayName", Symbol.Name);
384 }
385 
386 template <> void SymbolRecordImpl<ObjNameSym>::map(IO &IO) {
387   IO.mapRequired("Signature", Symbol.Signature);
388   IO.mapRequired("ObjectName", Symbol.Name);
389 }
390 
391 template <> void SymbolRecordImpl<Compile2Sym>::map(IO &IO) {
392   IO.mapRequired("Flags", Symbol.Flags);
393   IO.mapRequired("Machine", Symbol.Machine);
394   IO.mapRequired("FrontendMajor", Symbol.VersionFrontendMajor);
395   IO.mapRequired("FrontendMinor", Symbol.VersionFrontendMinor);
396   IO.mapRequired("FrontendBuild", Symbol.VersionFrontendBuild);
397   IO.mapRequired("BackendMajor", Symbol.VersionBackendMajor);
398   IO.mapRequired("BackendMinor", Symbol.VersionBackendMinor);
399   IO.mapRequired("BackendBuild", Symbol.VersionBackendBuild);
400   IO.mapRequired("Version", Symbol.Version);
401 }
402 
403 template <> void SymbolRecordImpl<Compile3Sym>::map(IO &IO) {
404   IO.mapRequired("Flags", Symbol.Flags);
405   IO.mapRequired("Machine", Symbol.Machine);
406   IO.mapRequired("FrontendMajor", Symbol.VersionFrontendMajor);
407   IO.mapRequired("FrontendMinor", Symbol.VersionFrontendMinor);
408   IO.mapRequired("FrontendBuild", Symbol.VersionFrontendBuild);
409   IO.mapRequired("FrontendQFE", Symbol.VersionFrontendQFE);
410   IO.mapRequired("BackendMajor", Symbol.VersionBackendMajor);
411   IO.mapRequired("BackendMinor", Symbol.VersionBackendMinor);
412   IO.mapRequired("BackendBuild", Symbol.VersionBackendBuild);
413   IO.mapRequired("BackendQFE", Symbol.VersionBackendQFE);
414   IO.mapRequired("Version", Symbol.Version);
415 }
416 
417 template <> void SymbolRecordImpl<FrameProcSym>::map(IO &IO) {
418   IO.mapRequired("TotalFrameBytes", Symbol.TotalFrameBytes);
419   IO.mapRequired("PaddingFrameBytes", Symbol.PaddingFrameBytes);
420   IO.mapRequired("OffsetToPadding", Symbol.OffsetToPadding);
421   IO.mapRequired("BytesOfCalleeSavedRegisters",
422                  Symbol.BytesOfCalleeSavedRegisters);
423   IO.mapRequired("OffsetOfExceptionHandler", Symbol.OffsetOfExceptionHandler);
424   IO.mapRequired("SectionIdOfExceptionHandler",
425                  Symbol.SectionIdOfExceptionHandler);
426   IO.mapRequired("Flags", Symbol.Flags);
427 }
428 
429 template <> void SymbolRecordImpl<CallSiteInfoSym>::map(IO &IO) {
430   IO.mapOptional("Offset", Symbol.CodeOffset, 0U);
431   IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
432   IO.mapRequired("Type", Symbol.Type);
433 }
434 
435 template <> void SymbolRecordImpl<FileStaticSym>::map(IO &IO) {
436   IO.mapRequired("Index", Symbol.Index);
437   IO.mapRequired("ModFilenameOffset", Symbol.ModFilenameOffset);
438   IO.mapRequired("Flags", Symbol.Flags);
439   IO.mapRequired("Name", Symbol.Name);
440 }
441 
442 template <> void SymbolRecordImpl<HeapAllocationSiteSym>::map(IO &IO) {
443   IO.mapOptional("Offset", Symbol.CodeOffset, 0U);
444   IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
445   IO.mapRequired("CallInstructionSize", Symbol.CallInstructionSize);
446   IO.mapRequired("Type", Symbol.Type);
447 }
448 
449 template <> void SymbolRecordImpl<FrameCookieSym>::map(IO &IO) {
450   IO.mapRequired("Register", Symbol.Register);
451   IO.mapRequired("CookieKind", Symbol.CookieKind);
452   IO.mapRequired("Flags", Symbol.Flags);
453 }
454 
455 template <> void SymbolRecordImpl<CallerSym>::map(IO &IO) {
456   IO.mapRequired("FuncID", Symbol.Indices);
457 }
458 
459 template <> void SymbolRecordImpl<UDTSym>::map(IO &IO) {
460   IO.mapRequired("Type", Symbol.Type);
461   IO.mapRequired("UDTName", Symbol.Name);
462 }
463 
464 template <> void SymbolRecordImpl<BuildInfoSym>::map(IO &IO) {
465   IO.mapRequired("BuildId", Symbol.BuildId);
466 }
467 
468 template <> void SymbolRecordImpl<BPRelativeSym>::map(IO &IO) {
469   IO.mapRequired("Offset", Symbol.Offset);
470   IO.mapRequired("Type", Symbol.Type);
471   IO.mapRequired("VarName", Symbol.Name);
472 }
473 
474 template <> void SymbolRecordImpl<RegRelativeSym>::map(IO &IO) {
475   IO.mapRequired("Offset", Symbol.Offset);
476   IO.mapRequired("Type", Symbol.Type);
477   IO.mapRequired("Register", Symbol.Register);
478   IO.mapRequired("VarName", Symbol.Name);
479 }
480 
481 template <> void SymbolRecordImpl<ConstantSym>::map(IO &IO) {
482   IO.mapRequired("Type", Symbol.Type);
483   IO.mapRequired("Value", Symbol.Value);
484   IO.mapRequired("Name", Symbol.Name);
485 }
486 
487 template <> void SymbolRecordImpl<DataSym>::map(IO &IO) {
488   IO.mapRequired("Type", Symbol.Type);
489   IO.mapOptional("Offset", Symbol.DataOffset, 0U);
490   IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
491   IO.mapRequired("DisplayName", Symbol.Name);
492 }
493 
494 template <> void SymbolRecordImpl<ThreadLocalDataSym>::map(IO &IO) {
495   IO.mapRequired("Type", Symbol.Type);
496   IO.mapOptional("Offset", Symbol.DataOffset, 0U);
497   IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
498   IO.mapRequired("DisplayName", Symbol.Name);
499 }
500 }
501 }
502 }
503 
504 CVSymbol CodeViewYAML::SymbolRecord::toCodeViewSymbol(
505     BumpPtrAllocator &Allocator, CodeViewContainer Container) const {
506   return Symbol->toCodeViewSymbol(Allocator, Container);
507 }
508 
509 namespace llvm {
510 namespace yaml {
511 template <> struct MappingTraits<SymbolRecordBase> {
512   static void mapping(IO &io, SymbolRecordBase &Record) { Record.map(io); }
513 };
514 }
515 }
516 
517 template <typename SymbolType>
518 static inline Expected<CodeViewYAML::SymbolRecord>
519 fromCodeViewSymbolImpl(CVSymbol Symbol) {
520   CodeViewYAML::SymbolRecord Result;
521 
522   auto Impl = std::make_shared<SymbolType>(Symbol.kind());
523   if (auto EC = Impl->fromCodeViewSymbol(Symbol))
524     return std::move(EC);
525   Result.Symbol = Impl;
526   return Result;
527 }
528 
529 Expected<CodeViewYAML::SymbolRecord>
530 CodeViewYAML::SymbolRecord::fromCodeViewSymbol(CVSymbol Symbol) {
531 #define SYMBOL_RECORD(EnumName, EnumVal, ClassName)                            \
532   case EnumName:                                                               \
533     return fromCodeViewSymbolImpl<SymbolRecordImpl<ClassName>>(Symbol);
534 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)           \
535   SYMBOL_RECORD(EnumName, EnumVal, ClassName)
536   switch (Symbol.kind()) {
537 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
538   default:
539     return fromCodeViewSymbolImpl<UnknownSymbolRecord>(Symbol);
540   }
541   return make_error<CodeViewError>(cv_error_code::corrupt_record);
542 }
543 
544 template <typename ConcreteType>
545 static void mapSymbolRecordImpl(IO &IO, const char *Class, SymbolKind Kind,
546                                 CodeViewYAML::SymbolRecord &Obj) {
547   if (!IO.outputting())
548     Obj.Symbol = std::make_shared<ConcreteType>(Kind);
549 
550   IO.mapRequired(Class, *Obj.Symbol);
551 }
552 
553 void MappingTraits<CodeViewYAML::SymbolRecord>::mapping(
554     IO &IO, CodeViewYAML::SymbolRecord &Obj) {
555   SymbolKind Kind;
556   if (IO.outputting())
557     Kind = Obj.Symbol->Kind;
558   IO.mapRequired("Kind", Kind);
559 
560 #define SYMBOL_RECORD(EnumName, EnumVal, ClassName)                            \
561   case EnumName:                                                               \
562     mapSymbolRecordImpl<SymbolRecordImpl<ClassName>>(IO, #ClassName, Kind,     \
563                                                      Obj);                     \
564     break;
565 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)           \
566   SYMBOL_RECORD(EnumName, EnumVal, ClassName)
567   switch (Kind) {
568 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
569   default:
570     mapSymbolRecordImpl<UnknownSymbolRecord>(IO, "UnknownSym", Kind, Obj);
571   }
572 }
573