llvm.org GIT mirror llvm / bc755e2
Fix line endings (CR/LF -> LF) introduced by rL329613 reviewer: zturner git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@329646 91177308-0d34-0410-b5e6-96231b3b80d8 Alexandre Ganea 1 year, 5 months ago
7 changed file(s) with 4298 addition(s) and 4298 deletion(s). Raw diff Collapse all Expand all
None //===- TypeRecord.h ---------------------------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H
10 #define LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H
11
12 #include "llvm/ADT/APSInt.h"
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/Optional.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/iterator_range.h"
18 #include "llvm/DebugInfo/CodeView/CVRecord.h"
19 #include "llvm/DebugInfo/CodeView/CodeView.h"
20 #include "llvm/DebugInfo/CodeView/GUID.h"
21 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
22 #include "llvm/Support/BinaryStreamArray.h"
23 #include "llvm/Support/Endian.h"
24 #include
25 #include
26 #include
27
28 namespace llvm {
29 namespace codeview {
30
31 using support::little32_t;
32 using support::ulittle16_t;
33 using support::ulittle32_t;
34
35 using CVType = CVRecord;
36 using RemappedType = RemappedRecord;
37
38 struct CVMemberRecord {
39 TypeLeafKind Kind;
40 ArrayRef Data;
41 };
42 using CVTypeArray = VarStreamArray;
43 using CVTypeRange = iterator_range;
44
45 /// Equvalent to CV_fldattr_t in cvinfo.h.
46 struct MemberAttributes {
47 uint16_t Attrs = 0;
48
49 enum {
50 MethodKindShift = 2,
51 };
52
53 MemberAttributes() = default;
54
55 explicit MemberAttributes(MemberAccess Access)
56 : Attrs(static_cast(Access)) {}
57
58 MemberAttributes(MemberAccess Access, MethodKind Kind, MethodOptions Flags) {
59 Attrs = static_cast(Access);
60 Attrs |= (static_cast(Kind) << MethodKindShift);
61 Attrs |= static_cast(Flags);
62 }
63
64 /// Get the access specifier. Valid for any kind of member.
65 MemberAccess getAccess() const {
66 return MemberAccess(unsigned(Attrs) & unsigned(MethodOptions::AccessMask));
67 }
68
69 /// Indicates if a method is defined with friend, virtual, static, etc.
70 MethodKind getMethodKind() const {
71 return MethodKind(
72 (unsigned(Attrs) & unsigned(MethodOptions::MethodKindMask)) >>
73 MethodKindShift);
74 }
75
76 /// Get the flags that are not included in access control or method
77 /// properties.
78 MethodOptions getFlags() const {
79 return MethodOptions(
80 unsigned(Attrs) &
81 ~unsigned(MethodOptions::AccessMask | MethodOptions::MethodKindMask));
82 }
83
84 /// Is this method virtual.
85 bool isVirtual() const {
86 auto MP = getMethodKind();
87 return MP != MethodKind::Vanilla && MP != MethodKind::Friend &&
88 MP != MethodKind::Static;
89 }
90
91 /// Does this member introduce a new virtual method.
92 bool isIntroducedVirtual() const {
93 auto MP = getMethodKind();
94 return MP == MethodKind::IntroducingVirtual ||
95 MP == MethodKind::PureIntroducingVirtual;
96 }
97 };
98
99 // Does not correspond to any tag, this is the tail of an LF_POINTER record
100 // if it represents a member pointer.
101 class MemberPointerInfo {
102 public:
103 MemberPointerInfo() = default;
104
105 MemberPointerInfo(TypeIndex ContainingType,
106 PointerToMemberRepresentation Representation)
107 : ContainingType(ContainingType), Representation(Representation) {}
108
109 TypeIndex getContainingType() const { return ContainingType; }
110 PointerToMemberRepresentation getRepresentation() const {
111 return Representation;
112 }
113
114 TypeIndex ContainingType;
115 PointerToMemberRepresentation Representation;
116 };
117
118 class TypeRecord {
119 protected:
120 TypeRecord() = default;
121 explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {}
122
123 public:
124 TypeRecordKind getKind() const { return Kind; }
125
126 TypeRecordKind Kind;
127 };
128
129 // LF_MODIFIER
130 class ModifierRecord : public TypeRecord {
131 public:
132 ModifierRecord() = default;
133 explicit ModifierRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
134 ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers)
135 : TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType),
136 Modifiers(Modifiers) {}
137
138 TypeIndex getModifiedType() const { return ModifiedType; }
139 ModifierOptions getModifiers() const { return Modifiers; }
140
141 TypeIndex ModifiedType;
142 ModifierOptions Modifiers;
143 };
144
145 // LF_PROCEDURE
146 class ProcedureRecord : public TypeRecord {
147 public:
148 ProcedureRecord() = default;
149 explicit ProcedureRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
150 ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv,
151 FunctionOptions Options, uint16_t ParameterCount,
152 TypeIndex ArgumentList)
153 : TypeRecord(TypeRecordKind::Procedure), ReturnType(ReturnType),
154 CallConv(CallConv), Options(Options), ParameterCount(ParameterCount),
155 ArgumentList(ArgumentList) {}
156
157 TypeIndex getReturnType() const { return ReturnType; }
158 CallingConvention getCallConv() const { return CallConv; }
159 FunctionOptions getOptions() const { return Options; }
160 uint16_t getParameterCount() const { return ParameterCount; }
161 TypeIndex getArgumentList() const { return ArgumentList; }
162
163 TypeIndex ReturnType;
164 CallingConvention CallConv;
165 FunctionOptions Options;
166 uint16_t ParameterCount;
167 TypeIndex ArgumentList;
168 };
169
170 // LF_MFUNCTION
171 class MemberFunctionRecord : public TypeRecord {
172 public:
173 MemberFunctionRecord() = default;
174 explicit MemberFunctionRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
175
176 MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType,
177 TypeIndex ThisType, CallingConvention CallConv,
178 FunctionOptions Options, uint16_t ParameterCount,
179 TypeIndex ArgumentList, int32_t ThisPointerAdjustment)
180 : TypeRecord(TypeRecordKind::MemberFunction), ReturnType(ReturnType),
181 ClassType(ClassType), ThisType(ThisType), CallConv(CallConv),
182 Options(Options), ParameterCount(ParameterCount),
183 ArgumentList(ArgumentList),
184 ThisPointerAdjustment(ThisPointerAdjustment) {}
185
186 TypeIndex getReturnType() const { return ReturnType; }
187 TypeIndex getClassType() const { return ClassType; }
188 TypeIndex getThisType() const { return ThisType; }
189 CallingConvention getCallConv() const { return CallConv; }
190 FunctionOptions getOptions() const { return Options; }
191 uint16_t getParameterCount() const { return ParameterCount; }
192 TypeIndex getArgumentList() const { return ArgumentList; }
193 int32_t getThisPointerAdjustment() const { return ThisPointerAdjustment; }
194
195 TypeIndex ReturnType;
196 TypeIndex ClassType;
197 TypeIndex ThisType;
198 CallingConvention CallConv;
199 FunctionOptions Options;
200 uint16_t ParameterCount;
201 TypeIndex ArgumentList;
202 int32_t ThisPointerAdjustment;
203 };
204
205 // LF_LABEL
206 class LabelRecord : public TypeRecord {
207 public:
208 LabelRecord() = default;
209 explicit LabelRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
210
211 LabelRecord(LabelType Mode) : TypeRecord(TypeRecordKind::Label), Mode(Mode) {}
212
213 LabelType Mode;
214 };
215
216 // LF_MFUNC_ID
217 class MemberFuncIdRecord : public TypeRecord {
218 public:
219 MemberFuncIdRecord() = default;
220 explicit MemberFuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
221 MemberFuncIdRecord(TypeIndex ClassType, TypeIndex FunctionType,
222 StringRef Name)
223 : TypeRecord(TypeRecordKind::MemberFuncId), ClassType(ClassType),
224 FunctionType(FunctionType), Name(Name) {}
225
226 TypeIndex getClassType() const { return ClassType; }
227 TypeIndex getFunctionType() const { return FunctionType; }
228 StringRef getName() const { return Name; }
229
230 TypeIndex ClassType;
231 TypeIndex FunctionType;
232 StringRef Name;
233 };
234
235 // LF_ARGLIST
236 class ArgListRecord : public TypeRecord {
237 public:
238 ArgListRecord() = default;
239 explicit ArgListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
240
241 ArgListRecord(TypeRecordKind Kind, ArrayRef Indices)
242 : TypeRecord(Kind), ArgIndices(Indices) {}
243
244 ArrayRef getIndices() const { return ArgIndices; }
245
246 std::vector ArgIndices;
247 };
248
249 // LF_SUBSTR_LIST
250 class StringListRecord : public TypeRecord {
251 public:
252 StringListRecord() = default;
253 explicit StringListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
254
255 StringListRecord(TypeRecordKind Kind, ArrayRef Indices)
256 : TypeRecord(Kind), StringIndices(Indices) {}
257
258 ArrayRef getIndices() const { return StringIndices; }
259
260 std::vector StringIndices;
261 };
262
263 // LF_POINTER
264 class PointerRecord : public TypeRecord {
265 public:
266 static const uint32_t PointerKindShift = 0;
267 static const uint32_t PointerKindMask = 0x1F;
268
269 static const uint32_t PointerModeShift = 5;
270 static const uint32_t PointerModeMask = 0x07;
271
272 static const uint32_t PointerOptionMask = 0xFF;
273
274 static const uint32_t PointerSizeShift = 13;
275 static const uint32_t PointerSizeMask = 0xFF;
276
277 PointerRecord() = default;
278 explicit PointerRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
279
280 PointerRecord(TypeIndex ReferentType, uint32_t Attrs)
281 : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
282 Attrs(Attrs) {}
283
284 PointerRecord(TypeIndex ReferentType, PointerKind PK, PointerMode PM,
285 PointerOptions PO, uint8_t Size)
286 : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
287 Attrs(calcAttrs(PK, PM, PO, Size)) {}
288
289 PointerRecord(TypeIndex ReferentType, PointerKind PK, PointerMode PM,
290 PointerOptions PO, uint8_t Size, const MemberPointerInfo &MPI)
291 : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
292 Attrs(calcAttrs(PK, PM, PO, Size)), MemberInfo(MPI) {}
293
294 TypeIndex getReferentType() const { return ReferentType; }
295
296 PointerKind getPointerKind() const {
297 return static_cast((Attrs >> PointerKindShift) &
298 PointerKindMask);
299 }
300
301 PointerMode getMode() const {
302 return static_cast((Attrs >> PointerModeShift) &
303 PointerModeMask);
304 }
305
306 PointerOptions getOptions() const {
307 return static_cast(Attrs);
308 }
309
310 uint8_t getSize() const {
311 return (Attrs >> PointerSizeShift) & PointerSizeMask;
312 }
313
314 MemberPointerInfo getMemberInfo() const { return *MemberInfo; }
315
316 bool isPointerToMember() const {
317 return getMode() == PointerMode::PointerToDataMember ||
318 getMode() == PointerMode::PointerToMemberFunction;
319 }
320
321 bool isFlat() const { return !!(Attrs & uint32_t(PointerOptions::Flat32)); }
322 bool isConst() const { return !!(Attrs & uint32_t(PointerOptions::Const)); }
323
324 bool isVolatile() const {
325 return !!(Attrs & uint32_t(PointerOptions::Volatile));
326 }
327
328 bool isUnaligned() const {
329 return !!(Attrs & uint32_t(PointerOptions::Unaligned));
330 }
331
332 bool isRestrict() const {
333 return !!(Attrs & uint32_t(PointerOptions::Restrict));
334 }
335
336 TypeIndex ReferentType;
337 uint32_t Attrs;
338 Optional MemberInfo;
339
340 void setAttrs(PointerKind PK, PointerMode PM, PointerOptions PO,
341 uint8_t Size) {
342 Attrs = calcAttrs(PK, PM, PO, Size);
343 }
344
345 private:
346 static uint32_t calcAttrs(PointerKind PK, PointerMode PM, PointerOptions PO,
347 uint8_t Size) {
348 uint32_t A = 0;
349 A |= static_cast(PK);
350 A |= static_cast(PO);
351 A |= (static_cast(PM) << PointerModeShift);
352 A |= (static_cast(Size) << PointerSizeShift);
353 return A;
354 }
355 };
356
357 // LF_NESTTYPE
358 class NestedTypeRecord : public TypeRecord {
359 public:
360 NestedTypeRecord() = default;
361 explicit NestedTypeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
362 NestedTypeRecord(TypeIndex Type, StringRef Name)
363 : TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {}
364
365 TypeIndex getNestedType() const { return Type; }
366 StringRef getName() const { return Name; }
367
368 TypeIndex Type;
369 StringRef Name;
370 };
371
372 // LF_FIELDLIST
373 class FieldListRecord : public TypeRecord {
374 public:
375 FieldListRecord() = default;
376 explicit FieldListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
377 explicit FieldListRecord(ArrayRef Data)
378 : TypeRecord(TypeRecordKind::FieldList), Data(Data) {}
379
380 ArrayRef Data;
381 };
382
383 // LF_ARRAY
384 class ArrayRecord : public TypeRecord {
385 public:
386 ArrayRecord() = default;
387 explicit ArrayRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
388 ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size,
389 StringRef Name)
390 : TypeRecord(TypeRecordKind::Array), ElementType(ElementType),
391 IndexType(IndexType), Size(Size), Name(Name) {}
392
393 TypeIndex getElementType() const { return ElementType; }
394 TypeIndex getIndexType() const { return IndexType; }
395 uint64_t getSize() const { return Size; }
396 StringRef getName() const { return Name; }
397
398 TypeIndex ElementType;
399 TypeIndex IndexType;
400 uint64_t Size;
401 StringRef Name;
402 };
403
404 class TagRecord : public TypeRecord {
405 protected:
406 TagRecord() = default;
407 explicit TagRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
408 TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
409 TypeIndex FieldList, StringRef Name, StringRef UniqueName)
410 : TypeRecord(Kind), MemberCount(MemberCount), Options(Options),
411 FieldList(FieldList), Name(Name), UniqueName(UniqueName) {}
412
413 public:
414 static const int HfaKindShift = 11;
415 static const int HfaKindMask = 0x1800;
416 static const int WinRTKindShift = 14;
417 static const int WinRTKindMask = 0xC000;
418
419 bool hasUniqueName() const {
420 return (Options & ClassOptions::HasUniqueName) != ClassOptions::None;
421 }
422
423 bool isNested() const {
424 return (Options & ClassOptions::Nested) != ClassOptions::None;
425 }
426
427 bool isForwardRef() const {
428 return (Options & ClassOptions::ForwardReference) != ClassOptions::None;
429 }
430
431 uint16_t getMemberCount() const { return MemberCount; }
432 ClassOptions getOptions() const { return Options; }
433 TypeIndex getFieldList() const { return FieldList; }
434 StringRef getName() const { return Name; }
435 StringRef getUniqueName() const { return UniqueName; }
436
437 uint16_t MemberCount;
438 ClassOptions Options;
439 TypeIndex FieldList;
440 StringRef Name;
441 StringRef UniqueName;
442 };
443
444 // LF_CLASS, LF_STRUCTURE, LF_INTERFACE
445 class ClassRecord : public TagRecord {
446 public:
447 ClassRecord() = default;
448 explicit ClassRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
449 ClassRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
450 TypeIndex FieldList, TypeIndex DerivationList,
451 TypeIndex VTableShape, uint64_t Size, StringRef Name,
452 StringRef UniqueName)
453 : TagRecord(Kind, MemberCount, Options, FieldList, Name, UniqueName),
454 DerivationList(DerivationList), VTableShape(VTableShape), Size(Size) {}
455
456 HfaKind getHfa() const {
457 uint16_t Value = static_cast(Options);
458 Value = (Value & HfaKindMask) >> HfaKindShift;
459 return static_cast(Value);
460 }
461
462 WindowsRTClassKind getWinRTKind() const {
463 uint16_t Value = static_cast(Options);
464 Value = (Value & WinRTKindMask) >> WinRTKindShift;
465 return static_cast(Value);
466 }
467
468 TypeIndex getDerivationList() const { return DerivationList; }
469 TypeIndex getVTableShape() const { return VTableShape; }
470 uint64_t getSize() const { return Size; }
471
472 TypeIndex DerivationList;
473 TypeIndex VTableShape;
474 uint64_t Size;
475 };
476
477 // LF_UNION
478 struct UnionRecord : public TagRecord {
479 UnionRecord() = default;
480 explicit UnionRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
481 UnionRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
482 uint64_t Size, StringRef Name, StringRef UniqueName)
483 : TagRecord(TypeRecordKind::Union, MemberCount, Options, FieldList, Name,
484 UniqueName),
485 Size(Size) {}
486
487 HfaKind getHfa() const {
488 uint16_t Value = static_cast(Options);
489 Value = (Value & HfaKindMask) >> HfaKindShift;
490 return static_cast(Value);
491 }
492
493 uint64_t getSize() const { return Size; }
494
495 uint64_t Size;
496 };
497
498 // LF_ENUM
499 class EnumRecord : public TagRecord {
500 public:
501 EnumRecord() = default;
502 explicit EnumRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
503 EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
504 StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType)
505 : TagRecord(TypeRecordKind::Enum, MemberCount, Options, FieldList, Name,
506 UniqueName),
507 UnderlyingType(UnderlyingType) {}
508
509 TypeIndex getUnderlyingType() const { return UnderlyingType; }
510
511 TypeIndex UnderlyingType;
512 };
513
514 // LF_BITFIELD
515 class BitFieldRecord : public TypeRecord {
516 public:
517 BitFieldRecord() = default;
518 explicit BitFieldRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
519 BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset)
520 : TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize),
521 BitOffset(BitOffset) {}
522
523 TypeIndex getType() const { return Type; }
524 uint8_t getBitOffset() const { return BitOffset; }
525 uint8_t getBitSize() const { return BitSize; }
526
527 TypeIndex Type;
528 uint8_t BitSize;
529 uint8_t BitOffset;
530 };
531
532 // LF_VTSHAPE
533 class VFTableShapeRecord : public TypeRecord {
534 public:
535 VFTableShapeRecord() = default;
536 explicit VFTableShapeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
537 explicit VFTableShapeRecord(ArrayRef Slots)
538 : TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {}
539 explicit VFTableShapeRecord(std::vector Slots)
540 : TypeRecord(TypeRecordKind::VFTableShape), Slots(std::move(Slots)) {}
541
542 ArrayRef getSlots() const {
543 if (!SlotsRef.empty())
544 return SlotsRef;
545 return Slots;
546 }
547
548 uint32_t getEntryCount() const { return getSlots().size(); }
549
550 ArrayRef SlotsRef;
551 std::vector Slots;
552 };
553
554 // LF_TYPESERVER2
555 class TypeServer2Record : public TypeRecord {
556 public:
557 TypeServer2Record() = default;
558 explicit TypeServer2Record(TypeRecordKind Kind) : TypeRecord(Kind) {}
559 TypeServer2Record(StringRef GuidStr, uint32_t Age, StringRef Name)
560 : TypeRecord(TypeRecordKind::TypeServer2), Age(Age), Name(Name) {
561 assert(GuidStr.size() == 16 && "guid isn't 16 bytes");
562 ::memcpy(Guid.Guid, GuidStr.data(), 16);
563 }
564
565 const GUID &getGuid() const { return Guid; }
566 uint32_t getAge() const { return Age; }
567 StringRef getName() const { return Name; }
568
569 GUID Guid;
570 uint32_t Age;
571 StringRef Name;
572 };
573
574 // LF_STRING_ID
575 class StringIdRecord : public TypeRecord {
576 public:
577 StringIdRecord() = default;
578 explicit StringIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
579 StringIdRecord(TypeIndex Id, StringRef String)
580 : TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {}
581
582 TypeIndex getId() const { return Id; }
583 StringRef getString() const { return String; }
584
585 TypeIndex Id;
586 StringRef String;
587 };
588
589 // LF_FUNC_ID
590 class FuncIdRecord : public TypeRecord {
591 public:
592 FuncIdRecord() = default;
593 explicit FuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
594 FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name)
595 : TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope),
596 FunctionType(FunctionType), Name(Name) {}
597
598 TypeIndex getParentScope() const { return ParentScope; }
599 TypeIndex getFunctionType() const { return FunctionType; }
600 StringRef getName() const { return Name; }
601
602 TypeIndex ParentScope;
603 TypeIndex FunctionType;
604 StringRef Name;
605 };
606
607 // LF_UDT_SRC_LINE
608 class UdtSourceLineRecord : public TypeRecord {
609 public:
610 UdtSourceLineRecord() = default;
611 explicit UdtSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
612 UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber)
613 : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
614 SourceFile(SourceFile), LineNumber(LineNumber) {}
615
616 TypeIndex getUDT() const { return UDT; }
617 TypeIndex getSourceFile() const { return SourceFile; }
618 uint32_t getLineNumber() const { return LineNumber; }
619
620 TypeIndex UDT;
621 TypeIndex SourceFile;
622 uint32_t LineNumber;
623 };
624
625 // LF_UDT_MOD_SRC_LINE
626 class UdtModSourceLineRecord : public TypeRecord {
627 public:
628 UdtModSourceLineRecord() = default;
629 explicit UdtModSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
630 UdtModSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile,
631 uint32_t LineNumber, uint16_t Module)
632 : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
633 SourceFile(SourceFile), LineNumber(LineNumber), Module(Module) {}
634
635 TypeIndex getUDT() const { return UDT; }
636 TypeIndex getSourceFile() const { return SourceFile; }
637 uint32_t getLineNumber() const { return LineNumber; }
638 uint16_t getModule() const { return Module; }
639
640 TypeIndex UDT;
641 TypeIndex SourceFile;
642 uint32_t LineNumber;
643 uint16_t Module;
644 };
645
646 // LF_BUILDINFO
647 class BuildInfoRecord : public TypeRecord {
648 public:
649 BuildInfoRecord() = default;
650 explicit BuildInfoRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
651 BuildInfoRecord(ArrayRef ArgIndices)
652 : TypeRecord(TypeRecordKind::BuildInfo),
653 ArgIndices(ArgIndices.begin(), ArgIndices.end()) {}
654
655 ArrayRef getArgs() const { return ArgIndices; }
656
657 SmallVector ArgIndices;
658 };
659
660 // LF_VFTABLE
661 class VFTableRecord : public TypeRecord {
662 public:
663 VFTableRecord() = default;
664 explicit VFTableRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
665 VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable,
666 uint32_t VFPtrOffset, StringRef Name,
667 ArrayRef Methods)
668 : TypeRecord(TypeRecordKind::VFTable), CompleteClass(CompleteClass),
669 OverriddenVFTable(OverriddenVFTable), VFPtrOffset(VFPtrOffset) {
670 MethodNames.push_back(Name);
671 MethodNames.insert(MethodNames.end(), Methods.begin(), Methods.end());
672 }
673
674 TypeIndex getCompleteClass() const { return CompleteClass; }
675 TypeIndex getOverriddenVTable() const { return OverriddenVFTable; }
676 uint32_t getVFPtrOffset() const { return VFPtrOffset; }
677 StringRef getName() const { return makeArrayRef(MethodNames).front(); }
678
679 ArrayRef getMethodNames() const {
680 return makeArrayRef(MethodNames).drop_front();
681 }
682
683 TypeIndex CompleteClass;
684 TypeIndex OverriddenVFTable;
685 uint32_t VFPtrOffset;
686 std::vector MethodNames;
687 };
688
689 // LF_ONEMETHOD
690 class OneMethodRecord : public TypeRecord {
691 public:
692 OneMethodRecord() = default;
693 explicit OneMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
694 OneMethodRecord(TypeIndex Type, MemberAttributes Attrs, int32_t VFTableOffset,
695 StringRef Name)
696 : TypeRecord(TypeRecordKind::OneMethod), Type(Type), Attrs(Attrs),
697 VFTableOffset(VFTableOffset), Name(Name) {}
698 OneMethodRecord(TypeIndex Type, MemberAccess Access, MethodKind MK,
699 MethodOptions Options, int32_t VFTableOffset, StringRef Name)
700 : TypeRecord(TypeRecordKind::OneMethod), Type(Type),
701 Attrs(Access, MK, Options), VFTableOffset(VFTableOffset), Name(Name) {}
702
703 TypeIndex getType() const { return Type; }
704 MethodKind getMethodKind() const { return Attrs.getMethodKind(); }
705 MethodOptions getOptions() const { return Attrs.getFlags(); }
706 MemberAccess getAccess() const { return Attrs.getAccess(); }
707 int32_t getVFTableOffset() const { return VFTableOffset; }
708 StringRef getName() const { return Name; }
709
710 bool isIntroducingVirtual() const {
711 return getMethodKind() == MethodKind::IntroducingVirtual ||
712 getMethodKind() == MethodKind::PureIntroducingVirtual;
713 }
714
715 TypeIndex Type;
716 MemberAttributes Attrs;
717 int32_t VFTableOffset;
718 StringRef Name;
719 };
720
721 // LF_METHODLIST
722 class MethodOverloadListRecord : public TypeRecord {
723 public:
724 MethodOverloadListRecord() = default;
725 explicit MethodOverloadListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
726 MethodOverloadListRecord(ArrayRef Methods)
727 : TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {}
728
729 ArrayRef getMethods() const { return Methods; }
730
731 std::vector Methods;
732 };
733
734 /// For method overload sets. LF_METHOD
735 class OverloadedMethodRecord : public TypeRecord {
736 public:
737 OverloadedMethodRecord() = default;
738 explicit OverloadedMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
739 OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList,
740 StringRef Name)
741 : TypeRecord(TypeRecordKind::OverloadedMethod),
742 NumOverloads(NumOverloads), MethodList(MethodList), Name(Name) {}
743
744 uint16_t getNumOverloads() const { return NumOverloads; }
745 TypeIndex getMethodList() const { return MethodList; }
746 StringRef getName() const { return Name; }
747
748 uint16_t NumOverloads;
749 TypeIndex MethodList;
750 StringRef Name;
751 };
752
753 // LF_MEMBER
754 class DataMemberRecord : public TypeRecord {
755 public:
756 DataMemberRecord() = default;
757 explicit DataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
758 DataMemberRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset,
759 StringRef Name)
760 : TypeRecord(TypeRecordKind::DataMember), Attrs(Attrs), Type(Type),
761 FieldOffset(Offset), Name(Name) {}
762 DataMemberRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset,
763 StringRef Name)
764 : TypeRecord(TypeRecordKind::DataMember), Attrs(Access), Type(Type),
765 FieldOffset(Offset), Name(Name) {}
766
767 MemberAccess getAccess() const { return Attrs.getAccess(); }
768 TypeIndex getType() const { return Type; }
769 uint64_t getFieldOffset() const { return FieldOffset; }
770 StringRef getName() const { return Name; }
771
772 MemberAttributes Attrs;
773 TypeIndex Type;
774 uint64_t FieldOffset;
775 StringRef Name;
776 };
777
778 // LF_STMEMBER
779 class StaticDataMemberRecord : public TypeRecord {
780 public:
781 StaticDataMemberRecord() = default;
782 explicit StaticDataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
783 StaticDataMemberRecord(MemberAttributes Attrs, TypeIndex Type, StringRef Name)
784 : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Attrs), Type(Type),
785 Name(Name) {}
786 StaticDataMemberRecord(MemberAccess Access, TypeIndex Type, StringRef Name)
787 : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Access), Type(Type),
788 Name(Name) {}
789
790 MemberAccess getAccess() const { return Attrs.getAccess(); }
791 TypeIndex getType() const { return Type; }
792 StringRef getName() const { return Name; }
793
794 MemberAttributes Attrs;
795 TypeIndex Type;
796 StringRef Name;
797 };
798
799 // LF_ENUMERATE
800 class EnumeratorRecord : public TypeRecord {
801 public:
802 EnumeratorRecord() = default;
803 explicit EnumeratorRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
804 EnumeratorRecord(MemberAttributes Attrs, APSInt Value, StringRef Name)
805 : TypeRecord(TypeRecordKind::Enumerator), Attrs(Attrs),
806 Value(std::move(Value)), Name(Name) {}
807 EnumeratorRecord(MemberAccess Access, APSInt Value, StringRef Name)
808 : TypeRecord(TypeRecordKind::Enumerator), Attrs(Access),
809 Value(std::move(Value)), Name(Name) {}
810
811 MemberAccess getAccess() const { return Attrs.getAccess(); }
812 APSInt getValue() const { return Value; }
813 StringRef getName() const { return Name; }
814
815 MemberAttributes Attrs;
816 APSInt Value;
817 StringRef Name;
818 };
819
820 // LF_VFUNCTAB
821 class VFPtrRecord : public TypeRecord {
822 public:
823 VFPtrRecord() = default;
824 explicit VFPtrRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
825 VFPtrRecord(TypeIndex Type)
826 : TypeRecord(TypeRecordKind::VFPtr), Type(Type) {}
827
828 TypeIndex getType() const { return Type; }
829
830 TypeIndex Type;
831 };
832
833 // LF_BCLASS, LF_BINTERFACE
834 class BaseClassRecord : public TypeRecord {
835 public:
836 BaseClassRecord() = default;
837 explicit BaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
838 BaseClassRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset)
839 : TypeRecord(TypeRecordKind::BaseClass), Attrs(Attrs), Type(Type),
840 Offset(Offset) {}
841 BaseClassRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset)
842 : TypeRecord(TypeRecordKind::BaseClass), Attrs(Access), Type(Type),
843 Offset(Offset) {}
844
845 MemberAccess getAccess() const { return Attrs.getAccess(); }
846 TypeIndex getBaseType() const { return Type; }
847 uint64_t getBaseOffset() const { return Offset; }
848
849 MemberAttributes Attrs;
850 TypeIndex Type;
851 uint64_t Offset;
852 };
853
854 // LF_VBCLASS, LF_IVBCLASS
855 class VirtualBaseClassRecord : public TypeRecord {
856 public:
857 VirtualBaseClassRecord() = default;
858 explicit VirtualBaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
859 VirtualBaseClassRecord(TypeRecordKind Kind, MemberAttributes Attrs,
860 TypeIndex BaseType, TypeIndex VBPtrType,
861 uint64_t Offset, uint64_t Index)
862 : TypeRecord(Kind), Attrs(Attrs), BaseType(BaseType),
863 VBPtrType(VBPtrType), VBPtrOffset(Offset), VTableIndex(Index) {}
864 VirtualBaseClassRecord(TypeRecordKind Kind, MemberAccess Access,
865 TypeIndex BaseType, TypeIndex VBPtrType,
866 uint64_t Offset, uint64_t Index)
867 : TypeRecord(Kind), Attrs(Access), BaseType(BaseType),
868 VBPtrType(VBPtrType), VBPtrOffset(Offset), VTableIndex(Index) {}
869
870 MemberAccess getAccess() const { return Attrs.getAccess(); }
871 TypeIndex getBaseType() const { return BaseType; }
872 TypeIndex getVBPtrType() const { return VBPtrType; }
873 uint64_t getVBPtrOffset() const { return VBPtrOffset; }
874 uint64_t getVTableIndex() const { return VTableIndex; }
875
876 MemberAttributes Attrs;
877 TypeIndex BaseType;
878 TypeIndex VBPtrType;
879 uint64_t VBPtrOffset;
880 uint64_t VTableIndex;
881 };
882
883 /// LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records
884 /// together. The first will end in an LF_INDEX record that points to the next.
885 class ListContinuationRecord : public TypeRecord {
886 public:
887 ListContinuationRecord() = default;
888 explicit ListContinuationRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
889 ListContinuationRecord(TypeIndex ContinuationIndex)
890 : TypeRecord(TypeRecordKind::ListContinuation),
891 ContinuationIndex(ContinuationIndex) {}
892
893 TypeIndex getContinuationIndex() const { return ContinuationIndex; }
894
895 TypeIndex ContinuationIndex;
896 };
897
898 // LF_PRECOMP
899 class PrecompRecord : public TypeRecord {
900 public:
901 PrecompRecord() = default;
902 explicit PrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
903
904 uint32_t getStartTypeIndex() const { return StartTypeIndex; }
905 uint32_t getTypesCount() const { return TypesCount; }
906 uint32_t getSignature() const { return Signature; }
907 StringRef getPrecompFilePath() const { return PrecompFilePath; }
908
909 uint32_t StartTypeIndex;
910 uint32_t TypesCount;
911 uint32_t Signature;
912 StringRef PrecompFilePath;
913 };
914
915 // LF_ENDPRECOMP
916 class EndPrecompRecord : public TypeRecord {
917 public:
918 EndPrecompRecord() = default;
919 explicit EndPrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
920
921 uint32_t getSignature() const { return Signature; }
922
923 uint32_t Signature;
924 };
925 } // end namespace codeview
926 } // end namespace llvm
927
928 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H
0 //===- TypeRecord.h ---------------------------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H
10 #define LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H
11
12 #include "llvm/ADT/APSInt.h"
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/Optional.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/iterator_range.h"
18 #include "llvm/DebugInfo/CodeView/CVRecord.h"
19 #include "llvm/DebugInfo/CodeView/CodeView.h"
20 #include "llvm/DebugInfo/CodeView/GUID.h"
21 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
22 #include "llvm/Support/BinaryStreamArray.h"
23 #include "llvm/Support/Endian.h"
24 #include
25 #include
26 #include
27
28 namespace llvm {
29 namespace codeview {
30
31 using support::little32_t;
32 using support::ulittle16_t;
33 using support::ulittle32_t;
34
35 using CVType = CVRecord;
36 using RemappedType = RemappedRecord;
37
38 struct CVMemberRecord {
39 TypeLeafKind Kind;
40 ArrayRef Data;
41 };
42 using CVTypeArray = VarStreamArray;
43 using CVTypeRange = iterator_range;
44
45 /// Equvalent to CV_fldattr_t in cvinfo.h.
46 struct MemberAttributes {
47 uint16_t Attrs = 0;
48
49 enum {
50 MethodKindShift = 2,
51 };
52
53 MemberAttributes() = default;
54
55 explicit MemberAttributes(MemberAccess Access)
56 : Attrs(static_cast(Access)) {}
57
58 MemberAttributes(MemberAccess Access, MethodKind Kind, MethodOptions Flags) {
59 Attrs = static_cast(Access);
60 Attrs |= (static_cast(Kind) << MethodKindShift);
61 Attrs |= static_cast(Flags);
62 }
63
64 /// Get the access specifier. Valid for any kind of member.
65 MemberAccess getAccess() const {
66 return MemberAccess(unsigned(Attrs) & unsigned(MethodOptions::AccessMask));
67 }
68
69 /// Indicates if a method is defined with friend, virtual, static, etc.
70 MethodKind getMethodKind() const {
71 return MethodKind(
72 (unsigned(Attrs) & unsigned(MethodOptions::MethodKindMask)) >>
73 MethodKindShift);
74 }
75
76 /// Get the flags that are not included in access control or method
77 /// properties.
78 MethodOptions getFlags() const {
79 return MethodOptions(
80 unsigned(Attrs) &
81 ~unsigned(MethodOptions::AccessMask | MethodOptions::MethodKindMask));
82 }
83
84 /// Is this method virtual.
85 bool isVirtual() const {
86 auto MP = getMethodKind();
87 return MP != MethodKind::Vanilla && MP != MethodKind::Friend &&
88 MP != MethodKind::Static;
89 }
90
91 /// Does this member introduce a new virtual method.
92 bool isIntroducedVirtual() const {
93 auto MP = getMethodKind();
94 return MP == MethodKind::IntroducingVirtual ||
95 MP == MethodKind::PureIntroducingVirtual;
96 }
97 };
98
99 // Does not correspond to any tag, this is the tail of an LF_POINTER record
100 // if it represents a member pointer.
101 class MemberPointerInfo {
102 public:
103 MemberPointerInfo() = default;
104
105 MemberPointerInfo(TypeIndex ContainingType,
106 PointerToMemberRepresentation Representation)
107 : ContainingType(ContainingType), Representation(Representation) {}
108
109 TypeIndex getContainingType() const { return ContainingType; }
110 PointerToMemberRepresentation getRepresentation() const {
111 return Representation;
112 }
113
114 TypeIndex ContainingType;
115 PointerToMemberRepresentation Representation;
116 };
117
118 class TypeRecord {
119 protected:
120 TypeRecord() = default;
121 explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {}
122
123 public:
124 TypeRecordKind getKind() const { return Kind; }
125
126 TypeRecordKind Kind;
127 };
128
129 // LF_MODIFIER
130 class ModifierRecord : public TypeRecord {
131 public:
132 ModifierRecord() = default;
133 explicit ModifierRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
134 ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers)
135 : TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType),
136 Modifiers(Modifiers) {}
137
138 TypeIndex getModifiedType() const { return ModifiedType; }
139 ModifierOptions getModifiers() const { return Modifiers; }
140
141 TypeIndex ModifiedType;
142 ModifierOptions Modifiers;
143 };
144
145 // LF_PROCEDURE
146 class ProcedureRecord : public TypeRecord {
147 public:
148 ProcedureRecord() = default;
149 explicit ProcedureRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
150 ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv,
151 FunctionOptions Options, uint16_t ParameterCount,
152 TypeIndex ArgumentList)
153 : TypeRecord(TypeRecordKind::Procedure), ReturnType(ReturnType),
154 CallConv(CallConv), Options(Options), ParameterCount(ParameterCount),
155 ArgumentList(ArgumentList) {}
156
157 TypeIndex getReturnType() const { return ReturnType; }
158 CallingConvention getCallConv() const { return CallConv; }
159 FunctionOptions getOptions() const { return Options; }
160 uint16_t getParameterCount() const { return ParameterCount; }
161 TypeIndex getArgumentList() const { return ArgumentList; }
162
163 TypeIndex ReturnType;
164 CallingConvention CallConv;
165 FunctionOptions Options;
166 uint16_t ParameterCount;
167 TypeIndex ArgumentList;
168 };
169
170 // LF_MFUNCTION
171 class MemberFunctionRecord : public TypeRecord {
172 public:
173 MemberFunctionRecord() = default;
174 explicit MemberFunctionRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
175
176 MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType,
177 TypeIndex ThisType, CallingConvention CallConv,
178 FunctionOptions Options, uint16_t ParameterCount,
179 TypeIndex ArgumentList, int32_t ThisPointerAdjustment)
180 : TypeRecord(TypeRecordKind::MemberFunction), ReturnType(ReturnType),
181 ClassType(ClassType), ThisType(ThisType), CallConv(CallConv),
182 Options(Options), ParameterCount(ParameterCount),
183 ArgumentList(ArgumentList),
184 ThisPointerAdjustment(ThisPointerAdjustment) {}
185
186 TypeIndex getReturnType() const { return ReturnType; }
187 TypeIndex getClassType() const { return ClassType; }
188 TypeIndex getThisType() const { return ThisType; }
189 CallingConvention getCallConv() const { return CallConv; }
190 FunctionOptions getOptions() const { return Options; }
191 uint16_t getParameterCount() const { return ParameterCount; }
192 TypeIndex getArgumentList() const { return ArgumentList; }
193 int32_t getThisPointerAdjustment() const { return ThisPointerAdjustment; }
194
195 TypeIndex ReturnType;
196 TypeIndex ClassType;
197 TypeIndex ThisType;
198 CallingConvention CallConv;
199 FunctionOptions Options;
200 uint16_t ParameterCount;
201 TypeIndex ArgumentList;
202 int32_t ThisPointerAdjustment;
203 };
204
205 // LF_LABEL
206 class LabelRecord : public TypeRecord {
207 public:
208 LabelRecord() = default;
209 explicit LabelRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
210
211 LabelRecord(LabelType Mode) : TypeRecord(TypeRecordKind::Label), Mode(Mode) {}
212
213 LabelType Mode;
214 };
215
216 // LF_MFUNC_ID
217 class MemberFuncIdRecord : public TypeRecord {
218 public:
219 MemberFuncIdRecord() = default;
220 explicit MemberFuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
221 MemberFuncIdRecord(TypeIndex ClassType, TypeIndex FunctionType,
222 StringRef Name)
223 : TypeRecord(TypeRecordKind::MemberFuncId), ClassType(ClassType),
224 FunctionType(FunctionType), Name(Name) {}
225
226 TypeIndex getClassType() const { return ClassType; }
227 TypeIndex getFunctionType() const { return FunctionType; }
228 StringRef getName() const { return Name; }
229
230 TypeIndex ClassType;
231 TypeIndex FunctionType;
232 StringRef Name;
233 };
234
235 // LF_ARGLIST
236 class ArgListRecord : public TypeRecord {
237 public:
238 ArgListRecord() = default;
239 explicit ArgListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
240
241 ArgListRecord(TypeRecordKind Kind, ArrayRef Indices)
242 : TypeRecord(Kind), ArgIndices(Indices) {}
243
244 ArrayRef getIndices() const { return ArgIndices; }
245
246 std::vector ArgIndices;
247 };
248
249 // LF_SUBSTR_LIST
250 class StringListRecord : public TypeRecord {
251 public:
252 StringListRecord() = default;
253 explicit StringListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
254
255 StringListRecord(TypeRecordKind Kind, ArrayRef Indices)
256 : TypeRecord(Kind), StringIndices(Indices) {}
257
258 ArrayRef getIndices() const { return StringIndices; }
259
260 std::vector StringIndices;
261 };
262
263 // LF_POINTER
264 class PointerRecord : public TypeRecord {
265 public:
266 static const uint32_t PointerKindShift = 0;
267 static const uint32_t PointerKindMask = 0x1F;
268
269 static const uint32_t PointerModeShift = 5;
270 static const uint32_t PointerModeMask = 0x07;
271
272 static const uint32_t PointerOptionMask = 0xFF;
273
274 static const uint32_t PointerSizeShift = 13;
275 static const uint32_t PointerSizeMask = 0xFF;
276
277 PointerRecord() = default;
278 explicit PointerRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
279
280 PointerRecord(TypeIndex ReferentType, uint32_t Attrs)
281 : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
282 Attrs(Attrs) {}
283
284 PointerRecord(TypeIndex ReferentType, PointerKind PK, PointerMode PM,
285 PointerOptions PO, uint8_t Size)
286 : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
287 Attrs(calcAttrs(PK, PM, PO, Size)) {}
288
289 PointerRecord(TypeIndex ReferentType, PointerKind PK, PointerMode PM,
290 PointerOptions PO, uint8_t Size, const MemberPointerInfo &MPI)
291 : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
292 Attrs(calcAttrs(PK, PM, PO, Size)), MemberInfo(MPI) {}
293
294 TypeIndex getReferentType() const { return ReferentType; }
295
296 PointerKind getPointerKind() const {
297 return static_cast((Attrs >> PointerKindShift) &
298 PointerKindMask);
299 }
300
301 PointerMode getMode() const {
302 return static_cast((Attrs >> PointerModeShift) &
303 PointerModeMask);
304 }
305
306 PointerOptions getOptions() const {
307 return static_cast(Attrs);
308 }
309
310 uint8_t getSize() const {
311 return (Attrs >> PointerSizeShift) & PointerSizeMask;
312 }
313
314 MemberPointerInfo getMemberInfo() const { return *MemberInfo; }
315
316 bool isPointerToMember() const {
317 return getMode() == PointerMode::PointerToDataMember ||
318 getMode() == PointerMode::PointerToMemberFunction;
319 }
320
321 bool isFlat() const { return !!(Attrs & uint32_t(PointerOptions::Flat32)); }
322 bool isConst() const { return !!(Attrs & uint32_t(PointerOptions::Const)); }
323
324 bool isVolatile() const {
325 return !!(Attrs & uint32_t(PointerOptions::Volatile));
326 }
327
328 bool isUnaligned() const {
329 return !!(Attrs & uint32_t(PointerOptions::Unaligned));
330 }
331
332 bool isRestrict() const {
333 return !!(Attrs & uint32_t(PointerOptions::Restrict));
334 }
335
336 TypeIndex ReferentType;
337 uint32_t Attrs;
338 Optional MemberInfo;
339
340 void setAttrs(PointerKind PK, PointerMode PM, PointerOptions PO,
341 uint8_t Size) {
342 Attrs = calcAttrs(PK, PM, PO, Size);
343 }
344
345 private:
346 static uint32_t calcAttrs(PointerKind PK, PointerMode PM, PointerOptions PO,
347 uint8_t Size) {
348 uint32_t A = 0;
349 A |= static_cast(PK);
350 A |= static_cast(PO);
351 A |= (static_cast(PM) << PointerModeShift);
352 A |= (static_cast(Size) << PointerSizeShift);
353 return A;
354 }
355 };
356
357 // LF_NESTTYPE
358 class NestedTypeRecord : public TypeRecord {
359 public:
360 NestedTypeRecord() = default;
361 explicit NestedTypeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
362 NestedTypeRecord(TypeIndex Type, StringRef Name)
363 : TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {}
364
365 TypeIndex getNestedType() const { return Type; }
366 StringRef getName() const { return Name; }
367
368 TypeIndex Type;
369 StringRef Name;
370 };
371
372 // LF_FIELDLIST
373 class FieldListRecord : public TypeRecord {
374 public:
375 FieldListRecord() = default;
376 explicit FieldListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
377 explicit FieldListRecord(ArrayRef Data)
378 : TypeRecord(TypeRecordKind::FieldList), Data(Data) {}
379
380 ArrayRef Data;
381 };
382
383 // LF_ARRAY
384 class ArrayRecord : public TypeRecord {
385 public:
386 ArrayRecord() = default;
387 explicit ArrayRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
388 ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size,
389 StringRef Name)
390 : TypeRecord(TypeRecordKind::Array), ElementType(ElementType),
391 IndexType(IndexType), Size(Size), Name(Name) {}
392
393 TypeIndex getElementType() const { return ElementType; }
394 TypeIndex getIndexType() const { return IndexType; }
395 uint64_t getSize() const { return Size; }
396 StringRef getName() const { return Name; }
397
398 TypeIndex ElementType;
399 TypeIndex IndexType;
400 uint64_t Size;
401 StringRef Name;
402 };
403
404 class TagRecord : public TypeRecord {
405 protected:
406 TagRecord() = default;
407 explicit TagRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
408 TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
409 TypeIndex FieldList, StringRef Name, StringRef UniqueName)
410 : TypeRecord(Kind), MemberCount(MemberCount), Options(Options),
411 FieldList(FieldList), Name(Name), UniqueName(UniqueName) {}
412
413 public:
414 static const int HfaKindShift = 11;
415 static const int HfaKindMask = 0x1800;
416 static const int WinRTKindShift = 14;
417 static const int WinRTKindMask = 0xC000;
418
419 bool hasUniqueName() const {
420 return (Options & ClassOptions::HasUniqueName) != ClassOptions::None;
421 }
422
423 bool isNested() const {
424 return (Options & ClassOptions::Nested) != ClassOptions::None;
425 }
426
427 bool isForwardRef() const {
428 return (Options & ClassOptions::ForwardReference) != ClassOptions::None;
429 }
430
431 uint16_t getMemberCount() const { return MemberCount; }
432 ClassOptions getOptions() const { return Options; }
433 TypeIndex getFieldList() const { return FieldList; }
434 StringRef getName() const { return Name; }
435 StringRef getUniqueName() const { return UniqueName; }
436
437 uint16_t MemberCount;
438 ClassOptions Options;
439 TypeIndex FieldList;
440 StringRef Name;
441 StringRef UniqueName;
442 };
443
444 // LF_CLASS, LF_STRUCTURE, LF_INTERFACE
445 class ClassRecord : public TagRecord {
446 public:
447 ClassRecord() = default;
448 explicit ClassRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
449 ClassRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
450 TypeIndex FieldList, TypeIndex DerivationList,
451 TypeIndex VTableShape, uint64_t Size, StringRef Name,
452 StringRef UniqueName)
453 : TagRecord(Kind, MemberCount, Options, FieldList, Name, UniqueName),
454 DerivationList(DerivationList), VTableShape(VTableShape), Size(Size) {}
455
456 HfaKind getHfa() const {
457 uint16_t Value = static_cast(Options);
458 Value = (Value & HfaKindMask) >> HfaKindShift;
459 return static_cast(Value);
460 }
461
462 WindowsRTClassKind getWinRTKind() const {
463 uint16_t Value = static_cast(Options);
464 Value = (Value & WinRTKindMask) >> WinRTKindShift;
465 return static_cast(Value);
466 }
467
468 TypeIndex getDerivationList() const { return DerivationList; }
469 TypeIndex getVTableShape() const { return VTableShape; }
470 uint64_t getSize() const { return Size; }
471
472 TypeIndex DerivationList;
473 TypeIndex VTableShape;
474 uint64_t Size;
475 };
476
477 // LF_UNION
478 struct UnionRecord : public TagRecord {
479 UnionRecord() = default;
480 explicit UnionRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
481 UnionRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
482 uint64_t Size, StringRef Name, StringRef UniqueName)
483 : TagRecord(TypeRecordKind::Union, MemberCount, Options, FieldList, Name,
484 UniqueName),
485 Size(Size) {}
486
487 HfaKind getHfa() const {
488 uint16_t Value = static_cast(Options);
489 Value = (Value & HfaKindMask) >> HfaKindShift;
490 return static_cast(Value);
491 }
492
493 uint64_t getSize() const { return Size; }
494
495 uint64_t Size;
496 };
497
498 // LF_ENUM
499 class EnumRecord : public TagRecord {
500 public:
501 EnumRecord() = default;
502 explicit EnumRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
503 EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
504 StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType)
505 : TagRecord(TypeRecordKind::Enum, MemberCount, Options, FieldList, Name,
506 UniqueName),
507 UnderlyingType(UnderlyingType) {}
508
509 TypeIndex getUnderlyingType() const { return UnderlyingType; }
510
511 TypeIndex UnderlyingType;
512 };
513
514 // LF_BITFIELD
515 class BitFieldRecord : public TypeRecord {
516 public:
517 BitFieldRecord() = default;
518 explicit BitFieldRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
519 BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset)
520 : TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize),
521 BitOffset(BitOffset) {}
522
523 TypeIndex getType() const { return Type; }
524 uint8_t getBitOffset() const { return BitOffset; }
525 uint8_t getBitSize() const { return BitSize; }
526
527 TypeIndex Type;
528 uint8_t BitSize;
529 uint8_t BitOffset;
530 };
531
532 // LF_VTSHAPE
533 class VFTableShapeRecord : public TypeRecord {
534 public:
535 VFTableShapeRecord() = default;
536 explicit VFTableShapeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
537 explicit VFTableShapeRecord(ArrayRef Slots)
538 : TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {}
539 explicit VFTableShapeRecord(std::vector Slots)
540 : TypeRecord(TypeRecordKind::VFTableShape), Slots(std::move(Slots)) {}
541
542 ArrayRef getSlots() const {
543 if (!SlotsRef.empty())
544 return SlotsRef;
545 return Slots;
546 }
547
548 uint32_t getEntryCount() const { return getSlots().size(); }
549
550 ArrayRef SlotsRef;
551 std::vector Slots;
552 };
553
554 // LF_TYPESERVER2
555 class TypeServer2Record : public TypeRecord {
556 public:
557 TypeServer2Record() = default;
558 explicit TypeServer2Record(TypeRecordKind Kind) : TypeRecord(Kind) {}
559 TypeServer2Record(StringRef GuidStr, uint32_t Age, StringRef Name)
560 : TypeRecord(TypeRecordKind::TypeServer2), Age(Age), Name(Name) {
561 assert(GuidStr.size() == 16 && "guid isn't 16 bytes");
562 ::memcpy(Guid.Guid, GuidStr.data(), 16);
563 }
564
565 const GUID &getGuid() const { return Guid; }
566 uint32_t getAge() const { return Age; }
567 StringRef getName() const { return Name; }
568
569 GUID Guid;
570 uint32_t Age;
571 StringRef Name;
572 };
573
574 // LF_STRING_ID
575 class StringIdRecord : public TypeRecord {
576 public:
577 StringIdRecord() = default;
578 explicit StringIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
579 StringIdRecord(TypeIndex Id, StringRef String)
580 : TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {}
581
582 TypeIndex getId() const { return Id; }
583 StringRef getString() const { return String; }
584
585 TypeIndex Id;
586 StringRef String;
587 };
588
589 // LF_FUNC_ID
590 class FuncIdRecord : public TypeRecord {
591 public:
592 FuncIdRecord() = default;
593 explicit FuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
594 FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name)
595 : TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope),
596 FunctionType(FunctionType), Name(Name) {}
597
598 TypeIndex getParentScope() const { return ParentScope; }
599 TypeIndex getFunctionType() const { return FunctionType; }
600 StringRef getName() const { return Name; }
601
602 TypeIndex ParentScope;
603 TypeIndex FunctionType;
604 StringRef Name;
605 };
606
607 // LF_UDT_SRC_LINE
608 class UdtSourceLineRecord : public TypeRecord {
609 public:
610 UdtSourceLineRecord() = default;
611 explicit UdtSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
612 UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber)
613 : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
614 SourceFile(SourceFile), LineNumber(LineNumber) {}
615
616 TypeIndex getUDT() const { return UDT; }
617 TypeIndex getSourceFile() const { return SourceFile; }
618 uint32_t getLineNumber() const { return LineNumber; }
619
620 TypeIndex UDT;
621 TypeIndex SourceFile;
622 uint32_t LineNumber;
623 };
624
625 // LF_UDT_MOD_SRC_LINE
626 class UdtModSourceLineRecord : public TypeRecord {
627 public:
628 UdtModSourceLineRecord() = default;
629 explicit UdtModSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
630 UdtModSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile,
631 uint32_t LineNumber, uint16_t Module)
632 : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
633 SourceFile(SourceFile), LineNumber(LineNumber), Module(Module) {}
634
635 TypeIndex getUDT() const { return UDT; }
636 TypeIndex getSourceFile() const { return SourceFile; }
637 uint32_t getLineNumber() const { return LineNumber; }
638 uint16_t getModule() const { return Module; }
639
640 TypeIndex UDT;
641 TypeIndex SourceFile;
642 uint32_t LineNumber;
643 uint16_t Module;
644 };
645
646 // LF_BUILDINFO
647 class BuildInfoRecord : public TypeRecord {
648 public:
649 BuildInfoRecord() = default;
650 explicit BuildInfoRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
651 BuildInfoRecord(ArrayRef ArgIndices)
652 : TypeRecord(TypeRecordKind::BuildInfo),
653 ArgIndices(ArgIndices.begin(), ArgIndices.end()) {}
654
655 ArrayRef getArgs() const { return ArgIndices; }
656
657 SmallVector ArgIndices;
658 };
659
660 // LF_VFTABLE
661 class VFTableRecord : public TypeRecord {
662 public:
663 VFTableRecord() = default;
664 explicit VFTableRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
665 VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable,
666 uint32_t VFPtrOffset, StringRef Name,
667 ArrayRef Methods)
668 : TypeRecord(TypeRecordKind::VFTable), CompleteClass(CompleteClass),
669 OverriddenVFTable(OverriddenVFTable), VFPtrOffset(VFPtrOffset) {
670 MethodNames.push_back(Name);
671 MethodNames.insert(MethodNames.end(), Methods.begin(), Methods.end());
672 }
673
674 TypeIndex getCompleteClass() const { return CompleteClass; }
675 TypeIndex getOverriddenVTable() const { return OverriddenVFTable; }
676 uint32_t getVFPtrOffset() const { return VFPtrOffset; }
677 StringRef getName() const { return makeArrayRef(MethodNames).front(); }
678
679 ArrayRef getMethodNames() const {
680 return makeArrayRef(MethodNames).drop_front();
681 }
682
683 TypeIndex CompleteClass;
684 TypeIndex OverriddenVFTable;
685 uint32_t VFPtrOffset;
686 std::vector MethodNames;
687 };
688
689 // LF_ONEMETHOD
690 class OneMethodRecord : public TypeRecord {
691 public:
692 OneMethodRecord() = default;
693 explicit OneMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
694 OneMethodRecord(TypeIndex Type, MemberAttributes Attrs, int32_t VFTableOffset,
695 StringRef Name)
696 : TypeRecord(TypeRecordKind::OneMethod), Type(Type), Attrs(Attrs),
697 VFTableOffset(VFTableOffset), Name(Name) {}
698 OneMethodRecord(TypeIndex Type, MemberAccess Access, MethodKind MK,
699 MethodOptions Options, int32_t VFTableOffset, StringRef Name)
700 : TypeRecord(TypeRecordKind::OneMethod), Type(Type),
701 Attrs(Access, MK, Options), VFTableOffset(VFTableOffset), Name(Name) {}
702
703 TypeIndex getType() const { return Type; }
704 MethodKind getMethodKind() const { return Attrs.getMethodKind(); }
705 MethodOptions getOptions() const { return Attrs.getFlags(); }
706 MemberAccess getAccess() const { return Attrs.getAccess(); }
707 int32_t getVFTableOffset() const { return VFTableOffset; }
708 StringRef getName() const { return Name; }
709
710 bool isIntroducingVirtual() const {
711 return getMethodKind() == MethodKind::IntroducingVirtual ||
712 getMethodKind() == MethodKind::PureIntroducingVirtual;
713 }
714
715 TypeIndex Type;
716 MemberAttributes Attrs;
717 int32_t VFTableOffset;
718 StringRef Name;
719 };
720
721 // LF_METHODLIST
722 class MethodOverloadListRecord : public TypeRecord {
723 public:
724 MethodOverloadListRecord() = default;
725 explicit MethodOverloadListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
726 MethodOverloadListRecord(ArrayRef Methods)
727 : TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {}
728
729 ArrayRef getMethods() const { return Methods; }
730
731 std::vector Methods;
732 };
733
734 /// For method overload sets. LF_METHOD
735 class OverloadedMethodRecord : public TypeRecord {
736 public:
737 OverloadedMethodRecord() = default;
738 explicit OverloadedMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
739 OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList,
740 StringRef Name)
741 : TypeRecord(TypeRecordKind::OverloadedMethod),
742 NumOverloads(NumOverloads), MethodList(MethodList), Name(Name) {}
743
744 uint16_t getNumOverloads() const { return NumOverloads; }
745 TypeIndex getMethodList() const { return MethodList; }
746 StringRef getName() const { return Name; }
747
748 uint16_t NumOverloads;
749 TypeIndex MethodList;
750 StringRef Name;
751 };
752
753 // LF_MEMBER
754 class DataMemberRecord : public TypeRecord {
755 public:
756 DataMemberRecord() = default;
757 explicit DataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
758 DataMemberRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset,
759 StringRef Name)
760 : TypeRecord(TypeRecordKind::DataMember), Attrs(Attrs), Type(Type),
761 FieldOffset(Offset), Name(Name) {}
762 DataMemberRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset,
763 StringRef Name)
764 : TypeRecord(TypeRecordKind::DataMember), Attrs(Access), Type(Type),
765 FieldOffset(Offset), Name(Name) {}
766
767 MemberAccess getAccess() const { return Attrs.getAccess(); }
768 TypeIndex getType() const { return Type; }
769 uint64_t getFieldOffset() const { return FieldOffset; }
770 StringRef getName() const { return Name; }
771
772 MemberAttributes Attrs;
773 TypeIndex Type;
774 uint64_t FieldOffset;
775 StringRef Name;
776 };
777
778 // LF_STMEMBER
779 class StaticDataMemberRecord : public TypeRecord {
780 public:
781 StaticDataMemberRecord() = default;
782 explicit StaticDataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
783 StaticDataMemberRecord(MemberAttributes Attrs, TypeIndex Type, StringRef Name)
784 : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Attrs), Type(Type),
785 Name(Name) {}
786 StaticDataMemberRecord(MemberAccess Access, TypeIndex Type, StringRef Name)
787 : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Access), Type(Type),
788 Name(Name) {}
789
790 MemberAccess getAccess() const { return Attrs.getAccess(); }
791 TypeIndex getType() const { return Type; }
792 StringRef getName() const { return Name; }
793
794 MemberAttributes Attrs;
795 TypeIndex Type;
796 StringRef Name;
797 };
798
799 // LF_ENUMERATE
800 class EnumeratorRecord : public TypeRecord {
801 public:
802 EnumeratorRecord() = default;
803 explicit EnumeratorRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
804 EnumeratorRecord(MemberAttributes Attrs, APSInt Value, StringRef Name)
805 : TypeRecord(TypeRecordKind::Enumerator), Attrs(Attrs),
806 Value(std::move(Value)), Name(Name) {}
807 EnumeratorRecord(MemberAccess Access, APSInt Value, StringRef Name)
808 : TypeRecord(TypeRecordKind::Enumerator), Attrs(Access),
809 Value(std::move(Value)), Name(Name) {}
810
811 MemberAccess getAccess() const { return Attrs.getAccess(); }
812 APSInt getValue() const { return Value; }
813 StringRef getName() const { return Name; }
814
815 MemberAttributes Attrs;
816 APSInt Value;
817 StringRef Name;
818 };
819
820 // LF_VFUNCTAB
821 class VFPtrRecord : public TypeRecord {
822 public:
823 VFPtrRecord() = default;
824 explicit VFPtrRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
825 VFPtrRecord(TypeIndex Type)
826 : TypeRecord(TypeRecordKind::VFPtr), Type(Type) {}
827
828 TypeIndex getType() const { return Type; }
829
830 TypeIndex Type;
831 };
832
833 // LF_BCLASS, LF_BINTERFACE
834 class BaseClassRecord : public TypeRecord {
835 public:
836 BaseClassRecord() = default;
837 explicit BaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
838 BaseClassRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset)
839 : TypeRecord(TypeRecordKind::BaseClass), Attrs(Attrs), Type(Type),
840 Offset(Offset) {}
841 BaseClassRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset)
842 : TypeRecord(TypeRecordKind::BaseClass), Attrs(Access), Type(Type),
843 Offset(Offset) {}
844
845 MemberAccess getAccess() const { return Attrs.getAccess(); }
846 TypeIndex getBaseType() const { return Type; }
847 uint64_t getBaseOffset() const { return Offset; }
848
849 MemberAttributes Attrs;
850 TypeIndex Type;
851 uint64_t Offset;
852 };
853
854 // LF_VBCLASS, LF_IVBCLASS
855 class VirtualBaseClassRecord : public TypeRecord {
856 public:
857 VirtualBaseClassRecord() = default;
858 explicit VirtualBaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
859 VirtualBaseClassRecord(TypeRecordKind Kind, MemberAttributes Attrs,
860 TypeIndex BaseType, TypeIndex VBPtrType,
861 uint64_t Offset, uint64_t Index)
862 : TypeRecord(Kind), Attrs(Attrs), BaseType(BaseType),
863 VBPtrType(VBPtrType), VBPtrOffset(Offset), VTableIndex(Index) {}
864 VirtualBaseClassRecord(TypeRecordKind Kind, MemberAccess Access,
865 TypeIndex BaseType, TypeIndex VBPtrType,
866 uint64_t Offset, uint64_t Index)
867 : TypeRecord(Kind), Attrs(Access), BaseType(BaseType),
868 VBPtrType(VBPtrType), VBPtrOffset(Offset), VTableIndex(Index) {}
869
870 MemberAccess getAccess() const { return Attrs.getAccess(); }
871 TypeIndex getBaseType() const { return BaseType; }
872 TypeIndex getVBPtrType() const { return VBPtrType; }
873 uint64_t getVBPtrOffset() const { return VBPtrOffset; }
874 uint64_t getVTableIndex() const { return VTableIndex; }
875
876 MemberAttributes Attrs;
877 TypeIndex BaseType;
878 TypeIndex VBPtrType;
879 uint64_t VBPtrOffset;
880 uint64_t VTableIndex;
881 };
882
883 /// LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records
884 /// together. The first will end in an LF_INDEX record that points to the next.
885 class ListContinuationRecord : public TypeRecord {
886 public:
887 ListContinuationRecord() = default;
888 explicit ListContinuationRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
889 ListContinuationRecord(TypeIndex ContinuationIndex)
890 : TypeRecord(TypeRecordKind::ListContinuation),
891 ContinuationIndex(ContinuationIndex) {}
892
893 TypeIndex getContinuationIndex() const { return ContinuationIndex; }
894
895 TypeIndex ContinuationIndex;
896 };
897
898 // LF_PRECOMP
899 class PrecompRecord : public TypeRecord {
900 public:
901 PrecompRecord() = default;
902 explicit PrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
903
904 uint32_t getStartTypeIndex() const { return StartTypeIndex; }
905 uint32_t getTypesCount() const { return TypesCount; }
906 uint32_t getSignature() const { return Signature; }
907 StringRef getPrecompFilePath() const { return PrecompFilePath; }
908
909 uint32_t StartTypeIndex;
910 uint32_t TypesCount;
911 uint32_t Signature;
912 StringRef PrecompFilePath;
913 };
914
915 // LF_ENDPRECOMP
916 class EndPrecompRecord : public TypeRecord {
917 public:
918 EndPrecompRecord() = default;
919 explicit EndPrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
920
921 uint32_t getSignature() const { return Signature; }
922
923 uint32_t Signature;
924 };
925 } // end namespace codeview
926 } // end namespace llvm
927
928 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H
None //===- RecordName.cpp ----------------------------------------- *- C++ --*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/DebugInfo/CodeView/RecordName.h"
10
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
13 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
14 #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
15 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
16 #include "llvm/Support/FormatVariadic.h"
17
18 using namespace llvm;
19 using namespace llvm::codeview;
20
21 namespace {
22 class TypeNameComputer : public TypeVisitorCallbacks {
23 /// The type collection. Used to calculate names of nested types.
24 TypeCollection &Types;
25 TypeIndex CurrentTypeIndex = TypeIndex::None();
26
27 /// Name of the current type. Only valid before visitTypeEnd.
28 SmallString<256> Name;
29
30 public:
31 explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}
32
33 StringRef name() const { return Name; }
34
35 /// Paired begin/end actions for all types. Receives all record data,
36 /// including the fixed-length record prefix.
37 Error visitTypeBegin(CVType &Record) override;
38 Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
39 Error visitTypeEnd(CVType &Record) override;
40
41 #define TYPE_RECORD(EnumName, EnumVal, Name) \
42 Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
43 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
44 #define MEMBER_RECORD(EnumName, EnumVal, Name)
45 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
46 };
47 } // namespace
48
49 Error TypeNameComputer::visitTypeBegin(CVType &Record) {
50 llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");
51 return Error::success();
52 }
53
54 Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {
55 // Reset Name to the empty string. If the visitor sets it, we know it.
56 Name = "";
57 CurrentTypeIndex = Index;
58 return Error::success();
59 }
60
61 Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }
62
63 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
64 FieldListRecord &FieldList) {
65 Name = "";
66 return Error::success();
67 }
68
69 Error TypeNameComputer::visitKnownRecord(CVRecord &CVR,
70 StringIdRecord &String) {
71 Name = String.getString();
72 return Error::success();
73 }
74
75 Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
76 auto Indices = Args.getIndices();
77 uint32_t Size = Indices.size();
78 Name = "(";
79 for (uint32_t I = 0; I < Size; ++I) {
80 assert(Indices[I] < CurrentTypeIndex);
81
82 Name.append(Types.getTypeName(Indices[I]));
83 if (I + 1 != Size)
84 Name.append(", ");
85 }
86 Name.push_back(')');
87 return Error::success();
88 }
89
90 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
91 StringListRecord &Strings) {
92 auto Indices = Strings.getIndices();
93 uint32_t Size = Indices.size();
94 Name = "\"";
95 for (uint32_t I = 0; I < Size; ++I) {
96 Name.append(Types.getTypeName(Indices[I]));
97 if (I + 1 != Size)
98 Name.append("\" \"");
99 }
100 Name.push_back('\"');
101 return Error::success();
102 }
103
104 Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
105 Name = Class.getName();
106 return Error::success();
107 }
108
109 Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
110 Name = Union.getName();
111 return Error::success();
112 }
113
114 Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
115 Name = Enum.getName();
116 return Error::success();
117 }
118
119 Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
120 Name = AT.getName();
121 return Error::success();
122 }
123
124 Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
125 Name = VFT.getName();
126 return Error::success();
127 }
128
129 Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
130 Name = Id.getName();
131 return Error::success();
132 }
133
134 Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
135 StringRef Ret = Types.getTypeName(Proc.getReturnType());
136 StringRef Params = Types.getTypeName(Proc.getArgumentList());
137 Name = formatv("{0} {1}", Ret, Params).sstr<256>();
138 return Error::success();
139 }
140
141 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
142 MemberFunctionRecord &MF) {
143 StringRef Ret = Types.getTypeName(MF.getReturnType());
144 StringRef Class = Types.getTypeName(MF.getClassType());
145 StringRef Params = Types.getTypeName(MF.getArgumentList());
146 Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();
147 return Error::success();
148 }
149
150 Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
151 Name = Func.getName();
152 return Error::success();
153 }
154
155 Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
156 Name = TS.getName();
157 return Error::success();
158 }
159
160 Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
161
162 if (Ptr.isPointerToMember()) {
163 const MemberPointerInfo &MI = Ptr.getMemberInfo();
164
165 StringRef Pointee = Types.getTypeName(Ptr.getReferentType());
166 StringRef Class = Types.getTypeName(MI.getContainingType());
167 Name = formatv("{0} {1}::*", Pointee, Class);
168 } else {
169 Name.append(Types.getTypeName(Ptr.getReferentType()));
170
171 if (Ptr.getMode() == PointerMode::LValueReference)
172 Name.append("&");
173 else if (Ptr.getMode() == PointerMode::RValueReference)
174 Name.append("&&");
175 else if (Ptr.getMode() == PointerMode::Pointer)
176 Name.append("*");
177
178 // Qualifiers in pointer records apply to the pointer, not the pointee, so
179 // they go on the right.
180 if (Ptr.isConst())
181 Name.append(" const");
182 if (Ptr.isVolatile())
183 Name.append(" volatile");
184 if (Ptr.isUnaligned())
185 Name.append(" __unaligned");
186 if (Ptr.isRestrict())
187 Name.append(" __restrict");
188 }
189 return Error::success();
190 }
191
192 Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
193 uint16_t Mods = static_cast(Mod.getModifiers());
194
195 if (Mods & uint16_t(ModifierOptions::Const))
196 Name.append("const ");
197 if (Mods & uint16_t(ModifierOptions::Volatile))
198 Name.append("volatile ");
199 if (Mods & uint16_t(ModifierOptions::Unaligned))
200 Name.append("__unaligned ");
201 Name.append(Types.getTypeName(Mod.getModifiedType()));
202 return Error::success();
203 }
204
205 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
206 VFTableShapeRecord &Shape) {
207 Name = formatv("", Shape.getEntryCount());
208 return Error::success();
209 }
210
211 Error TypeNameComputer::visitKnownRecord(
212 CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
213 return Error::success();
214 }
215
216 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
217 UdtSourceLineRecord &SourceLine) {
218 return Error::success();
219 }
220
221 Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
222 return Error::success();
223 }
224
225 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
226 MethodOverloadListRecord &Overloads) {
227 return Error::success();
228 }
229
230 Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
231 return Error::success();
232 }
233
234 Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) {
235 return Error::success();
236 }
237
238 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
239 PrecompRecord &Precomp) {
240 return Error::success();
241 }
242
243 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
244 EndPrecompRecord &EndPrecomp) {
245 return Error::success();
246 }
247
248 std::string llvm::codeview::computeTypeName(TypeCollection &Types,
249 TypeIndex Index) {
250 TypeNameComputer Computer(Types);
251 CVType Record = Types.getType(Index);
252 if (auto EC = visitTypeRecord(Record, Index, Computer)) {
253 consumeError(std::move(EC));
254 return "";
255 }
256 return Computer.name();
257 }
258
259 static int getSymbolNameOffset(CVSymbol Sym) {
260 switch (Sym.kind()) {
261 // See ProcSym
262 case SymbolKind::S_GPROC32:
263 case SymbolKind::S_LPROC32:
264 case SymbolKind::S_GPROC32_ID:
265 case SymbolKind::S_LPROC32_ID:
266 case SymbolKind::S_LPROC32_DPC:
267 case SymbolKind::S_LPROC32_DPC_ID:
268 return 35;
269 // See Thunk32Sym
270 case SymbolKind::S_THUNK32:
271 return 21;
272 // See SectionSym
273 case SymbolKind::S_SECTION:
274 return 16;
275 // See CoffGroupSym
276 case SymbolKind::S_COFFGROUP:
277 return 14;
278 // See PublicSym32, FileStaticSym, RegRelativeSym, DataSym, ThreadLocalDataSym
279 case SymbolKind::S_PUB32:
280 case SymbolKind::S_FILESTATIC:
281 case SymbolKind::S_REGREL32:
282 case SymbolKind::S_GDATA32:
283 case SymbolKind::S_LDATA32:
284 case SymbolKind::S_LMANDATA:
285 case SymbolKind::S_GMANDATA:
286 case SymbolKind::S_LTHREAD32:
287 case SymbolKind::S_GTHREAD32:
288 return 10;
289 // See RegisterSym and LocalSym
290 case SymbolKind::S_REGISTER:
291 case SymbolKind::S_LOCAL:
292 return 6;
293 // See BlockSym
294 case SymbolKind::S_BLOCK32:
295 return 18;
296 // See LabelSym
297 case SymbolKind::S_LABEL32:
298 return 7;
299 // See ObjNameSym, ExportSym, and UDTSym
300 case SymbolKind::S_OBJNAME:
301 case SymbolKind::S_EXPORT:
302 case SymbolKind::S_UDT:
303 return 4;
304 // See BPRelativeSym
305 case SymbolKind::S_BPREL32:
306 return 8;
307 default:
308 return -1;
309 }
310 }
311
312 StringRef llvm::codeview::getSymbolName(CVSymbol Sym) {
313 if (Sym.kind() == SymbolKind::S_CONSTANT) {
314 // S_CONSTANT is preceded by an APSInt, which has a variable length. So we
315 // have to do a full deserialization.
316 BinaryStreamReader Reader(Sym.content(), llvm::support::little);
317 // The container doesn't matter for single records.
318 SymbolRecordMapping Mapping(Reader, CodeViewContainer::ObjectFile);
319 ConstantSym Const(SymbolKind::S_CONSTANT);
320 cantFail(Mapping.visitSymbolBegin(Sym));
321 cantFail(Mapping.visitKnownRecord(Sym, Const));
322 cantFail(Mapping.visitSymbolEnd(Sym));
323 return Const.Name;
324 }
325
326 int Offset = getSymbolNameOffset(Sym);
327 if (Offset == -1)
328 return StringRef();
329
330 StringRef StringData = toStringRef(Sym.content()).drop_front(Offset);
331 return StringData.split('\0').first;
332 }
0 //===- RecordName.cpp ----------------------------------------- *- C++ --*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/DebugInfo/CodeView/RecordName.h"
10
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
13 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
14 #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
15 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
16 #include "llvm/Support/FormatVariadic.h"
17
18 using namespace llvm;
19 using namespace llvm::codeview;
20
21 namespace {
22 class TypeNameComputer : public TypeVisitorCallbacks {
23 /// The type collection. Used to calculate names of nested types.
24 TypeCollection &Types;
25 TypeIndex CurrentTypeIndex = TypeIndex::None();
26
27 /// Name of the current type. Only valid before visitTypeEnd.
28 SmallString<256> Name;
29
30 public:
31 explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}
32
33 StringRef name() const { return Name; }
34
35 /// Paired begin/end actions for all types. Receives all record data,
36 /// including the fixed-length record prefix.
37 Error visitTypeBegin(CVType &Record) override;
38 Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
39 Error visitTypeEnd(CVType &Record) override;
40
41 #define TYPE_RECORD(EnumName, EnumVal, Name) \
42 Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
43 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
44 #define MEMBER_RECORD(EnumName, EnumVal, Name)
45 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
46 };
47 } // namespace
48
49 Error TypeNameComputer::visitTypeBegin(CVType &Record) {
50 llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");
51 return Error::success();
52 }
53
54 Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {
55 // Reset Name to the empty string. If the visitor sets it, we know it.
56 Name = "";
57 CurrentTypeIndex = Index;
58 return Error::success();
59 }
60
61 Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }
62
63 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
64 FieldListRecord &FieldList) {
65 Name = "";
66 return Error::success();
67 }
68
69 Error TypeNameComputer::visitKnownRecord(CVRecord &CVR,
70 StringIdRecord &String) {
71 Name = String.getString();
72 return Error::success();
73 }
74
75 Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
76 auto Indices = Args.getIndices();
77 uint32_t Size = Indices.size();
78 Name = "(";
79 for (uint32_t I = 0; I < Size; ++I) {
80 assert(Indices[I] < CurrentTypeIndex);
81
82 Name.append(Types.getTypeName(Indices[I]));
83 if (I + 1 != Size)
84 Name.append(", ");
85 }
86 Name.push_back(')');
87 return Error::success();
88 }
89
90 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
91 StringListRecord &Strings) {
92 auto Indices = Strings.getIndices();
93 uint32_t Size = Indices.size();
94 Name = "\"";
95 for (uint32_t I = 0; I < Size; ++I) {
96 Name.append(Types.getTypeName(Indices[I]));
97 if (I + 1 != Size)
98 Name.append("\" \"");
99 }
100 Name.push_back('\"');
101 return Error::success();
102 }
103
104 Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
105 Name = Class.getName();
106 return Error::success();
107 }
108
109 Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
110 Name = Union.getName();
111 return Error::success();
112 }
113
114 Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
115 Name = Enum.getName();
116 return Error::success();
117 }
118
119 Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
120 Name = AT.getName();
121 return Error::success();
122 }
123
124 Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
125 Name = VFT.getName();
126 return Error::success();
127 }
128
129 Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
130 Name = Id.getName();
131 return Error::success();
132 }
133
134 Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
135 StringRef Ret = Types.getTypeName(Proc.getReturnType());
136 StringRef Params = Types.getTypeName(Proc.getArgumentList());
137 Name = formatv("{0} {1}", Ret, Params).sstr<256>();
138 return Error::success();
139 }
140
141 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
142 MemberFunctionRecord &MF) {
143 StringRef Ret = Types.getTypeName(MF.getReturnType());
144 StringRef Class = Types.getTypeName(MF.getClassType());
145 StringRef Params = Types.getTypeName(MF.getArgumentList());
146 Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();
147 return Error::success();
148 }
149
150 Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
151 Name = Func.getName();
152 return Error::success();
153 }
154
155 Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
156 Name = TS.getName();
157 return Error::success();
158 }
159
160 Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
161
162 if (Ptr.isPointerToMember()) {
163 const MemberPointerInfo &MI = Ptr.getMemberInfo();
164
165 StringRef Pointee = Types.getTypeName(Ptr.getReferentType());
166 StringRef Class = Types.getTypeName(MI.getContainingType());
167 Name = formatv("{0} {1}::*", Pointee, Class);
168 } else {
169 Name.append(Types.getTypeName(Ptr.getReferentType()));
170
171 if (Ptr.getMode() == PointerMode::LValueReference)
172 Name.append("&");
173 else if (Ptr.getMode() == PointerMode::RValueReference)
174 Name.append("&&");
175 else if (Ptr.getMode() == PointerMode::Pointer)
176 Name.append("*");
177
178 // Qualifiers in pointer records apply to the pointer, not the pointee, so
179 // they go on the right.
180 if (Ptr.isConst())
181 Name.append(" const");
182 if (Ptr.isVolatile())
183 Name.append(" volatile");
184 if (Ptr.isUnaligned())
185 Name.append(" __unaligned");
186 if (Ptr.isRestrict())
187 Name.append(" __restrict");
188 }
189 return Error::success();
190 }
191
192 Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
193 uint16_t Mods = static_cast(Mod.getModifiers());
194
195 if (Mods & uint16_t(ModifierOptions::Const))
196 Name.append("const ");
197 if (Mods & uint16_t(ModifierOptions::Volatile))
198 Name.append("volatile ");
199 if (Mods & uint16_t(ModifierOptions::Unaligned))
200 Name.append("__unaligned ");
201 Name.append(Types.getTypeName(Mod.getModifiedType()));
202 return Error::success();
203 }
204
205 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
206 VFTableShapeRecord &Shape) {
207 Name = formatv("", Shape.getEntryCount());
208 return Error::success();
209 }
210
211 Error TypeNameComputer::visitKnownRecord(
212 CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
213 return Error::success();
214 }
215
216 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
217 UdtSourceLineRecord &SourceLine) {
218 return Error::success();
219 }
220
221 Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
222 return Error::success();
223 }
224
225 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
226 MethodOverloadListRecord &Overloads) {
227 return Error::success();
228 }
229
230 Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
231 return Error::success();
232 }
233
234 Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) {
235 return Error::success();
236 }
237
238 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
239 PrecompRecord &Precomp) {
240 return Error::success();
241 }
242
243 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
244 EndPrecompRecord &EndPrecomp) {
245 return Error::success();
246 }
247
248 std::string llvm::codeview::computeTypeName(TypeCollection &Types,
249 TypeIndex Index) {
250 TypeNameComputer Computer(Types);
251 CVType Record = Types.getType(Index);
252 if (auto EC = visitTypeRecord(Record, Index, Computer)) {
253 consumeError(std::move(EC));
254 return "";
255 }
256 return Computer.name();
257 }
258
259 static int getSymbolNameOffset(CVSymbol Sym) {
260 switch (Sym.kind()) {
261 // See ProcSym
262 case SymbolKind::S_GPROC32:
263 case SymbolKind::S_LPROC32:
264 case SymbolKind::S_GPROC32_ID:
265 case SymbolKind::S_LPROC32_ID:
266 case SymbolKind::S_LPROC32_DPC:
267 case SymbolKind::S_LPROC32_DPC_ID:
268 return 35;
269 // See Thunk32Sym
270 case SymbolKind::S_THUNK32:
271 return 21;
272 // See SectionSym
273 case SymbolKind::S_SECTION:
274 return 16;
275 // See CoffGroupSym
276 case SymbolKind::S_COFFGROUP:
277 return 14;
278 // See PublicSym32, FileStaticSym, RegRelativeSym, DataSym, ThreadLocalDataSym
279 case SymbolKind::S_PUB32:
280 case SymbolKind::S_FILESTATIC:
281 case SymbolKind::S_REGREL32:
282 case SymbolKind::S_GDATA32:
283 case SymbolKind::S_LDATA32:
284 case SymbolKind::S_LMANDATA:
285 case SymbolKind::S_GMANDATA:
286 case SymbolKind::S_LTHREAD32:
287 case SymbolKind::S_GTHREAD32:
288 return 10;
289 // See RegisterSym and LocalSym
290 case SymbolKind::S_REGISTER:
291 case SymbolKind::S_LOCAL:
292 return 6;
293 // See BlockSym
294 case SymbolKind::S_BLOCK32:
295 return 18;
296 // See LabelSym
297 case SymbolKind::S_LABEL32:
298 return 7;
299 // See ObjNameSym, ExportSym, and UDTSym
300 case SymbolKind::S_OBJNAME:
301 case SymbolKind::S_EXPORT:
302 case SymbolKind::S_UDT:
303 return 4;
304 // See BPRelativeSym
305 case SymbolKind::S_BPREL32:
306 return 8;
307 default:
308 return -1;
309 }
310 }
311
312 StringRef llvm::codeview::getSymbolName(CVSymbol Sym) {
313 if (Sym.kind() == SymbolKind::S_CONSTANT) {
314 // S_CONSTANT is preceded by an APSInt, which has a variable length. So we
315 // have to do a full deserialization.
316 BinaryStreamReader Reader(Sym.content(), llvm::support::little);
317 // The container doesn't matter for single records.
318 SymbolRecordMapping Mapping(Reader, CodeViewContainer::ObjectFile);
319 ConstantSym Const(SymbolKind::S_CONSTANT);
320 cantFail(Mapping.visitSymbolBegin(Sym));
321 cantFail(Mapping.visitKnownRecord(Sym, Const));
322 cantFail(Mapping.visitSymbolEnd(Sym));
323 return Const.Name;
324 }
325
326 int Offset = getSymbolNameOffset(Sym);
327 if (Offset == -1)
328 return StringRef();
329
330 StringRef StringData = toStringRef(Sym.content()).drop_front(Offset);
331 return StringData.split('\0').first;
332 }
None //===-- TypeDumpVisitor.cpp - CodeView type info dumper ----------*- C++-*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
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 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 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 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 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 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 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 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 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 TypeModifierNames[] = {
106 ENUM_ENTRY(ModifierOptions, Const), ENUM_ENTRY(ModifierOptions, Volatile),
107 ENUM_ENTRY(ModifierOptions, Unaligned),
108 };
109
110 static const EnumEntry 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 FunctionOptionEnum[] = {
138 ENUM_ENTRY(FunctionOptions, CxxReturnUdt),
139 ENUM_ENTRY(FunctionOptions, Constructor),
140 ENUM_ENTRY(FunctionOptions, ConstructorWithVirtualBases),
141 };
142
143 static const EnumEntry LabelTypeEnum[] = {
144 ENUM_ENTRY(LabelType, Near), ENUM_ENTRY(LabelType, Far),
145 };
146
147 #undef ENUM_ENTRY
148
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
161 void TypeDumpVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const {
162 codeview::printTypeIndex(*W, FieldName, TI, TpiTypes);
163 }
164
165 void TypeDumpVisitor::printItemIndex(StringRef FieldName, TypeIndex TI) const {
166 codeview::printTypeIndex(*W, FieldName, TI, getSourceTypes());
167 }
168
169 Error TypeDumpVisitor::visitTypeBegin(CVType &Record) {
170 return visitTypeBegin(Record, TypeIndex::fromArrayIndex(TpiTypes.size()));
171 }
172
173 Error TypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) {
174 W->startLine() << getLeafTypeName(Record.Type);
175 W->getOStream() << " (" << HexNumber(Index.getIndex()) << ")";
176 W->getOStream() << " {\n";
177 W->indent();
178 W->printEnum("TypeLeafKind", unsigned(Record.Type),
179 makeArrayRef(LeafTypeNames));
180 return Error::success();
181 }
182
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
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
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
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
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
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
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
246 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
247 uint16_t Props = static_cast(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
260 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
261 uint16_t Props = static_cast(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
272 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
273 uint16_t Props = static_cast(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
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
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
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
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
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
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
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
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
361 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
362 printTypeIndex("PointeeType", Ptr.getReferentType());
363 W->printHex("PointerAttributes", uint32_t(Ptr.getOptions()));
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("SizeOf", Ptr.getSize());
374
375 if (Ptr.isPointerToMember()) {
376 const MemberPointerInfo &MI = Ptr.getMemberInfo();
377
378 printTypeIndex("ClassType", MI.getContainingType());
379 W->printEnum("Representation", uint16_t(MI.getRepresentation()),
380 makeArrayRef(PtrMemberRepNames));
381 }
382
383 return Error::success();
384 }
385
386 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
387 uint16_t Mods = static_cast(Mod.getModifiers());
388 printTypeIndex("ModifiedType", Mod.getModifiedType());
389 W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames));
390
391 return Error::success();
392 }
393
394 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BitFieldRecord &BitField) {
395 printTypeIndex("Type", BitField.getType());
396 W->printNumber("BitSize", BitField.getBitSize());
397 W->printNumber("BitOffset", BitField.getBitOffset());
398 return Error::success();
399 }
400
401 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
402 VFTableShapeRecord &Shape) {
403 W->printNumber("VFEntryCount", Shape.getEntryCount());
404 return Error::success();
405 }
406
407 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
408 UdtSourceLineRecord &Line) {
409 printTypeIndex("UDT", Line.getUDT());
410 printItemIndex("SourceFile", Line.getSourceFile());
411 W->printNumber("LineNumber", Line.getLineNumber());
412 return Error::success();
413 }
414
415 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
416 UdtModSourceLineRecord &Line) {
417 printTypeIndex("UDT", Line.getUDT());
418 printItemIndex("SourceFile", Line.getSourceFile());
419 W->printNumber("LineNumber", Line.getLineNumber());
420 W->printNumber("Module", Line.getModule());
421 return Error::success();
422 }
423
424 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &Args) {
425 W->printNumber("NumArgs", static_cast(Args.getArgs().size()));
426
427 ListScope Arguments(*W, "Arguments");
428 for (auto Arg : Args.getArgs()) {
429 printItemIndex("ArgType", Arg);
430 }
431 return Error::success();
432 }
433
434 void TypeDumpVisitor::printMemberAttributes(MemberAttributes Attrs) {
435 return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(),
436 Attrs.getFlags());
437 }
438
439 void TypeDumpVisitor::printMemberAttributes(MemberAccess Access,
440 MethodKind Kind,
441 MethodOptions Options) {
442 W->printEnum("AccessSpecifier", uint8_t(Access),
443 makeArrayRef(MemberAccessNames));
444 // Data members will be vanilla. Don't try to print a method kind for them.
445 if (Kind != MethodKind::Vanilla)
446 W->printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames));
447 if (Options != MethodOptions::None) {
448 W->printFlags("MethodOptions", unsigned(Options),
449 makeArrayRef(MethodOptionNames));
450 }
451 }
452
453 Error TypeDumpVisitor::visitUnknownMember(CVMemberRecord &Record) {
454 W->printHex("UnknownMember", unsigned(Record.Kind));
455 return Error::success();
456 }
457
458 Error TypeDumpVisitor::visitUnknownType(CVType &Record) {
459 W->printEnum("Kind", uint16_t(Record.kind()), makeArrayRef(LeafTypeNames));
460 W->printNumber("Length", uint32_t(Record.content().size()));
461 return Error::success();
462 }
463
464 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
465 NestedTypeRecord &Nested) {
466 printTypeIndex("Type", Nested.getNestedType());
467 W->printString("Name", Nested.getName());
468 return Error::success();
469 }
470
471 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
472 OneMethodRecord &Method) {
473 MethodKind K = Method.getMethodKind();
474 printMemberAttributes(Method.getAccess(), K, Method.getOptions());
475 printTypeIndex("Type", Method.getType());
476 // If virtual, then read the vftable offset.
477 if (Method.isIntroducingVirtual())
478 W->printHex("VFTableOffset", Method.getVFTableOffset());
479 W->printString("Name", Method.getName());
480 return Error::success();
481 }
482
483 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
484 OverloadedMethodRecord &Method) {
485 W->printHex("MethodCount", Method.getNumOverloads());
486 printTypeIndex("MethodListIndex", Method.getMethodList());
487 W->printString("Name", Method.getName());
488 return Error::success();
489 }
490
491 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
492 DataMemberRecord &Field) {
493 printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
494 MethodOptions::None);
495 printTypeIndex("Type", Field.getType());
496 W->printHex("FieldOffset", Field.getFieldOffset());
497 W->printString("Name", Field.getName());
498 return Error::success();
499 }
500
501 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
502 StaticDataMemberRecord &Field) {
503 printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
504 MethodOptions::None);
505 printTypeIndex("Type", Field.getType());
506 W->printString("Name", Field.getName());
507 return Error::success();
508 }
509
510 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
511 VFPtrRecord &VFTable) {
512 printTypeIndex("Type", VFTable.getType());
513 return Error::success();
514 }
515
516 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
517 EnumeratorRecord &Enum) {
518 printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
519 MethodOptions::None);
520 W->printNumber("EnumValue", Enum.getValue());
521 W->printString("Name", Enum.getName());
522 return Error::success();
523 }
524
525 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
526 BaseClassRecord &Base) {
527 printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
528 MethodOptions::None);
529 printTypeIndex("BaseType", Base.getBaseType());
530 W->printHex("BaseOffset", Base.getBaseOffset());
531 return Error::success();
532 }
533
534 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
535 VirtualBaseClassRecord &Base) {
536 printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
537 MethodOptions::None);
538 printTypeIndex("BaseType", Base.getBaseType());
539 printTypeIndex("VBPtrType", Base.getVBPtrType());
540 W->printHex("VBPtrOffset", Base.getVBPtrOffset());
541 W->printHex("VBTableIndex", Base.getVTableIndex());
542 return Error::success();
543 }
544
545 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
546 ListContinuationRecord &Cont) {
547 printTypeIndex("ContinuationIndex", Cont.getContinuationIndex());
548 return Error::success();
549 }
550
551 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, LabelRecord &LR) {
552 W->printEnum("Mode", uint16_t(LR.Mode), makeArrayRef(LabelTypeEnum));
553 return Error::success();
554 }
555
556 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
557 PrecompRecord &Precomp) {
558 W->printHex("StartIndex", Precomp.getStartTypeIndex());
559 W->printHex("Count", Precomp.getTypesCount());
560 W->printHex("Signature", Precomp.getSignature());
561 W->printString("PrecompFile", Precomp.getPrecompFilePath());
562 return Error::success();
563 }
564
565 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
566 EndPrecompRecord &EndPrecomp) {
567 W->printHex("Signature", EndPrecomp.getSignature());
568 return Error::success();
569 }
0 //===-- TypeDumpVisitor.cpp - CodeView type info dumper ----------*- C++-*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
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 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 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 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 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 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 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 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 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 TypeModifierNames[] = {
106 ENUM_ENTRY(ModifierOptions, Const), ENUM_ENTRY(ModifierOptions, Volatile),
107 ENUM_ENTRY(ModifierOptions, Unaligned),
108 };
109
110 static const EnumEntry 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 FunctionOptionEnum[] = {
138 ENUM_ENTRY(FunctionOptions, CxxReturnUdt),
139 ENUM_ENTRY(FunctionOptions, Constructor),
140 ENUM_ENTRY(FunctionOptions, ConstructorWithVirtualBases),
141 };
142
143 static const EnumEntry LabelTypeEnum[] = {
144 ENUM_ENTRY(LabelType, Near), ENUM_ENTRY(LabelType, Far),
145 };
146
147 #undef ENUM_ENTRY
148
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
161 void TypeDumpVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const {
162 codeview::printTypeIndex(*W, FieldName, TI, TpiTypes);
163 }
164
165 void TypeDumpVisitor::printItemIndex(StringRef FieldName, TypeIndex TI) const {
166 codeview::printTypeIndex(*W, FieldName, TI, getSourceTypes());
167 }
168
169 Error TypeDumpVisitor::visitTypeBegin(CVType &Record) {
170 return visitTypeBegin(Record, TypeIndex::fromArrayIndex(TpiTypes.size()));
171 }
172
173 Error TypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) {
174 W->startLine() << getLeafTypeName(Record.Type);
175 W->getOStream() << " (" << HexNumber(Index.getIndex()) << ")";
176 W->getOStream() << " {\n";
177 W->indent();
178 W->printEnum("TypeLeafKind", unsigned(Record.Type),
179 makeArrayRef(LeafTypeNames));
180 return Error::success();
181 }
182
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
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
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
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
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
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
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
246 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
247 uint16_t Props = static_cast(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
260 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
261 uint16_t Props = static_cast(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
272 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
273 uint16_t Props = static_cast(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
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
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
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
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
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
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
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
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
361 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
362 printTypeIndex("PointeeType", Ptr.getReferentType());
363 W->printHex("PointerAttributes", uint32_t(Ptr.getOptions()));
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("SizeOf", Ptr.getSize());
374
375 if (Ptr.isPointerToMember()) {
376 const MemberPointerInfo &MI = Ptr.getMemberInfo();
377
378 printTypeIndex("ClassType", MI.getContainingType());
379 W->printEnum("Representation", uint16_t(MI.getRepresentation()),
380 makeArrayRef(PtrMemberRepNames));
381 }
382
383 return Error::success();
384 }
385
386 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
387 uint16_t Mods = static_cast(Mod.getModifiers());
388 printTypeIndex("ModifiedType", Mod.getModifiedType());
389 W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames));
390
391 return Error::success();
392 }
393
394 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BitFieldRecord &BitField) {
395 printTypeIndex("Type", BitField.getType());
396 W->printNumber("BitSize", BitField.getBitSize());
397 W->printNumber("BitOffset", BitField.getBitOffset());
398 return Error::success();
399 }
400
401 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
402 VFTableShapeRecord &Shape) {
403 W->printNumber("VFEntryCount", Shape.getEntryCount());
404 return Error::success();
405 }
406
407 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
408 UdtSourceLineRecord &Line) {
409 printTypeIndex("UDT", Line.getUDT());
410 printItemIndex("SourceFile", Line.getSourceFile());
411 W->printNumber("LineNumber", Line.getLineNumber());
412 return Error::success();
413 }
414
415 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
416 UdtModSourceLineRecord &Line) {
417 printTypeIndex("UDT", Line.getUDT());
418 printItemIndex("SourceFile", Line.getSourceFile());
419 W->printNumber("LineNumber", Line.getLineNumber());
420 W->printNumber("Module", Line.getModule());
421 return Error::success();
422 }
423
424 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &Args) {
425 W->printNumber("NumArgs", static_cast(Args.getArgs().size()));
426
427 ListScope Arguments(*W, "Arguments");
428 for (auto Arg : Args.getArgs()) {
429 printItemIndex("ArgType", Arg);
430 }
431 return Error::success();
432 }
433
434 void TypeDumpVisitor::printMemberAttributes(MemberAttributes Attrs) {
435 return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(),
436 Attrs.getFlags());
437 }
438
439 void TypeDumpVisitor::printMemberAttributes(MemberAccess Access,
440 MethodKind Kind,
441 MethodOptions Options) {
442 W->printEnum("AccessSpecifier", uint8_t(Access),
443 makeArrayRef(MemberAccessNames));
444 // Data members will be vanilla. Don't try to print a method kind for them.
445 if (Kind != MethodKind::Vanilla)
446 W->printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames));
447 if (Options != MethodOptions::None) {
448 W->printFlags("MethodOptions", unsigned(Options),
449 makeArrayRef(MethodOptionNames));
450 }
451 }
452
453 Error TypeDumpVisitor::visitUnknownMember(CVMemberRecord &Record) {
454 W->printHex("UnknownMember", unsigned(Record.Kind));
455 return Error::success();
456 }
457
458 Error TypeDumpVisitor::visitUnknownType(CVType &Record) {
459 W->printEnum("Kind", uint16_t(Record.kind()), makeArrayRef(LeafTypeNames));
460 W->printNumber("Length", uint32_t(Record.content().size()));
461 return Error::success();
462 }
463
464 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
465 NestedTypeRecord &Nested) {
466 printTypeIndex("Type", Nested.getNestedType());
467 W->printString("Name", Nested.getName());
468 return Error::success();
469 }
470
471 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
472 OneMethodRecord &Method) {
473 MethodKind K = Method.getMethodKind();
474 printMemberAttributes(Method.getAccess(), K, Method.getOptions());
475 printTypeIndex("Type", Method.getType());
476 // If virtual, then read the vftable offset.
477 if (Method.isIntroducingVirtual())
478 W->printHex("VFTableOffset", Method.getVFTableOffset());
479 W->printString("Name", Method.getName());
480 return Error::success();
481 }
482
483 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
484 OverloadedMethodRecord &Method) {
485 W->printHex("MethodCount", Method.getNumOverloads());
486 printTypeIndex("MethodListIndex", Method.getMethodList());
487 W->printString("Name", Method.getName());
488 return Error::success();
489 }
490
491 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
492 DataMemberRecord &Field) {
493 printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
494 MethodOptions::None);
495 printTypeIndex("Type", Field.getType());
496 W->printHex("FieldOffset", Field.getFieldOffset());
497 W->printString("Name", Field.getName());
498 return Error::success();
499 }
500
501 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
502 StaticDataMemberRecord &Field) {
503 printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
504 MethodOptions::None);
505 printTypeIndex("Type", Field.getType());
506 W->printString("Name", Field.getName());
507 return Error::success();
508 }
509
510 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
511 VFPtrRecord &VFTable) {
512 printTypeIndex("Type", VFTable.getType());
513 return Error::success();
514 }
515
516 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
517 EnumeratorRecord &Enum) {
518 printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
519 MethodOptions::None);
520 W->printNumber("EnumValue", Enum.getValue());
521 W->printString("Name", Enum.getName());
522 return Error::success();
523 }
524
525 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
526 BaseClassRecord &Base) {
527 printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
528 MethodOptions::None);
529 printTypeIndex("BaseType", Base.getBaseType());
530 W->printHex("BaseOffset", Base.getBaseOffset());
531 return Error::success();
532