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