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