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