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 
MemberAttributesMemberAttributes49   explicit MemberAttributes(MemberAccess Access)
50       : Attrs(static_cast<uint16_t>(Access)) {}
51 
MemberAttributesMemberAttributes52   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.
getAccessMemberAttributes59   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.
getMethodKindMemberAttributes64   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.
getFlagsMemberAttributes72   MethodOptions getFlags() const {
73     return MethodOptions(
74         unsigned(Attrs) &
75         ~unsigned(MethodOptions::AccessMask | MethodOptions::MethodKindMask));
76   }
77 
78   /// Is this method virtual.
isVirtualMemberAttributes79   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.
isIntroducedVirtualMemberAttributes86   bool isIntroducedVirtual() const {
87     auto MP = getMethodKind();
88     return MP == MethodKind::IntroducingVirtual ||
89            MP == MethodKind::PureIntroducingVirtual;
90   }
91 
92   /// Is this method static.
isStaticMemberAttributes93   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 
MemberPointerInfo(TypeIndex ContainingType,PointerToMemberRepresentation Representation)104   MemberPointerInfo(TypeIndex ContainingType,
105                     PointerToMemberRepresentation Representation)
106       : ContainingType(ContainingType), Representation(Representation) {}
107 
getContainingType()108   TypeIndex getContainingType() const { return ContainingType; }
getRepresentation()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;
TypeRecord(TypeRecordKind Kind)120   explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {}
121 
122 public:
getKind()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;
ModifierRecord(TypeRecordKind Kind)132   explicit ModifierRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ModifierRecord(TypeIndex ModifiedType,ModifierOptions Modifiers)133   ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers)
134       : TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType),
135         Modifiers(Modifiers) {}
136 
getModifiedType()137   TypeIndex getModifiedType() const { return ModifiedType; }
getModifiers()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;
ProcedureRecord(TypeRecordKind Kind)148   explicit ProcedureRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ProcedureRecord(TypeIndex ReturnType,CallingConvention CallConv,FunctionOptions Options,uint16_t ParameterCount,TypeIndex ArgumentList)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 
getReturnType()156   TypeIndex getReturnType() const { return ReturnType; }
getCallConv()157   CallingConvention getCallConv() const { return CallConv; }
getOptions()158   FunctionOptions getOptions() const { return Options; }
getParameterCount()159   uint16_t getParameterCount() const { return ParameterCount; }
getArgumentList()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;
MemberFunctionRecord(TypeRecordKind Kind)173   explicit MemberFunctionRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
174 
MemberFunctionRecord(TypeIndex ReturnType,TypeIndex ClassType,TypeIndex ThisType,CallingConvention CallConv,FunctionOptions Options,uint16_t ParameterCount,TypeIndex ArgumentList,int32_t ThisPointerAdjustment)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 
getReturnType()185   TypeIndex getReturnType() const { return ReturnType; }
getClassType()186   TypeIndex getClassType() const { return ClassType; }
getThisType()187   TypeIndex getThisType() const { return ThisType; }
getCallConv()188   CallingConvention getCallConv() const { return CallConv; }
getOptions()189   FunctionOptions getOptions() const { return Options; }
getParameterCount()190   uint16_t getParameterCount() const { return ParameterCount; }
getArgumentList()191   TypeIndex getArgumentList() const { return ArgumentList; }
getThisPointerAdjustment()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;
LabelRecord(TypeRecordKind Kind)208   explicit LabelRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
209 
LabelRecord(LabelType Mode)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;
MemberFuncIdRecord(TypeRecordKind Kind)219   explicit MemberFuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
MemberFuncIdRecord(TypeIndex ClassType,TypeIndex FunctionType,StringRef Name)220   MemberFuncIdRecord(TypeIndex ClassType, TypeIndex FunctionType,
221                          StringRef Name)
222       : TypeRecord(TypeRecordKind::MemberFuncId), ClassType(ClassType),
223         FunctionType(FunctionType), Name(Name) {}
224 
getClassType()225   TypeIndex getClassType() const { return ClassType; }
getFunctionType()226   TypeIndex getFunctionType() const { return FunctionType; }
getName()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;
ArgListRecord(TypeRecordKind Kind)238   explicit ArgListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
239 
ArgListRecord(TypeRecordKind Kind,ArrayRef<TypeIndex> Indices)240   ArgListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
241       : TypeRecord(Kind), ArgIndices(Indices) {}
242 
getIndices()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;
StringListRecord(TypeRecordKind Kind)252   explicit StringListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
253 
StringListRecord(TypeRecordKind Kind,ArrayRef<TypeIndex> Indices)254   StringListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
255       : TypeRecord(Kind), StringIndices(Indices) {}
256 
getIndices()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;
PointerRecord(TypeRecordKind Kind)281   explicit PointerRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
282 
PointerRecord(TypeIndex ReferentType,uint32_t Attrs)283   PointerRecord(TypeIndex ReferentType, uint32_t Attrs)
284       : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
285         Attrs(Attrs) {}
286 
PointerRecord(TypeIndex ReferentType,PointerKind PK,PointerMode PM,PointerOptions PO,uint8_t Size)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 
PointerRecord(TypeIndex ReferentType,PointerKind PK,PointerMode PM,PointerOptions PO,uint8_t Size,const MemberPointerInfo & MPI)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 
getReferentType()297   TypeIndex getReferentType() const { return ReferentType; }
298 
getPointerKind()299   PointerKind getPointerKind() const {
300     return static_cast<PointerKind>((Attrs >> PointerKindShift) &
301                                     PointerKindMask);
302   }
303 
getMode()304   PointerMode getMode() const {
305     return static_cast<PointerMode>((Attrs >> PointerModeShift) &
306                                     PointerModeMask);
307   }
308 
getOptions()309   PointerOptions getOptions() const {
310     return static_cast<PointerOptions>(Attrs & PointerOptionMask);
311   }
312 
getSize()313   uint8_t getSize() const {
314     return (Attrs >> PointerSizeShift) & PointerSizeMask;
315   }
316 
getMemberInfo()317   MemberPointerInfo getMemberInfo() const { return *MemberInfo; }
318 
isPointerToMember()319   bool isPointerToMember() const {
320     return getMode() == PointerMode::PointerToDataMember ||
321            getMode() == PointerMode::PointerToMemberFunction;
322   }
323 
isFlat()324   bool isFlat() const { return !!(Attrs & uint32_t(PointerOptions::Flat32)); }
isConst()325   bool isConst() const { return !!(Attrs & uint32_t(PointerOptions::Const)); }
326 
isVolatile()327   bool isVolatile() const {
328     return !!(Attrs & uint32_t(PointerOptions::Volatile));
329   }
330 
isUnaligned()331   bool isUnaligned() const {
332     return !!(Attrs & uint32_t(PointerOptions::Unaligned));
333   }
334 
isRestrict()335   bool isRestrict() const {
336     return !!(Attrs & uint32_t(PointerOptions::Restrict));
337   }
338 
isLValueReferenceThisPtr()339   bool isLValueReferenceThisPtr() const {
340     return !!(Attrs & uint32_t(PointerOptions::LValueRefThisPointer));
341   }
342 
isRValueReferenceThisPtr()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 
setAttrs(PointerKind PK,PointerMode PM,PointerOptions PO,uint8_t Size)351   void setAttrs(PointerKind PK, PointerMode PM, PointerOptions PO,
352                 uint8_t Size) {
353     Attrs = calcAttrs(PK, PM, PO, Size);
354   }
355 
356 private:
calcAttrs(PointerKind PK,PointerMode PM,PointerOptions PO,uint8_t Size)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;
NestedTypeRecord(TypeRecordKind Kind)372   explicit NestedTypeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
NestedTypeRecord(TypeIndex Type,StringRef Name)373   NestedTypeRecord(TypeIndex Type, StringRef Name)
374       : TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {}
375 
getNestedType()376   TypeIndex getNestedType() const { return Type; }
getName()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;
FieldListRecord(TypeRecordKind Kind)387   explicit FieldListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
FieldListRecord(ArrayRef<uint8_t> Data)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;
ArrayRecord(TypeRecordKind Kind)398   explicit ArrayRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ArrayRecord(TypeIndex ElementType,TypeIndex IndexType,uint64_t Size,StringRef Name)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 
getElementType()404   TypeIndex getElementType() const { return ElementType; }
getIndexType()405   TypeIndex getIndexType() const { return IndexType; }
getSize()406   uint64_t getSize() const { return Size; }
getName()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;
TagRecord(TypeRecordKind Kind)418   explicit TagRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
TagRecord(TypeRecordKind Kind,uint16_t MemberCount,ClassOptions Options,TypeIndex FieldList,StringRef Name,StringRef UniqueName)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 
hasUniqueName()430   bool hasUniqueName() const {
431     return (Options & ClassOptions::HasUniqueName) != ClassOptions::None;
432   }
433 
isNested()434   bool isNested() const {
435     return (Options & ClassOptions::Nested) != ClassOptions::None;
436   }
437 
isForwardRef()438   bool isForwardRef() const {
439     return (Options & ClassOptions::ForwardReference) != ClassOptions::None;
440   }
441 
containsNestedClass()442   bool containsNestedClass() const {
443     return (Options & ClassOptions::ContainsNestedClass) != ClassOptions::None;
444   }
445 
isScoped()446   bool isScoped() const {
447     return (Options & ClassOptions::Scoped) != ClassOptions::None;
448   }
449 
getMemberCount()450   uint16_t getMemberCount() const { return MemberCount; }
getOptions()451   ClassOptions getOptions() const { return Options; }
getFieldList()452   TypeIndex getFieldList() const { return FieldList; }
getName()453   StringRef getName() const { return Name; }
getUniqueName()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;
ClassRecord(TypeRecordKind Kind)467   explicit ClassRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
ClassRecord(TypeRecordKind Kind,uint16_t MemberCount,ClassOptions Options,TypeIndex FieldList,TypeIndex DerivationList,TypeIndex VTableShape,uint64_t Size,StringRef Name,StringRef UniqueName)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 
getHfa()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 
getWinRTKind()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 
getDerivationList()487   TypeIndex getDerivationList() const { return DerivationList; }
getVTableShape()488   TypeIndex getVTableShape() const { return VTableShape; }
getSize()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;
UnionRecordUnionRecord499   explicit UnionRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
UnionRecordUnionRecord500   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 
getHfaUnionRecord506   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 
getSizeUnionRecord512   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;
EnumRecord(TypeRecordKind Kind)521   explicit EnumRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
EnumRecord(uint16_t MemberCount,ClassOptions Options,TypeIndex FieldList,StringRef Name,StringRef UniqueName,TypeIndex UnderlyingType)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 
getUnderlyingType()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;
BitFieldRecord(TypeRecordKind Kind)537   explicit BitFieldRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
BitFieldRecord(TypeIndex Type,uint8_t BitSize,uint8_t BitOffset)538   BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset)
539       : TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize),
540         BitOffset(BitOffset) {}
541 
getType()542   TypeIndex getType() const { return Type; }
getBitOffset()543   uint8_t getBitOffset() const { return BitOffset; }
getBitSize()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;
VFTableShapeRecord(TypeRecordKind Kind)555   explicit VFTableShapeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots)556   explicit VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots)
557       : TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {}
VFTableShapeRecord(std::vector<VFTableSlotKind> Slots)558   explicit VFTableShapeRecord(std::vector<VFTableSlotKind> Slots)
559       : TypeRecord(TypeRecordKind::VFTableShape), Slots(std::move(Slots)) {}
560 
getSlots()561   ArrayRef<VFTableSlotKind> getSlots() const {
562     if (!SlotsRef.empty())
563       return SlotsRef;
564     return Slots;
565   }
566 
getEntryCount()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;
TypeServer2Record(TypeRecordKind Kind)577   explicit TypeServer2Record(TypeRecordKind Kind) : TypeRecord(Kind) {}
TypeServer2Record(StringRef GuidStr,uint32_t Age,StringRef Name)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 
getGuid()584   const GUID &getGuid() const { return Guid; }
getAge()585   uint32_t getAge() const { return Age; }
getName()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;
StringIdRecord(TypeRecordKind Kind)597   explicit StringIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
StringIdRecord(TypeIndex Id,StringRef String)598   StringIdRecord(TypeIndex Id, StringRef String)
599       : TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {}
600 
getId()601   TypeIndex getId() const { return Id; }
getString()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;
FuncIdRecord(TypeRecordKind Kind)612   explicit FuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
FuncIdRecord(TypeIndex ParentScope,TypeIndex FunctionType,StringRef Name)613   FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name)
614       : TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope),
615         FunctionType(FunctionType), Name(Name) {}
616 
getParentScope()617   TypeIndex getParentScope() const { return ParentScope; }
getFunctionType()618   TypeIndex getFunctionType() const { return FunctionType; }
getName()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;
UdtSourceLineRecord(TypeRecordKind Kind)630   explicit UdtSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
UdtSourceLineRecord(TypeIndex UDT,TypeIndex SourceFile,uint32_t LineNumber)631   UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber)
632       : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
633         SourceFile(SourceFile), LineNumber(LineNumber) {}
634 
getUDT()635   TypeIndex getUDT() const { return UDT; }
getSourceFile()636   TypeIndex getSourceFile() const { return SourceFile; }
getLineNumber()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;
UdtModSourceLineRecord(TypeRecordKind Kind)648   explicit UdtModSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
UdtModSourceLineRecord(TypeIndex UDT,TypeIndex SourceFile,uint32_t LineNumber,uint16_t Module)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 
getUDT()654   TypeIndex getUDT() const { return UDT; }
getSourceFile()655   TypeIndex getSourceFile() const { return SourceFile; }
getLineNumber()656   uint32_t getLineNumber() const { return LineNumber; }
getModule()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;
BuildInfoRecord(TypeRecordKind Kind)669   explicit BuildInfoRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices)670   BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices)
671       : TypeRecord(TypeRecordKind::BuildInfo),
672         ArgIndices(ArgIndices.begin(), ArgIndices.end()) {}
673 
getArgs()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;
VFTableRecord(TypeRecordKind Kind)693   explicit VFTableRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
VFTableRecord(TypeIndex CompleteClass,TypeIndex OverriddenVFTable,uint32_t VFPtrOffset,StringRef Name,ArrayRef<StringRef> Methods)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 
getCompleteClass()703   TypeIndex getCompleteClass() const { return CompleteClass; }
getOverriddenVTable()704   TypeIndex getOverriddenVTable() const { return OverriddenVFTable; }
getVFPtrOffset()705   uint32_t getVFPtrOffset() const { return VFPtrOffset; }
getName()706   StringRef getName() const { return makeArrayRef(MethodNames).front(); }
707 
getMethodNames()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;
OneMethodRecord(TypeRecordKind Kind)722   explicit OneMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
OneMethodRecord(TypeIndex Type,MemberAttributes Attrs,int32_t VFTableOffset,StringRef Name)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) {}
OneMethodRecord(TypeIndex Type,MemberAccess Access,MethodKind MK,MethodOptions Options,int32_t VFTableOffset,StringRef 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 
getType()732   TypeIndex getType() const { return Type; }
getMethodKind()733   MethodKind getMethodKind() const { return Attrs.getMethodKind(); }
getOptions()734   MethodOptions getOptions() const { return Attrs.getFlags(); }
getAccess()735   MemberAccess getAccess() const { return Attrs.getAccess(); }
getVFTableOffset()736   int32_t getVFTableOffset() const { return VFTableOffset; }
getName()737   StringRef getName() const { return Name; }
738 
isIntroducingVirtual()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;
MethodOverloadListRecord(TypeRecordKind Kind)754   explicit MethodOverloadListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods)755   MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods)
756       : TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {}
757 
getMethods()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;
OverloadedMethodRecord(TypeRecordKind Kind)767   explicit OverloadedMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
OverloadedMethodRecord(uint16_t NumOverloads,TypeIndex MethodList,StringRef Name)768   OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList,
769                          StringRef Name)
770       : TypeRecord(TypeRecordKind::OverloadedMethod),
771         NumOverloads(NumOverloads), MethodList(MethodList), Name(Name) {}
772 
getNumOverloads()773   uint16_t getNumOverloads() const { return NumOverloads; }
getMethodList()774   TypeIndex getMethodList() const { return MethodList; }
getName()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;
DataMemberRecord(TypeRecordKind Kind)786   explicit DataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
DataMemberRecord(MemberAttributes Attrs,TypeIndex Type,uint64_t Offset,StringRef Name)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) {}
DataMemberRecord(MemberAccess Access,TypeIndex Type,uint64_t Offset,StringRef 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 
getAccess()796   MemberAccess getAccess() const { return Attrs.getAccess(); }
getType()797   TypeIndex getType() const { return Type; }
getFieldOffset()798   uint64_t getFieldOffset() const { return FieldOffset; }
getName()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;
StaticDataMemberRecord(TypeRecordKind Kind)811   explicit StaticDataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
StaticDataMemberRecord(MemberAttributes Attrs,TypeIndex Type,StringRef Name)812   StaticDataMemberRecord(MemberAttributes Attrs, TypeIndex Type, StringRef Name)
813       : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Attrs), Type(Type),
814         Name(Name) {}
StaticDataMemberRecord(MemberAccess Access,TypeIndex Type,StringRef Name)815   StaticDataMemberRecord(MemberAccess Access, TypeIndex Type, StringRef Name)
816       : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Access), Type(Type),
817         Name(Name) {}
818 
getAccess()819   MemberAccess getAccess() const { return Attrs.getAccess(); }
getType()820   TypeIndex getType() const { return Type; }
getName()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;
EnumeratorRecord(TypeRecordKind Kind)832   explicit EnumeratorRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
EnumeratorRecord(MemberAttributes Attrs,APSInt Value,StringRef Name)833   EnumeratorRecord(MemberAttributes Attrs, APSInt Value, StringRef Name)
834       : TypeRecord(TypeRecordKind::Enumerator), Attrs(Attrs),
835         Value(std::move(Value)), Name(Name) {}
EnumeratorRecord(MemberAccess Access,APSInt Value,StringRef Name)836   EnumeratorRecord(MemberAccess Access, APSInt Value, StringRef Name)
837       : TypeRecord(TypeRecordKind::Enumerator), Attrs(Access),
838         Value(std::move(Value)), Name(Name) {}
839 
getAccess()840   MemberAccess getAccess() const { return Attrs.getAccess(); }
getValue()841   APSInt getValue() const { return Value; }
getName()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;
VFPtrRecord(TypeRecordKind Kind)853   explicit VFPtrRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
VFPtrRecord(TypeIndex Type)854   VFPtrRecord(TypeIndex Type)
855       : TypeRecord(TypeRecordKind::VFPtr), Type(Type) {}
856 
getType()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;
BaseClassRecord(TypeRecordKind Kind)866   explicit BaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
BaseClassRecord(MemberAttributes Attrs,TypeIndex Type,uint64_t Offset)867   BaseClassRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset)
868       : TypeRecord(TypeRecordKind::BaseClass), Attrs(Attrs), Type(Type),
869         Offset(Offset) {}
BaseClassRecord(MemberAccess Access,TypeIndex Type,uint64_t Offset)870   BaseClassRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset)
871       : TypeRecord(TypeRecordKind::BaseClass), Attrs(Access), Type(Type),
872         Offset(Offset) {}
873 
getAccess()874   MemberAccess getAccess() const { return Attrs.getAccess(); }
getBaseType()875   TypeIndex getBaseType() const { return Type; }
getBaseOffset()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;
VirtualBaseClassRecord(TypeRecordKind Kind)887   explicit VirtualBaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
VirtualBaseClassRecord(TypeRecordKind Kind,MemberAttributes Attrs,TypeIndex BaseType,TypeIndex VBPtrType,uint64_t Offset,uint64_t Index)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) {}
VirtualBaseClassRecord(TypeRecordKind Kind,MemberAccess Access,TypeIndex BaseType,TypeIndex VBPtrType,uint64_t Offset,uint64_t 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 
getAccess()899   MemberAccess getAccess() const { return Attrs.getAccess(); }
getBaseType()900   TypeIndex getBaseType() const { return BaseType; }
getVBPtrType()901   TypeIndex getVBPtrType() const { return VBPtrType; }
getVBPtrOffset()902   uint64_t getVBPtrOffset() const { return VBPtrOffset; }
getVTableIndex()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;
ListContinuationRecord(TypeRecordKind Kind)917   explicit ListContinuationRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ListContinuationRecord(TypeIndex ContinuationIndex)918   ListContinuationRecord(TypeIndex ContinuationIndex)
919       : TypeRecord(TypeRecordKind::ListContinuation),
920         ContinuationIndex(ContinuationIndex) {}
921 
getContinuationIndex()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;
PrecompRecord(TypeRecordKind Kind)931   explicit PrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
932 
getStartTypeIndex()933   uint32_t getStartTypeIndex() const { return StartTypeIndex; }
getTypesCount()934   uint32_t getTypesCount() const { return TypesCount; }
getSignature()935   uint32_t getSignature() const { return Signature; }
getPrecompFilePath()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;
EndPrecompRecord(TypeRecordKind Kind)948   explicit EndPrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
949 
getSignature()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