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       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   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),
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
691 class VFTableRecord : public TypeRecord {
692 public:
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 makeArrayRef(MethodNames).front(); }
708 
709   ArrayRef<StringRef> getMethodNames() const {
710     return makeArrayRef(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
720 class OneMethodRecord : public TypeRecord {
721 public:
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
752 class MethodOverloadListRecord : public TypeRecord {
753 public:
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
765 class OverloadedMethodRecord : public TypeRecord {
766 public:
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
784 class DataMemberRecord : public TypeRecord {
785 public:
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
809 class StaticDataMemberRecord : public TypeRecord {
810 public:
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
830 class EnumeratorRecord : public TypeRecord {
831 public:
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
851 class VFPtrRecord : public TypeRecord {
852 public:
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
864 class BaseClassRecord : public TypeRecord {
865 public:
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
885 class VirtualBaseClassRecord : public TypeRecord {
886 public:
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.
915 class ListContinuationRecord : public TypeRecord {
916 public:
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
929 class PrecompRecord : public TypeRecord {
930 public:
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
946 class EndPrecompRecord : public TypeRecord {
947 public:
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