1 //===-- TypeDumpVisitor.cpp - CodeView type info dumper ----------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
10 
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
13 #include "llvm/DebugInfo/CodeView/Formatters.h"
14 #include "llvm/DebugInfo/CodeView/TypeCollection.h"
15 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
16 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
17 #include "llvm/Support/FormatVariadic.h"
18 #include "llvm/Support/ScopedPrinter.h"
19 
20 using namespace llvm;
21 using namespace llvm::codeview;
22 
23 static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
24 #define CV_TYPE(enum, val) {#enum, enum},
25 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
26 };
27 
28 #define ENUM_ENTRY(enum_class, enum)                                           \
29   { #enum, std::underlying_type < enum_class > ::type(enum_class::enum) }
30 
31 static const EnumEntry<uint16_t> ClassOptionNames[] = {
32     ENUM_ENTRY(ClassOptions, Packed),
33     ENUM_ENTRY(ClassOptions, HasConstructorOrDestructor),
34     ENUM_ENTRY(ClassOptions, HasOverloadedOperator),
35     ENUM_ENTRY(ClassOptions, Nested),
36     ENUM_ENTRY(ClassOptions, ContainsNestedClass),
37     ENUM_ENTRY(ClassOptions, HasOverloadedAssignmentOperator),
38     ENUM_ENTRY(ClassOptions, HasConversionOperator),
39     ENUM_ENTRY(ClassOptions, ForwardReference),
40     ENUM_ENTRY(ClassOptions, Scoped),
41     ENUM_ENTRY(ClassOptions, HasUniqueName),
42     ENUM_ENTRY(ClassOptions, Sealed),
43     ENUM_ENTRY(ClassOptions, Intrinsic),
44 };
45 
46 static const EnumEntry<uint8_t> MemberAccessNames[] = {
47     ENUM_ENTRY(MemberAccess, None), ENUM_ENTRY(MemberAccess, Private),
48     ENUM_ENTRY(MemberAccess, Protected), ENUM_ENTRY(MemberAccess, Public),
49 };
50 
51 static const EnumEntry<uint16_t> MethodOptionNames[] = {
52     ENUM_ENTRY(MethodOptions, Pseudo),
53     ENUM_ENTRY(MethodOptions, NoInherit),
54     ENUM_ENTRY(MethodOptions, NoConstruct),
55     ENUM_ENTRY(MethodOptions, CompilerGenerated),
56     ENUM_ENTRY(MethodOptions, Sealed),
57 };
58 
59 static const EnumEntry<uint16_t> MemberKindNames[] = {
60     ENUM_ENTRY(MethodKind, Vanilla),
61     ENUM_ENTRY(MethodKind, Virtual),
62     ENUM_ENTRY(MethodKind, Static),
63     ENUM_ENTRY(MethodKind, Friend),
64     ENUM_ENTRY(MethodKind, IntroducingVirtual),
65     ENUM_ENTRY(MethodKind, PureVirtual),
66     ENUM_ENTRY(MethodKind, PureIntroducingVirtual),
67 };
68 
69 static const EnumEntry<uint8_t> PtrKindNames[] = {
70     ENUM_ENTRY(PointerKind, Near16),
71     ENUM_ENTRY(PointerKind, Far16),
72     ENUM_ENTRY(PointerKind, Huge16),
73     ENUM_ENTRY(PointerKind, BasedOnSegment),
74     ENUM_ENTRY(PointerKind, BasedOnValue),
75     ENUM_ENTRY(PointerKind, BasedOnSegmentValue),
76     ENUM_ENTRY(PointerKind, BasedOnAddress),
77     ENUM_ENTRY(PointerKind, BasedOnSegmentAddress),
78     ENUM_ENTRY(PointerKind, BasedOnType),
79     ENUM_ENTRY(PointerKind, BasedOnSelf),
80     ENUM_ENTRY(PointerKind, Near32),
81     ENUM_ENTRY(PointerKind, Far32),
82     ENUM_ENTRY(PointerKind, Near64),
83 };
84 
85 static const EnumEntry<uint8_t> PtrModeNames[] = {
86     ENUM_ENTRY(PointerMode, Pointer),
87     ENUM_ENTRY(PointerMode, LValueReference),
88     ENUM_ENTRY(PointerMode, PointerToDataMember),
89     ENUM_ENTRY(PointerMode, PointerToMemberFunction),
90     ENUM_ENTRY(PointerMode, RValueReference),
91 };
92 
93 static const EnumEntry<uint16_t> PtrMemberRepNames[] = {
94     ENUM_ENTRY(PointerToMemberRepresentation, Unknown),
95     ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceData),
96     ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceData),
97     ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceData),
98     ENUM_ENTRY(PointerToMemberRepresentation, GeneralData),
99     ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceFunction),
100     ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceFunction),
101     ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceFunction),
102     ENUM_ENTRY(PointerToMemberRepresentation, GeneralFunction),
103 };
104 
105 static const EnumEntry<uint16_t> TypeModifierNames[] = {
106     ENUM_ENTRY(ModifierOptions, Const), ENUM_ENTRY(ModifierOptions, Volatile),
107     ENUM_ENTRY(ModifierOptions, Unaligned),
108 };
109 
110 static const EnumEntry<uint8_t> CallingConventions[] = {
111     ENUM_ENTRY(CallingConvention, NearC),
112     ENUM_ENTRY(CallingConvention, FarC),
113     ENUM_ENTRY(CallingConvention, NearPascal),
114     ENUM_ENTRY(CallingConvention, FarPascal),
115     ENUM_ENTRY(CallingConvention, NearFast),
116     ENUM_ENTRY(CallingConvention, FarFast),
117     ENUM_ENTRY(CallingConvention, NearStdCall),
118     ENUM_ENTRY(CallingConvention, FarStdCall),
119     ENUM_ENTRY(CallingConvention, NearSysCall),
120     ENUM_ENTRY(CallingConvention, FarSysCall),
121     ENUM_ENTRY(CallingConvention, ThisCall),
122     ENUM_ENTRY(CallingConvention, MipsCall),
123     ENUM_ENTRY(CallingConvention, Generic),
124     ENUM_ENTRY(CallingConvention, AlphaCall),
125     ENUM_ENTRY(CallingConvention, PpcCall),
126     ENUM_ENTRY(CallingConvention, SHCall),
127     ENUM_ENTRY(CallingConvention, ArmCall),
128     ENUM_ENTRY(CallingConvention, AM33Call),
129     ENUM_ENTRY(CallingConvention, TriCall),
130     ENUM_ENTRY(CallingConvention, SH5Call),
131     ENUM_ENTRY(CallingConvention, M32RCall),
132     ENUM_ENTRY(CallingConvention, ClrCall),
133     ENUM_ENTRY(CallingConvention, Inline),
134     ENUM_ENTRY(CallingConvention, NearVector),
135 };
136 
137 static const EnumEntry<uint8_t> FunctionOptionEnum[] = {
138     ENUM_ENTRY(FunctionOptions, CxxReturnUdt),
139     ENUM_ENTRY(FunctionOptions, Constructor),
140     ENUM_ENTRY(FunctionOptions, ConstructorWithVirtualBases),
141 };
142 
143 static const EnumEntry<uint16_t> LabelTypeEnum[] = {
144     ENUM_ENTRY(LabelType, Near), ENUM_ENTRY(LabelType, Far),
145 };
146 
147 #undef ENUM_ENTRY
148 
getLeafTypeName(TypeLeafKind LT)149 static StringRef getLeafTypeName(TypeLeafKind LT) {
150   switch (LT) {
151 #define TYPE_RECORD(ename, value, name)                                        \
152   case ename:                                                                  \
153     return #name;
154 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
155   default:
156     break;
157   }
158   return "UnknownLeaf";
159 }
160 
printTypeIndex(StringRef FieldName,TypeIndex TI) const161 void TypeDumpVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const {
162   codeview::printTypeIndex(*W, FieldName, TI, TpiTypes);
163 }
164 
printItemIndex(StringRef FieldName,TypeIndex TI) const165 void TypeDumpVisitor::printItemIndex(StringRef FieldName, TypeIndex TI) const {
166   codeview::printTypeIndex(*W, FieldName, TI, getSourceTypes());
167 }
168 
visitTypeBegin(CVType & Record)169 Error TypeDumpVisitor::visitTypeBegin(CVType &Record) {
170   return visitTypeBegin(Record, TypeIndex::fromArrayIndex(TpiTypes.size()));
171 }
172 
visitTypeBegin(CVType & Record,TypeIndex Index)173 Error TypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) {
174   W->startLine() << getLeafTypeName(Record.kind());
175   W->getOStream() << " (" << HexNumber(Index.getIndex()) << ")";
176   W->getOStream() << " {\n";
177   W->indent();
178   W->printEnum("TypeLeafKind", unsigned(Record.kind()),
179                makeArrayRef(LeafTypeNames));
180   return Error::success();
181 }
182 
visitTypeEnd(CVType & Record)183 Error TypeDumpVisitor::visitTypeEnd(CVType &Record) {
184   if (PrintRecordBytes)
185     W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.content()));
186 
187   W->unindent();
188   W->startLine() << "}\n";
189   return Error::success();
190 }
191 
visitMemberBegin(CVMemberRecord & Record)192 Error TypeDumpVisitor::visitMemberBegin(CVMemberRecord &Record) {
193   W->startLine() << getLeafTypeName(Record.Kind);
194   W->getOStream() << " {\n";
195   W->indent();
196   W->printEnum("TypeLeafKind", unsigned(Record.Kind),
197                makeArrayRef(LeafTypeNames));
198   return Error::success();
199 }
200 
visitMemberEnd(CVMemberRecord & Record)201 Error TypeDumpVisitor::visitMemberEnd(CVMemberRecord &Record) {
202   if (PrintRecordBytes)
203     W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data));
204 
205   W->unindent();
206   W->startLine() << "}\n";
207   return Error::success();
208 }
209 
visitKnownRecord(CVType & CVR,FieldListRecord & FieldList)210 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
211                                         FieldListRecord &FieldList) {
212   if (auto EC = codeview::visitMemberRecordStream(FieldList.Data, *this))
213     return EC;
214 
215   return Error::success();
216 }
217 
visitKnownRecord(CVType & CVR,StringIdRecord & String)218 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, StringIdRecord &String) {
219   printItemIndex("Id", String.getId());
220   W->printString("StringData", String.getString());
221   return Error::success();
222 }
223 
visitKnownRecord(CVType & CVR,ArgListRecord & Args)224 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
225   auto Indices = Args.getIndices();
226   uint32_t Size = Indices.size();
227   W->printNumber("NumArgs", Size);
228   ListScope Arguments(*W, "Arguments");
229   for (uint32_t I = 0; I < Size; ++I) {
230     printTypeIndex("ArgType", Indices[I]);
231   }
232   return Error::success();
233 }
234 
visitKnownRecord(CVType & CVR,StringListRecord & Strs)235 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, StringListRecord &Strs) {
236   auto Indices = Strs.getIndices();
237   uint32_t Size = Indices.size();
238   W->printNumber("NumStrings", Size);
239   ListScope Arguments(*W, "Strings");
240   for (uint32_t I = 0; I < Size; ++I) {
241     printItemIndex("String", Indices[I]);
242   }
243   return Error::success();
244 }
245 
visitKnownRecord(CVType & CVR,ClassRecord & Class)246 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
247   uint16_t Props = static_cast<uint16_t>(Class.getOptions());
248   W->printNumber("MemberCount", Class.getMemberCount());
249   W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
250   printTypeIndex("FieldList", Class.getFieldList());
251   printTypeIndex("DerivedFrom", Class.getDerivationList());
252   printTypeIndex("VShape", Class.getVTableShape());
253   W->printNumber("SizeOf", Class.getSize());
254   W->printString("Name", Class.getName());
255   if (Props & uint16_t(ClassOptions::HasUniqueName))
256     W->printString("LinkageName", Class.getUniqueName());
257   return Error::success();
258 }
259 
visitKnownRecord(CVType & CVR,UnionRecord & Union)260 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
261   uint16_t Props = static_cast<uint16_t>(Union.getOptions());
262   W->printNumber("MemberCount", Union.getMemberCount());
263   W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
264   printTypeIndex("FieldList", Union.getFieldList());
265   W->printNumber("SizeOf", Union.getSize());
266   W->printString("Name", Union.getName());
267   if (Props & uint16_t(ClassOptions::HasUniqueName))
268     W->printString("LinkageName", Union.getUniqueName());
269   return Error::success();
270 }
271 
visitKnownRecord(CVType & CVR,EnumRecord & Enum)272 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
273   uint16_t Props = static_cast<uint16_t>(Enum.getOptions());
274   W->printNumber("NumEnumerators", Enum.getMemberCount());
275   W->printFlags("Properties", uint16_t(Enum.getOptions()),
276                 makeArrayRef(ClassOptionNames));
277   printTypeIndex("UnderlyingType", Enum.getUnderlyingType());
278   printTypeIndex("FieldListType", Enum.getFieldList());
279   W->printString("Name", Enum.getName());
280   if (Props & uint16_t(ClassOptions::HasUniqueName))
281     W->printString("LinkageName", Enum.getUniqueName());
282   return Error::success();
283 }
284 
visitKnownRecord(CVType & CVR,ArrayRecord & AT)285 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
286   printTypeIndex("ElementType", AT.getElementType());
287   printTypeIndex("IndexType", AT.getIndexType());
288   W->printNumber("SizeOf", AT.getSize());
289   W->printString("Name", AT.getName());
290   return Error::success();
291 }
292 
visitKnownRecord(CVType & CVR,VFTableRecord & VFT)293 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
294   printTypeIndex("CompleteClass", VFT.getCompleteClass());
295   printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable());
296   W->printHex("VFPtrOffset", VFT.getVFPtrOffset());
297   W->printString("VFTableName", VFT.getName());
298   for (auto N : VFT.getMethodNames())
299     W->printString("MethodName", N);
300   return Error::success();
301 }
302 
visitKnownRecord(CVType & CVR,MemberFuncIdRecord & Id)303 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
304   printTypeIndex("ClassType", Id.getClassType());
305   printTypeIndex("FunctionType", Id.getFunctionType());
306   W->printString("Name", Id.getName());
307   return Error::success();
308 }
309 
visitKnownRecord(CVType & CVR,ProcedureRecord & Proc)310 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
311   printTypeIndex("ReturnType", Proc.getReturnType());
312   W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()),
313                makeArrayRef(CallingConventions));
314   W->printFlags("FunctionOptions", uint8_t(Proc.getOptions()),
315                 makeArrayRef(FunctionOptionEnum));
316   W->printNumber("NumParameters", Proc.getParameterCount());
317   printTypeIndex("ArgListType", Proc.getArgumentList());
318   return Error::success();
319 }
320 
visitKnownRecord(CVType & CVR,MemberFunctionRecord & MF)321 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, MemberFunctionRecord &MF) {
322   printTypeIndex("ReturnType", MF.getReturnType());
323   printTypeIndex("ClassType", MF.getClassType());
324   printTypeIndex("ThisType", MF.getThisType());
325   W->printEnum("CallingConvention", uint8_t(MF.getCallConv()),
326                makeArrayRef(CallingConventions));
327   W->printFlags("FunctionOptions", uint8_t(MF.getOptions()),
328                 makeArrayRef(FunctionOptionEnum));
329   W->printNumber("NumParameters", MF.getParameterCount());
330   printTypeIndex("ArgListType", MF.getArgumentList());
331   W->printNumber("ThisAdjustment", MF.getThisPointerAdjustment());
332   return Error::success();
333 }
334 
visitKnownRecord(CVType & CVR,MethodOverloadListRecord & MethodList)335 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
336                                         MethodOverloadListRecord &MethodList) {
337   for (auto &M : MethodList.getMethods()) {
338     ListScope S(*W, "Method");
339     printMemberAttributes(M.getAccess(), M.getMethodKind(), M.getOptions());
340     printTypeIndex("Type", M.getType());
341     if (M.isIntroducingVirtual())
342       W->printHex("VFTableOffset", M.getVFTableOffset());
343   }
344   return Error::success();
345 }
346 
visitKnownRecord(CVType & CVR,FuncIdRecord & Func)347 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
348   printItemIndex("ParentScope", Func.getParentScope());
349   printTypeIndex("FunctionType", Func.getFunctionType());
350   W->printString("Name", Func.getName());
351   return Error::success();
352 }
353 
visitKnownRecord(CVType & CVR,TypeServer2Record & TS)354 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
355   W->printString("Guid", formatv("{0}", TS.getGuid()).str());
356   W->printNumber("Age", TS.getAge());
357   W->printString("Name", TS.getName());
358   return Error::success();
359 }
360 
visitKnownRecord(CVType & CVR,PointerRecord & Ptr)361 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
362   printTypeIndex("PointeeType", Ptr.getReferentType());
363   W->printEnum("PtrType", unsigned(Ptr.getPointerKind()),
364                makeArrayRef(PtrKindNames));
365   W->printEnum("PtrMode", unsigned(Ptr.getMode()), makeArrayRef(PtrModeNames));
366 
367   W->printNumber("IsFlat", Ptr.isFlat());
368   W->printNumber("IsConst", Ptr.isConst());
369   W->printNumber("IsVolatile", Ptr.isVolatile());
370   W->printNumber("IsUnaligned", Ptr.isUnaligned());
371   W->printNumber("IsRestrict", Ptr.isRestrict());
372   W->printNumber("IsThisPtr&", Ptr.isLValueReferenceThisPtr());
373   W->printNumber("IsThisPtr&&", Ptr.isRValueReferenceThisPtr());
374   W->printNumber("SizeOf", Ptr.getSize());
375 
376   if (Ptr.isPointerToMember()) {
377     const MemberPointerInfo &MI = Ptr.getMemberInfo();
378 
379     printTypeIndex("ClassType", MI.getContainingType());
380     W->printEnum("Representation", uint16_t(MI.getRepresentation()),
381                  makeArrayRef(PtrMemberRepNames));
382   }
383 
384   return Error::success();
385 }
386 
visitKnownRecord(CVType & CVR,ModifierRecord & Mod)387 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
388   uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
389   printTypeIndex("ModifiedType", Mod.getModifiedType());
390   W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames));
391 
392   return Error::success();
393 }
394 
visitKnownRecord(CVType & CVR,BitFieldRecord & BitField)395 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BitFieldRecord &BitField) {
396   printTypeIndex("Type", BitField.getType());
397   W->printNumber("BitSize", BitField.getBitSize());
398   W->printNumber("BitOffset", BitField.getBitOffset());
399   return Error::success();
400 }
401 
visitKnownRecord(CVType & CVR,VFTableShapeRecord & Shape)402 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
403                                         VFTableShapeRecord &Shape) {
404   W->printNumber("VFEntryCount", Shape.getEntryCount());
405   return Error::success();
406 }
407 
visitKnownRecord(CVType & CVR,UdtSourceLineRecord & Line)408 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
409                                         UdtSourceLineRecord &Line) {
410   printTypeIndex("UDT", Line.getUDT());
411   printItemIndex("SourceFile", Line.getSourceFile());
412   W->printNumber("LineNumber", Line.getLineNumber());
413   return Error::success();
414 }
415 
visitKnownRecord(CVType & CVR,UdtModSourceLineRecord & Line)416 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
417                                         UdtModSourceLineRecord &Line) {
418   printTypeIndex("UDT", Line.getUDT());
419   printItemIndex("SourceFile", Line.getSourceFile());
420   W->printNumber("LineNumber", Line.getLineNumber());
421   W->printNumber("Module", Line.getModule());
422   return Error::success();
423 }
424 
visitKnownRecord(CVType & CVR,BuildInfoRecord & Args)425 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &Args) {
426   W->printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size()));
427 
428   ListScope Arguments(*W, "Arguments");
429   for (auto Arg : Args.getArgs()) {
430     printItemIndex("ArgType", Arg);
431   }
432   return Error::success();
433 }
434 
printMemberAttributes(MemberAttributes Attrs)435 void TypeDumpVisitor::printMemberAttributes(MemberAttributes Attrs) {
436   return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(),
437                                Attrs.getFlags());
438 }
439 
printMemberAttributes(MemberAccess Access,MethodKind Kind,MethodOptions Options)440 void TypeDumpVisitor::printMemberAttributes(MemberAccess Access,
441                                             MethodKind Kind,
442                                             MethodOptions Options) {
443   W->printEnum("AccessSpecifier", uint8_t(Access),
444                makeArrayRef(MemberAccessNames));
445   // Data members will be vanilla. Don't try to print a method kind for them.
446   if (Kind != MethodKind::Vanilla)
447     W->printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames));
448   if (Options != MethodOptions::None) {
449     W->printFlags("MethodOptions", unsigned(Options),
450                   makeArrayRef(MethodOptionNames));
451   }
452 }
453 
visitUnknownMember(CVMemberRecord & Record)454 Error TypeDumpVisitor::visitUnknownMember(CVMemberRecord &Record) {
455   W->printHex("UnknownMember", unsigned(Record.Kind));
456   return Error::success();
457 }
458 
visitUnknownType(CVType & Record)459 Error TypeDumpVisitor::visitUnknownType(CVType &Record) {
460   W->printEnum("Kind", uint16_t(Record.kind()), makeArrayRef(LeafTypeNames));
461   W->printNumber("Length", uint32_t(Record.content().size()));
462   return Error::success();
463 }
464 
visitKnownMember(CVMemberRecord & CVR,NestedTypeRecord & Nested)465 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
466                                         NestedTypeRecord &Nested) {
467   printTypeIndex("Type", Nested.getNestedType());
468   W->printString("Name", Nested.getName());
469   return Error::success();
470 }
471 
visitKnownMember(CVMemberRecord & CVR,OneMethodRecord & Method)472 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
473                                         OneMethodRecord &Method) {
474   MethodKind K = Method.getMethodKind();
475   printMemberAttributes(Method.getAccess(), K, Method.getOptions());
476   printTypeIndex("Type", Method.getType());
477   // If virtual, then read the vftable offset.
478   if (Method.isIntroducingVirtual())
479     W->printHex("VFTableOffset", Method.getVFTableOffset());
480   W->printString("Name", Method.getName());
481   return Error::success();
482 }
483 
visitKnownMember(CVMemberRecord & CVR,OverloadedMethodRecord & Method)484 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
485                                         OverloadedMethodRecord &Method) {
486   W->printHex("MethodCount", Method.getNumOverloads());
487   printTypeIndex("MethodListIndex", Method.getMethodList());
488   W->printString("Name", Method.getName());
489   return Error::success();
490 }
491 
visitKnownMember(CVMemberRecord & CVR,DataMemberRecord & Field)492 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
493                                         DataMemberRecord &Field) {
494   printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
495                         MethodOptions::None);
496   printTypeIndex("Type", Field.getType());
497   W->printHex("FieldOffset", Field.getFieldOffset());
498   W->printString("Name", Field.getName());
499   return Error::success();
500 }
501 
visitKnownMember(CVMemberRecord & CVR,StaticDataMemberRecord & Field)502 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
503                                         StaticDataMemberRecord &Field) {
504   printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
505                         MethodOptions::None);
506   printTypeIndex("Type", Field.getType());
507   W->printString("Name", Field.getName());
508   return Error::success();
509 }
510 
visitKnownMember(CVMemberRecord & CVR,VFPtrRecord & VFTable)511 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
512                                         VFPtrRecord &VFTable) {
513   printTypeIndex("Type", VFTable.getType());
514   return Error::success();
515 }
516 
visitKnownMember(CVMemberRecord & CVR,EnumeratorRecord & Enum)517 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
518                                         EnumeratorRecord &Enum) {
519   printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
520                         MethodOptions::None);
521   W->printNumber("EnumValue", Enum.getValue());
522   W->printString("Name", Enum.getName());
523   return Error::success();
524 }
525 
visitKnownMember(CVMemberRecord & CVR,BaseClassRecord & Base)526 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
527                                         BaseClassRecord &Base) {
528   printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
529                         MethodOptions::None);
530   printTypeIndex("BaseType", Base.getBaseType());
531   W->printHex("BaseOffset", Base.getBaseOffset());
532   return Error::success();
533 }
534 
visitKnownMember(CVMemberRecord & CVR,VirtualBaseClassRecord & Base)535 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
536                                         VirtualBaseClassRecord &Base) {
537   printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
538                         MethodOptions::None);
539   printTypeIndex("BaseType", Base.getBaseType());
540   printTypeIndex("VBPtrType", Base.getVBPtrType());
541   W->printHex("VBPtrOffset", Base.getVBPtrOffset());
542   W->printHex("VBTableIndex", Base.getVTableIndex());
543   return Error::success();
544 }
545 
visitKnownMember(CVMemberRecord & CVR,ListContinuationRecord & Cont)546 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
547                                         ListContinuationRecord &Cont) {
548   printTypeIndex("ContinuationIndex", Cont.getContinuationIndex());
549   return Error::success();
550 }
551 
visitKnownRecord(CVType & CVR,LabelRecord & LR)552 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, LabelRecord &LR) {
553   W->printEnum("Mode", uint16_t(LR.Mode), makeArrayRef(LabelTypeEnum));
554   return Error::success();
555 }
556 
visitKnownRecord(CVType & CVR,PrecompRecord & Precomp)557 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
558                                         PrecompRecord &Precomp) {
559   W->printHex("StartIndex", Precomp.getStartTypeIndex());
560   W->printHex("Count", Precomp.getTypesCount());
561   W->printHex("Signature", Precomp.getSignature());
562   W->printString("PrecompFile", Precomp.getPrecompFilePath());
563   return Error::success();
564 }
565 
visitKnownRecord(CVType & CVR,EndPrecompRecord & EndPrecomp)566 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
567                                         EndPrecompRecord &EndPrecomp) {
568   W->printHex("Signature", EndPrecomp.getSignature());
569   return Error::success();
570 }
571