1//===- TypeRecord.h ---------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#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/SmallVector.h"
15#include "llvm/ADT/StringRef.h"
16#include "llvm/DebugInfo/CodeView/CVRecord.h"
17#include "llvm/DebugInfo/CodeView/CodeView.h"
18#include "llvm/DebugInfo/CodeView/GUID.h"
19#include "llvm/DebugInfo/CodeView/TypeIndex.h"
20#include "llvm/Support/BinaryStreamArray.h"
21#include "llvm/Support/Endian.h"
22#include <algorithm>
23#include <cstdint>
24#include <optional>
25#include <vector>
26
27namespace llvm {
28namespace codeview {
29
30using support::little32_t;
31using support::ulittle16_t;
32using support::ulittle32_t;
33
34struct CVMemberRecord {
35  TypeLeafKind Kind;
36  ArrayRef<uint8_t> Data;
37};
38
39/// Equvalent to CV_fldattr_t in cvinfo.h.
40struct MemberAttributes {
41  uint16_t Attrs = 0;
42
43  enum {
44    MethodKindShift = 2,
45  };
46
47  MemberAttributes() = default;
48
49  explicit MemberAttributes(MemberAccess Access)
50      : Attrs(static_cast<uint16_t>(Access)) {}
51
52  MemberAttributes(MemberAccess Access, MethodKind Kind, MethodOptions Flags) {
53    Attrs = static_cast<uint16_t>(Access);
54    Attrs |= (static_cast<uint16_t>(Kind) << MethodKindShift);
55    Attrs |= static_cast<uint16_t>(Flags);
56  }
57
58  /// Get the access specifier. Valid for any kind of member.
59  MemberAccess getAccess() const {
60    return MemberAccess(unsigned(Attrs) & unsigned(MethodOptions::AccessMask));
61  }
62
63  /// Indicates if a method is defined with friend, virtual, static, etc.
64  MethodKind getMethodKind() const {
65    return MethodKind(
66        (unsigned(Attrs) & unsigned(MethodOptions::MethodKindMask)) >>
67        MethodKindShift);
68  }
69
70  /// Get the flags that are not included in access control or method
71  /// properties.
72  MethodOptions getFlags() const {
73    return MethodOptions(
74        unsigned(Attrs) &
75        ~unsigned(MethodOptions::AccessMask | MethodOptions::MethodKindMask));
76  }
77
78  /// Is this method virtual.
79  bool isVirtual() const {
80    auto MP = getMethodKind();
81    return MP != MethodKind::Vanilla && MP != MethodKind::Friend &&
82           MP != MethodKind::Static;
83  }
84
85  /// Does this member introduce a new virtual method.
86  bool isIntroducedVirtual() const {
87    auto MP = getMethodKind();
88    return MP == MethodKind::IntroducingVirtual ||
89           MP == MethodKind::PureIntroducingVirtual;
90  }
91
92  /// Is this method static.
93  bool isStatic() const {
94    return getMethodKind() == MethodKind::Static;
95  }
96};
97
98// Does not correspond to any tag, this is the tail of an LF_POINTER record
99// if it represents a member pointer.
100class MemberPointerInfo {
101public:
102  MemberPointerInfo() = default;
103
104  MemberPointerInfo(TypeIndex ContainingType,
105                    PointerToMemberRepresentation Representation)
106      : ContainingType(ContainingType), Representation(Representation) {}
107
108  TypeIndex getContainingType() const { return ContainingType; }
109  PointerToMemberRepresentation getRepresentation() const {
110    return Representation;
111  }
112
113  TypeIndex ContainingType;
114  PointerToMemberRepresentation Representation =
115      PointerToMemberRepresentation::Unknown;
116};
117
118class TypeRecord {
119protected:
120  TypeRecord() = default;
121  explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {}
122
123public:
124  TypeRecordKind getKind() const { return Kind; }
125
126  TypeRecordKind Kind;
127};
128
129// LF_MODIFIER
130class ModifierRecord : public TypeRecord {
131public:
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 = ModifierOptions::None;
143};
144
145// LF_PROCEDURE
146class ProcedureRecord : public TypeRecord {
147public:
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 = CallingConvention::NearC;
165  FunctionOptions Options = FunctionOptions::None;
166  uint16_t ParameterCount = 0;
167  TypeIndex ArgumentList;
168};
169
170// LF_MFUNCTION
171class MemberFunctionRecord : public TypeRecord {
172public:
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 = CallingConvention::NearC;
199  FunctionOptions Options = FunctionOptions::None;
200  uint16_t ParameterCount = 0;
201  TypeIndex ArgumentList;
202  int32_t ThisPointerAdjustment = 0;
203};
204
205// LF_LABEL
206class LabelRecord : public TypeRecord {
207public:
208  LabelRecord() = default;
209  explicit LabelRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
210
211  LabelRecord(LabelType Mode) : TypeRecord(TypeRecordKind::Label), Mode(Mode) {}
212
213  LabelType Mode = LabelType::Near;
214};
215
216// LF_MFUNC_ID
217class MemberFuncIdRecord : public TypeRecord {
218public:
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
236class ArgListRecord : public TypeRecord {
237public:
238  ArgListRecord() = default;
239  explicit ArgListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
240
241  ArgListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
242      : TypeRecord(Kind), ArgIndices(Indices) {}
243
244  ArrayRef<TypeIndex> getIndices() const { return ArgIndices; }
245
246  std::vector<TypeIndex> ArgIndices;
247};
248
249// LF_SUBSTR_LIST
250class StringListRecord : public TypeRecord {
251public:
252  StringListRecord() = default;
253  explicit StringListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
254
255  StringListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
256      : TypeRecord(Kind), StringIndices(Indices) {}
257
258  ArrayRef<TypeIndex> getIndices() const { return StringIndices; }
259
260  std::vector<TypeIndex> StringIndices;
261};
262
263// LF_POINTER
264class PointerRecord : public TypeRecord {
265public:
266  // ---------------------------XXXXX
267  static const uint32_t PointerKindShift = 0;
268  static const uint32_t PointerKindMask = 0x1F;
269
270  // ------------------------XXX-----
271  static const uint32_t PointerModeShift = 5;
272  static const uint32_t PointerModeMask = 0x07;
273
274  // ----------XXX------XXXXX--------
275  static const uint32_t PointerOptionMask = 0x381f00;
276
277  // -------------XXXXXX------------
278  static const uint32_t PointerSizeShift = 13;
279  static const uint32_t PointerSizeMask = 0xFF;
280
281  PointerRecord() = default;
282  explicit PointerRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
283
284  PointerRecord(TypeIndex ReferentType, uint32_t Attrs)
285      : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
286        Attrs(Attrs) {}
287
288  PointerRecord(TypeIndex ReferentType, PointerKind PK, PointerMode PM,
289                PointerOptions PO, uint8_t Size)
290      : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
291        Attrs(calcAttrs(PK, PM, PO, Size)) {}
292
293  PointerRecord(TypeIndex ReferentType, PointerKind PK, PointerMode PM,
294                PointerOptions PO, uint8_t Size, const MemberPointerInfo &MPI)
295      : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
296        Attrs(calcAttrs(PK, PM, PO, Size)), MemberInfo(MPI) {}
297
298  TypeIndex getReferentType() const { return ReferentType; }
299
300  PointerKind getPointerKind() const {
301    return static_cast<PointerKind>((Attrs >> PointerKindShift) &
302                                    PointerKindMask);
303  }
304
305  PointerMode getMode() const {
306    return static_cast<PointerMode>((Attrs >> PointerModeShift) &
307                                    PointerModeMask);
308  }
309
310  PointerOptions getOptions() const {
311    return static_cast<PointerOptions>(Attrs & PointerOptionMask);
312  }
313
314  uint8_t getSize() const {
315    return (Attrs >> PointerSizeShift) & PointerSizeMask;
316  }
317
318  MemberPointerInfo getMemberInfo() const { return *MemberInfo; }
319
320  bool isPointerToMember() const {
321    return getMode() == PointerMode::PointerToDataMember ||
322           getMode() == PointerMode::PointerToMemberFunction;
323  }
324
325  bool isFlat() const { return !!(Attrs & uint32_t(PointerOptions::Flat32)); }
326  bool isConst() const { return !!(Attrs & uint32_t(PointerOptions::Const)); }
327
328  bool isVolatile() const {
329    return !!(Attrs & uint32_t(PointerOptions::Volatile));
330  }
331
332  bool isUnaligned() const {
333    return !!(Attrs & uint32_t(PointerOptions::Unaligned));
334  }
335
336  bool isRestrict() const {
337    return !!(Attrs & uint32_t(PointerOptions::Restrict));
338  }
339
340  bool isLValueReferenceThisPtr() const {
341    return !!(Attrs & uint32_t(PointerOptions::LValueRefThisPointer));
342  }
343
344  bool isRValueReferenceThisPtr() const {
345    return !!(Attrs & uint32_t(PointerOptions::RValueRefThisPointer));
346  }
347
348  TypeIndex ReferentType;
349  uint32_t Attrs = 0;
350  std::optional<MemberPointerInfo> MemberInfo;
351
352  void setAttrs(PointerKind PK, PointerMode PM, PointerOptions PO,
353                uint8_t Size) {
354    Attrs = calcAttrs(PK, PM, PO, Size);
355  }
356
357private:
358  static uint32_t calcAttrs(PointerKind PK, PointerMode PM, PointerOptions PO,
359                            uint8_t Size) {
360    uint32_t A = 0;
361    A |= static_cast<uint32_t>(PK);
362    A |= static_cast<uint32_t>(PO);
363    A |= (static_cast<uint32_t>(PM) << PointerModeShift);
364    A |= (static_cast<uint32_t>(Size) << PointerSizeShift);
365    return A;
366  }
367};
368
369// LF_NESTTYPE
370class NestedTypeRecord : public TypeRecord {
371public:
372  NestedTypeRecord() = default;
373  explicit NestedTypeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
374  NestedTypeRecord(TypeIndex Type, StringRef Name)
375      : TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {}
376
377  TypeIndex getNestedType() const { return Type; }
378  StringRef getName() const { return Name; }
379
380  TypeIndex Type;
381  StringRef Name;
382};
383
384// LF_FIELDLIST
385class FieldListRecord : public TypeRecord {
386public:
387  FieldListRecord() = default;
388  explicit FieldListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
389  explicit FieldListRecord(ArrayRef<uint8_t> Data)
390      : TypeRecord(TypeRecordKind::FieldList), Data(Data) {}
391
392  ArrayRef<uint8_t> Data;
393};
394
395// LF_ARRAY
396class ArrayRecord : public TypeRecord {
397public:
398  ArrayRecord() = default;
399  explicit ArrayRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
400  ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size,
401              StringRef Name)
402      : TypeRecord(TypeRecordKind::Array), ElementType(ElementType),
403        IndexType(IndexType), Size(Size), Name(Name) {}
404
405  TypeIndex getElementType() const { return ElementType; }
406  TypeIndex getIndexType() const { return IndexType; }
407  uint64_t getSize() const { return Size; }
408  StringRef getName() const { return Name; }
409
410  TypeIndex ElementType;
411  TypeIndex IndexType;
412  uint64_t Size = 0;
413  StringRef Name;
414};
415
416class TagRecord : public TypeRecord {
417protected:
418  TagRecord() = default;
419  explicit TagRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
420  TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
421            TypeIndex FieldList, StringRef Name, StringRef UniqueName)
422      : TypeRecord(Kind), MemberCount(MemberCount), Options(Options),
423        FieldList(FieldList), Name(Name), UniqueName(UniqueName) {}
424
425public:
426  static const int HfaKindShift = 11;
427  static const int HfaKindMask = 0x1800;
428  static const int WinRTKindShift = 14;
429  static const int WinRTKindMask = 0xC000;
430
431  bool hasUniqueName() const {
432    return (Options & ClassOptions::HasUniqueName) != ClassOptions::None;
433  }
434
435  bool isNested() const {
436    return (Options & ClassOptions::Nested) != ClassOptions::None;
437  }
438
439  bool isForwardRef() const {
440    return (Options & ClassOptions::ForwardReference) != ClassOptions::None;
441  }
442
443  bool containsNestedClass() const {
444    return (Options & ClassOptions::ContainsNestedClass) != ClassOptions::None;
445  }
446
447  bool isScoped() const {
448    return (Options & ClassOptions::Scoped) != ClassOptions::None;
449  }
450
451  uint16_t getMemberCount() const { return MemberCount; }
452  ClassOptions getOptions() const { return Options; }
453  TypeIndex getFieldList() const { return FieldList; }
454  StringRef getName() const { return Name; }
455  StringRef getUniqueName() const { return UniqueName; }
456
457  uint16_t MemberCount = 0;
458  ClassOptions Options = ClassOptions::None;
459  TypeIndex FieldList;
460  StringRef Name;
461  StringRef UniqueName;
462};
463
464// LF_CLASS, LF_STRUCTURE, LF_INTERFACE
465class ClassRecord : public TagRecord {
466public:
467  ClassRecord() = default;
468  explicit ClassRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
469  ClassRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
470              TypeIndex FieldList, TypeIndex DerivationList,
471              TypeIndex VTableShape, uint64_t Size, StringRef Name,
472              StringRef UniqueName)
473      : TagRecord(Kind, MemberCount, Options, FieldList, Name, UniqueName),
474        DerivationList(DerivationList), VTableShape(VTableShape), Size(Size) {}
475
476  HfaKind getHfa() const {
477    uint16_t Value = static_cast<uint16_t>(Options);
478    Value = (Value & HfaKindMask) >> HfaKindShift;
479    return static_cast<HfaKind>(Value);
480  }
481
482  WindowsRTClassKind getWinRTKind() const {
483    uint16_t Value = static_cast<uint16_t>(Options);
484    Value = (Value & WinRTKindMask) >> WinRTKindShift;
485    return static_cast<WindowsRTClassKind>(Value);
486  }
487
488  TypeIndex getDerivationList() const { return DerivationList; }
489  TypeIndex getVTableShape() const { return VTableShape; }
490  uint64_t getSize() const { return Size; }
491
492  TypeIndex DerivationList;
493  TypeIndex VTableShape;
494  uint64_t Size = 0;
495};
496
497// LF_UNION
498struct UnionRecord : public TagRecord {
499  UnionRecord() = default;
500  explicit UnionRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
501  UnionRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
502              uint64_t Size, StringRef Name, StringRef UniqueName)
503      : TagRecord(TypeRecordKind::Union, MemberCount, Options, FieldList, Name,
504                  UniqueName),
505        Size(Size) {}
506
507  HfaKind getHfa() const {
508    uint16_t Value = static_cast<uint16_t>(Options);
509    Value = (Value & HfaKindMask) >> HfaKindShift;
510    return static_cast<HfaKind>(Value);
511  }
512
513  uint64_t getSize() const { return Size; }
514
515  uint64_t Size = 0;
516};
517
518// LF_ENUM
519class EnumRecord : public TagRecord {
520public:
521  EnumRecord() = default;
522  explicit EnumRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
523  EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
524             StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType)
525      : TagRecord(TypeRecordKind::Enum, MemberCount, Options, FieldList, Name,
526                  UniqueName),
527        UnderlyingType(UnderlyingType) {}
528
529  TypeIndex getUnderlyingType() const { return UnderlyingType; }
530
531  TypeIndex UnderlyingType;
532};
533
534// LF_BITFIELD
535class BitFieldRecord : public TypeRecord {
536public:
537  BitFieldRecord() = default;
538  explicit BitFieldRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
539  BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset)
540      : TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize),
541        BitOffset(BitOffset) {}
542
543  TypeIndex getType() const { return Type; }
544  uint8_t getBitOffset() const { return BitOffset; }
545  uint8_t getBitSize() const { return BitSize; }
546
547  TypeIndex Type;
548  uint8_t BitSize = 0;
549  uint8_t BitOffset = 0;
550};
551
552// LF_VTSHAPE
553class VFTableShapeRecord : public TypeRecord {
554public:
555  VFTableShapeRecord() = default;
556  explicit VFTableShapeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
557  explicit VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots)
558      : TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {}
559  explicit VFTableShapeRecord(std::vector<VFTableSlotKind> Slots)
560      : TypeRecord(TypeRecordKind::VFTableShape), Slots(std::move(Slots)) {}
561
562  ArrayRef<VFTableSlotKind> getSlots() const {
563    if (!SlotsRef.empty())
564      return SlotsRef;
565    return Slots;
566  }
567
568  uint32_t getEntryCount() const { return getSlots().size(); }
569
570  ArrayRef<VFTableSlotKind> SlotsRef;
571  std::vector<VFTableSlotKind> Slots;
572};
573
574// LF_TYPESERVER2
575class TypeServer2Record : public TypeRecord {
576public:
577  TypeServer2Record() = default;
578  explicit TypeServer2Record(TypeRecordKind Kind) : TypeRecord(Kind) {}
579  TypeServer2Record(StringRef GuidStr, uint32_t Age, StringRef Name)
580      : TypeRecord(TypeRecordKind::TypeServer2), Age(Age), Name(Name) {
581    assert(GuidStr.size() == 16 && "guid isn't 16 bytes");
582    ::memcpy(Guid.Guid, GuidStr.data(), 16);
583  }
584
585  const GUID &getGuid() const { return Guid; }
586  uint32_t getAge() const { return Age; }
587  StringRef getName() const { return Name; }
588
589  GUID Guid = {};
590  uint32_t Age = 0;
591  StringRef Name;
592};
593
594// LF_STRING_ID
595class StringIdRecord : public TypeRecord {
596public:
597  StringIdRecord() = default;
598  explicit StringIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
599  StringIdRecord(TypeIndex Id, StringRef String)
600      : TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {}
601
602  TypeIndex getId() const { return Id; }
603  StringRef getString() const { return String; }
604
605  TypeIndex Id;
606  StringRef String;
607};
608
609// LF_FUNC_ID
610class FuncIdRecord : public TypeRecord {
611public:
612  FuncIdRecord() = default;
613  explicit FuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
614  FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name)
615      : TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope),
616        FunctionType(FunctionType), Name(Name) {}
617
618  TypeIndex getParentScope() const { return ParentScope; }
619  TypeIndex getFunctionType() const { return FunctionType; }
620  StringRef getName() const { return Name; }
621
622  TypeIndex ParentScope;
623  TypeIndex FunctionType;
624  StringRef Name;
625};
626
627// LF_UDT_SRC_LINE
628class UdtSourceLineRecord : public TypeRecord {
629public:
630  UdtSourceLineRecord() = default;
631  explicit UdtSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
632  UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber)
633      : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
634        SourceFile(SourceFile), LineNumber(LineNumber) {}
635
636  TypeIndex getUDT() const { return UDT; }
637  TypeIndex getSourceFile() const { return SourceFile; }
638  uint32_t getLineNumber() const { return LineNumber; }
639
640  TypeIndex UDT;
641  TypeIndex SourceFile;
642  uint32_t LineNumber = 0;
643};
644
645// LF_UDT_MOD_SRC_LINE
646class UdtModSourceLineRecord : public TypeRecord {
647public:
648  UdtModSourceLineRecord() = default;
649  explicit UdtModSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
650  UdtModSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile,
651                         uint32_t LineNumber, uint16_t Module)
652      : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
653        SourceFile(SourceFile), LineNumber(LineNumber), Module(Module) {}
654
655  TypeIndex getUDT() const { return UDT; }
656  TypeIndex getSourceFile() const { return SourceFile; }
657  uint32_t getLineNumber() const { return LineNumber; }
658  uint16_t getModule() const { return Module; }
659
660  TypeIndex UDT;
661  TypeIndex SourceFile;
662  uint32_t LineNumber = 0;
663  uint16_t Module = 0;
664};
665
666// LF_BUILDINFO
667class BuildInfoRecord : public TypeRecord {
668public:
669  BuildInfoRecord() = default;
670  explicit BuildInfoRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
671  BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices)
672      : TypeRecord(TypeRecordKind::BuildInfo),
673        ArgIndices(ArgIndices.begin(), ArgIndices.end()) {}
674
675  ArrayRef<TypeIndex> getArgs() const { return ArgIndices; }
676
677  /// Indices of known build info arguments.
678  enum BuildInfoArg {
679    CurrentDirectory, ///< Absolute CWD path
680    BuildTool,        ///< Absolute compiler path
681    SourceFile,       ///< Path to main source file, relative or absolute
682    TypeServerPDB,    ///< Absolute path of type server PDB (/Fd)
683    CommandLine,      ///< Full canonical command line (maybe -cc1)
684    MaxArgs
685  };
686
687  SmallVector<TypeIndex, MaxArgs> ArgIndices;
688};
689
690// LF_VFTABLE
691class VFTableRecord : public TypeRecord {
692public:
693  VFTableRecord() = default;
694  explicit VFTableRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
695  VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable,
696                uint32_t VFPtrOffset, StringRef Name,
697                ArrayRef<StringRef> Methods)
698      : TypeRecord(TypeRecordKind::VFTable), CompleteClass(CompleteClass),
699        OverriddenVFTable(OverriddenVFTable), VFPtrOffset(VFPtrOffset) {
700    MethodNames.push_back(Name);
701    llvm::append_range(MethodNames, Methods);
702  }
703
704  TypeIndex getCompleteClass() const { return CompleteClass; }
705  TypeIndex getOverriddenVTable() const { return OverriddenVFTable; }
706  uint32_t getVFPtrOffset() const { return VFPtrOffset; }
707  StringRef getName() const { return ArrayRef(MethodNames).front(); }
708
709  ArrayRef<StringRef> getMethodNames() const {
710    return ArrayRef(MethodNames).drop_front();
711  }
712
713  TypeIndex CompleteClass;
714  TypeIndex OverriddenVFTable;
715  uint32_t VFPtrOffset = 0;
716  std::vector<StringRef> MethodNames;
717};
718
719// LF_ONEMETHOD
720class OneMethodRecord : public TypeRecord {
721public:
722  OneMethodRecord() = default;
723  explicit OneMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
724  OneMethodRecord(TypeIndex Type, MemberAttributes Attrs, int32_t VFTableOffset,
725                  StringRef Name)
726      : TypeRecord(TypeRecordKind::OneMethod), Type(Type), Attrs(Attrs),
727        VFTableOffset(VFTableOffset), Name(Name) {}
728  OneMethodRecord(TypeIndex Type, MemberAccess Access, MethodKind MK,
729                  MethodOptions Options, int32_t VFTableOffset, StringRef Name)
730      : TypeRecord(TypeRecordKind::OneMethod), Type(Type),
731        Attrs(Access, MK, Options), VFTableOffset(VFTableOffset), Name(Name) {}
732
733  TypeIndex getType() const { return Type; }
734  MethodKind getMethodKind() const { return Attrs.getMethodKind(); }
735  MethodOptions getOptions() const { return Attrs.getFlags(); }
736  MemberAccess getAccess() const { return Attrs.getAccess(); }
737  int32_t getVFTableOffset() const { return VFTableOffset; }
738  StringRef getName() const { return Name; }
739
740  bool isIntroducingVirtual() const {
741    return getMethodKind() == MethodKind::IntroducingVirtual ||
742           getMethodKind() == MethodKind::PureIntroducingVirtual;
743  }
744
745  TypeIndex Type;
746  MemberAttributes Attrs;
747  int32_t VFTableOffset = 0;
748  StringRef Name;
749};
750
751// LF_METHODLIST
752class MethodOverloadListRecord : public TypeRecord {
753public:
754  MethodOverloadListRecord() = default;
755  explicit MethodOverloadListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
756  MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods)
757      : TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {}
758
759  ArrayRef<OneMethodRecord> getMethods() const { return Methods; }
760
761  std::vector<OneMethodRecord> Methods;
762};
763
764/// For method overload sets.  LF_METHOD
765class OverloadedMethodRecord : public TypeRecord {
766public:
767  OverloadedMethodRecord() = default;
768  explicit OverloadedMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
769  OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList,
770                         StringRef Name)
771      : TypeRecord(TypeRecordKind::OverloadedMethod),
772        NumOverloads(NumOverloads), MethodList(MethodList), Name(Name) {}
773
774  uint16_t getNumOverloads() const { return NumOverloads; }
775  TypeIndex getMethodList() const { return MethodList; }
776  StringRef getName() const { return Name; }
777
778  uint16_t NumOverloads = 0;
779  TypeIndex MethodList;
780  StringRef Name;
781};
782
783// LF_MEMBER
784class DataMemberRecord : public TypeRecord {
785public:
786  DataMemberRecord() = default;
787  explicit DataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
788  DataMemberRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset,
789                   StringRef Name)
790      : TypeRecord(TypeRecordKind::DataMember), Attrs(Attrs), Type(Type),
791        FieldOffset(Offset), Name(Name) {}
792  DataMemberRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset,
793                   StringRef Name)
794      : TypeRecord(TypeRecordKind::DataMember), Attrs(Access), Type(Type),
795        FieldOffset(Offset), Name(Name) {}
796
797  MemberAccess getAccess() const { return Attrs.getAccess(); }
798  TypeIndex getType() const { return Type; }
799  uint64_t getFieldOffset() const { return FieldOffset; }
800  StringRef getName() const { return Name; }
801
802  MemberAttributes Attrs;
803  TypeIndex Type;
804  uint64_t FieldOffset = 0;
805  StringRef Name;
806};
807
808// LF_STMEMBER
809class StaticDataMemberRecord : public TypeRecord {
810public:
811  StaticDataMemberRecord() = default;
812  explicit StaticDataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
813  StaticDataMemberRecord(MemberAttributes Attrs, TypeIndex Type, StringRef Name)
814      : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Attrs), Type(Type),
815        Name(Name) {}
816  StaticDataMemberRecord(MemberAccess Access, TypeIndex Type, StringRef Name)
817      : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Access), Type(Type),
818        Name(Name) {}
819
820  MemberAccess getAccess() const { return Attrs.getAccess(); }
821  TypeIndex getType() const { return Type; }
822  StringRef getName() const { return Name; }
823
824  MemberAttributes Attrs;
825  TypeIndex Type;
826  StringRef Name;
827};
828
829// LF_ENUMERATE
830class EnumeratorRecord : public TypeRecord {
831public:
832  EnumeratorRecord() = default;
833  explicit EnumeratorRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
834  EnumeratorRecord(MemberAttributes Attrs, APSInt Value, StringRef Name)
835      : TypeRecord(TypeRecordKind::Enumerator), Attrs(Attrs),
836        Value(std::move(Value)), Name(Name) {}
837  EnumeratorRecord(MemberAccess Access, APSInt Value, StringRef Name)
838      : TypeRecord(TypeRecordKind::Enumerator), Attrs(Access),
839        Value(std::move(Value)), Name(Name) {}
840
841  MemberAccess getAccess() const { return Attrs.getAccess(); }
842  APSInt getValue() const { return Value; }
843  StringRef getName() const { return Name; }
844
845  MemberAttributes Attrs;
846  APSInt Value;
847  StringRef Name;
848};
849
850// LF_VFUNCTAB
851class VFPtrRecord : public TypeRecord {
852public:
853  VFPtrRecord() = default;
854  explicit VFPtrRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
855  VFPtrRecord(TypeIndex Type)
856      : TypeRecord(TypeRecordKind::VFPtr), Type(Type) {}
857
858  TypeIndex getType() const { return Type; }
859
860  TypeIndex Type;
861};
862
863// LF_BCLASS, LF_BINTERFACE
864class BaseClassRecord : public TypeRecord {
865public:
866  BaseClassRecord() = default;
867  explicit BaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
868  BaseClassRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset)
869      : TypeRecord(TypeRecordKind::BaseClass), Attrs(Attrs), Type(Type),
870        Offset(Offset) {}
871  BaseClassRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset)
872      : TypeRecord(TypeRecordKind::BaseClass), Attrs(Access), Type(Type),
873        Offset(Offset) {}
874
875  MemberAccess getAccess() const { return Attrs.getAccess(); }
876  TypeIndex getBaseType() const { return Type; }
877  uint64_t getBaseOffset() const { return Offset; }
878
879  MemberAttributes Attrs;
880  TypeIndex Type;
881  uint64_t Offset = 0;
882};
883
884// LF_VBCLASS, LF_IVBCLASS
885class VirtualBaseClassRecord : public TypeRecord {
886public:
887  VirtualBaseClassRecord() = default;
888  explicit VirtualBaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
889  VirtualBaseClassRecord(TypeRecordKind Kind, MemberAttributes Attrs,
890                         TypeIndex BaseType, TypeIndex VBPtrType,
891                         uint64_t Offset, uint64_t Index)
892      : TypeRecord(Kind), Attrs(Attrs), BaseType(BaseType),
893        VBPtrType(VBPtrType), VBPtrOffset(Offset), VTableIndex(Index) {}
894  VirtualBaseClassRecord(TypeRecordKind Kind, MemberAccess Access,
895                         TypeIndex BaseType, TypeIndex VBPtrType,
896                         uint64_t Offset, uint64_t Index)
897      : TypeRecord(Kind), Attrs(Access), BaseType(BaseType),
898        VBPtrType(VBPtrType), VBPtrOffset(Offset), VTableIndex(Index) {}
899
900  MemberAccess getAccess() const { return Attrs.getAccess(); }
901  TypeIndex getBaseType() const { return BaseType; }
902  TypeIndex getVBPtrType() const { return VBPtrType; }
903  uint64_t getVBPtrOffset() const { return VBPtrOffset; }
904  uint64_t getVTableIndex() const { return VTableIndex; }
905
906  MemberAttributes Attrs;
907  TypeIndex BaseType;
908  TypeIndex VBPtrType;
909  uint64_t VBPtrOffset = 0;
910  uint64_t VTableIndex = 0;
911};
912
913/// LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records
914/// together. The first will end in an LF_INDEX record that points to the next.
915class ListContinuationRecord : public TypeRecord {
916public:
917  ListContinuationRecord() = default;
918  explicit ListContinuationRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
919  ListContinuationRecord(TypeIndex ContinuationIndex)
920      : TypeRecord(TypeRecordKind::ListContinuation),
921        ContinuationIndex(ContinuationIndex) {}
922
923  TypeIndex getContinuationIndex() const { return ContinuationIndex; }
924
925  TypeIndex ContinuationIndex;
926};
927
928// LF_PRECOMP
929class PrecompRecord : public TypeRecord {
930public:
931  PrecompRecord() = default;
932  explicit PrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
933
934  uint32_t getStartTypeIndex() const { return StartTypeIndex; }
935  uint32_t getTypesCount() const { return TypesCount; }
936  uint32_t getSignature() const { return Signature; }
937  StringRef getPrecompFilePath() const { return PrecompFilePath; }
938
939  uint32_t StartTypeIndex = 0;
940  uint32_t TypesCount = 0;
941  uint32_t Signature = 0;
942  StringRef PrecompFilePath;
943};
944
945// LF_ENDPRECOMP
946class EndPrecompRecord : public TypeRecord {
947public:
948  EndPrecompRecord() = default;
949  explicit EndPrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
950
951  uint32_t getSignature() const { return Signature; }
952
953  uint32_t Signature = 0;
954};
955
956} // end namespace codeview
957} // end namespace llvm
958
959#endif // LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H
960