xref: /llvm-project/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h (revision 7df9da7d780f1ece175020c5aef44b4b06df05b7)
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 
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       PointerToMemberRepresentation::Unknown;
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 = ModifierOptions::None;
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 = CallingConvention::NearC;
165   FunctionOptions Options = FunctionOptions::None;
166   uint16_t ParameterCount = 0;
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 = 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
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 = LabelType::Near;
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<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
250 class StringListRecord : public TypeRecord {
251 public:
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
264 class PointerRecord : public TypeRecord {
265 public:
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 
357 private:
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
370 class NestedTypeRecord : public TypeRecord {
371 public:
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
385 class FieldListRecord : public TypeRecord {
386 public:
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
396 class ArrayRecord : public TypeRecord {
397 public:
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 
416 class TagRecord : public TypeRecord {
417 protected:
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 
425 public:
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
465 class ClassRecord : public TagRecord {
466 public:
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
498 struct 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
519 class EnumRecord : public TagRecord {
520 public:
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
535 class BitFieldRecord : public TypeRecord {
536 public:
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
553 class VFTableShapeRecord : public TypeRecord {
554 public:
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
575 class TypeServer2Record : public TypeRecord {
576 public:
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
595 class StringIdRecord : public TypeRecord {
596 public:
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
610 class FuncIdRecord : public TypeRecord {
611 public:
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
628 class UdtSourceLineRecord : public TypeRecord {
629 public:
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
646 class UdtModSourceLineRecord : public TypeRecord {
647 public:
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
667 class BuildInfoRecord : public TypeRecord {
668 public:
669   BuildInfoRecord() = default;
670   explicit BuildInfoRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
671   BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices)
672       : TypeRecord(TypeRecordKind::BuildInfo), ArgIndices(ArgIndices) {}
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 ArrayRef(MethodNames).front(); }
707 
708   ArrayRef<StringRef> getMethodNames() const {
709     return ArrayRef(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