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