10b57cec5SDimitry Andric //===- TypeRecordMapping.cpp ------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
1081ad6265SDimitry Andric 
1181ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h"
1281ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h"
1381ad6265SDimitry Andric #include "llvm/ADT/SmallString.h"
1481ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h"
1581ad6265SDimitry Andric #include "llvm/ADT/StringRef.h"
1681ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
1781ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h"
188bcb0991SDimitry Andric #include "llvm/DebugInfo/CodeView/EnumTables.h"
1981ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
2081ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeIndex.h"
2181ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeRecord.h"
2281ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h"
23fe6060f1SDimitry Andric #include "llvm/Support/MD5.h"
2481ad6265SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
2581ad6265SDimitry Andric 
2681ad6265SDimitry Andric #include <algorithm>
2781ad6265SDimitry Andric #include <cassert>
2881ad6265SDimitry Andric #include <cstddef>
2981ad6265SDimitry Andric #include <cstdint>
3081ad6265SDimitry Andric #include <string>
3181ad6265SDimitry Andric #include <vector>
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric using namespace llvm;
340b57cec5SDimitry Andric using namespace llvm::codeview;
350b57cec5SDimitry Andric 
368bcb0991SDimitry Andric namespace {
378bcb0991SDimitry Andric 
380b57cec5SDimitry Andric #define error(X)                                                               \
39fcaf7f86SDimitry Andric   do {                                                                         \
400b57cec5SDimitry Andric     if (auto EC = X)                                                           \
41fcaf7f86SDimitry Andric       return EC;                                                               \
42fcaf7f86SDimitry Andric   } while (false)
430b57cec5SDimitry Andric 
448bcb0991SDimitry Andric static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
458bcb0991SDimitry Andric #define CV_TYPE(enum, val) {#enum, enum},
468bcb0991SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
478bcb0991SDimitry Andric };
488bcb0991SDimitry Andric 
getLeafTypeName(TypeLeafKind LT)498bcb0991SDimitry Andric static StringRef getLeafTypeName(TypeLeafKind LT) {
508bcb0991SDimitry Andric   switch (LT) {
518bcb0991SDimitry Andric #define TYPE_RECORD(ename, value, name)                                        \
528bcb0991SDimitry Andric   case ename:                                                                  \
538bcb0991SDimitry Andric     return #name;
548bcb0991SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
558bcb0991SDimitry Andric   default:
568bcb0991SDimitry Andric     break;
578bcb0991SDimitry Andric   }
588bcb0991SDimitry Andric   return "UnknownLeaf";
598bcb0991SDimitry Andric }
608bcb0991SDimitry Andric 
618bcb0991SDimitry Andric template <typename T>
compEnumNames(const EnumEntry<T> & lhs,const EnumEntry<T> & rhs)628bcb0991SDimitry Andric static bool compEnumNames(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) {
638bcb0991SDimitry Andric   return lhs.Name < rhs.Name;
648bcb0991SDimitry Andric }
658bcb0991SDimitry Andric 
668bcb0991SDimitry Andric template <typename T, typename TFlag>
getFlagNames(CodeViewRecordIO & IO,T Value,ArrayRef<EnumEntry<TFlag>> Flags)678bcb0991SDimitry Andric static std::string getFlagNames(CodeViewRecordIO &IO, T Value,
688bcb0991SDimitry Andric                                 ArrayRef<EnumEntry<TFlag>> Flags) {
698bcb0991SDimitry Andric   if (!IO.isStreaming())
708bcb0991SDimitry Andric     return std::string("");
718bcb0991SDimitry Andric   typedef EnumEntry<TFlag> FlagEntry;
728bcb0991SDimitry Andric   typedef SmallVector<FlagEntry, 10> FlagVector;
738bcb0991SDimitry Andric   FlagVector SetFlags;
748bcb0991SDimitry Andric   for (const auto &Flag : Flags) {
758bcb0991SDimitry Andric     if (Flag.Value == 0)
768bcb0991SDimitry Andric       continue;
778bcb0991SDimitry Andric     if ((Value & Flag.Value) == Flag.Value) {
788bcb0991SDimitry Andric       SetFlags.push_back(Flag);
798bcb0991SDimitry Andric     }
808bcb0991SDimitry Andric   }
818bcb0991SDimitry Andric 
828bcb0991SDimitry Andric   llvm::sort(SetFlags, &compEnumNames<TFlag>);
838bcb0991SDimitry Andric 
848bcb0991SDimitry Andric   std::string FlagLabel;
858bcb0991SDimitry Andric   bool FirstOcc = true;
868bcb0991SDimitry Andric   for (const auto &Flag : SetFlags) {
878bcb0991SDimitry Andric     if (FirstOcc)
888bcb0991SDimitry Andric       FirstOcc = false;
898bcb0991SDimitry Andric     else
908bcb0991SDimitry Andric       FlagLabel += (" | ");
918bcb0991SDimitry Andric 
928bcb0991SDimitry Andric     FlagLabel += (Flag.Name.str() + " (0x" + utohexstr(Flag.Value) + ")");
938bcb0991SDimitry Andric   }
948bcb0991SDimitry Andric 
958bcb0991SDimitry Andric   if (!FlagLabel.empty()) {
968bcb0991SDimitry Andric     std::string LabelWithBraces(" ( ");
978bcb0991SDimitry Andric     LabelWithBraces += FlagLabel + " )";
988bcb0991SDimitry Andric     return LabelWithBraces;
998bcb0991SDimitry Andric   } else
1008bcb0991SDimitry Andric     return FlagLabel;
1018bcb0991SDimitry Andric }
1028bcb0991SDimitry Andric 
1038bcb0991SDimitry Andric template <typename T, typename TEnum>
getEnumName(CodeViewRecordIO & IO,T Value,ArrayRef<EnumEntry<TEnum>> EnumValues)1048bcb0991SDimitry Andric static StringRef getEnumName(CodeViewRecordIO &IO, T Value,
1058bcb0991SDimitry Andric                              ArrayRef<EnumEntry<TEnum>> EnumValues) {
1068bcb0991SDimitry Andric   if (!IO.isStreaming())
1078bcb0991SDimitry Andric     return "";
1088bcb0991SDimitry Andric   StringRef Name;
1098bcb0991SDimitry Andric   for (const auto &EnumItem : EnumValues) {
1108bcb0991SDimitry Andric     if (EnumItem.Value == Value) {
1118bcb0991SDimitry Andric       Name = EnumItem.Name;
1128bcb0991SDimitry Andric       break;
1138bcb0991SDimitry Andric     }
1148bcb0991SDimitry Andric   }
1158bcb0991SDimitry Andric 
1168bcb0991SDimitry Andric   return Name;
1178bcb0991SDimitry Andric }
1188bcb0991SDimitry Andric 
getMemberAttributes(CodeViewRecordIO & IO,MemberAccess Access,MethodKind Kind,MethodOptions Options)1198bcb0991SDimitry Andric static std::string getMemberAttributes(CodeViewRecordIO &IO,
1208bcb0991SDimitry Andric                                        MemberAccess Access, MethodKind Kind,
1218bcb0991SDimitry Andric                                        MethodOptions Options) {
1228bcb0991SDimitry Andric   if (!IO.isStreaming())
1238bcb0991SDimitry Andric     return "";
1245ffd83dbSDimitry Andric   std::string AccessSpecifier = std::string(
125bdd1243dSDimitry Andric       getEnumName(IO, uint8_t(Access), ArrayRef(getMemberAccessNames())));
1268bcb0991SDimitry Andric   std::string MemberAttrs(AccessSpecifier);
1278bcb0991SDimitry Andric   if (Kind != MethodKind::Vanilla) {
1285ffd83dbSDimitry Andric     std::string MethodKind = std::string(
129bdd1243dSDimitry Andric         getEnumName(IO, unsigned(Kind), ArrayRef(getMemberKindNames())));
1308bcb0991SDimitry Andric     MemberAttrs += ", " + MethodKind;
1318bcb0991SDimitry Andric   }
1328bcb0991SDimitry Andric   if (Options != MethodOptions::None) {
133bdd1243dSDimitry Andric     std::string MethodOptions =
134bdd1243dSDimitry Andric         getFlagNames(IO, unsigned(Options), ArrayRef(getMethodOptionNames()));
1358bcb0991SDimitry Andric     MemberAttrs += ", " + MethodOptions;
1368bcb0991SDimitry Andric   }
1378bcb0991SDimitry Andric   return MemberAttrs;
1388bcb0991SDimitry Andric }
1398bcb0991SDimitry Andric 
1400b57cec5SDimitry Andric struct MapOneMethodRecord {
MapOneMethodRecord__anon6dfefdac0111::MapOneMethodRecord1410b57cec5SDimitry Andric   explicit MapOneMethodRecord(bool IsFromOverloadList)
1420b57cec5SDimitry Andric       : IsFromOverloadList(IsFromOverloadList) {}
1430b57cec5SDimitry Andric 
operator ()__anon6dfefdac0111::MapOneMethodRecord1440b57cec5SDimitry Andric   Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method) const {
1458bcb0991SDimitry Andric     std::string Attrs = getMemberAttributes(
1468bcb0991SDimitry Andric         IO, Method.getAccess(), Method.getMethodKind(), Method.getOptions());
1478bcb0991SDimitry Andric     error(IO.mapInteger(Method.Attrs.Attrs, "Attrs: " + Attrs));
1480b57cec5SDimitry Andric     if (IsFromOverloadList) {
1490b57cec5SDimitry Andric       uint16_t Padding = 0;
1508bcb0991SDimitry Andric       error(IO.mapInteger(Padding));
1510b57cec5SDimitry Andric     }
1520b57cec5SDimitry Andric     error(IO.mapInteger(Method.Type, "Type"));
1530b57cec5SDimitry Andric     if (Method.isIntroducingVirtual()) {
1540b57cec5SDimitry Andric       error(IO.mapInteger(Method.VFTableOffset, "VFTableOffset"));
1550b57cec5SDimitry Andric     } else if (IO.isReading())
1560b57cec5SDimitry Andric       Method.VFTableOffset = -1;
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric     if (!IsFromOverloadList)
1590b57cec5SDimitry Andric       error(IO.mapStringZ(Method.Name, "Name"));
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric     return Error::success();
1620b57cec5SDimitry Andric   }
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric private:
1650b57cec5SDimitry Andric   bool IsFromOverloadList;
1660b57cec5SDimitry Andric };
1678bcb0991SDimitry Andric } // namespace
1680b57cec5SDimitry Andric 
169fe6060f1SDimitry Andric // Computes a string representation of a hash of the specified name, suitable
170fe6060f1SDimitry Andric // for use when emitting CodeView type names.
computeHashString(StringRef Name,SmallString<32> & StringifiedHash)171fe6060f1SDimitry Andric static void computeHashString(StringRef Name,
172fe6060f1SDimitry Andric                               SmallString<32> &StringifiedHash) {
173fe6060f1SDimitry Andric   llvm::MD5 Hash;
174fe6060f1SDimitry Andric   llvm::MD5::MD5Result Result;
175fe6060f1SDimitry Andric   Hash.update(Name);
176fe6060f1SDimitry Andric   Hash.final(Result);
177fe6060f1SDimitry Andric   Hash.stringifyResult(Result, StringifiedHash);
178fe6060f1SDimitry Andric }
179fe6060f1SDimitry Andric 
mapNameAndUniqueName(CodeViewRecordIO & IO,StringRef & Name,StringRef & UniqueName,bool HasUniqueName)1800b57cec5SDimitry Andric static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name,
1810b57cec5SDimitry Andric                                   StringRef &UniqueName, bool HasUniqueName) {
1820b57cec5SDimitry Andric   if (IO.isWriting()) {
1830b57cec5SDimitry Andric     // Try to be smart about what we write here.  We can't write anything too
184fe6060f1SDimitry Andric     // large, so if we're going to go over the limit, replace lengthy names with
185fe6060f1SDimitry Andric     // a stringified hash value.
1860b57cec5SDimitry Andric     size_t BytesLeft = IO.maxFieldLength();
1870b57cec5SDimitry Andric     if (HasUniqueName) {
1880b57cec5SDimitry Andric       size_t BytesNeeded = Name.size() + UniqueName.size() + 2;
1890b57cec5SDimitry Andric       if (BytesNeeded > BytesLeft) {
190fe6060f1SDimitry Andric         // The minimum space required for emitting hashes of both names.
191fe6060f1SDimitry Andric         assert(BytesLeft >= 70);
1920b57cec5SDimitry Andric 
193fe6060f1SDimitry Andric         // Replace the entire unique name with a hash of the unique name.
194fe6060f1SDimitry Andric         SmallString<32> Hash;
195fe6060f1SDimitry Andric         computeHashString(UniqueName, Hash);
196fe6060f1SDimitry Andric         std::string UniqueB = Twine("??@" + Hash + "@").str();
197fe6060f1SDimitry Andric         assert(UniqueB.size() == 36);
1980b57cec5SDimitry Andric 
199fe6060f1SDimitry Andric         // Truncate the name if necessary and append a hash of the name.
200fe6060f1SDimitry Andric         // The name length, hash included, is limited to 4096 bytes.
201fe6060f1SDimitry Andric         const size_t MaxTakeN = 4096;
202fe6060f1SDimitry Andric         size_t TakeN = std::min(MaxTakeN, BytesLeft - UniqueB.size() - 2) - 32;
203fe6060f1SDimitry Andric         computeHashString(Name, Hash);
204fe6060f1SDimitry Andric         std::string NameB = (Name.take_front(TakeN) + Hash).str();
205fe6060f1SDimitry Andric 
206fe6060f1SDimitry Andric         StringRef N = NameB;
207fe6060f1SDimitry Andric         StringRef U = UniqueB;
2080b57cec5SDimitry Andric         error(IO.mapStringZ(N));
2090b57cec5SDimitry Andric         error(IO.mapStringZ(U));
2100b57cec5SDimitry Andric       } else {
211fe6060f1SDimitry Andric         error(IO.mapStringZ(Name));
212fe6060f1SDimitry Andric         error(IO.mapStringZ(UniqueName));
213fe6060f1SDimitry Andric       }
214fe6060f1SDimitry Andric     } else {
2150b57cec5SDimitry Andric       // Cap the length of the string at however many bytes we have available,
2160b57cec5SDimitry Andric       // plus one for the required null terminator.
2170b57cec5SDimitry Andric       auto N = StringRef(Name).take_front(BytesLeft - 1);
2180b57cec5SDimitry Andric       error(IO.mapStringZ(N));
2190b57cec5SDimitry Andric     }
2200b57cec5SDimitry Andric   } else {
2210b57cec5SDimitry Andric     // Reading & Streaming mode come after writing mode is executed for each
2220b57cec5SDimitry Andric     // record. Truncating large names are done during writing, so its not
2230b57cec5SDimitry Andric     // necessary to do it while reading or streaming.
2240b57cec5SDimitry Andric     error(IO.mapStringZ(Name, "Name"));
2250b57cec5SDimitry Andric     if (HasUniqueName)
2260b57cec5SDimitry Andric       error(IO.mapStringZ(UniqueName, "LinkageName"));
2270b57cec5SDimitry Andric   }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   return Error::success();
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric 
visitTypeBegin(CVType & CVR)2320b57cec5SDimitry Andric Error TypeRecordMapping::visitTypeBegin(CVType &CVR) {
23381ad6265SDimitry Andric   assert(!TypeKind && "Already in a type mapping!");
23481ad6265SDimitry Andric   assert(!MemberKind && "Already in a member mapping!");
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   // FieldList and MethodList records can be any length because they can be
2370b57cec5SDimitry Andric   // split with continuation records.  All other record types cannot be
2380b57cec5SDimitry Andric   // longer than the maximum record length.
239bdd1243dSDimitry Andric   std::optional<uint32_t> MaxLen;
2400b57cec5SDimitry Andric   if (CVR.kind() != TypeLeafKind::LF_FIELDLIST &&
2410b57cec5SDimitry Andric       CVR.kind() != TypeLeafKind::LF_METHODLIST)
2420b57cec5SDimitry Andric     MaxLen = MaxRecordLength - sizeof(RecordPrefix);
2430b57cec5SDimitry Andric   error(IO.beginRecord(MaxLen));
2440b57cec5SDimitry Andric   TypeKind = CVR.kind();
2458bcb0991SDimitry Andric 
2468bcb0991SDimitry Andric   if (IO.isStreaming()) {
2478bcb0991SDimitry Andric     auto RecordKind = CVR.kind();
2488bcb0991SDimitry Andric     uint16_t RecordLen = CVR.length() - 2;
2495ffd83dbSDimitry Andric     std::string RecordKindName = std::string(
250bdd1243dSDimitry Andric         getEnumName(IO, unsigned(RecordKind), ArrayRef(LeafTypeNames)));
2518bcb0991SDimitry Andric     error(IO.mapInteger(RecordLen, "Record length"));
2528bcb0991SDimitry Andric     error(IO.mapEnum(RecordKind, "Record kind: " + RecordKindName));
2538bcb0991SDimitry Andric   }
2540b57cec5SDimitry Andric   return Error::success();
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric 
visitTypeBegin(CVType & CVR,TypeIndex Index)2570b57cec5SDimitry Andric Error TypeRecordMapping::visitTypeBegin(CVType &CVR, TypeIndex Index) {
2588bcb0991SDimitry Andric   if (IO.isStreaming())
2598bcb0991SDimitry Andric     IO.emitRawComment(" " + getLeafTypeName(CVR.kind()) + " (0x" +
2608bcb0991SDimitry Andric                       utohexstr(Index.getIndex()) + ")");
2610b57cec5SDimitry Andric   return visitTypeBegin(CVR);
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric 
visitTypeEnd(CVType & Record)2640b57cec5SDimitry Andric Error TypeRecordMapping::visitTypeEnd(CVType &Record) {
26581ad6265SDimitry Andric   assert(TypeKind && "Not in a type mapping!");
26681ad6265SDimitry Andric   assert(!MemberKind && "Still in a member mapping!");
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   error(IO.endRecord());
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   TypeKind.reset();
2710b57cec5SDimitry Andric   return Error::success();
2720b57cec5SDimitry Andric }
2730b57cec5SDimitry Andric 
visitMemberBegin(CVMemberRecord & Record)2740b57cec5SDimitry Andric Error TypeRecordMapping::visitMemberBegin(CVMemberRecord &Record) {
27581ad6265SDimitry Andric   assert(TypeKind && "Not in a type mapping!");
27681ad6265SDimitry Andric   assert(!MemberKind && "Already in a member mapping!");
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   // The largest possible subrecord is one in which there is a record prefix,
2790b57cec5SDimitry Andric   // followed by the subrecord, followed by a continuation, and that entire
280e8d8bef9SDimitry Andric   // sequence spawns `MaxRecordLength` bytes.  So the record's length is
2810b57cec5SDimitry Andric   // calculated as follows.
2828bcb0991SDimitry Andric 
2830b57cec5SDimitry Andric   constexpr uint32_t ContinuationLength = 8;
2840b57cec5SDimitry Andric   error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix) -
2850b57cec5SDimitry Andric                        ContinuationLength));
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric   MemberKind = Record.Kind;
2888bcb0991SDimitry Andric   if (IO.isStreaming()) {
2895ffd83dbSDimitry Andric     std::string MemberKindName = std::string(getLeafTypeName(Record.Kind));
2908bcb0991SDimitry Andric     MemberKindName +=
2918bcb0991SDimitry Andric         " ( " +
292bdd1243dSDimitry Andric         (getEnumName(IO, unsigned(Record.Kind), ArrayRef(LeafTypeNames)))
2938bcb0991SDimitry Andric             .str() +
2948bcb0991SDimitry Andric         " )";
2958bcb0991SDimitry Andric     error(IO.mapEnum(Record.Kind, "Member kind: " + MemberKindName));
2968bcb0991SDimitry Andric   }
2970b57cec5SDimitry Andric   return Error::success();
2980b57cec5SDimitry Andric }
2990b57cec5SDimitry Andric 
visitMemberEnd(CVMemberRecord & Record)3000b57cec5SDimitry Andric Error TypeRecordMapping::visitMemberEnd(CVMemberRecord &Record) {
30181ad6265SDimitry Andric   assert(TypeKind && "Not in a type mapping!");
30281ad6265SDimitry Andric   assert(MemberKind && "Not in a member mapping!");
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric   if (IO.isReading()) {
3050b57cec5SDimitry Andric     if (auto EC = IO.skipPadding())
3060b57cec5SDimitry Andric       return EC;
3070b57cec5SDimitry Andric   }
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   MemberKind.reset();
3100b57cec5SDimitry Andric   error(IO.endRecord());
3110b57cec5SDimitry Andric   return Error::success();
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,ModifierRecord & Record)3140b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ModifierRecord &Record) {
3158bcb0991SDimitry Andric   std::string ModifierNames =
3168bcb0991SDimitry Andric       getFlagNames(IO, static_cast<uint16_t>(Record.Modifiers),
317bdd1243dSDimitry Andric                    ArrayRef(getTypeModifierNames()));
3180b57cec5SDimitry Andric   error(IO.mapInteger(Record.ModifiedType, "ModifiedType"));
3198bcb0991SDimitry Andric   error(IO.mapEnum(Record.Modifiers, "Modifiers" + ModifierNames));
3200b57cec5SDimitry Andric   return Error::success();
3210b57cec5SDimitry Andric }
3220b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,ProcedureRecord & Record)3230b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
3240b57cec5SDimitry Andric                                           ProcedureRecord &Record) {
3255ffd83dbSDimitry Andric   std::string CallingConvName = std::string(getEnumName(
326bdd1243dSDimitry Andric       IO, uint8_t(Record.CallConv), ArrayRef(getCallingConventions())));
3278bcb0991SDimitry Andric   std::string FuncOptionNames =
3288bcb0991SDimitry Andric       getFlagNames(IO, static_cast<uint16_t>(Record.Options),
329bdd1243dSDimitry Andric                    ArrayRef(getFunctionOptionEnum()));
3300b57cec5SDimitry Andric   error(IO.mapInteger(Record.ReturnType, "ReturnType"));
3318bcb0991SDimitry Andric   error(IO.mapEnum(Record.CallConv, "CallingConvention: " + CallingConvName));
3328bcb0991SDimitry Andric   error(IO.mapEnum(Record.Options, "FunctionOptions" + FuncOptionNames));
3330b57cec5SDimitry Andric   error(IO.mapInteger(Record.ParameterCount, "NumParameters"));
3340b57cec5SDimitry Andric   error(IO.mapInteger(Record.ArgumentList, "ArgListType"));
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   return Error::success();
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,MemberFunctionRecord & Record)3390b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
3400b57cec5SDimitry Andric                                           MemberFunctionRecord &Record) {
3415ffd83dbSDimitry Andric   std::string CallingConvName = std::string(getEnumName(
342bdd1243dSDimitry Andric       IO, uint8_t(Record.CallConv), ArrayRef(getCallingConventions())));
3438bcb0991SDimitry Andric   std::string FuncOptionNames =
3448bcb0991SDimitry Andric       getFlagNames(IO, static_cast<uint16_t>(Record.Options),
345bdd1243dSDimitry Andric                    ArrayRef(getFunctionOptionEnum()));
3460b57cec5SDimitry Andric   error(IO.mapInteger(Record.ReturnType, "ReturnType"));
3470b57cec5SDimitry Andric   error(IO.mapInteger(Record.ClassType, "ClassType"));
3480b57cec5SDimitry Andric   error(IO.mapInteger(Record.ThisType, "ThisType"));
3498bcb0991SDimitry Andric   error(IO.mapEnum(Record.CallConv, "CallingConvention: " + CallingConvName));
3508bcb0991SDimitry Andric   error(IO.mapEnum(Record.Options, "FunctionOptions" + FuncOptionNames));
3510b57cec5SDimitry Andric   error(IO.mapInteger(Record.ParameterCount, "NumParameters"));
3520b57cec5SDimitry Andric   error(IO.mapInteger(Record.ArgumentList, "ArgListType"));
3530b57cec5SDimitry Andric   error(IO.mapInteger(Record.ThisPointerAdjustment, "ThisAdjustment"));
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric   return Error::success();
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,ArgListRecord & Record)3580b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArgListRecord &Record) {
3590b57cec5SDimitry Andric   error(IO.mapVectorN<uint32_t>(
3600b57cec5SDimitry Andric       Record.ArgIndices,
3610b57cec5SDimitry Andric       [](CodeViewRecordIO &IO, TypeIndex &N) {
3620b57cec5SDimitry Andric         return IO.mapInteger(N, "Argument");
3630b57cec5SDimitry Andric       },
3640b57cec5SDimitry Andric       "NumArgs"));
3650b57cec5SDimitry Andric   return Error::success();
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,StringListRecord & Record)3680b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
3690b57cec5SDimitry Andric                                           StringListRecord &Record) {
3700b57cec5SDimitry Andric   error(IO.mapVectorN<uint32_t>(
3710b57cec5SDimitry Andric       Record.StringIndices,
3720b57cec5SDimitry Andric       [](CodeViewRecordIO &IO, TypeIndex &N) {
3730b57cec5SDimitry Andric         return IO.mapInteger(N, "Strings");
3740b57cec5SDimitry Andric       },
3750b57cec5SDimitry Andric       "NumStrings"));
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric   return Error::success();
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,PointerRecord & Record)3800b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR, PointerRecord &Record) {
3818bcb0991SDimitry Andric 
3828bcb0991SDimitry Andric   SmallString<128> Attr("Attrs: ");
3838bcb0991SDimitry Andric 
3848bcb0991SDimitry Andric   if (IO.isStreaming()) {
385bdd1243dSDimitry Andric     std::string PtrType = std::string(getEnumName(
386bdd1243dSDimitry Andric         IO, unsigned(Record.getPointerKind()), ArrayRef(getPtrKindNames())));
3878bcb0991SDimitry Andric     Attr += "[ Type: " + PtrType;
3888bcb0991SDimitry Andric 
3895ffd83dbSDimitry Andric     std::string PtrMode = std::string(getEnumName(
390bdd1243dSDimitry Andric         IO, unsigned(Record.getMode()), ArrayRef(getPtrModeNames())));
3918bcb0991SDimitry Andric     Attr += ", Mode: " + PtrMode;
3928bcb0991SDimitry Andric 
3938bcb0991SDimitry Andric     auto PtrSizeOf = Record.getSize();
3948bcb0991SDimitry Andric     Attr += ", SizeOf: " + itostr(PtrSizeOf);
3958bcb0991SDimitry Andric 
3968bcb0991SDimitry Andric     if (Record.isFlat())
3978bcb0991SDimitry Andric       Attr += ", isFlat";
3988bcb0991SDimitry Andric     if (Record.isConst())
3998bcb0991SDimitry Andric       Attr += ", isConst";
4008bcb0991SDimitry Andric     if (Record.isVolatile())
4018bcb0991SDimitry Andric       Attr += ", isVolatile";
4028bcb0991SDimitry Andric     if (Record.isUnaligned())
4038bcb0991SDimitry Andric       Attr += ", isUnaligned";
4048bcb0991SDimitry Andric     if (Record.isRestrict())
4058bcb0991SDimitry Andric       Attr += ", isRestricted";
4068bcb0991SDimitry Andric     if (Record.isLValueReferenceThisPtr())
4078bcb0991SDimitry Andric       Attr += ", isThisPtr&";
4088bcb0991SDimitry Andric     if (Record.isRValueReferenceThisPtr())
4098bcb0991SDimitry Andric       Attr += ", isThisPtr&&";
4108bcb0991SDimitry Andric     Attr += " ]";
4118bcb0991SDimitry Andric   }
4128bcb0991SDimitry Andric 
4130b57cec5SDimitry Andric   error(IO.mapInteger(Record.ReferentType, "PointeeType"));
4148bcb0991SDimitry Andric   error(IO.mapInteger(Record.Attrs, Attr));
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   if (Record.isPointerToMember()) {
4170b57cec5SDimitry Andric     if (IO.isReading())
4180b57cec5SDimitry Andric       Record.MemberInfo.emplace();
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric     MemberPointerInfo &M = *Record.MemberInfo;
4210b57cec5SDimitry Andric     error(IO.mapInteger(M.ContainingType, "ClassType"));
4225ffd83dbSDimitry Andric     std::string PtrMemberGetRepresentation = std::string(getEnumName(
423bdd1243dSDimitry Andric         IO, uint16_t(M.Representation), ArrayRef(getPtrMemberRepNames())));
4248bcb0991SDimitry Andric     error(IO.mapEnum(M.Representation,
4258bcb0991SDimitry Andric                      "Representation: " + PtrMemberGetRepresentation));
4260b57cec5SDimitry Andric   }
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric   return Error::success();
4290b57cec5SDimitry Andric }
4300b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,ArrayRecord & Record)4310b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArrayRecord &Record) {
4320b57cec5SDimitry Andric   error(IO.mapInteger(Record.ElementType, "ElementType"));
4330b57cec5SDimitry Andric   error(IO.mapInteger(Record.IndexType, "IndexType"));
4340b57cec5SDimitry Andric   error(IO.mapEncodedInteger(Record.Size, "SizeOf"));
4350b57cec5SDimitry Andric   error(IO.mapStringZ(Record.Name, "Name"));
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric   return Error::success();
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,ClassRecord & Record)4400b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ClassRecord &Record) {
4410b57cec5SDimitry Andric   assert((CVR.kind() == TypeLeafKind::LF_STRUCTURE) ||
4420b57cec5SDimitry Andric          (CVR.kind() == TypeLeafKind::LF_CLASS) ||
4430b57cec5SDimitry Andric          (CVR.kind() == TypeLeafKind::LF_INTERFACE));
4440b57cec5SDimitry Andric 
4458bcb0991SDimitry Andric   std::string PropertiesNames =
4468bcb0991SDimitry Andric       getFlagNames(IO, static_cast<uint16_t>(Record.Options),
447bdd1243dSDimitry Andric                    ArrayRef(getClassOptionNames()));
4480b57cec5SDimitry Andric   error(IO.mapInteger(Record.MemberCount, "MemberCount"));
4498bcb0991SDimitry Andric   error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames));
4500b57cec5SDimitry Andric   error(IO.mapInteger(Record.FieldList, "FieldList"));
4510b57cec5SDimitry Andric   error(IO.mapInteger(Record.DerivationList, "DerivedFrom"));
4520b57cec5SDimitry Andric   error(IO.mapInteger(Record.VTableShape, "VShape"));
4530b57cec5SDimitry Andric   error(IO.mapEncodedInteger(Record.Size, "SizeOf"));
4540b57cec5SDimitry Andric   error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
4550b57cec5SDimitry Andric                              Record.hasUniqueName()));
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric   return Error::success();
4580b57cec5SDimitry Andric }
4590b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,UnionRecord & Record)4600b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR, UnionRecord &Record) {
4618bcb0991SDimitry Andric   std::string PropertiesNames =
4628bcb0991SDimitry Andric       getFlagNames(IO, static_cast<uint16_t>(Record.Options),
463bdd1243dSDimitry Andric                    ArrayRef(getClassOptionNames()));
4640b57cec5SDimitry Andric   error(IO.mapInteger(Record.MemberCount, "MemberCount"));
4658bcb0991SDimitry Andric   error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames));
4660b57cec5SDimitry Andric   error(IO.mapInteger(Record.FieldList, "FieldList"));
4670b57cec5SDimitry Andric   error(IO.mapEncodedInteger(Record.Size, "SizeOf"));
4680b57cec5SDimitry Andric   error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
4690b57cec5SDimitry Andric                              Record.hasUniqueName()));
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric   return Error::success();
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,EnumRecord & Record)4740b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR, EnumRecord &Record) {
4758bcb0991SDimitry Andric   std::string PropertiesNames =
4768bcb0991SDimitry Andric       getFlagNames(IO, static_cast<uint16_t>(Record.Options),
477bdd1243dSDimitry Andric                    ArrayRef(getClassOptionNames()));
4780b57cec5SDimitry Andric   error(IO.mapInteger(Record.MemberCount, "NumEnumerators"));
4798bcb0991SDimitry Andric   error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames));
4800b57cec5SDimitry Andric   error(IO.mapInteger(Record.UnderlyingType, "UnderlyingType"));
4810b57cec5SDimitry Andric   error(IO.mapInteger(Record.FieldList, "FieldListType"));
4820b57cec5SDimitry Andric   error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
4830b57cec5SDimitry Andric                              Record.hasUniqueName()));
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric   return Error::success();
4860b57cec5SDimitry Andric }
4870b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,BitFieldRecord & Record)4880b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR, BitFieldRecord &Record) {
4890b57cec5SDimitry Andric   error(IO.mapInteger(Record.Type, "Type"));
4900b57cec5SDimitry Andric   error(IO.mapInteger(Record.BitSize, "BitSize"));
4910b57cec5SDimitry Andric   error(IO.mapInteger(Record.BitOffset, "BitOffset"));
4920b57cec5SDimitry Andric 
4930b57cec5SDimitry Andric   return Error::success();
4940b57cec5SDimitry Andric }
4950b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,VFTableShapeRecord & Record)4960b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
4970b57cec5SDimitry Andric                                           VFTableShapeRecord &Record) {
4980b57cec5SDimitry Andric   uint16_t Size;
4990b57cec5SDimitry Andric   if (!IO.isReading()) {
5000b57cec5SDimitry Andric     ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
5010b57cec5SDimitry Andric     Size = Slots.size();
5020b57cec5SDimitry Andric     error(IO.mapInteger(Size, "VFEntryCount"));
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric     for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
5050b57cec5SDimitry Andric       uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
5060b57cec5SDimitry Andric       if ((SlotIndex + 1) < Slots.size()) {
5070b57cec5SDimitry Andric         Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
5080b57cec5SDimitry Andric       }
5090b57cec5SDimitry Andric       error(IO.mapInteger(Byte));
5100b57cec5SDimitry Andric     }
5110b57cec5SDimitry Andric   } else {
5120b57cec5SDimitry Andric     error(IO.mapInteger(Size));
5130b57cec5SDimitry Andric     for (uint16_t I = 0; I < Size; I += 2) {
5140b57cec5SDimitry Andric       uint8_t Byte;
5150b57cec5SDimitry Andric       error(IO.mapInteger(Byte));
5160b57cec5SDimitry Andric       Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte & 0xF));
5170b57cec5SDimitry Andric       if ((I + 1) < Size)
5180b57cec5SDimitry Andric         Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte >> 4));
5190b57cec5SDimitry Andric     }
5200b57cec5SDimitry Andric   }
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric   return Error::success();
5230b57cec5SDimitry Andric }
5240b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,VFTableRecord & Record)5250b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR, VFTableRecord &Record) {
5260b57cec5SDimitry Andric   error(IO.mapInteger(Record.CompleteClass, "CompleteClass"));
5270b57cec5SDimitry Andric   error(IO.mapInteger(Record.OverriddenVFTable, "OverriddenVFTable"));
5280b57cec5SDimitry Andric   error(IO.mapInteger(Record.VFPtrOffset, "VFPtrOffset"));
5290b57cec5SDimitry Andric   uint32_t NamesLen = 0;
5300b57cec5SDimitry Andric   if (!IO.isReading()) {
5310b57cec5SDimitry Andric     for (auto Name : Record.MethodNames)
5320b57cec5SDimitry Andric       NamesLen += Name.size() + 1;
5330b57cec5SDimitry Andric   }
5340b57cec5SDimitry Andric   error(IO.mapInteger(NamesLen));
5350b57cec5SDimitry Andric   error(IO.mapVectorTail(
5360b57cec5SDimitry Andric       Record.MethodNames,
5370b57cec5SDimitry Andric       [](CodeViewRecordIO &IO, StringRef &S) {
5380b57cec5SDimitry Andric         return IO.mapStringZ(S, "MethodName");
5390b57cec5SDimitry Andric       },
5400b57cec5SDimitry Andric       "VFTableName"));
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric   return Error::success();
5430b57cec5SDimitry Andric }
5440b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,StringIdRecord & Record)5450b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR, StringIdRecord &Record) {
5460b57cec5SDimitry Andric   error(IO.mapInteger(Record.Id, "Id"));
5470b57cec5SDimitry Andric   error(IO.mapStringZ(Record.String, "StringData"));
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric   return Error::success();
5500b57cec5SDimitry Andric }
5510b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,UdtSourceLineRecord & Record)5520b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
5530b57cec5SDimitry Andric                                           UdtSourceLineRecord &Record) {
5540b57cec5SDimitry Andric   error(IO.mapInteger(Record.UDT, "UDT"));
5550b57cec5SDimitry Andric   error(IO.mapInteger(Record.SourceFile, "SourceFile"));
5560b57cec5SDimitry Andric   error(IO.mapInteger(Record.LineNumber, "LineNumber"));
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric   return Error::success();
5590b57cec5SDimitry Andric }
5600b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,UdtModSourceLineRecord & Record)5610b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
5620b57cec5SDimitry Andric                                           UdtModSourceLineRecord &Record) {
5630b57cec5SDimitry Andric   error(IO.mapInteger(Record.UDT, "UDT"));
5640b57cec5SDimitry Andric   error(IO.mapInteger(Record.SourceFile, "SourceFile"));
5650b57cec5SDimitry Andric   error(IO.mapInteger(Record.LineNumber, "LineNumber"));
5660b57cec5SDimitry Andric   error(IO.mapInteger(Record.Module, "Module"));
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric   return Error::success();
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,FuncIdRecord & Record)5710b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR, FuncIdRecord &Record) {
5720b57cec5SDimitry Andric   error(IO.mapInteger(Record.ParentScope, "ParentScope"));
5730b57cec5SDimitry Andric   error(IO.mapInteger(Record.FunctionType, "FunctionType"));
5740b57cec5SDimitry Andric   error(IO.mapStringZ(Record.Name, "Name"));
5750b57cec5SDimitry Andric 
5760b57cec5SDimitry Andric   return Error::success();
5770b57cec5SDimitry Andric }
5780b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,MemberFuncIdRecord & Record)5790b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
5800b57cec5SDimitry Andric                                           MemberFuncIdRecord &Record) {
5810b57cec5SDimitry Andric   error(IO.mapInteger(Record.ClassType, "ClassType"));
5820b57cec5SDimitry Andric   error(IO.mapInteger(Record.FunctionType, "FunctionType"));
5830b57cec5SDimitry Andric   error(IO.mapStringZ(Record.Name, "Name"));
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric   return Error::success();
5860b57cec5SDimitry Andric }
5870b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,BuildInfoRecord & Record)5880b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
5890b57cec5SDimitry Andric                                           BuildInfoRecord &Record) {
5900b57cec5SDimitry Andric   error(IO.mapVectorN<uint16_t>(
5910b57cec5SDimitry Andric       Record.ArgIndices,
5920b57cec5SDimitry Andric       [](CodeViewRecordIO &IO, TypeIndex &N) {
5930b57cec5SDimitry Andric         return IO.mapInteger(N, "Argument");
5940b57cec5SDimitry Andric       },
5950b57cec5SDimitry Andric       "NumArgs"));
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric   return Error::success();
5980b57cec5SDimitry Andric }
5990b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,MethodOverloadListRecord & Record)6000b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
6010b57cec5SDimitry Andric                                           MethodOverloadListRecord &Record) {
6020b57cec5SDimitry Andric   // TODO: Split the list into multiple records if it's longer than 64KB, using
6030b57cec5SDimitry Andric   // a subrecord of TypeRecordKind::Index to chain the records together.
6040b57cec5SDimitry Andric   error(IO.mapVectorTail(Record.Methods, MapOneMethodRecord(true), "Method"));
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric   return Error::success();
6070b57cec5SDimitry Andric }
6080b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,FieldListRecord & Record)6090b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
6100b57cec5SDimitry Andric                                           FieldListRecord &Record) {
6118bcb0991SDimitry Andric   if (IO.isStreaming()) {
6128bcb0991SDimitry Andric     if (auto EC = codeview::visitMemberRecordStream(Record.Data, *this))
6138bcb0991SDimitry Andric       return EC;
6148bcb0991SDimitry Andric   } else
6150b57cec5SDimitry Andric     error(IO.mapByteVectorTail(Record.Data));
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric   return Error::success();
6180b57cec5SDimitry Andric }
6190b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,TypeServer2Record & Record)6200b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
6210b57cec5SDimitry Andric                                           TypeServer2Record &Record) {
6220b57cec5SDimitry Andric   error(IO.mapGuid(Record.Guid, "Guid"));
6230b57cec5SDimitry Andric   error(IO.mapInteger(Record.Age, "Age"));
6240b57cec5SDimitry Andric   error(IO.mapStringZ(Record.Name, "Name"));
6250b57cec5SDimitry Andric   return Error::success();
6260b57cec5SDimitry Andric }
6270b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,LabelRecord & Record)6280b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR, LabelRecord &Record) {
6295ffd83dbSDimitry Andric   std::string ModeName = std::string(
630bdd1243dSDimitry Andric       getEnumName(IO, uint16_t(Record.Mode), ArrayRef(getLabelTypeEnum())));
6318bcb0991SDimitry Andric   error(IO.mapEnum(Record.Mode, "Mode: " + ModeName));
6320b57cec5SDimitry Andric   return Error::success();
6330b57cec5SDimitry Andric }
6340b57cec5SDimitry Andric 
visitKnownMember(CVMemberRecord & CVR,BaseClassRecord & Record)6350b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
6360b57cec5SDimitry Andric                                           BaseClassRecord &Record) {
6378bcb0991SDimitry Andric   std::string Attrs = getMemberAttributes(
6388bcb0991SDimitry Andric       IO, Record.getAccess(), MethodKind::Vanilla, MethodOptions::None);
6398bcb0991SDimitry Andric   error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
6400b57cec5SDimitry Andric   error(IO.mapInteger(Record.Type, "BaseType"));
6410b57cec5SDimitry Andric   error(IO.mapEncodedInteger(Record.Offset, "BaseOffset"));
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric   return Error::success();
6440b57cec5SDimitry Andric }
6450b57cec5SDimitry Andric 
visitKnownMember(CVMemberRecord & CVR,EnumeratorRecord & Record)6460b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
6470b57cec5SDimitry Andric                                           EnumeratorRecord &Record) {
6488bcb0991SDimitry Andric   std::string Attrs = getMemberAttributes(
6498bcb0991SDimitry Andric       IO, Record.getAccess(), MethodKind::Vanilla, MethodOptions::None);
6508bcb0991SDimitry Andric   error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric   // FIXME: Handle full APInt such as __int128.
6530b57cec5SDimitry Andric   error(IO.mapEncodedInteger(Record.Value, "EnumValue"));
6540b57cec5SDimitry Andric   error(IO.mapStringZ(Record.Name, "Name"));
6550b57cec5SDimitry Andric 
6560b57cec5SDimitry Andric   return Error::success();
6570b57cec5SDimitry Andric }
6580b57cec5SDimitry Andric 
visitKnownMember(CVMemberRecord & CVR,DataMemberRecord & Record)6590b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
6600b57cec5SDimitry Andric                                           DataMemberRecord &Record) {
6618bcb0991SDimitry Andric   std::string Attrs = getMemberAttributes(
6628bcb0991SDimitry Andric       IO, Record.getAccess(), MethodKind::Vanilla, MethodOptions::None);
6638bcb0991SDimitry Andric   error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
6640b57cec5SDimitry Andric   error(IO.mapInteger(Record.Type, "Type"));
6650b57cec5SDimitry Andric   error(IO.mapEncodedInteger(Record.FieldOffset, "FieldOffset"));
6660b57cec5SDimitry Andric   error(IO.mapStringZ(Record.Name, "Name"));
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric   return Error::success();
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric 
visitKnownMember(CVMemberRecord & CVR,OverloadedMethodRecord & Record)6710b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
6720b57cec5SDimitry Andric                                           OverloadedMethodRecord &Record) {
6730b57cec5SDimitry Andric   error(IO.mapInteger(Record.NumOverloads, "MethodCount"));
6740b57cec5SDimitry Andric   error(IO.mapInteger(Record.MethodList, "MethodListIndex"));
6750b57cec5SDimitry Andric   error(IO.mapStringZ(Record.Name, "Name"));
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric   return Error::success();
6780b57cec5SDimitry Andric }
6790b57cec5SDimitry Andric 
visitKnownMember(CVMemberRecord & CVR,OneMethodRecord & Record)6800b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
6810b57cec5SDimitry Andric                                           OneMethodRecord &Record) {
6820b57cec5SDimitry Andric   const bool IsFromOverloadList = (TypeKind == LF_METHODLIST);
6830b57cec5SDimitry Andric   MapOneMethodRecord Mapper(IsFromOverloadList);
6840b57cec5SDimitry Andric   return Mapper(IO, Record);
6850b57cec5SDimitry Andric }
6860b57cec5SDimitry Andric 
visitKnownMember(CVMemberRecord & CVR,NestedTypeRecord & Record)6870b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
6880b57cec5SDimitry Andric                                           NestedTypeRecord &Record) {
6890b57cec5SDimitry Andric   uint16_t Padding = 0;
6900b57cec5SDimitry Andric   error(IO.mapInteger(Padding, "Padding"));
6910b57cec5SDimitry Andric   error(IO.mapInteger(Record.Type, "Type"));
6920b57cec5SDimitry Andric   error(IO.mapStringZ(Record.Name, "Name"));
6930b57cec5SDimitry Andric 
6940b57cec5SDimitry Andric   return Error::success();
6950b57cec5SDimitry Andric }
6960b57cec5SDimitry Andric 
visitKnownMember(CVMemberRecord & CVR,StaticDataMemberRecord & Record)6970b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
6980b57cec5SDimitry Andric                                           StaticDataMemberRecord &Record) {
6990b57cec5SDimitry Andric 
7008bcb0991SDimitry Andric   std::string Attrs = getMemberAttributes(
7018bcb0991SDimitry Andric       IO, Record.getAccess(), MethodKind::Vanilla, MethodOptions::None);
7028bcb0991SDimitry Andric   error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
7030b57cec5SDimitry Andric   error(IO.mapInteger(Record.Type, "Type"));
7040b57cec5SDimitry Andric   error(IO.mapStringZ(Record.Name, "Name"));
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric   return Error::success();
7070b57cec5SDimitry Andric }
7080b57cec5SDimitry Andric 
visitKnownMember(CVMemberRecord & CVR,VirtualBaseClassRecord & Record)7090b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
7100b57cec5SDimitry Andric                                           VirtualBaseClassRecord &Record) {
7110b57cec5SDimitry Andric 
7128bcb0991SDimitry Andric   std::string Attrs = getMemberAttributes(
7138bcb0991SDimitry Andric       IO, Record.getAccess(), MethodKind::Vanilla, MethodOptions::None);
7148bcb0991SDimitry Andric   error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
7150b57cec5SDimitry Andric   error(IO.mapInteger(Record.BaseType, "BaseType"));
7160b57cec5SDimitry Andric   error(IO.mapInteger(Record.VBPtrType, "VBPtrType"));
7170b57cec5SDimitry Andric   error(IO.mapEncodedInteger(Record.VBPtrOffset, "VBPtrOffset"));
7180b57cec5SDimitry Andric   error(IO.mapEncodedInteger(Record.VTableIndex, "VBTableIndex"));
7190b57cec5SDimitry Andric 
7200b57cec5SDimitry Andric   return Error::success();
7210b57cec5SDimitry Andric }
7220b57cec5SDimitry Andric 
visitKnownMember(CVMemberRecord & CVR,VFPtrRecord & Record)7230b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
7240b57cec5SDimitry Andric                                           VFPtrRecord &Record) {
7250b57cec5SDimitry Andric   uint16_t Padding = 0;
7260b57cec5SDimitry Andric   error(IO.mapInteger(Padding, "Padding"));
7270b57cec5SDimitry Andric   error(IO.mapInteger(Record.Type, "Type"));
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric   return Error::success();
7300b57cec5SDimitry Andric }
7310b57cec5SDimitry Andric 
visitKnownMember(CVMemberRecord & CVR,ListContinuationRecord & Record)7320b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
7330b57cec5SDimitry Andric                                           ListContinuationRecord &Record) {
7340b57cec5SDimitry Andric   uint16_t Padding = 0;
7350b57cec5SDimitry Andric   error(IO.mapInteger(Padding, "Padding"));
7360b57cec5SDimitry Andric   error(IO.mapInteger(Record.ContinuationIndex, "ContinuationIndex"));
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric   return Error::success();
7390b57cec5SDimitry Andric }
7400b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,PrecompRecord & Precomp)7410b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
7420b57cec5SDimitry Andric                                           PrecompRecord &Precomp) {
7430b57cec5SDimitry Andric   error(IO.mapInteger(Precomp.StartTypeIndex, "StartIndex"));
7440b57cec5SDimitry Andric   error(IO.mapInteger(Precomp.TypesCount, "Count"));
7450b57cec5SDimitry Andric   error(IO.mapInteger(Precomp.Signature, "Signature"));
7460b57cec5SDimitry Andric   error(IO.mapStringZ(Precomp.PrecompFilePath, "PrecompFile"));
7470b57cec5SDimitry Andric   return Error::success();
7480b57cec5SDimitry Andric }
7490b57cec5SDimitry Andric 
visitKnownRecord(CVType & CVR,EndPrecompRecord & EndPrecomp)7500b57cec5SDimitry Andric Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
7510b57cec5SDimitry Andric                                           EndPrecompRecord &EndPrecomp) {
7520b57cec5SDimitry Andric   error(IO.mapInteger(EndPrecomp.Signature, "Signature"));
7530b57cec5SDimitry Andric   return Error::success();
7540b57cec5SDimitry Andric }
755