[RISCV] Eliminate dead li after emitting VSETVLIs (#65934)
[llvm-project.git] / llvm / tools / llvm-pdbutil / MinimalTypeDumper.cpp
blobaaa430a9572e800be6105b758157c73b30ec4239
1 //===- MinimalTypeDumper.cpp ---------------------------------- *- 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 //===----------------------------------------------------------------------===//
9 #include "MinimalTypeDumper.h"
11 #include "TypeReferenceTracker.h"
13 #include "llvm-pdbutil.h"
14 #include "llvm/ADT/StringExtras.h"
15 #include "llvm/DebugInfo/CodeView/CVRecord.h"
16 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
17 #include "llvm/DebugInfo/CodeView/CodeView.h"
18 #include "llvm/DebugInfo/CodeView/Formatters.h"
19 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
20 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
21 #include "llvm/DebugInfo/PDB/Native/FormatUtil.h"
22 #include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
23 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
24 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
25 #include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
26 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
27 #include "llvm/Object/COFF.h"
28 #include "llvm/Support/FormatVariadic.h"
29 #include "llvm/Support/MathExtras.h"
31 using namespace llvm;
32 using namespace llvm::codeview;
33 using namespace llvm::pdb;
35 static std::string formatClassOptions(uint32_t IndentLevel,
36 ClassOptions Options, TpiStream *Stream,
37 TypeIndex CurrentTypeIndex) {
38 std::vector<std::string> Opts;
40 if (Stream && Stream->supportsTypeLookup() &&
41 !opts::dump::DontResolveForwardRefs &&
42 ((Options & ClassOptions::ForwardReference) != ClassOptions::None)) {
43 // If we're able to resolve forward references, do that.
44 Expected<TypeIndex> ETI =
45 Stream->findFullDeclForForwardRef(CurrentTypeIndex);
46 if (!ETI) {
47 consumeError(ETI.takeError());
48 PUSH_FLAG(ClassOptions, ForwardReference, Options, "forward ref (??\?)");
49 } else {
50 const char *Direction = (*ETI == CurrentTypeIndex)
51 ? "="
52 : ((*ETI < CurrentTypeIndex) ? "<-" : "->");
53 std::string Formatted =
54 formatv("forward ref ({0} {1})", Direction, *ETI).str();
55 PUSH_FLAG(ClassOptions, ForwardReference, Options, std::move(Formatted));
57 } else {
58 PUSH_FLAG(ClassOptions, ForwardReference, Options, "forward ref");
61 PUSH_FLAG(ClassOptions, HasConstructorOrDestructor, Options,
62 "has ctor / dtor");
63 PUSH_FLAG(ClassOptions, ContainsNestedClass, Options,
64 "contains nested class");
65 PUSH_FLAG(ClassOptions, HasConversionOperator, Options,
66 "conversion operator");
67 PUSH_FLAG(ClassOptions, HasUniqueName, Options, "has unique name");
68 PUSH_FLAG(ClassOptions, Intrinsic, Options, "intrin");
69 PUSH_FLAG(ClassOptions, Nested, Options, "is nested");
70 PUSH_FLAG(ClassOptions, HasOverloadedOperator, Options,
71 "overloaded operator");
72 PUSH_FLAG(ClassOptions, HasOverloadedAssignmentOperator, Options,
73 "overloaded operator=");
74 PUSH_FLAG(ClassOptions, Packed, Options, "packed");
75 PUSH_FLAG(ClassOptions, Scoped, Options, "scoped");
76 PUSH_FLAG(ClassOptions, Sealed, Options, "sealed");
78 return typesetItemList(Opts, 4, IndentLevel, " | ");
81 static std::string pointerOptions(PointerOptions Options) {
82 std::vector<std::string> Opts;
83 PUSH_FLAG(PointerOptions, Flat32, Options, "flat32");
84 PUSH_FLAG(PointerOptions, Volatile, Options, "volatile");
85 PUSH_FLAG(PointerOptions, Const, Options, "const");
86 PUSH_FLAG(PointerOptions, Unaligned, Options, "unaligned");
87 PUSH_FLAG(PointerOptions, Restrict, Options, "restrict");
88 PUSH_FLAG(PointerOptions, WinRTSmartPointer, Options, "winrt");
89 if (Opts.empty())
90 return "None";
91 return join(Opts, " | ");
94 static std::string modifierOptions(ModifierOptions Options) {
95 std::vector<std::string> Opts;
96 PUSH_FLAG(ModifierOptions, Const, Options, "const");
97 PUSH_FLAG(ModifierOptions, Volatile, Options, "volatile");
98 PUSH_FLAG(ModifierOptions, Unaligned, Options, "unaligned");
99 if (Opts.empty())
100 return "None";
101 return join(Opts, " | ");
104 static std::string formatCallingConvention(CallingConvention Convention) {
105 switch (Convention) {
106 RETURN_CASE(CallingConvention, AlphaCall, "alphacall");
107 RETURN_CASE(CallingConvention, AM33Call, "am33call");
108 RETURN_CASE(CallingConvention, ArmCall, "armcall");
109 RETURN_CASE(CallingConvention, ClrCall, "clrcall");
110 RETURN_CASE(CallingConvention, FarC, "far cdecl");
111 RETURN_CASE(CallingConvention, FarFast, "far fastcall");
112 RETURN_CASE(CallingConvention, FarPascal, "far pascal");
113 RETURN_CASE(CallingConvention, FarStdCall, "far stdcall");
114 RETURN_CASE(CallingConvention, FarSysCall, "far syscall");
115 RETURN_CASE(CallingConvention, Generic, "generic");
116 RETURN_CASE(CallingConvention, Inline, "inline");
117 RETURN_CASE(CallingConvention, M32RCall, "m32rcall");
118 RETURN_CASE(CallingConvention, MipsCall, "mipscall");
119 RETURN_CASE(CallingConvention, NearC, "cdecl");
120 RETURN_CASE(CallingConvention, NearFast, "fastcall");
121 RETURN_CASE(CallingConvention, NearPascal, "pascal");
122 RETURN_CASE(CallingConvention, NearStdCall, "stdcall");
123 RETURN_CASE(CallingConvention, NearSysCall, "near syscall");
124 RETURN_CASE(CallingConvention, NearVector, "vectorcall");
125 RETURN_CASE(CallingConvention, PpcCall, "ppccall");
126 RETURN_CASE(CallingConvention, SHCall, "shcall");
127 RETURN_CASE(CallingConvention, SH5Call, "sh5call");
128 RETURN_CASE(CallingConvention, ThisCall, "thiscall");
129 RETURN_CASE(CallingConvention, TriCall, "tricall");
131 return formatUnknownEnum(Convention);
134 static std::string formatPointerMode(PointerMode Mode) {
135 switch (Mode) {
136 RETURN_CASE(PointerMode, LValueReference, "ref");
137 RETURN_CASE(PointerMode, Pointer, "pointer");
138 RETURN_CASE(PointerMode, PointerToDataMember, "data member pointer");
139 RETURN_CASE(PointerMode, PointerToMemberFunction, "member fn pointer");
140 RETURN_CASE(PointerMode, RValueReference, "rvalue ref");
142 return formatUnknownEnum(Mode);
145 static std::string memberAccess(MemberAccess Access) {
146 switch (Access) {
147 RETURN_CASE(MemberAccess, None, "");
148 RETURN_CASE(MemberAccess, Private, "private");
149 RETURN_CASE(MemberAccess, Protected, "protected");
150 RETURN_CASE(MemberAccess, Public, "public");
152 return formatUnknownEnum(Access);
155 static std::string methodKind(MethodKind Kind) {
156 switch (Kind) {
157 RETURN_CASE(MethodKind, Vanilla, "");
158 RETURN_CASE(MethodKind, Virtual, "virtual");
159 RETURN_CASE(MethodKind, Static, "static");
160 RETURN_CASE(MethodKind, Friend, "friend");
161 RETURN_CASE(MethodKind, IntroducingVirtual, "intro virtual");
162 RETURN_CASE(MethodKind, PureVirtual, "pure virtual");
163 RETURN_CASE(MethodKind, PureIntroducingVirtual, "pure intro virtual");
165 return formatUnknownEnum(Kind);
168 static std::string pointerKind(PointerKind Kind) {
169 switch (Kind) {
170 RETURN_CASE(PointerKind, Near16, "ptr16");
171 RETURN_CASE(PointerKind, Far16, "far ptr16");
172 RETURN_CASE(PointerKind, Huge16, "huge ptr16");
173 RETURN_CASE(PointerKind, BasedOnSegment, "segment based");
174 RETURN_CASE(PointerKind, BasedOnValue, "value based");
175 RETURN_CASE(PointerKind, BasedOnSegmentValue, "segment value based");
176 RETURN_CASE(PointerKind, BasedOnAddress, "address based");
177 RETURN_CASE(PointerKind, BasedOnSegmentAddress, "segment address based");
178 RETURN_CASE(PointerKind, BasedOnType, "type based");
179 RETURN_CASE(PointerKind, BasedOnSelf, "self based");
180 RETURN_CASE(PointerKind, Near32, "ptr32");
181 RETURN_CASE(PointerKind, Far32, "far ptr32");
182 RETURN_CASE(PointerKind, Near64, "ptr64");
184 return formatUnknownEnum(Kind);
187 static std::string memberAttributes(const MemberAttributes &Attrs) {
188 std::vector<std::string> Opts;
189 std::string Access = memberAccess(Attrs.getAccess());
190 std::string Kind = methodKind(Attrs.getMethodKind());
191 if (!Access.empty())
192 Opts.push_back(Access);
193 if (!Kind.empty())
194 Opts.push_back(Kind);
195 MethodOptions Flags = Attrs.getFlags();
196 PUSH_FLAG(MethodOptions, Pseudo, Flags, "pseudo");
197 PUSH_FLAG(MethodOptions, NoInherit, Flags, "noinherit");
198 PUSH_FLAG(MethodOptions, NoConstruct, Flags, "noconstruct");
199 PUSH_FLAG(MethodOptions, CompilerGenerated, Flags, "compiler-generated");
200 PUSH_FLAG(MethodOptions, Sealed, Flags, "sealed");
201 return join(Opts, " ");
204 static std::string formatPointerAttrs(const PointerRecord &Record) {
205 PointerMode Mode = Record.getMode();
206 PointerOptions Opts = Record.getOptions();
207 PointerKind Kind = Record.getPointerKind();
208 return std::string(formatv("mode = {0}, opts = {1}, kind = {2}",
209 formatPointerMode(Mode), pointerOptions(Opts),
210 pointerKind(Kind)));
213 static std::string formatFunctionOptions(FunctionOptions Options) {
214 std::vector<std::string> Opts;
216 PUSH_FLAG(FunctionOptions, CxxReturnUdt, Options, "returns cxx udt");
217 PUSH_FLAG(FunctionOptions, ConstructorWithVirtualBases, Options,
218 "constructor with virtual bases");
219 PUSH_FLAG(FunctionOptions, Constructor, Options, "constructor");
220 if (Opts.empty())
221 return "None";
222 return join(Opts, " | ");
225 Error MinimalTypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) {
226 CurrentTypeIndex = Index;
227 // formatLine puts the newline at the beginning, so we use formatLine here
228 // to start a new line, and then individual visit methods use format to
229 // append to the existing line.
230 P.formatLine("{0} | {1} [size = {2}",
231 fmt_align(Index, AlignStyle::Right, Width),
232 formatTypeLeafKind(Record.kind()), Record.length());
233 if (Hashes) {
234 std::string H;
235 if (Index.toArrayIndex() >= HashValues.size()) {
236 H = "(not present)";
237 } else {
238 uint32_t Hash = HashValues[Index.toArrayIndex()];
239 Expected<uint32_t> MaybeHash = hashTypeRecord(Record);
240 if (!MaybeHash)
241 return MaybeHash.takeError();
242 uint32_t OurHash = *MaybeHash;
243 OurHash %= NumHashBuckets;
244 if (Hash == OurHash)
245 H = "0x" + utohexstr(Hash);
246 else
247 H = "0x" + utohexstr(Hash) + ", our hash = 0x" + utohexstr(OurHash);
249 P.format(", hash = {0}", H);
251 if (RefTracker) {
252 if (RefTracker->isTypeReferenced(Index))
253 P.format(", referenced");
254 else
255 P.format(", unreferenced");
257 P.format("]");
258 P.Indent(Width + 3);
259 return Error::success();
262 Error MinimalTypeDumpVisitor::visitTypeEnd(CVType &Record) {
263 P.Unindent(Width + 3);
264 if (RecordBytes) {
265 AutoIndent Indent(P, 9);
266 P.formatBinary("Bytes", Record.RecordData, 0);
268 return Error::success();
271 Error MinimalTypeDumpVisitor::visitMemberBegin(CVMemberRecord &Record) {
272 P.formatLine("- {0}", formatTypeLeafKind(Record.Kind));
273 return Error::success();
276 Error MinimalTypeDumpVisitor::visitMemberEnd(CVMemberRecord &Record) {
277 if (RecordBytes) {
278 AutoIndent Indent(P, 2);
279 P.formatBinary("Bytes", Record.Data, 0);
281 return Error::success();
284 StringRef MinimalTypeDumpVisitor::getTypeName(TypeIndex TI) const {
285 if (TI.isNoneType())
286 return "";
287 return Types.getTypeName(TI);
290 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
291 FieldListRecord &FieldList) {
292 if (auto EC = codeview::visitMemberRecordStream(FieldList.Data, *this))
293 return EC;
295 return Error::success();
298 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
299 StringIdRecord &String) {
300 P.format(" ID: {0}, String: {1}", String.getId(), String.getString());
301 return Error::success();
304 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
305 ArgListRecord &Args) {
306 auto Indices = Args.getIndices();
307 if (Indices.empty())
308 return Error::success();
310 auto Max = std::max_element(Indices.begin(), Indices.end());
311 uint32_t W = NumDigits(Max->getIndex()) + 2;
313 for (auto I : Indices)
314 P.formatLine("{0}: `{1}`", fmt_align(I, AlignStyle::Right, W),
315 getTypeName(I));
316 return Error::success();
319 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
320 StringListRecord &Strings) {
321 auto Indices = Strings.getIndices();
322 if (Indices.empty())
323 return Error::success();
325 auto Max = std::max_element(Indices.begin(), Indices.end());
326 uint32_t W = NumDigits(Max->getIndex()) + 2;
328 for (auto I : Indices)
329 P.formatLine("{0}: `{1}`", fmt_align(I, AlignStyle::Right, W),
330 getTypeName(I));
331 return Error::success();
334 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
335 ClassRecord &Class) {
336 P.format(" `{0}`", Class.Name);
337 if (Class.hasUniqueName())
338 P.formatLine("unique name: `{0}`", Class.UniqueName);
339 P.formatLine("vtable: {0}, base list: {1}, field list: {2}",
340 Class.VTableShape, Class.DerivationList, Class.FieldList);
341 P.formatLine("options: {0}, sizeof {1}",
342 formatClassOptions(P.getIndentLevel(), Class.Options, Stream,
343 CurrentTypeIndex),
344 Class.Size);
345 return Error::success();
348 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
349 UnionRecord &Union) {
350 P.format(" `{0}`", Union.Name);
351 if (Union.hasUniqueName())
352 P.formatLine("unique name: `{0}`", Union.UniqueName);
353 P.formatLine("field list: {0}", Union.FieldList);
354 P.formatLine("options: {0}, sizeof {1}",
355 formatClassOptions(P.getIndentLevel(), Union.Options, Stream,
356 CurrentTypeIndex),
357 Union.Size);
358 return Error::success();
361 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
362 P.format(" `{0}`", Enum.Name);
363 if (Enum.hasUniqueName())
364 P.formatLine("unique name: `{0}`", Enum.UniqueName);
365 P.formatLine("field list: {0}, underlying type: {1}", Enum.FieldList,
366 Enum.UnderlyingType);
367 P.formatLine("options: {0}",
368 formatClassOptions(P.getIndentLevel(), Enum.Options, Stream,
369 CurrentTypeIndex));
370 return Error::success();
373 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
374 if (AT.Name.empty()) {
375 P.formatLine("size: {0}, index type: {1}, element type: {2}", AT.Size,
376 AT.IndexType, AT.ElementType);
377 } else {
378 P.formatLine("name: {0}, size: {1}, index type: {2}, element type: {3}",
379 AT.Name, AT.Size, AT.IndexType, AT.ElementType);
381 return Error::success();
384 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
385 VFTableRecord &VFT) {
386 P.formatLine("offset: {0}, complete class: {1}, overridden vftable: {2}",
387 VFT.VFPtrOffset, VFT.CompleteClass, VFT.OverriddenVFTable);
388 P.formatLine("method names: ");
389 if (!VFT.MethodNames.empty()) {
390 std::string Sep =
391 formatv("\n{0}",
392 fmt_repeat(' ', P.getIndentLevel() + strlen("method names: ")))
393 .str();
394 P.print(join(VFT.MethodNames, Sep));
396 return Error::success();
399 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
400 MemberFuncIdRecord &Id) {
401 P.formatLine("name = {0}, type = {1}, class type = {2}", Id.Name,
402 Id.FunctionType, Id.ClassType);
403 return Error::success();
406 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
407 ProcedureRecord &Proc) {
408 P.formatLine("return type = {0}, # args = {1}, param list = {2}",
409 Proc.ReturnType, Proc.ParameterCount, Proc.ArgumentList);
410 P.formatLine("calling conv = {0}, options = {1}",
411 formatCallingConvention(Proc.CallConv),
412 formatFunctionOptions(Proc.Options));
413 return Error::success();
416 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
417 MemberFunctionRecord &MF) {
418 P.formatLine("return type = {0}, # args = {1}, param list = {2}",
419 MF.ReturnType, MF.ParameterCount, MF.ArgumentList);
420 P.formatLine("class type = {0}, this type = {1}, this adjust = {2}",
421 MF.ClassType, MF.ThisType, MF.ThisPointerAdjustment);
422 P.formatLine("calling conv = {0}, options = {1}",
423 formatCallingConvention(MF.CallConv),
424 formatFunctionOptions(MF.Options));
425 return Error::success();
428 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
429 FuncIdRecord &Func) {
430 P.formatLine("name = {0}, type = {1}, parent scope = {2}", Func.Name,
431 Func.FunctionType, Func.ParentScope);
432 return Error::success();
435 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
436 TypeServer2Record &TS) {
437 P.formatLine("name = {0}, age = {1}, guid = {2}", TS.Name, TS.Age, TS.Guid);
438 return Error::success();
441 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
442 PointerRecord &Ptr) {
443 P.formatLine("referent = {0}, {1}", Ptr.ReferentType,
444 formatPointerAttrs(Ptr));
445 return Error::success();
448 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
449 ModifierRecord &Mod) {
450 P.formatLine("referent = {0}, modifiers = {1}", Mod.ModifiedType,
451 modifierOptions(Mod.Modifiers));
452 return Error::success();
455 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
456 VFTableShapeRecord &Shape) {
457 return Error::success();
460 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
461 UdtModSourceLineRecord &U) {
462 P.formatLine("udt = {0}, mod = {1}, file = {2}, line = {3}", U.UDT, U.Module,
463 U.SourceFile.getIndex(), U.LineNumber);
464 return Error::success();
467 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
468 UdtSourceLineRecord &U) {
469 P.formatLine("udt = {0}, file = {1}, line = {2}", U.UDT,
470 U.SourceFile.getIndex(), U.LineNumber);
471 return Error::success();
474 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
475 BitFieldRecord &BF) {
476 P.formatLine("type = {0}, bit offset = {1}, # bits = {2}", BF.Type,
477 BF.BitOffset, BF.BitSize);
478 return Error::success();
481 Error MinimalTypeDumpVisitor::visitKnownRecord(
482 CVType &CVR, MethodOverloadListRecord &Overloads) {
483 for (auto &M : Overloads.Methods)
484 P.formatLine("- Method [type = {0}, vftable offset = {1}, attrs = {2}]",
485 M.Type, M.VFTableOffset, memberAttributes(M.Attrs));
486 return Error::success();
489 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
490 BuildInfoRecord &BI) {
491 auto Indices = BI.ArgIndices;
492 if (Indices.empty())
493 return Error::success();
495 auto Max = std::max_element(Indices.begin(), Indices.end());
496 uint32_t W = NumDigits(Max->getIndex()) + 2;
498 for (auto I : Indices)
499 P.formatLine("{0}: `{1}`", fmt_align(I, AlignStyle::Right, W),
500 getTypeName(I));
501 return Error::success();
504 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, LabelRecord &R) {
505 std::string Type = (R.Mode == LabelType::Far) ? "far" : "near";
506 P.format(" type = {0}", Type);
507 return Error::success();
510 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
511 PrecompRecord &Precomp) {
512 P.format(" start index = {0:X+}, types count = {1:X+}, signature = {2:X+},"
513 " precomp path = {3}",
514 Precomp.StartTypeIndex, Precomp.TypesCount, Precomp.Signature,
515 Precomp.PrecompFilePath);
516 return Error::success();
519 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
520 EndPrecompRecord &EP) {
521 P.format(" signature = {0:X+}", EP.Signature);
522 return Error::success();
525 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
526 NestedTypeRecord &Nested) {
527 P.format(" [name = `{0}`, parent = {1}]", Nested.Name, Nested.Type);
528 return Error::success();
531 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
532 OneMethodRecord &Method) {
533 P.format(" [name = `{0}`]", Method.Name);
534 AutoIndent Indent(P);
535 P.formatLine("type = {0}, vftable offset = {1}, attrs = {2}", Method.Type,
536 Method.VFTableOffset, memberAttributes(Method.Attrs));
537 return Error::success();
540 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
541 OverloadedMethodRecord &Method) {
542 P.format(" [name = `{0}`, # overloads = {1}, overload list = {2}]",
543 Method.Name, Method.NumOverloads, Method.MethodList);
544 return Error::success();
547 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
548 DataMemberRecord &Field) {
549 P.format(" [name = `{0}`, Type = {1}, offset = {2}, attrs = {3}]", Field.Name,
550 Field.Type, Field.FieldOffset, memberAttributes(Field.Attrs));
551 return Error::success();
554 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
555 StaticDataMemberRecord &Field) {
556 P.format(" [name = `{0}`, type = {1}, attrs = {2}]", Field.Name, Field.Type,
557 memberAttributes(Field.Attrs));
558 return Error::success();
561 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
562 EnumeratorRecord &Enum) {
563 P.format(" [{0} = {1}]", Enum.Name,
564 toString(Enum.Value, 10, Enum.Value.isSigned()));
565 return Error::success();
568 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
569 BaseClassRecord &Base) {
570 AutoIndent Indent(P);
571 P.formatLine("type = {0}, offset = {1}, attrs = {2}", Base.Type, Base.Offset,
572 memberAttributes(Base.Attrs));
573 return Error::success();
576 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
577 VirtualBaseClassRecord &Base) {
578 AutoIndent Indent(P);
579 P.formatLine(
580 "base = {0}, vbptr = {1}, vbptr offset = {2}, vtable index = {3}",
581 Base.BaseType, Base.VBPtrType, Base.VBPtrOffset, Base.VTableIndex);
582 P.formatLine("attrs = {0}", memberAttributes(Base.Attrs));
583 return Error::success();
586 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
587 ListContinuationRecord &Cont) {
588 P.format(" continuation = {0}", Cont.ContinuationIndex);
589 return Error::success();
592 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
593 VFPtrRecord &VFP) {
594 P.format(" type = {0}", VFP.Type);
595 return Error::success();