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