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