11b88f4f3SZachary Turner //===- CodeViewYAMLTypes.cpp - CodeView YAMLIO types implementation -------===//
21b88f4f3SZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61b88f4f3SZachary Turner //
71b88f4f3SZachary Turner //===----------------------------------------------------------------------===//
81b88f4f3SZachary Turner //
91b88f4f3SZachary Turner // This file defines classes for handling the YAML representation of CodeView
101b88f4f3SZachary Turner // Debug Info.
111b88f4f3SZachary Turner //
121b88f4f3SZachary Turner //===----------------------------------------------------------------------===//
131b88f4f3SZachary Turner 
141b88f4f3SZachary Turner #include "llvm/ObjectYAML/CodeViewYAMLTypes.h"
1528082ab0SEugene Zelenko #include "llvm/ADT/APSInt.h"
1628082ab0SEugene Zelenko #include "llvm/ADT/ArrayRef.h"
1728082ab0SEugene Zelenko #include "llvm/ADT/StringRef.h"
1828082ab0SEugene Zelenko #include "llvm/BinaryFormat/COFF.h"
19ca6dbf14SZachary Turner #include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h"
201b88f4f3SZachary Turner #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
2128082ab0SEugene Zelenko #include "llvm/DebugInfo/CodeView/CodeView.h"
221b88f4f3SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewError.h"
236900de1dSZachary Turner #include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h"
241b88f4f3SZachary Turner #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
2528082ab0SEugene Zelenko #include "llvm/DebugInfo/CodeView/TypeIndex.h"
2628082ab0SEugene Zelenko #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
2728082ab0SEugene Zelenko #include "llvm/Support/Allocator.h"
2828082ab0SEugene Zelenko #include "llvm/Support/BinaryStreamReader.h"
29deb39130SZachary Turner #include "llvm/Support/BinaryStreamWriter.h"
3028082ab0SEugene Zelenko #include "llvm/Support/Endian.h"
3128082ab0SEugene Zelenko #include "llvm/Support/Error.h"
3228082ab0SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
3328082ab0SEugene Zelenko #include "llvm/Support/YAMLTraits.h"
3428082ab0SEugene Zelenko #include "llvm/Support/raw_ostream.h"
3528082ab0SEugene Zelenko #include <algorithm>
3628082ab0SEugene Zelenko #include <cassert>
3728082ab0SEugene Zelenko #include <cstdint>
3828082ab0SEugene Zelenko #include <vector>
391b88f4f3SZachary Turner 
401b88f4f3SZachary Turner using namespace llvm;
411b88f4f3SZachary Turner using namespace llvm::codeview;
421b88f4f3SZachary Turner using namespace llvm::CodeViewYAML;
431b88f4f3SZachary Turner using namespace llvm::CodeViewYAML::detail;
441b88f4f3SZachary Turner using namespace llvm::yaml;
451b88f4f3SZachary Turner 
461b88f4f3SZachary Turner LLVM_YAML_IS_SEQUENCE_VECTOR(OneMethodRecord)
471b88f4f3SZachary Turner LLVM_YAML_IS_SEQUENCE_VECTOR(VFTableSlotKind)
481b88f4f3SZachary Turner LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex)
491b88f4f3SZachary Turner 
50b213b27eSFrancis Visoiu Mistrih LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, QuotingType::None)
51b213b27eSFrancis Visoiu Mistrih LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, QuotingType::None)
521b88f4f3SZachary Turner 
531b88f4f3SZachary Turner LLVM_YAML_DECLARE_ENUM_TRAITS(TypeLeafKind)
541b88f4f3SZachary Turner LLVM_YAML_DECLARE_ENUM_TRAITS(PointerToMemberRepresentation)
551b88f4f3SZachary Turner LLVM_YAML_DECLARE_ENUM_TRAITS(VFTableSlotKind)
561b88f4f3SZachary Turner LLVM_YAML_DECLARE_ENUM_TRAITS(CallingConvention)
571b88f4f3SZachary Turner LLVM_YAML_DECLARE_ENUM_TRAITS(PointerKind)
581b88f4f3SZachary Turner LLVM_YAML_DECLARE_ENUM_TRAITS(PointerMode)
591b88f4f3SZachary Turner LLVM_YAML_DECLARE_ENUM_TRAITS(HfaKind)
601b88f4f3SZachary Turner LLVM_YAML_DECLARE_ENUM_TRAITS(MemberAccess)
611b88f4f3SZachary Turner LLVM_YAML_DECLARE_ENUM_TRAITS(MethodKind)
621b88f4f3SZachary Turner LLVM_YAML_DECLARE_ENUM_TRAITS(WindowsRTClassKind)
631b88f4f3SZachary Turner LLVM_YAML_DECLARE_ENUM_TRAITS(LabelType)
641b88f4f3SZachary Turner 
651b88f4f3SZachary Turner LLVM_YAML_DECLARE_BITSET_TRAITS(PointerOptions)
661b88f4f3SZachary Turner LLVM_YAML_DECLARE_BITSET_TRAITS(ModifierOptions)
671b88f4f3SZachary Turner LLVM_YAML_DECLARE_BITSET_TRAITS(FunctionOptions)
681b88f4f3SZachary Turner LLVM_YAML_DECLARE_BITSET_TRAITS(ClassOptions)
691b88f4f3SZachary Turner LLVM_YAML_DECLARE_BITSET_TRAITS(MethodOptions)
701b88f4f3SZachary Turner 
711b88f4f3SZachary Turner LLVM_YAML_DECLARE_MAPPING_TRAITS(OneMethodRecord)
721b88f4f3SZachary Turner LLVM_YAML_DECLARE_MAPPING_TRAITS(MemberPointerInfo)
731b88f4f3SZachary Turner 
741b88f4f3SZachary Turner namespace llvm {
751b88f4f3SZachary Turner namespace CodeViewYAML {
761b88f4f3SZachary Turner namespace detail {
771b88f4f3SZachary Turner 
781b88f4f3SZachary Turner struct LeafRecordBase {
791b88f4f3SZachary Turner   TypeLeafKind Kind;
801b88f4f3SZachary Turner 
LeafRecordBasellvm::CodeViewYAML::detail::LeafRecordBase8128082ab0SEugene Zelenko   explicit LeafRecordBase(TypeLeafKind K) : Kind(K) {}
8228082ab0SEugene Zelenko   virtual ~LeafRecordBase() = default;
8328082ab0SEugene Zelenko 
841b88f4f3SZachary Turner   virtual void map(yaml::IO &io) = 0;
85ca6dbf14SZachary Turner   virtual CVType toCodeViewRecord(AppendingTypeTableBuilder &TS) const = 0;
861b88f4f3SZachary Turner   virtual Error fromCodeViewRecord(CVType Type) = 0;
871b88f4f3SZachary Turner };
881b88f4f3SZachary Turner 
891b88f4f3SZachary Turner template <typename T> struct LeafRecordImpl : public LeafRecordBase {
LeafRecordImplllvm::CodeViewYAML::detail::LeafRecordImpl901b88f4f3SZachary Turner   explicit LeafRecordImpl(TypeLeafKind K)
911b88f4f3SZachary Turner       : LeafRecordBase(K), Record(static_cast<TypeRecordKind>(K)) {}
921b88f4f3SZachary Turner 
931b88f4f3SZachary Turner   void map(yaml::IO &io) override;
941b88f4f3SZachary Turner 
fromCodeViewRecordllvm::CodeViewYAML::detail::LeafRecordImpl951b88f4f3SZachary Turner   Error fromCodeViewRecord(CVType Type) override {
961b88f4f3SZachary Turner     return TypeDeserializer::deserializeAs<T>(Type, Record);
971b88f4f3SZachary Turner   }
981b88f4f3SZachary Turner 
toCodeViewRecordllvm::CodeViewYAML::detail::LeafRecordImpl99ca6dbf14SZachary Turner   CVType toCodeViewRecord(AppendingTypeTableBuilder &TS) const override {
1006900de1dSZachary Turner     TS.writeLeafType(Record);
101e10d0041SReid Kleckner     return CVType(TS.records().back());
1021b88f4f3SZachary Turner   }
1031b88f4f3SZachary Turner 
1041b88f4f3SZachary Turner   mutable T Record;
1051b88f4f3SZachary Turner };
1061b88f4f3SZachary Turner 
1071b88f4f3SZachary Turner template <> struct LeafRecordImpl<FieldListRecord> : public LeafRecordBase {
LeafRecordImplllvm::CodeViewYAML::detail::LeafRecordImpl1081b88f4f3SZachary Turner   explicit LeafRecordImpl(TypeLeafKind K) : LeafRecordBase(K) {}
1091b88f4f3SZachary Turner 
1101b88f4f3SZachary Turner   void map(yaml::IO &io) override;
111ca6dbf14SZachary Turner   CVType toCodeViewRecord(AppendingTypeTableBuilder &TS) const override;
1121b88f4f3SZachary Turner   Error fromCodeViewRecord(CVType Type) override;
1131b88f4f3SZachary Turner 
1141b88f4f3SZachary Turner   std::vector<MemberRecord> Members;
1151b88f4f3SZachary Turner };
1161b88f4f3SZachary Turner 
1171b88f4f3SZachary Turner struct MemberRecordBase {
1181b88f4f3SZachary Turner   TypeLeafKind Kind;
1191b88f4f3SZachary Turner 
MemberRecordBasellvm::CodeViewYAML::detail::MemberRecordBase12028082ab0SEugene Zelenko   explicit MemberRecordBase(TypeLeafKind K) : Kind(K) {}
12128082ab0SEugene Zelenko   virtual ~MemberRecordBase() = default;
12228082ab0SEugene Zelenko 
1231b88f4f3SZachary Turner   virtual void map(yaml::IO &io) = 0;
1246900de1dSZachary Turner   virtual void writeTo(ContinuationRecordBuilder &CRB) = 0;
1251b88f4f3SZachary Turner };
1261b88f4f3SZachary Turner 
1271b88f4f3SZachary Turner template <typename T> struct MemberRecordImpl : public MemberRecordBase {
MemberRecordImplllvm::CodeViewYAML::detail::MemberRecordImpl1281b88f4f3SZachary Turner   explicit MemberRecordImpl(TypeLeafKind K)
1291b88f4f3SZachary Turner       : MemberRecordBase(K), Record(static_cast<TypeRecordKind>(K)) {}
13028082ab0SEugene Zelenko 
1311b88f4f3SZachary Turner   void map(yaml::IO &io) override;
1321b88f4f3SZachary Turner 
writeTollvm::CodeViewYAML::detail::MemberRecordImpl1336900de1dSZachary Turner   void writeTo(ContinuationRecordBuilder &CRB) override {
1346900de1dSZachary Turner     CRB.writeMemberType(Record);
1351b88f4f3SZachary Turner   }
1361b88f4f3SZachary Turner 
1371b88f4f3SZachary Turner   mutable T Record;
1381b88f4f3SZachary Turner };
13928082ab0SEugene Zelenko 
14028082ab0SEugene Zelenko } // end namespace detail
14128082ab0SEugene Zelenko } // end namespace CodeViewYAML
14228082ab0SEugene Zelenko } // end namespace llvm
1431b88f4f3SZachary Turner 
output(const GUID & G,void *,llvm::raw_ostream & OS)14467653ee0SReid Kleckner void ScalarTraits<GUID>::output(const GUID &G, void *, llvm::raw_ostream &OS) {
14567653ee0SReid Kleckner   OS << G;
14667653ee0SReid Kleckner }
14767653ee0SReid Kleckner 
input(StringRef Scalar,void * Ctx,GUID & S)14867653ee0SReid Kleckner StringRef ScalarTraits<GUID>::input(StringRef Scalar, void *Ctx, GUID &S) {
14967653ee0SReid Kleckner   if (Scalar.size() != 38)
15067653ee0SReid Kleckner     return "GUID strings are 38 characters long";
151f47a4c07SAlex Orlov   if (Scalar.front() != '{' || Scalar.back() != '}')
15267653ee0SReid Kleckner     return "GUID is not enclosed in {}";
153f47a4c07SAlex Orlov   Scalar = Scalar.substr(1, Scalar.size() - 2);
154f47a4c07SAlex Orlov   SmallVector<StringRef, 6> A;
155f47a4c07SAlex Orlov   Scalar.split(A, '-', 5);
156f47a4c07SAlex Orlov   if (A.size() != 5 || Scalar[8] != '-' || Scalar[13] != '-' ||
157f47a4c07SAlex Orlov       Scalar[18] != '-' || Scalar[23] != '-')
15867653ee0SReid Kleckner     return "GUID sections are not properly delineated with dashes";
159f47a4c07SAlex Orlov   struct MSGuid {
160f47a4c07SAlex Orlov     support::ulittle32_t Data1;
161f47a4c07SAlex Orlov     support::ulittle16_t Data2;
162f47a4c07SAlex Orlov     support::ulittle16_t Data3;
163f47a4c07SAlex Orlov     support::ubig64_t Data4;
164f47a4c07SAlex Orlov   };
165f47a4c07SAlex Orlov   MSGuid G = {};
166f47a4c07SAlex Orlov   uint64_t D41{}, D42{};
167f47a4c07SAlex Orlov   if (!to_integer(A[0], G.Data1, 16) || !to_integer(A[1], G.Data2, 16) ||
168f47a4c07SAlex Orlov       !to_integer(A[2], G.Data3, 16) || !to_integer(A[3], D41, 16) ||
169f47a4c07SAlex Orlov       !to_integer(A[4], D42, 16))
170f47a4c07SAlex Orlov     return "GUID contains non hex digits";
171f47a4c07SAlex Orlov   G.Data4 = (D41 << 48) | D42;
172f47a4c07SAlex Orlov   ::memcpy(&S, &G, sizeof(GUID));
17367653ee0SReid Kleckner   return "";
17467653ee0SReid Kleckner }
17567653ee0SReid Kleckner 
output(const TypeIndex & S,void *,raw_ostream & OS)1761b88f4f3SZachary Turner void ScalarTraits<TypeIndex>::output(const TypeIndex &S, void *,
17728082ab0SEugene Zelenko                                      raw_ostream &OS) {
1781b88f4f3SZachary Turner   OS << S.getIndex();
1791b88f4f3SZachary Turner }
1801b88f4f3SZachary Turner 
input(StringRef Scalar,void * Ctx,TypeIndex & S)1811b88f4f3SZachary Turner StringRef ScalarTraits<TypeIndex>::input(StringRef Scalar, void *Ctx,
1821b88f4f3SZachary Turner                                          TypeIndex &S) {
1831b88f4f3SZachary Turner   uint32_t I;
1841b88f4f3SZachary Turner   StringRef Result = ScalarTraits<uint32_t>::input(Scalar, Ctx, I);
1851b88f4f3SZachary Turner   S.setIndex(I);
1861b88f4f3SZachary Turner   return Result;
1871b88f4f3SZachary Turner }
1881b88f4f3SZachary Turner 
output(const APSInt & S,void *,raw_ostream & OS)18928082ab0SEugene Zelenko void ScalarTraits<APSInt>::output(const APSInt &S, void *, raw_ostream &OS) {
1904d2711fbSBob Haarman   S.print(OS, S.isSigned());
1911b88f4f3SZachary Turner }
1921b88f4f3SZachary Turner 
input(StringRef Scalar,void * Ctx,APSInt & S)1931b88f4f3SZachary Turner StringRef ScalarTraits<APSInt>::input(StringRef Scalar, void *Ctx, APSInt &S) {
1941b88f4f3SZachary Turner   S = APSInt(Scalar);
1951b88f4f3SZachary Turner   return "";
1961b88f4f3SZachary Turner }
1971b88f4f3SZachary Turner 
enumeration(IO & io,TypeLeafKind & Value)1981b88f4f3SZachary Turner void ScalarEnumerationTraits<TypeLeafKind>::enumeration(IO &io,
1991b88f4f3SZachary Turner                                                         TypeLeafKind &Value) {
2001b88f4f3SZachary Turner #define CV_TYPE(name, val) io.enumCase(Value, #name, name);
2011b88f4f3SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
2021b88f4f3SZachary Turner #undef CV_TYPE
2031b88f4f3SZachary Turner }
2041b88f4f3SZachary Turner 
enumeration(IO & IO,PointerToMemberRepresentation & Value)2051b88f4f3SZachary Turner void ScalarEnumerationTraits<PointerToMemberRepresentation>::enumeration(
2061b88f4f3SZachary Turner     IO &IO, PointerToMemberRepresentation &Value) {
2071b88f4f3SZachary Turner   IO.enumCase(Value, "Unknown", PointerToMemberRepresentation::Unknown);
2081b88f4f3SZachary Turner   IO.enumCase(Value, "SingleInheritanceData",
2091b88f4f3SZachary Turner               PointerToMemberRepresentation::SingleInheritanceData);
2101b88f4f3SZachary Turner   IO.enumCase(Value, "MultipleInheritanceData",
2111b88f4f3SZachary Turner               PointerToMemberRepresentation::MultipleInheritanceData);
2121b88f4f3SZachary Turner   IO.enumCase(Value, "VirtualInheritanceData",
2131b88f4f3SZachary Turner               PointerToMemberRepresentation::VirtualInheritanceData);
2141b88f4f3SZachary Turner   IO.enumCase(Value, "GeneralData", PointerToMemberRepresentation::GeneralData);
2151b88f4f3SZachary Turner   IO.enumCase(Value, "SingleInheritanceFunction",
2161b88f4f3SZachary Turner               PointerToMemberRepresentation::SingleInheritanceFunction);
2171b88f4f3SZachary Turner   IO.enumCase(Value, "MultipleInheritanceFunction",
2181b88f4f3SZachary Turner               PointerToMemberRepresentation::MultipleInheritanceFunction);
2191b88f4f3SZachary Turner   IO.enumCase(Value, "VirtualInheritanceFunction",
2201b88f4f3SZachary Turner               PointerToMemberRepresentation::VirtualInheritanceFunction);
2211b88f4f3SZachary Turner   IO.enumCase(Value, "GeneralFunction",
2221b88f4f3SZachary Turner               PointerToMemberRepresentation::GeneralFunction);
2231b88f4f3SZachary Turner }
2241b88f4f3SZachary Turner 
enumeration(IO & IO,VFTableSlotKind & Kind)2251b88f4f3SZachary Turner void ScalarEnumerationTraits<VFTableSlotKind>::enumeration(
2261b88f4f3SZachary Turner     IO &IO, VFTableSlotKind &Kind) {
2271b88f4f3SZachary Turner   IO.enumCase(Kind, "Near16", VFTableSlotKind::Near16);
2281b88f4f3SZachary Turner   IO.enumCase(Kind, "Far16", VFTableSlotKind::Far16);
2291b88f4f3SZachary Turner   IO.enumCase(Kind, "This", VFTableSlotKind::This);
2301b88f4f3SZachary Turner   IO.enumCase(Kind, "Outer", VFTableSlotKind::Outer);
2311b88f4f3SZachary Turner   IO.enumCase(Kind, "Meta", VFTableSlotKind::Meta);
2321b88f4f3SZachary Turner   IO.enumCase(Kind, "Near", VFTableSlotKind::Near);
2331b88f4f3SZachary Turner   IO.enumCase(Kind, "Far", VFTableSlotKind::Far);
2341b88f4f3SZachary Turner }
2351b88f4f3SZachary Turner 
enumeration(IO & IO,CallingConvention & Value)2361b88f4f3SZachary Turner void ScalarEnumerationTraits<CallingConvention>::enumeration(
2371b88f4f3SZachary Turner     IO &IO, CallingConvention &Value) {
2381b88f4f3SZachary Turner   IO.enumCase(Value, "NearC", CallingConvention::NearC);
2391b88f4f3SZachary Turner   IO.enumCase(Value, "FarC", CallingConvention::FarC);
2401b88f4f3SZachary Turner   IO.enumCase(Value, "NearPascal", CallingConvention::NearPascal);
2411b88f4f3SZachary Turner   IO.enumCase(Value, "FarPascal", CallingConvention::FarPascal);
2421b88f4f3SZachary Turner   IO.enumCase(Value, "NearFast", CallingConvention::NearFast);
2431b88f4f3SZachary Turner   IO.enumCase(Value, "FarFast", CallingConvention::FarFast);
2441b88f4f3SZachary Turner   IO.enumCase(Value, "NearStdCall", CallingConvention::NearStdCall);
2451b88f4f3SZachary Turner   IO.enumCase(Value, "FarStdCall", CallingConvention::FarStdCall);
2461b88f4f3SZachary Turner   IO.enumCase(Value, "NearSysCall", CallingConvention::NearSysCall);
2471b88f4f3SZachary Turner   IO.enumCase(Value, "FarSysCall", CallingConvention::FarSysCall);
2481b88f4f3SZachary Turner   IO.enumCase(Value, "ThisCall", CallingConvention::ThisCall);
2491b88f4f3SZachary Turner   IO.enumCase(Value, "MipsCall", CallingConvention::MipsCall);
2501b88f4f3SZachary Turner   IO.enumCase(Value, "Generic", CallingConvention::Generic);
2511b88f4f3SZachary Turner   IO.enumCase(Value, "AlphaCall", CallingConvention::AlphaCall);
2521b88f4f3SZachary Turner   IO.enumCase(Value, "PpcCall", CallingConvention::PpcCall);
2531b88f4f3SZachary Turner   IO.enumCase(Value, "SHCall", CallingConvention::SHCall);
2541b88f4f3SZachary Turner   IO.enumCase(Value, "ArmCall", CallingConvention::ArmCall);
2551b88f4f3SZachary Turner   IO.enumCase(Value, "AM33Call", CallingConvention::AM33Call);
2561b88f4f3SZachary Turner   IO.enumCase(Value, "TriCall", CallingConvention::TriCall);
2571b88f4f3SZachary Turner   IO.enumCase(Value, "SH5Call", CallingConvention::SH5Call);
2581b88f4f3SZachary Turner   IO.enumCase(Value, "M32RCall", CallingConvention::M32RCall);
2591b88f4f3SZachary Turner   IO.enumCase(Value, "ClrCall", CallingConvention::ClrCall);
2601b88f4f3SZachary Turner   IO.enumCase(Value, "Inline", CallingConvention::Inline);
2611b88f4f3SZachary Turner   IO.enumCase(Value, "NearVector", CallingConvention::NearVector);
2621b88f4f3SZachary Turner }
2631b88f4f3SZachary Turner 
enumeration(IO & IO,PointerKind & Kind)2641b88f4f3SZachary Turner void ScalarEnumerationTraits<PointerKind>::enumeration(IO &IO,
2651b88f4f3SZachary Turner                                                        PointerKind &Kind) {
2661b88f4f3SZachary Turner   IO.enumCase(Kind, "Near16", PointerKind::Near16);
2671b88f4f3SZachary Turner   IO.enumCase(Kind, "Far16", PointerKind::Far16);
2681b88f4f3SZachary Turner   IO.enumCase(Kind, "Huge16", PointerKind::Huge16);
2691b88f4f3SZachary Turner   IO.enumCase(Kind, "BasedOnSegment", PointerKind::BasedOnSegment);
2701b88f4f3SZachary Turner   IO.enumCase(Kind, "BasedOnValue", PointerKind::BasedOnValue);
2711b88f4f3SZachary Turner   IO.enumCase(Kind, "BasedOnSegmentValue", PointerKind::BasedOnSegmentValue);
2721b88f4f3SZachary Turner   IO.enumCase(Kind, "BasedOnAddress", PointerKind::BasedOnAddress);
2731b88f4f3SZachary Turner   IO.enumCase(Kind, "BasedOnSegmentAddress",
2741b88f4f3SZachary Turner               PointerKind::BasedOnSegmentAddress);
2751b88f4f3SZachary Turner   IO.enumCase(Kind, "BasedOnType", PointerKind::BasedOnType);
2761b88f4f3SZachary Turner   IO.enumCase(Kind, "BasedOnSelf", PointerKind::BasedOnSelf);
2771b88f4f3SZachary Turner   IO.enumCase(Kind, "Near32", PointerKind::Near32);
2781b88f4f3SZachary Turner   IO.enumCase(Kind, "Far32", PointerKind::Far32);
2791b88f4f3SZachary Turner   IO.enumCase(Kind, "Near64", PointerKind::Near64);
2801b88f4f3SZachary Turner }
2811b88f4f3SZachary Turner 
enumeration(IO & IO,PointerMode & Mode)2821b88f4f3SZachary Turner void ScalarEnumerationTraits<PointerMode>::enumeration(IO &IO,
2831b88f4f3SZachary Turner                                                        PointerMode &Mode) {
2841b88f4f3SZachary Turner   IO.enumCase(Mode, "Pointer", PointerMode::Pointer);
2851b88f4f3SZachary Turner   IO.enumCase(Mode, "LValueReference", PointerMode::LValueReference);
2861b88f4f3SZachary Turner   IO.enumCase(Mode, "PointerToDataMember", PointerMode::PointerToDataMember);
2871b88f4f3SZachary Turner   IO.enumCase(Mode, "PointerToMemberFunction",
2881b88f4f3SZachary Turner               PointerMode::PointerToMemberFunction);
2891b88f4f3SZachary Turner   IO.enumCase(Mode, "RValueReference", PointerMode::RValueReference);
2901b88f4f3SZachary Turner }
2911b88f4f3SZachary Turner 
enumeration(IO & IO,HfaKind & Value)2921b88f4f3SZachary Turner void ScalarEnumerationTraits<HfaKind>::enumeration(IO &IO, HfaKind &Value) {
2931b88f4f3SZachary Turner   IO.enumCase(Value, "None", HfaKind::None);
2941b88f4f3SZachary Turner   IO.enumCase(Value, "Float", HfaKind::Float);
2951b88f4f3SZachary Turner   IO.enumCase(Value, "Double", HfaKind::Double);
2961b88f4f3SZachary Turner   IO.enumCase(Value, "Other", HfaKind::Other);
2971b88f4f3SZachary Turner }
2981b88f4f3SZachary Turner 
enumeration(IO & IO,MemberAccess & Access)2991b88f4f3SZachary Turner void ScalarEnumerationTraits<MemberAccess>::enumeration(IO &IO,
3001b88f4f3SZachary Turner                                                         MemberAccess &Access) {
3011b88f4f3SZachary Turner   IO.enumCase(Access, "None", MemberAccess::None);
3021b88f4f3SZachary Turner   IO.enumCase(Access, "Private", MemberAccess::Private);
3031b88f4f3SZachary Turner   IO.enumCase(Access, "Protected", MemberAccess::Protected);
3041b88f4f3SZachary Turner   IO.enumCase(Access, "Public", MemberAccess::Public);
3051b88f4f3SZachary Turner }
3061b88f4f3SZachary Turner 
enumeration(IO & IO,MethodKind & Kind)3071b88f4f3SZachary Turner void ScalarEnumerationTraits<MethodKind>::enumeration(IO &IO,
3081b88f4f3SZachary Turner                                                       MethodKind &Kind) {
3091b88f4f3SZachary Turner   IO.enumCase(Kind, "Vanilla", MethodKind::Vanilla);
3101b88f4f3SZachary Turner   IO.enumCase(Kind, "Virtual", MethodKind::Virtual);
3111b88f4f3SZachary Turner   IO.enumCase(Kind, "Static", MethodKind::Static);
3121b88f4f3SZachary Turner   IO.enumCase(Kind, "Friend", MethodKind::Friend);
3131b88f4f3SZachary Turner   IO.enumCase(Kind, "IntroducingVirtual", MethodKind::IntroducingVirtual);
3141b88f4f3SZachary Turner   IO.enumCase(Kind, "PureVirtual", MethodKind::PureVirtual);
3151b88f4f3SZachary Turner   IO.enumCase(Kind, "PureIntroducingVirtual",
3161b88f4f3SZachary Turner               MethodKind::PureIntroducingVirtual);
3171b88f4f3SZachary Turner }
3181b88f4f3SZachary Turner 
enumeration(IO & IO,WindowsRTClassKind & Value)3191b88f4f3SZachary Turner void ScalarEnumerationTraits<WindowsRTClassKind>::enumeration(
3201b88f4f3SZachary Turner     IO &IO, WindowsRTClassKind &Value) {
3211b88f4f3SZachary Turner   IO.enumCase(Value, "None", WindowsRTClassKind::None);
3221b88f4f3SZachary Turner   IO.enumCase(Value, "Ref", WindowsRTClassKind::RefClass);
3231b88f4f3SZachary Turner   IO.enumCase(Value, "Value", WindowsRTClassKind::ValueClass);
3241b88f4f3SZachary Turner   IO.enumCase(Value, "Interface", WindowsRTClassKind::Interface);
3251b88f4f3SZachary Turner }
3261b88f4f3SZachary Turner 
enumeration(IO & IO,LabelType & Value)3271b88f4f3SZachary Turner void ScalarEnumerationTraits<LabelType>::enumeration(IO &IO, LabelType &Value) {
3281b88f4f3SZachary Turner   IO.enumCase(Value, "Near", LabelType::Near);
3291b88f4f3SZachary Turner   IO.enumCase(Value, "Far", LabelType::Far);
3301b88f4f3SZachary Turner }
3311b88f4f3SZachary Turner 
bitset(IO & IO,PointerOptions & Options)3321b88f4f3SZachary Turner void ScalarBitSetTraits<PointerOptions>::bitset(IO &IO,
3331b88f4f3SZachary Turner                                                 PointerOptions &Options) {
3341b88f4f3SZachary Turner   IO.bitSetCase(Options, "None", PointerOptions::None);
3351b88f4f3SZachary Turner   IO.bitSetCase(Options, "Flat32", PointerOptions::Flat32);
3361b88f4f3SZachary Turner   IO.bitSetCase(Options, "Volatile", PointerOptions::Volatile);
3371b88f4f3SZachary Turner   IO.bitSetCase(Options, "Const", PointerOptions::Const);
3381b88f4f3SZachary Turner   IO.bitSetCase(Options, "Unaligned", PointerOptions::Unaligned);
3391b88f4f3SZachary Turner   IO.bitSetCase(Options, "Restrict", PointerOptions::Restrict);
3401b88f4f3SZachary Turner   IO.bitSetCase(Options, "WinRTSmartPointer",
3411b88f4f3SZachary Turner                 PointerOptions::WinRTSmartPointer);
3421b88f4f3SZachary Turner }
3431b88f4f3SZachary Turner 
bitset(IO & IO,ModifierOptions & Options)3441b88f4f3SZachary Turner void ScalarBitSetTraits<ModifierOptions>::bitset(IO &IO,
3451b88f4f3SZachary Turner                                                  ModifierOptions &Options) {
3461b88f4f3SZachary Turner   IO.bitSetCase(Options, "None", ModifierOptions::None);
3471b88f4f3SZachary Turner   IO.bitSetCase(Options, "Const", ModifierOptions::Const);
3481b88f4f3SZachary Turner   IO.bitSetCase(Options, "Volatile", ModifierOptions::Volatile);
3491b88f4f3SZachary Turner   IO.bitSetCase(Options, "Unaligned", ModifierOptions::Unaligned);
3501b88f4f3SZachary Turner }
3511b88f4f3SZachary Turner 
bitset(IO & IO,FunctionOptions & Options)3521b88f4f3SZachary Turner void ScalarBitSetTraits<FunctionOptions>::bitset(IO &IO,
3531b88f4f3SZachary Turner                                                  FunctionOptions &Options) {
3541b88f4f3SZachary Turner   IO.bitSetCase(Options, "None", FunctionOptions::None);
3551b88f4f3SZachary Turner   IO.bitSetCase(Options, "CxxReturnUdt", FunctionOptions::CxxReturnUdt);
3561b88f4f3SZachary Turner   IO.bitSetCase(Options, "Constructor", FunctionOptions::Constructor);
3571b88f4f3SZachary Turner   IO.bitSetCase(Options, "ConstructorWithVirtualBases",
3581b88f4f3SZachary Turner                 FunctionOptions::ConstructorWithVirtualBases);
3591b88f4f3SZachary Turner }
3601b88f4f3SZachary Turner 
bitset(IO & IO,ClassOptions & Options)3611b88f4f3SZachary Turner void ScalarBitSetTraits<ClassOptions>::bitset(IO &IO, ClassOptions &Options) {
3621b88f4f3SZachary Turner   IO.bitSetCase(Options, "None", ClassOptions::None);
3631b88f4f3SZachary Turner   IO.bitSetCase(Options, "HasConstructorOrDestructor",
3641b88f4f3SZachary Turner                 ClassOptions::HasConstructorOrDestructor);
3651b88f4f3SZachary Turner   IO.bitSetCase(Options, "HasOverloadedOperator",
3661b88f4f3SZachary Turner                 ClassOptions::HasOverloadedOperator);
3671b88f4f3SZachary Turner   IO.bitSetCase(Options, "Nested", ClassOptions::Nested);
3681b88f4f3SZachary Turner   IO.bitSetCase(Options, "ContainsNestedClass",
3691b88f4f3SZachary Turner                 ClassOptions::ContainsNestedClass);
3701b88f4f3SZachary Turner   IO.bitSetCase(Options, "HasOverloadedAssignmentOperator",
3711b88f4f3SZachary Turner                 ClassOptions::HasOverloadedAssignmentOperator);
3721b88f4f3SZachary Turner   IO.bitSetCase(Options, "HasConversionOperator",
3731b88f4f3SZachary Turner                 ClassOptions::HasConversionOperator);
3741b88f4f3SZachary Turner   IO.bitSetCase(Options, "ForwardReference", ClassOptions::ForwardReference);
3751b88f4f3SZachary Turner   IO.bitSetCase(Options, "Scoped", ClassOptions::Scoped);
3761b88f4f3SZachary Turner   IO.bitSetCase(Options, "HasUniqueName", ClassOptions::HasUniqueName);
3771b88f4f3SZachary Turner   IO.bitSetCase(Options, "Sealed", ClassOptions::Sealed);
3781b88f4f3SZachary Turner   IO.bitSetCase(Options, "Intrinsic", ClassOptions::Intrinsic);
3791b88f4f3SZachary Turner }
3801b88f4f3SZachary Turner 
bitset(IO & IO,MethodOptions & Options)3811b88f4f3SZachary Turner void ScalarBitSetTraits<MethodOptions>::bitset(IO &IO, MethodOptions &Options) {
3821b88f4f3SZachary Turner   IO.bitSetCase(Options, "None", MethodOptions::None);
3831b88f4f3SZachary Turner   IO.bitSetCase(Options, "Pseudo", MethodOptions::Pseudo);
3841b88f4f3SZachary Turner   IO.bitSetCase(Options, "NoInherit", MethodOptions::NoInherit);
3851b88f4f3SZachary Turner   IO.bitSetCase(Options, "NoConstruct", MethodOptions::NoConstruct);
3861b88f4f3SZachary Turner   IO.bitSetCase(Options, "CompilerGenerated", MethodOptions::CompilerGenerated);
3871b88f4f3SZachary Turner   IO.bitSetCase(Options, "Sealed", MethodOptions::Sealed);
3881b88f4f3SZachary Turner }
3891b88f4f3SZachary Turner 
mapping(IO & IO,MemberPointerInfo & MPI)3901b88f4f3SZachary Turner void MappingTraits<MemberPointerInfo>::mapping(IO &IO, MemberPointerInfo &MPI) {
3911b88f4f3SZachary Turner   IO.mapRequired("ContainingType", MPI.ContainingType);
3921b88f4f3SZachary Turner   IO.mapRequired("Representation", MPI.Representation);
3931b88f4f3SZachary Turner }
3941b88f4f3SZachary Turner 
3951b88f4f3SZachary Turner namespace llvm {
3961b88f4f3SZachary Turner namespace CodeViewYAML {
3971b88f4f3SZachary Turner namespace detail {
39828082ab0SEugene Zelenko 
map(IO & IO)3991b88f4f3SZachary Turner template <> void LeafRecordImpl<ModifierRecord>::map(IO &IO) {
4001b88f4f3SZachary Turner   IO.mapRequired("ModifiedType", Record.ModifiedType);
4011b88f4f3SZachary Turner   IO.mapRequired("Modifiers", Record.Modifiers);
4021b88f4f3SZachary Turner }
4031b88f4f3SZachary Turner 
map(IO & IO)4041b88f4f3SZachary Turner template <> void LeafRecordImpl<ProcedureRecord>::map(IO &IO) {
4051b88f4f3SZachary Turner   IO.mapRequired("ReturnType", Record.ReturnType);
4061b88f4f3SZachary Turner   IO.mapRequired("CallConv", Record.CallConv);
4071b88f4f3SZachary Turner   IO.mapRequired("Options", Record.Options);
4081b88f4f3SZachary Turner   IO.mapRequired("ParameterCount", Record.ParameterCount);
4091b88f4f3SZachary Turner   IO.mapRequired("ArgumentList", Record.ArgumentList);
4101b88f4f3SZachary Turner }
4111b88f4f3SZachary Turner 
map(IO & IO)4121b88f4f3SZachary Turner template <> void LeafRecordImpl<MemberFunctionRecord>::map(IO &IO) {
4131b88f4f3SZachary Turner   IO.mapRequired("ReturnType", Record.ReturnType);
4141b88f4f3SZachary Turner   IO.mapRequired("ClassType", Record.ClassType);
4151b88f4f3SZachary Turner   IO.mapRequired("ThisType", Record.ThisType);
4161b88f4f3SZachary Turner   IO.mapRequired("CallConv", Record.CallConv);
4171b88f4f3SZachary Turner   IO.mapRequired("Options", Record.Options);
4181b88f4f3SZachary Turner   IO.mapRequired("ParameterCount", Record.ParameterCount);
4191b88f4f3SZachary Turner   IO.mapRequired("ArgumentList", Record.ArgumentList);
4201b88f4f3SZachary Turner   IO.mapRequired("ThisPointerAdjustment", Record.ThisPointerAdjustment);
4211b88f4f3SZachary Turner }
4221b88f4f3SZachary Turner 
map(IO & IO)4231b88f4f3SZachary Turner template <> void LeafRecordImpl<LabelRecord>::map(IO &IO) {
4241b88f4f3SZachary Turner   IO.mapRequired("Mode", Record.Mode);
4251b88f4f3SZachary Turner }
4261b88f4f3SZachary Turner 
map(IO & IO)4271b88f4f3SZachary Turner template <> void LeafRecordImpl<MemberFuncIdRecord>::map(IO &IO) {
4281b88f4f3SZachary Turner   IO.mapRequired("ClassType", Record.ClassType);
4291b88f4f3SZachary Turner   IO.mapRequired("FunctionType", Record.FunctionType);
4301b88f4f3SZachary Turner   IO.mapRequired("Name", Record.Name);
4311b88f4f3SZachary Turner }
4321b88f4f3SZachary Turner 
map(IO & IO)4331b88f4f3SZachary Turner template <> void LeafRecordImpl<ArgListRecord>::map(IO &IO) {
4341b88f4f3SZachary Turner   IO.mapRequired("ArgIndices", Record.ArgIndices);
4351b88f4f3SZachary Turner }
4361b88f4f3SZachary Turner 
map(IO & IO)4371b88f4f3SZachary Turner template <> void LeafRecordImpl<StringListRecord>::map(IO &IO) {
4381b88f4f3SZachary Turner   IO.mapRequired("StringIndices", Record.StringIndices);
4391b88f4f3SZachary Turner }
4401b88f4f3SZachary Turner 
map(IO & IO)4411b88f4f3SZachary Turner template <> void LeafRecordImpl<PointerRecord>::map(IO &IO) {
4421b88f4f3SZachary Turner   IO.mapRequired("ReferentType", Record.ReferentType);
4431b88f4f3SZachary Turner   IO.mapRequired("Attrs", Record.Attrs);
4441b88f4f3SZachary Turner   IO.mapOptional("MemberInfo", Record.MemberInfo);
4451b88f4f3SZachary Turner }
4461b88f4f3SZachary Turner 
map(IO & IO)4471b88f4f3SZachary Turner template <> void LeafRecordImpl<ArrayRecord>::map(IO &IO) {
4481b88f4f3SZachary Turner   IO.mapRequired("ElementType", Record.ElementType);
4491b88f4f3SZachary Turner   IO.mapRequired("IndexType", Record.IndexType);
4501b88f4f3SZachary Turner   IO.mapRequired("Size", Record.Size);
4511b88f4f3SZachary Turner   IO.mapRequired("Name", Record.Name);
4521b88f4f3SZachary Turner }
4531b88f4f3SZachary Turner 
map(IO & IO)4541b88f4f3SZachary Turner void LeafRecordImpl<FieldListRecord>::map(IO &IO) {
4551b88f4f3SZachary Turner   IO.mapRequired("FieldList", Members);
4561b88f4f3SZachary Turner }
45728082ab0SEugene Zelenko 
45828082ab0SEugene Zelenko } // end namespace detail
45928082ab0SEugene Zelenko } // end namespace CodeViewYAML
46028082ab0SEugene Zelenko } // end namespace llvm
4611b88f4f3SZachary Turner 
4621b88f4f3SZachary Turner namespace {
46328082ab0SEugene Zelenko 
4641b88f4f3SZachary Turner class MemberRecordConversionVisitor : public TypeVisitorCallbacks {
4651b88f4f3SZachary Turner public:
MemberRecordConversionVisitor(std::vector<MemberRecord> & Records)4661b88f4f3SZachary Turner   explicit MemberRecordConversionVisitor(std::vector<MemberRecord> &Records)
4671b88f4f3SZachary Turner       : Records(Records) {}
4681b88f4f3SZachary Turner 
4691b88f4f3SZachary Turner #define TYPE_RECORD(EnumName, EnumVal, Name)
4701b88f4f3SZachary Turner #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
4711b88f4f3SZachary Turner   Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
4721b88f4f3SZachary Turner     return visitKnownMemberImpl(Record);                                       \
4731b88f4f3SZachary Turner   }
4741b88f4f3SZachary Turner #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
4751b88f4f3SZachary Turner #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
4761b88f4f3SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
4771b88f4f3SZachary Turner private:
visitKnownMemberImpl(T & Record)4781b88f4f3SZachary Turner   template <typename T> Error visitKnownMemberImpl(T &Record) {
4791b88f4f3SZachary Turner     TypeLeafKind K = static_cast<TypeLeafKind>(Record.getKind());
4801b88f4f3SZachary Turner     auto Impl = std::make_shared<MemberRecordImpl<T>>(K);
4811b88f4f3SZachary Turner     Impl->Record = Record;
4821b88f4f3SZachary Turner     Records.push_back(MemberRecord{Impl});
4831b88f4f3SZachary Turner     return Error::success();
4841b88f4f3SZachary Turner   }
4851b88f4f3SZachary Turner 
4861b88f4f3SZachary Turner   std::vector<MemberRecord> &Records;
4871b88f4f3SZachary Turner };
48828082ab0SEugene Zelenko 
48928082ab0SEugene Zelenko } // end anonymous namespace
4901b88f4f3SZachary Turner 
fromCodeViewRecord(CVType Type)4911b88f4f3SZachary Turner Error LeafRecordImpl<FieldListRecord>::fromCodeViewRecord(CVType Type) {
4921b88f4f3SZachary Turner   MemberRecordConversionVisitor V(Members);
493*bd2044c1SZequan Wu   FieldListRecord FieldList;
494*bd2044c1SZequan Wu   cantFail(TypeDeserializer::deserializeAs<FieldListRecord>(Type,
495*bd2044c1SZequan Wu                                                             FieldList));
496*bd2044c1SZequan Wu   return visitMemberRecordStream(FieldList.Data, V);
4971b88f4f3SZachary Turner }
4981b88f4f3SZachary Turner 
toCodeViewRecord(AppendingTypeTableBuilder & TS) const499ca6dbf14SZachary Turner CVType LeafRecordImpl<FieldListRecord>::toCodeViewRecord(
500ca6dbf14SZachary Turner     AppendingTypeTableBuilder &TS) const {
5016900de1dSZachary Turner   ContinuationRecordBuilder CRB;
5026900de1dSZachary Turner   CRB.begin(ContinuationRecordKind::FieldList);
5031b88f4f3SZachary Turner   for (const auto &Member : Members) {
5046900de1dSZachary Turner     Member.Member->writeTo(CRB);
5051b88f4f3SZachary Turner   }
5066900de1dSZachary Turner   TS.insertRecord(CRB);
507e10d0041SReid Kleckner   return CVType(TS.records().back());
5081b88f4f3SZachary Turner }
5091b88f4f3SZachary Turner 
mapping(IO & io,OneMethodRecord & Record)5101b88f4f3SZachary Turner void MappingTraits<OneMethodRecord>::mapping(IO &io, OneMethodRecord &Record) {
5111b88f4f3SZachary Turner   io.mapRequired("Type", Record.Type);
5121b88f4f3SZachary Turner   io.mapRequired("Attrs", Record.Attrs.Attrs);
5131b88f4f3SZachary Turner   io.mapRequired("VFTableOffset", Record.VFTableOffset);
5141b88f4f3SZachary Turner   io.mapRequired("Name", Record.Name);
5151b88f4f3SZachary Turner }
5161b88f4f3SZachary Turner 
5171b88f4f3SZachary Turner namespace llvm {
5181b88f4f3SZachary Turner namespace CodeViewYAML {
5191b88f4f3SZachary Turner namespace detail {
52028082ab0SEugene Zelenko 
map(IO & IO)5211b88f4f3SZachary Turner template <> void LeafRecordImpl<ClassRecord>::map(IO &IO) {
5221b88f4f3SZachary Turner   IO.mapRequired("MemberCount", Record.MemberCount);
5231b88f4f3SZachary Turner   IO.mapRequired("Options", Record.Options);
5241b88f4f3SZachary Turner   IO.mapRequired("FieldList", Record.FieldList);
5251b88f4f3SZachary Turner   IO.mapRequired("Name", Record.Name);
5261b88f4f3SZachary Turner   IO.mapRequired("UniqueName", Record.UniqueName);
5271b88f4f3SZachary Turner   IO.mapRequired("DerivationList", Record.DerivationList);
5281b88f4f3SZachary Turner   IO.mapRequired("VTableShape", Record.VTableShape);
5291b88f4f3SZachary Turner   IO.mapRequired("Size", Record.Size);
5301b88f4f3SZachary Turner }
5311b88f4f3SZachary Turner 
map(IO & IO)5321b88f4f3SZachary Turner template <> void LeafRecordImpl<UnionRecord>::map(IO &IO) {
5331b88f4f3SZachary Turner   IO.mapRequired("MemberCount", Record.MemberCount);
5341b88f4f3SZachary Turner   IO.mapRequired("Options", Record.Options);
5351b88f4f3SZachary Turner   IO.mapRequired("FieldList", Record.FieldList);
5361b88f4f3SZachary Turner   IO.mapRequired("Name", Record.Name);
5371b88f4f3SZachary Turner   IO.mapRequired("UniqueName", Record.UniqueName);
5381b88f4f3SZachary Turner   IO.mapRequired("Size", Record.Size);
5391b88f4f3SZachary Turner }
5401b88f4f3SZachary Turner 
map(IO & IO)5411b88f4f3SZachary Turner template <> void LeafRecordImpl<EnumRecord>::map(IO &IO) {
5421b88f4f3SZachary Turner   IO.mapRequired("NumEnumerators", Record.MemberCount);
5431b88f4f3SZachary Turner   IO.mapRequired("Options", Record.Options);
5441b88f4f3SZachary Turner   IO.mapRequired("FieldList", Record.FieldList);
5451b88f4f3SZachary Turner   IO.mapRequired("Name", Record.Name);
5461b88f4f3SZachary Turner   IO.mapRequired("UniqueName", Record.UniqueName);
5471b88f4f3SZachary Turner   IO.mapRequired("UnderlyingType", Record.UnderlyingType);
5481b88f4f3SZachary Turner }
5491b88f4f3SZachary Turner 
map(IO & IO)5501b88f4f3SZachary Turner template <> void LeafRecordImpl<BitFieldRecord>::map(IO &IO) {
5511b88f4f3SZachary Turner   IO.mapRequired("Type", Record.Type);
5521b88f4f3SZachary Turner   IO.mapRequired("BitSize", Record.BitSize);
5531b88f4f3SZachary Turner   IO.mapRequired("BitOffset", Record.BitOffset);
5541b88f4f3SZachary Turner }
5551b88f4f3SZachary Turner 
map(IO & IO)5561b88f4f3SZachary Turner template <> void LeafRecordImpl<VFTableShapeRecord>::map(IO &IO) {
5571b88f4f3SZachary Turner   IO.mapRequired("Slots", Record.Slots);
5581b88f4f3SZachary Turner }
5591b88f4f3SZachary Turner 
map(IO & IO)5601b88f4f3SZachary Turner template <> void LeafRecordImpl<TypeServer2Record>::map(IO &IO) {
5611b88f4f3SZachary Turner   IO.mapRequired("Guid", Record.Guid);
5621b88f4f3SZachary Turner   IO.mapRequired("Age", Record.Age);
5631b88f4f3SZachary Turner   IO.mapRequired("Name", Record.Name);
5641b88f4f3SZachary Turner }
5651b88f4f3SZachary Turner 
map(IO & IO)5661b88f4f3SZachary Turner template <> void LeafRecordImpl<StringIdRecord>::map(IO &IO) {
5671b88f4f3SZachary Turner   IO.mapRequired("Id", Record.Id);
5681b88f4f3SZachary Turner   IO.mapRequired("String", Record.String);
5691b88f4f3SZachary Turner }
5701b88f4f3SZachary Turner 
map(IO & IO)5711b88f4f3SZachary Turner template <> void LeafRecordImpl<FuncIdRecord>::map(IO &IO) {
5721b88f4f3SZachary Turner   IO.mapRequired("ParentScope", Record.ParentScope);
5731b88f4f3SZachary Turner   IO.mapRequired("FunctionType", Record.FunctionType);
5741b88f4f3SZachary Turner   IO.mapRequired("Name", Record.Name);
5751b88f4f3SZachary Turner }
5761b88f4f3SZachary Turner 
map(IO & IO)5771b88f4f3SZachary Turner template <> void LeafRecordImpl<UdtSourceLineRecord>::map(IO &IO) {
5781b88f4f3SZachary Turner   IO.mapRequired("UDT", Record.UDT);
5791b88f4f3SZachary Turner   IO.mapRequired("SourceFile", Record.SourceFile);
5801b88f4f3SZachary Turner   IO.mapRequired("LineNumber", Record.LineNumber);
5811b88f4f3SZachary Turner }
5821b88f4f3SZachary Turner 
map(IO & IO)5831b88f4f3SZachary Turner template <> void LeafRecordImpl<UdtModSourceLineRecord>::map(IO &IO) {
5841b88f4f3SZachary Turner   IO.mapRequired("UDT", Record.UDT);
5851b88f4f3SZachary Turner   IO.mapRequired("SourceFile", Record.SourceFile);
5861b88f4f3SZachary Turner   IO.mapRequired("LineNumber", Record.LineNumber);
5871b88f4f3SZachary Turner   IO.mapRequired("Module", Record.Module);
5881b88f4f3SZachary Turner }
5891b88f4f3SZachary Turner 
map(IO & IO)5901b88f4f3SZachary Turner template <> void LeafRecordImpl<BuildInfoRecord>::map(IO &IO) {
5911b88f4f3SZachary Turner   IO.mapRequired("ArgIndices", Record.ArgIndices);
5921b88f4f3SZachary Turner }
5931b88f4f3SZachary Turner 
map(IO & IO)5941b88f4f3SZachary Turner template <> void LeafRecordImpl<VFTableRecord>::map(IO &IO) {
5951b88f4f3SZachary Turner   IO.mapRequired("CompleteClass", Record.CompleteClass);
5961b88f4f3SZachary Turner   IO.mapRequired("OverriddenVFTable", Record.OverriddenVFTable);
5971b88f4f3SZachary Turner   IO.mapRequired("VFPtrOffset", Record.VFPtrOffset);
5981b88f4f3SZachary Turner   IO.mapRequired("MethodNames", Record.MethodNames);
5991b88f4f3SZachary Turner }
6001b88f4f3SZachary Turner 
map(IO & IO)6011b88f4f3SZachary Turner template <> void LeafRecordImpl<MethodOverloadListRecord>::map(IO &IO) {
6021b88f4f3SZachary Turner   IO.mapRequired("Methods", Record.Methods);
6031b88f4f3SZachary Turner }
6041b88f4f3SZachary Turner 
map(IO & IO)605d9e96741SAlexandre Ganea template <> void LeafRecordImpl<PrecompRecord>::map(IO &IO) {
606d9e96741SAlexandre Ganea   IO.mapRequired("StartTypeIndex", Record.StartTypeIndex);
607d9e96741SAlexandre Ganea   IO.mapRequired("TypesCount", Record.TypesCount);
608d9e96741SAlexandre Ganea   IO.mapRequired("Signature", Record.Signature);
609d9e96741SAlexandre Ganea   IO.mapRequired("PrecompFilePath", Record.PrecompFilePath);
610d9e96741SAlexandre Ganea }
611d9e96741SAlexandre Ganea 
map(IO & IO)612d9e96741SAlexandre Ganea template <> void LeafRecordImpl<EndPrecompRecord>::map(IO &IO) {
613d9e96741SAlexandre Ganea   IO.mapRequired("Signature", Record.Signature);
614d9e96741SAlexandre Ganea }
615d9e96741SAlexandre Ganea 
map(IO & IO)6161b88f4f3SZachary Turner template <> void MemberRecordImpl<OneMethodRecord>::map(IO &IO) {
6171b88f4f3SZachary Turner   MappingTraits<OneMethodRecord>::mapping(IO, Record);
6181b88f4f3SZachary Turner }
6191b88f4f3SZachary Turner 
map(IO & IO)6201b88f4f3SZachary Turner template <> void MemberRecordImpl<OverloadedMethodRecord>::map(IO &IO) {
6211b88f4f3SZachary Turner   IO.mapRequired("NumOverloads", Record.NumOverloads);
6221b88f4f3SZachary Turner   IO.mapRequired("MethodList", Record.MethodList);
6231b88f4f3SZachary Turner   IO.mapRequired("Name", Record.Name);
6241b88f4f3SZachary Turner }
6251b88f4f3SZachary Turner 
map(IO & IO)6261b88f4f3SZachary Turner template <> void MemberRecordImpl<NestedTypeRecord>::map(IO &IO) {
6271b88f4f3SZachary Turner   IO.mapRequired("Type", Record.Type);
6281b88f4f3SZachary Turner   IO.mapRequired("Name", Record.Name);
6291b88f4f3SZachary Turner }
6301b88f4f3SZachary Turner 
map(IO & IO)6311b88f4f3SZachary Turner template <> void MemberRecordImpl<DataMemberRecord>::map(IO &IO) {
6321b88f4f3SZachary Turner   IO.mapRequired("Attrs", Record.Attrs.Attrs);
6331b88f4f3SZachary Turner   IO.mapRequired("Type", Record.Type);
6341b88f4f3SZachary Turner   IO.mapRequired("FieldOffset", Record.FieldOffset);
6351b88f4f3SZachary Turner   IO.mapRequired("Name", Record.Name);
6361b88f4f3SZachary Turner }
6371b88f4f3SZachary Turner 
map(IO & IO)6381b88f4f3SZachary Turner template <> void MemberRecordImpl<StaticDataMemberRecord>::map(IO &IO) {
6391b88f4f3SZachary Turner   IO.mapRequired("Attrs", Record.Attrs.Attrs);
6401b88f4f3SZachary Turner   IO.mapRequired("Type", Record.Type);
6411b88f4f3SZachary Turner   IO.mapRequired("Name", Record.Name);
6421b88f4f3SZachary Turner }
6431b88f4f3SZachary Turner 
map(IO & IO)6441b88f4f3SZachary Turner template <> void MemberRecordImpl<EnumeratorRecord>::map(IO &IO) {
6451b88f4f3SZachary Turner   IO.mapRequired("Attrs", Record.Attrs.Attrs);
6461b88f4f3SZachary Turner   IO.mapRequired("Value", Record.Value);
6471b88f4f3SZachary Turner   IO.mapRequired("Name", Record.Name);
6481b88f4f3SZachary Turner }
6491b88f4f3SZachary Turner 
map(IO & IO)6501b88f4f3SZachary Turner template <> void MemberRecordImpl<VFPtrRecord>::map(IO &IO) {
6511b88f4f3SZachary Turner   IO.mapRequired("Type", Record.Type);
6521b88f4f3SZachary Turner }
6531b88f4f3SZachary Turner 
map(IO & IO)6541b88f4f3SZachary Turner template <> void MemberRecordImpl<BaseClassRecord>::map(IO &IO) {
6551b88f4f3SZachary Turner   IO.mapRequired("Attrs", Record.Attrs.Attrs);
6561b88f4f3SZachary Turner   IO.mapRequired("Type", Record.Type);
6571b88f4f3SZachary Turner   IO.mapRequired("Offset", Record.Offset);
6581b88f4f3SZachary Turner }
6591b88f4f3SZachary Turner 
map(IO & IO)6601b88f4f3SZachary Turner template <> void MemberRecordImpl<VirtualBaseClassRecord>::map(IO &IO) {
6611b88f4f3SZachary Turner   IO.mapRequired("Attrs", Record.Attrs.Attrs);
6621b88f4f3SZachary Turner   IO.mapRequired("BaseType", Record.BaseType);
6631b88f4f3SZachary Turner   IO.mapRequired("VBPtrType", Record.VBPtrType);
6641b88f4f3SZachary Turner   IO.mapRequired("VBPtrOffset", Record.VBPtrOffset);
6651b88f4f3SZachary Turner   IO.mapRequired("VTableIndex", Record.VTableIndex);
6661b88f4f3SZachary Turner }
6671b88f4f3SZachary Turner 
map(IO & IO)6681b88f4f3SZachary Turner template <> void MemberRecordImpl<ListContinuationRecord>::map(IO &IO) {
6691b88f4f3SZachary Turner   IO.mapRequired("ContinuationIndex", Record.ContinuationIndex);
6701b88f4f3SZachary Turner }
67128082ab0SEugene Zelenko 
67228082ab0SEugene Zelenko } // end namespace detail
67328082ab0SEugene Zelenko } // end namespace CodeViewYAML
67428082ab0SEugene Zelenko } // end namespace llvm
6751b88f4f3SZachary Turner 
6761b88f4f3SZachary Turner template <typename T>
fromCodeViewRecordImpl(CVType Type)6771b88f4f3SZachary Turner static inline Expected<LeafRecord> fromCodeViewRecordImpl(CVType Type) {
6781b88f4f3SZachary Turner   LeafRecord Result;
6791b88f4f3SZachary Turner 
6801b88f4f3SZachary Turner   auto Impl = std::make_shared<LeafRecordImpl<T>>(Type.kind());
6811b88f4f3SZachary Turner   if (auto EC = Impl->fromCodeViewRecord(Type))
682c55cf4afSBill Wendling     return std::move(EC);
6831b88f4f3SZachary Turner   Result.Leaf = Impl;
6841b88f4f3SZachary Turner   return Result;
6851b88f4f3SZachary Turner }
6861b88f4f3SZachary Turner 
fromCodeViewRecord(CVType Type)6871b88f4f3SZachary Turner Expected<LeafRecord> LeafRecord::fromCodeViewRecord(CVType Type) {
6881b88f4f3SZachary Turner #define TYPE_RECORD(EnumName, EnumVal, ClassName)                              \
6891b88f4f3SZachary Turner   case EnumName:                                                               \
6901b88f4f3SZachary Turner     return fromCodeViewRecordImpl<ClassName##Record>(Type);
6911b88f4f3SZachary Turner #define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)             \
6921b88f4f3SZachary Turner   TYPE_RECORD(EnumName, EnumVal, ClassName)
6931b88f4f3SZachary Turner #define MEMBER_RECORD(EnumName, EnumVal, ClassName)
6941b88f4f3SZachary Turner #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)
6951b88f4f3SZachary Turner   switch (Type.kind()) {
6961b88f4f3SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
69728082ab0SEugene Zelenko   default:
69828082ab0SEugene Zelenko       llvm_unreachable("Unknown leaf kind!");
6991b88f4f3SZachary Turner   }
7001b88f4f3SZachary Turner   return make_error<CodeViewError>(cv_error_code::corrupt_record);
7011b88f4f3SZachary Turner }
7021b88f4f3SZachary Turner 
703ca6dbf14SZachary Turner CVType
toCodeViewRecord(AppendingTypeTableBuilder & Serializer) const704ca6dbf14SZachary Turner LeafRecord::toCodeViewRecord(AppendingTypeTableBuilder &Serializer) const {
7056900de1dSZachary Turner   return Leaf->toCodeViewRecord(Serializer);
7061b88f4f3SZachary Turner }
7071b88f4f3SZachary Turner 
7081b88f4f3SZachary Turner namespace llvm {
7091b88f4f3SZachary Turner namespace yaml {
71028082ab0SEugene Zelenko 
7111b88f4f3SZachary Turner template <> struct MappingTraits<LeafRecordBase> {
mappingllvm::yaml::MappingTraits7121b88f4f3SZachary Turner   static void mapping(IO &io, LeafRecordBase &Record) { Record.map(io); }
7131b88f4f3SZachary Turner };
7141b88f4f3SZachary Turner 
7151b88f4f3SZachary Turner template <> struct MappingTraits<MemberRecordBase> {
mappingllvm::yaml::MappingTraits7161b88f4f3SZachary Turner   static void mapping(IO &io, MemberRecordBase &Record) { Record.map(io); }
7171b88f4f3SZachary Turner };
71828082ab0SEugene Zelenko 
71928082ab0SEugene Zelenko } // end namespace yaml
72028082ab0SEugene Zelenko } // end namespace llvm
7211b88f4f3SZachary Turner 
7221b88f4f3SZachary Turner template <typename ConcreteType>
mapLeafRecordImpl(IO & IO,const char * Class,TypeLeafKind Kind,LeafRecord & Obj)7231b88f4f3SZachary Turner static void mapLeafRecordImpl(IO &IO, const char *Class, TypeLeafKind Kind,
7241b88f4f3SZachary Turner                               LeafRecord &Obj) {
7251b88f4f3SZachary Turner   if (!IO.outputting())
7261b88f4f3SZachary Turner     Obj.Leaf = std::make_shared<LeafRecordImpl<ConcreteType>>(Kind);
7271b88f4f3SZachary Turner 
7281b88f4f3SZachary Turner   if (Kind == LF_FIELDLIST)
7291b88f4f3SZachary Turner     Obj.Leaf->map(IO);
7301b88f4f3SZachary Turner   else
7311b88f4f3SZachary Turner     IO.mapRequired(Class, *Obj.Leaf);
7321b88f4f3SZachary Turner }
7331b88f4f3SZachary Turner 
mapping(IO & IO,LeafRecord & Obj)7341b88f4f3SZachary Turner void MappingTraits<LeafRecord>::mapping(IO &IO, LeafRecord &Obj) {
7351b88f4f3SZachary Turner   TypeLeafKind Kind;
7361b88f4f3SZachary Turner   if (IO.outputting())
7371b88f4f3SZachary Turner     Kind = Obj.Leaf->Kind;
7381b88f4f3SZachary Turner   IO.mapRequired("Kind", Kind);
7391b88f4f3SZachary Turner 
7401b88f4f3SZachary Turner #define TYPE_RECORD(EnumName, EnumVal, ClassName)                              \
7411b88f4f3SZachary Turner   case EnumName:                                                               \
7421b88f4f3SZachary Turner     mapLeafRecordImpl<ClassName##Record>(IO, #ClassName, Kind, Obj);           \
7431b88f4f3SZachary Turner     break;
7441b88f4f3SZachary Turner #define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)             \
7451b88f4f3SZachary Turner   TYPE_RECORD(EnumName, EnumVal, ClassName)
7461b88f4f3SZachary Turner #define MEMBER_RECORD(EnumName, EnumVal, ClassName)
7471b88f4f3SZachary Turner #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)
7481b88f4f3SZachary Turner   switch (Kind) {
7491b88f4f3SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
7501b88f4f3SZachary Turner   default: { llvm_unreachable("Unknown leaf kind!"); }
7511b88f4f3SZachary Turner   }
7521b88f4f3SZachary Turner }
7531b88f4f3SZachary Turner 
7541b88f4f3SZachary Turner template <typename ConcreteType>
mapMemberRecordImpl(IO & IO,const char * Class,TypeLeafKind Kind,MemberRecord & Obj)7551b88f4f3SZachary Turner static void mapMemberRecordImpl(IO &IO, const char *Class, TypeLeafKind Kind,
7561b88f4f3SZachary Turner                                 MemberRecord &Obj) {
7571b88f4f3SZachary Turner   if (!IO.outputting())
7581b88f4f3SZachary Turner     Obj.Member = std::make_shared<MemberRecordImpl<ConcreteType>>(Kind);
7591b88f4f3SZachary Turner 
7601b88f4f3SZachary Turner   IO.mapRequired(Class, *Obj.Member);
7611b88f4f3SZachary Turner }
7621b88f4f3SZachary Turner 
mapping(IO & IO,MemberRecord & Obj)7631b88f4f3SZachary Turner void MappingTraits<MemberRecord>::mapping(IO &IO, MemberRecord &Obj) {
7641b88f4f3SZachary Turner   TypeLeafKind Kind;
7651b88f4f3SZachary Turner   if (IO.outputting())
7661b88f4f3SZachary Turner     Kind = Obj.Member->Kind;
7671b88f4f3SZachary Turner   IO.mapRequired("Kind", Kind);
7681b88f4f3SZachary Turner 
7691b88f4f3SZachary Turner #define MEMBER_RECORD(EnumName, EnumVal, ClassName)                            \
7701b88f4f3SZachary Turner   case EnumName:                                                               \
7711b88f4f3SZachary Turner     mapMemberRecordImpl<ClassName##Record>(IO, #ClassName, Kind, Obj);         \
7721b88f4f3SZachary Turner     break;
7731b88f4f3SZachary Turner #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)           \
7741b88f4f3SZachary Turner   MEMBER_RECORD(EnumName, EnumVal, ClassName)
7751b88f4f3SZachary Turner #define TYPE_RECORD(EnumName, EnumVal, ClassName)
7761b88f4f3SZachary Turner #define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)
7771b88f4f3SZachary Turner   switch (Kind) {
7781b88f4f3SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
7791b88f4f3SZachary Turner   default: { llvm_unreachable("Unknown member kind!"); }
7801b88f4f3SZachary Turner   }
7811b88f4f3SZachary Turner }
782a8cfc29cSZachary Turner 
783a8cfc29cSZachary Turner std::vector<LeafRecord>
fromDebugT(ArrayRef<uint8_t> DebugTorP,StringRef SectionName)784d9e96741SAlexandre Ganea llvm::CodeViewYAML::fromDebugT(ArrayRef<uint8_t> DebugTorP,
785d9e96741SAlexandre Ganea                                StringRef SectionName) {
786d9e96741SAlexandre Ganea   ExitOnError Err("Invalid " + std::string(SectionName) + " section!");
787d9e96741SAlexandre Ganea   BinaryStreamReader Reader(DebugTorP, support::little);
788a8cfc29cSZachary Turner   CVTypeArray Types;
789a8cfc29cSZachary Turner   uint32_t Magic;
790a8cfc29cSZachary Turner 
791a8cfc29cSZachary Turner   Err(Reader.readInteger(Magic));
792d9e96741SAlexandre Ganea   assert(Magic == COFF::DEBUG_SECTION_MAGIC &&
793d9e96741SAlexandre Ganea          "Invalid .debug$T or .debug$P section!");
794a8cfc29cSZachary Turner 
795a8cfc29cSZachary Turner   std::vector<LeafRecord> Result;
796a8cfc29cSZachary Turner   Err(Reader.readArray(Types, Reader.bytesRemaining()));
797a8cfc29cSZachary Turner   for (const auto &T : Types) {
798a8cfc29cSZachary Turner     auto CVT = Err(LeafRecord::fromCodeViewRecord(T));
799a8cfc29cSZachary Turner     Result.push_back(CVT);
800a8cfc29cSZachary Turner   }
801a8cfc29cSZachary Turner   return Result;
802a8cfc29cSZachary Turner }
803a8cfc29cSZachary Turner 
toDebugT(ArrayRef<LeafRecord> Leafs,BumpPtrAllocator & Alloc,StringRef SectionName)804a8cfc29cSZachary Turner ArrayRef<uint8_t> llvm::CodeViewYAML::toDebugT(ArrayRef<LeafRecord> Leafs,
805d9e96741SAlexandre Ganea                                                BumpPtrAllocator &Alloc,
806d9e96741SAlexandre Ganea                                                StringRef SectionName) {
807ca6dbf14SZachary Turner   AppendingTypeTableBuilder TS(Alloc);
808a8cfc29cSZachary Turner   uint32_t Size = sizeof(uint32_t);
809a8cfc29cSZachary Turner   for (const auto &Leaf : Leafs) {
8106900de1dSZachary Turner     CVType T = Leaf.Leaf->toCodeViewRecord(TS);
811a8cfc29cSZachary Turner     Size += T.length();
812a8cfc29cSZachary Turner     assert(T.length() % 4 == 0 && "Improper type record alignment!");
813a8cfc29cSZachary Turner   }
814a8cfc29cSZachary Turner   uint8_t *ResultBuffer = Alloc.Allocate<uint8_t>(Size);
815a8cfc29cSZachary Turner   MutableArrayRef<uint8_t> Output(ResultBuffer, Size);
816a8cfc29cSZachary Turner   BinaryStreamWriter Writer(Output, support::little);
817d9e96741SAlexandre Ganea   ExitOnError Err("Error writing type record to " + std::string(SectionName) +
818d9e96741SAlexandre Ganea                   " section");
819a8cfc29cSZachary Turner   Err(Writer.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC));
8206900de1dSZachary Turner   for (const auto &R : TS.records()) {
821a8cfc29cSZachary Turner     Err(Writer.writeBytes(R));
822a8cfc29cSZachary Turner   }
823a8cfc29cSZachary Turner   assert(Writer.bytesRemaining() == 0 && "Didn't write all type record bytes!");
824a8cfc29cSZachary Turner   return Output;
825a8cfc29cSZachary Turner }
826