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