• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- TypeRecord.h ---------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H
11 #define LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H
12 
13 #include "llvm/ADT/APSInt.h"
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/DebugInfo/CodeView/CVRecord.h"
17 #include "llvm/DebugInfo/CodeView/CodeView.h"
18 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
19 #include "llvm/Support/ErrorOr.h"
20 #include <cinttypes>
21 #include <utility>
22 
23 namespace llvm {
24 namespace codeview {
25 
26 using llvm::support::little32_t;
27 using llvm::support::ulittle16_t;
28 using llvm::support::ulittle32_t;
29 
30 /// Equvalent to CV_fldattr_t in cvinfo.h.
31 struct MemberAttributes {
32   ulittle16_t Attrs;
33   enum {
34     MethodKindShift = 2,
35   };
36 
37   /// Get the access specifier. Valid for any kind of member.
getAccessMemberAttributes38   MemberAccess getAccess() const {
39     return MemberAccess(unsigned(Attrs) & unsigned(MethodOptions::AccessMask));
40   }
41 
42   /// Indicates if a method is defined with friend, virtual, static, etc.
getMethodKindMemberAttributes43   MethodKind getMethodKind() const {
44     return MethodKind(
45         (unsigned(Attrs) & unsigned(MethodOptions::MethodKindMask)) >>
46         MethodKindShift);
47   }
48 
49   /// Get the flags that are not included in access control or method
50   /// properties.
getFlagsMemberAttributes51   MethodOptions getFlags() const {
52     return MethodOptions(
53         unsigned(Attrs) &
54         ~unsigned(MethodOptions::AccessMask | MethodOptions::MethodKindMask));
55   }
56 
57   /// Is this method virtual.
isVirtualMemberAttributes58   bool isVirtual() const {
59     auto MP = getMethodKind();
60     return MP != MethodKind::Vanilla && MP != MethodKind::Friend &&
61            MP != MethodKind::Static;
62   }
63 
64   /// Does this member introduce a new virtual method.
isIntroducedVirtualMemberAttributes65   bool isIntroducedVirtual() const {
66     auto MP = getMethodKind();
67     return MP == MethodKind::IntroducingVirtual ||
68            MP == MethodKind::PureIntroducingVirtual;
69   }
70 };
71 
72 // Does not correspond to any tag, this is the tail of an LF_POINTER record
73 // if it represents a member pointer.
74 class MemberPointerInfo {
75 public:
MemberPointerInfo()76   MemberPointerInfo() {}
77 
MemberPointerInfo(TypeIndex ContainingType,PointerToMemberRepresentation Representation)78   MemberPointerInfo(TypeIndex ContainingType,
79                     PointerToMemberRepresentation Representation)
80       : ContainingType(ContainingType), Representation(Representation) {}
81 
82   /// Rewrite member type indices with IndexMap. Returns false if a type index
83   /// is not in the map.
84   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
85 
86   static ErrorOr<MemberPointerInfo> deserialize(ArrayRef<uint8_t> &Data);
87 
getContainingType()88   TypeIndex getContainingType() const { return ContainingType; }
getRepresentation()89   PointerToMemberRepresentation getRepresentation() const {
90     return Representation;
91   }
92 
93 private:
94   struct Layout {
95     TypeIndex ClassType;
96     ulittle16_t Representation; // PointerToMemberRepresentation
97   };
98 
99   TypeIndex ContainingType;
100   PointerToMemberRepresentation Representation;
101 };
102 
103 class TypeRecord {
104 protected:
TypeRecord(TypeRecordKind Kind)105   explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {}
106 
107 public:
getKind()108   TypeRecordKind getKind() const { return Kind; }
109 
110 private:
111   TypeRecordKind Kind;
112 };
113 
114 // LF_MODIFIER
115 class ModifierRecord : public TypeRecord {
116 public:
ModifierRecord(TypeIndex ModifiedType,ModifierOptions Modifiers)117   ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers)
118       : TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType),
119         Modifiers(Modifiers) {}
120 
121   /// Rewrite member type indices with IndexMap. Returns false if a type index
122   /// is not in the map.
123   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
124 
125   static ErrorOr<ModifierRecord> deserialize(TypeRecordKind Kind,
126                                              ArrayRef<uint8_t> &Data);
127 
getModifiedType()128   TypeIndex getModifiedType() const { return ModifiedType; }
getModifiers()129   ModifierOptions getModifiers() const { return Modifiers; }
130 
131 private:
132   struct Layout {
133     TypeIndex ModifiedType;
134     ulittle16_t Modifiers; // ModifierOptions
135   };
136 
137   TypeIndex ModifiedType;
138   ModifierOptions Modifiers;
139 };
140 
141 // LF_PROCEDURE
142 class ProcedureRecord : public TypeRecord {
143 public:
ProcedureRecord(TypeIndex ReturnType,CallingConvention CallConv,FunctionOptions Options,uint16_t ParameterCount,TypeIndex ArgumentList)144   ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv,
145                   FunctionOptions Options, uint16_t ParameterCount,
146                   TypeIndex ArgumentList)
147       : TypeRecord(TypeRecordKind::Procedure), ReturnType(ReturnType),
148         CallConv(CallConv), Options(Options), ParameterCount(ParameterCount),
149         ArgumentList(ArgumentList) {}
150 
151   /// Rewrite member type indices with IndexMap. Returns false if a type index
152   /// is not in the map.
153   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
154 
155   static ErrorOr<ProcedureRecord> deserialize(TypeRecordKind Kind,
156                                               ArrayRef<uint8_t> &Data);
157 
getLayoutSize()158   static uint32_t getLayoutSize() { return 2 + sizeof(Layout); }
159 
getReturnType()160   TypeIndex getReturnType() const { return ReturnType; }
getCallConv()161   CallingConvention getCallConv() const { return CallConv; }
getOptions()162   FunctionOptions getOptions() const { return Options; }
getParameterCount()163   uint16_t getParameterCount() const { return ParameterCount; }
getArgumentList()164   TypeIndex getArgumentList() const { return ArgumentList; }
165 
166 private:
167   struct Layout {
168     TypeIndex ReturnType;
169     CallingConvention CallConv;
170     FunctionOptions Options;
171     ulittle16_t NumParameters;
172     TypeIndex ArgListType;
173   };
174 
175   TypeIndex ReturnType;
176   CallingConvention CallConv;
177   FunctionOptions Options;
178   uint16_t ParameterCount;
179   TypeIndex ArgumentList;
180 };
181 
182 // LF_MFUNCTION
183 class MemberFunctionRecord : public TypeRecord {
184 public:
MemberFunctionRecord(TypeIndex ReturnType,TypeIndex ClassType,TypeIndex ThisType,CallingConvention CallConv,FunctionOptions Options,uint16_t ParameterCount,TypeIndex ArgumentList,int32_t ThisPointerAdjustment)185   MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType,
186                        TypeIndex ThisType, CallingConvention CallConv,
187                        FunctionOptions Options, uint16_t ParameterCount,
188                        TypeIndex ArgumentList, int32_t ThisPointerAdjustment)
189       : TypeRecord(TypeRecordKind::MemberFunction), ReturnType(ReturnType),
190         ClassType(ClassType), ThisType(ThisType), CallConv(CallConv),
191         Options(Options), ParameterCount(ParameterCount),
192         ArgumentList(ArgumentList),
193         ThisPointerAdjustment(ThisPointerAdjustment) {}
194 
195   /// Rewrite member type indices with IndexMap. Returns false if a type index
196   /// is not in the map.
197   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
198 
199   static ErrorOr<MemberFunctionRecord> deserialize(TypeRecordKind Kind,
200                                                    ArrayRef<uint8_t> &Data);
201 
getReturnType()202   TypeIndex getReturnType() const { return ReturnType; }
getClassType()203   TypeIndex getClassType() const { return ClassType; }
getThisType()204   TypeIndex getThisType() const { return ThisType; }
getCallConv()205   CallingConvention getCallConv() const { return CallConv; }
getOptions()206   FunctionOptions getOptions() const { return Options; }
getParameterCount()207   uint16_t getParameterCount() const { return ParameterCount; }
getArgumentList()208   TypeIndex getArgumentList() const { return ArgumentList; }
getThisPointerAdjustment()209   int32_t getThisPointerAdjustment() const { return ThisPointerAdjustment; }
210 
211 private:
212   struct Layout {
213     TypeIndex ReturnType;
214     TypeIndex ClassType;
215     TypeIndex ThisType;
216     CallingConvention CallConv;
217     FunctionOptions Options;
218     ulittle16_t NumParameters;
219     TypeIndex ArgListType;
220     little32_t ThisAdjustment;
221   };
222 
223   TypeIndex ReturnType;
224   TypeIndex ClassType;
225   TypeIndex ThisType;
226   CallingConvention CallConv;
227   FunctionOptions Options;
228   uint16_t ParameterCount;
229   TypeIndex ArgumentList;
230   int32_t ThisPointerAdjustment;
231 };
232 
233 // LF_MFUNC_ID
234 class MemberFuncIdRecord : public TypeRecord {
235 public:
MemberFuncIdRecord(TypeIndex ClassType,TypeIndex FunctionType,StringRef Name)236   MemberFuncIdRecord(TypeIndex ClassType, TypeIndex FunctionType,
237                          StringRef Name)
238       : TypeRecord(TypeRecordKind::MemberFuncId), ClassType(ClassType),
239         FunctionType(FunctionType), Name(Name) {}
240 
241   /// Rewrite member type indices with IndexMap. Returns false if a type index
242   /// is not in the map.
243   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
244 
245   static ErrorOr<MemberFuncIdRecord> deserialize(TypeRecordKind Kind,
246                                                  ArrayRef<uint8_t> &Data);
getClassType()247   TypeIndex getClassType() const { return ClassType; }
getFunctionType()248   TypeIndex getFunctionType() const { return FunctionType; }
getName()249   StringRef getName() const { return Name; }
250 
251 private:
252   struct Layout {
253     TypeIndex ClassType;
254     TypeIndex FunctionType;
255     // Name: The null-terminated name follows.
256   };
257   TypeIndex ClassType;
258   TypeIndex FunctionType;
259   StringRef Name;
260 };
261 
262 // LF_ARGLIST, LF_SUBSTR_LIST
263 class ArgListRecord : public TypeRecord {
264 public:
ArgListRecord(TypeRecordKind Kind,ArrayRef<TypeIndex> Indices)265   ArgListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
266       : TypeRecord(Kind), StringIndices(Indices) {}
267 
268   /// Rewrite member type indices with IndexMap. Returns false if a type index
269   /// is not in the map.
270   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
271 
272   static ErrorOr<ArgListRecord> deserialize(TypeRecordKind Kind,
273                                             ArrayRef<uint8_t> &Data);
274 
getIndices()275   ArrayRef<TypeIndex> getIndices() const { return StringIndices; }
276 
getLayoutSize()277   static uint32_t getLayoutSize() { return 2 + sizeof(Layout); }
278 
279 private:
280   struct Layout {
281     ulittle32_t NumArgs; // Number of arguments
282                          // ArgTypes[]: Type indicies of arguments
283   };
284 
285   std::vector<TypeIndex> StringIndices;
286 };
287 
288 // LF_POINTER
289 class PointerRecord : public TypeRecord {
290 public:
291   static const uint32_t PointerKindShift = 0;
292   static const uint32_t PointerKindMask = 0x1F;
293 
294   static const uint32_t PointerModeShift = 5;
295   static const uint32_t PointerModeMask = 0x07;
296 
297   static const uint32_t PointerSizeShift = 13;
298   static const uint32_t PointerSizeMask = 0xFF;
299 
PointerRecord(TypeIndex ReferentType,PointerKind Kind,PointerMode Mode,PointerOptions Options,uint8_t Size)300   PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
301                 PointerOptions Options, uint8_t Size)
302       : PointerRecord(ReferentType, Kind, Mode, Options, Size,
303                       MemberPointerInfo()) {}
304 
PointerRecord(TypeIndex ReferentType,PointerKind Kind,PointerMode Mode,PointerOptions Options,uint8_t Size,const MemberPointerInfo & Member)305   PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
306                 PointerOptions Options, uint8_t Size,
307                 const MemberPointerInfo &Member)
308       : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
309         PtrKind(Kind), Mode(Mode), Options(Options), Size(Size),
310         MemberInfo(Member) {}
311 
312   /// Rewrite member type indices with IndexMap. Returns false if a type index
313   /// is not in the map.
314   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
315 
316   static ErrorOr<PointerRecord> deserialize(TypeRecordKind Kind,
317                                             ArrayRef<uint8_t> &Data);
318 
getReferentType()319   TypeIndex getReferentType() const { return ReferentType; }
getPointerKind()320   PointerKind getPointerKind() const { return PtrKind; }
getMode()321   PointerMode getMode() const { return Mode; }
getOptions()322   PointerOptions getOptions() const { return Options; }
getSize()323   uint8_t getSize() const { return Size; }
getMemberInfo()324   MemberPointerInfo getMemberInfo() const { return MemberInfo; }
325 
isPointerToMember()326   bool isPointerToMember() const {
327     return Mode == PointerMode::PointerToDataMember ||
328            Mode == PointerMode::PointerToMemberFunction;
329   }
isFlat()330   bool isFlat() const {
331     return !!(uint32_t(Options) & uint32_t(PointerOptions::Flat32));
332   }
isConst()333   bool isConst() const {
334     return !!(uint32_t(Options) & uint32_t(PointerOptions::Const));
335   }
isVolatile()336   bool isVolatile() const {
337     return !!(uint32_t(Options) & uint32_t(PointerOptions::Volatile));
338   }
isUnaligned()339   bool isUnaligned() const {
340     return !!(uint32_t(Options) & uint32_t(PointerOptions::Unaligned));
341   }
342 
343 private:
344   struct Layout {
345     TypeIndex PointeeType;
346     ulittle32_t Attrs; // pointer attributes
347                        // if pointer to member:
348                        //   PointerToMemberTail
getPtrKindLayout349     PointerKind getPtrKind() const {
350       return PointerKind(Attrs & PointerKindMask);
351     }
getPtrModeLayout352     PointerMode getPtrMode() const {
353       return PointerMode((Attrs >> PointerModeShift) & PointerModeMask);
354     }
getPtrSizeLayout355     uint8_t getPtrSize() const {
356       return (Attrs >> PointerSizeShift) & PointerSizeMask;
357     }
isFlatLayout358     bool isFlat() const { return Attrs & (1 << 8); }
isVolatileLayout359     bool isVolatile() const { return Attrs & (1 << 9); }
isConstLayout360     bool isConst() const { return Attrs & (1 << 10); }
isUnalignedLayout361     bool isUnaligned() const { return Attrs & (1 << 11); }
362 
isPointerToDataMemberLayout363     bool isPointerToDataMember() const {
364       return getPtrMode() == PointerMode::PointerToDataMember;
365     }
isPointerToMemberFunctionLayout366     bool isPointerToMemberFunction() const {
367       return getPtrMode() == PointerMode::PointerToMemberFunction;
368     }
isPointerToMemberLayout369     bool isPointerToMember() const {
370       return isPointerToMemberFunction() || isPointerToDataMember();
371     }
372   };
373 
374   TypeIndex ReferentType;
375   PointerKind PtrKind;
376   PointerMode Mode;
377   PointerOptions Options;
378   uint8_t Size;
379   MemberPointerInfo MemberInfo;
380 };
381 
382 // LF_NESTTYPE
383 class NestedTypeRecord : public TypeRecord {
384 public:
NestedTypeRecord(TypeIndex Type,StringRef Name)385   NestedTypeRecord(TypeIndex Type, StringRef Name)
386       : TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {}
387 
388   /// Rewrite member type indices with IndexMap. Returns false if a type index
389   /// is not in the map.
390   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
391 
392   static ErrorOr<NestedTypeRecord> deserialize(TypeRecordKind Kind,
393                                                ArrayRef<uint8_t> &Data);
394 
getNestedType()395   TypeIndex getNestedType() const { return Type; }
getName()396   StringRef getName() const { return Name; }
397 
398 private:
399   struct Layout {
400     ulittle16_t Pad0; // Should be zero
401     TypeIndex Type;   // Type index of nested type
402                       // Name: Null-terminated string
403   };
404 
405   TypeIndex Type;
406   StringRef Name;
407 };
408 
409 // LF_ARRAY
410 class ArrayRecord : public TypeRecord {
411 public:
ArrayRecord(TypeIndex ElementType,TypeIndex IndexType,uint64_t Size,StringRef Name)412   ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size,
413               StringRef Name)
414       : TypeRecord(TypeRecordKind::Array), ElementType(ElementType),
415         IndexType(IndexType), Size(Size), Name(Name) {}
416 
417   /// Rewrite member type indices with IndexMap. Returns false if a type index
418   /// is not in the map.
419   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
420 
421   static ErrorOr<ArrayRecord> deserialize(TypeRecordKind Kind,
422                                           ArrayRef<uint8_t> &Data);
423 
getElementType()424   TypeIndex getElementType() const { return ElementType; }
getIndexType()425   TypeIndex getIndexType() const { return IndexType; }
getSize()426   uint64_t getSize() const { return Size; }
getName()427   llvm::StringRef getName() const { return Name; }
428 
429 private:
430   struct Layout {
431     TypeIndex ElementType;
432     TypeIndex IndexType;
433     // SizeOf: LF_NUMERIC encoded size in bytes. Not element count!
434     // Name: The null-terminated name follows.
435   };
436 
437   TypeIndex ElementType;
438   TypeIndex IndexType;
439   uint64_t Size;
440   llvm::StringRef Name;
441 };
442 
443 class TagRecord : public TypeRecord {
444 protected:
TagRecord(TypeRecordKind Kind,uint16_t MemberCount,ClassOptions Options,TypeIndex FieldList,StringRef Name,StringRef UniqueName)445   TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
446             TypeIndex FieldList, StringRef Name, StringRef UniqueName)
447       : TypeRecord(Kind), MemberCount(MemberCount), Options(Options),
448         FieldList(FieldList), Name(Name), UniqueName(UniqueName) {}
449 
450 public:
451   /// Rewrite member type indices with IndexMap. Returns false if a type index
452   /// is not in the map.
453   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
454 
455   static const int HfaKindShift = 11;
456   static const int HfaKindMask = 0x1800;
457   static const int WinRTKindShift = 14;
458   static const int WinRTKindMask = 0xC000;
459 
getMemberCount()460   uint16_t getMemberCount() const { return MemberCount; }
getOptions()461   ClassOptions getOptions() const { return Options; }
getFieldList()462   TypeIndex getFieldList() const { return FieldList; }
getName()463   StringRef getName() const { return Name; }
getUniqueName()464   StringRef getUniqueName() const { return UniqueName; }
465 
466 private:
467   uint16_t MemberCount;
468   ClassOptions Options;
469   TypeIndex FieldList;
470   StringRef Name;
471   StringRef UniqueName;
472 };
473 
474 // LF_CLASS, LF_STRUCTURE, LF_INTERFACE
475 class ClassRecord : public TagRecord {
476 public:
ClassRecord(TypeRecordKind Kind,uint16_t MemberCount,ClassOptions Options,HfaKind Hfa,WindowsRTClassKind WinRTKind,TypeIndex FieldList,TypeIndex DerivationList,TypeIndex VTableShape,uint64_t Size,StringRef Name,StringRef UniqueName)477   ClassRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
478               HfaKind Hfa, WindowsRTClassKind WinRTKind, TypeIndex FieldList,
479               TypeIndex DerivationList, TypeIndex VTableShape, uint64_t Size,
480               StringRef Name, StringRef UniqueName)
481       : TagRecord(Kind, MemberCount, Options, FieldList, Name, UniqueName),
482         Hfa(Hfa), WinRTKind(WinRTKind), DerivationList(DerivationList),
483         VTableShape(VTableShape), Size(Size) {}
484 
485   /// Rewrite member type indices with IndexMap. Returns false if a type index
486   /// is not in the map.
487   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
488 
489   static ErrorOr<ClassRecord> deserialize(TypeRecordKind Kind,
490                                           ArrayRef<uint8_t> &Data);
491 
getHfa()492   HfaKind getHfa() const { return Hfa; }
getWinRTKind()493   WindowsRTClassKind getWinRTKind() const { return WinRTKind; }
getDerivationList()494   TypeIndex getDerivationList() const { return DerivationList; }
getVTableShape()495   TypeIndex getVTableShape() const { return VTableShape; }
getSize()496   uint64_t getSize() const { return Size; }
497 
498 private:
499   struct Layout {
500     ulittle16_t MemberCount; // Number of members in FieldList.
501     ulittle16_t Properties;  // ClassOptions bitset
502     TypeIndex FieldList;     // LF_FIELDLIST: List of all kinds of members
503     TypeIndex DerivedFrom;   // LF_DERIVED: List of known derived classes
504     TypeIndex VShape;        // LF_VTSHAPE: Shape of the vftable
505     // SizeOf: The 'sizeof' the UDT in bytes is encoded as an LF_NUMERIC
506     // integer.
507     // Name: The null-terminated name follows.
508 
hasUniqueNameLayout509     bool hasUniqueName() const {
510       return Properties & uint16_t(ClassOptions::HasUniqueName);
511     }
512   };
513 
514   HfaKind Hfa;
515   WindowsRTClassKind WinRTKind;
516   TypeIndex DerivationList;
517   TypeIndex VTableShape;
518   uint64_t Size;
519 };
520 
521 // LF_UNION
522 struct UnionRecord : public TagRecord {
UnionRecordUnionRecord523   UnionRecord(uint16_t MemberCount, ClassOptions Options, HfaKind Hfa,
524               TypeIndex FieldList, uint64_t Size, StringRef Name,
525               StringRef UniqueName)
526       : TagRecord(TypeRecordKind::Union, MemberCount, Options, FieldList, Name,
527                   UniqueName),
528         Hfa(Hfa), Size(Size) {}
529 
530   static ErrorOr<UnionRecord> deserialize(TypeRecordKind Kind,
531                                           ArrayRef<uint8_t> &Data);
532 
getHfaUnionRecord533   HfaKind getHfa() const { return Hfa; }
getSizeUnionRecord534   uint64_t getSize() const { return Size; }
535 
536 private:
537   struct Layout {
538     ulittle16_t MemberCount; // Number of members in FieldList.
539     ulittle16_t Properties;  // ClassOptions bitset
540     TypeIndex FieldList;     // LF_FIELDLIST: List of all kinds of members
541     // SizeOf: The 'sizeof' the UDT in bytes is encoded as an LF_NUMERIC
542     // integer.
543     // Name: The null-terminated name follows.
544 
hasUniqueNameUnionRecord::Layout545     bool hasUniqueName() const {
546       return Properties & uint16_t(ClassOptions::HasUniqueName);
547     }
548   };
549 
550   HfaKind Hfa;
551   uint64_t Size;
552 };
553 
554 // LF_ENUM
555 class EnumRecord : public TagRecord {
556 public:
EnumRecord(uint16_t MemberCount,ClassOptions Options,TypeIndex FieldList,StringRef Name,StringRef UniqueName,TypeIndex UnderlyingType)557   EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
558              StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType)
559       : TagRecord(TypeRecordKind::Enum, MemberCount, Options, FieldList, Name,
560                   UniqueName),
561         UnderlyingType(UnderlyingType) {}
562 
563   /// Rewrite member type indices with IndexMap. Returns false if a type index is not in the map.
564   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
565 
566   static ErrorOr<EnumRecord> deserialize(TypeRecordKind Kind,
567                                          ArrayRef<uint8_t> &Data);
568 
getUnderlyingType()569   TypeIndex getUnderlyingType() const { return UnderlyingType; }
570 
571 private:
572   struct Layout {
573     ulittle16_t NumEnumerators; // Number of enumerators
574     ulittle16_t Properties;
575     TypeIndex UnderlyingType;
576     TypeIndex FieldListType;
577     // Name: The null-terminated name follows.
578 
hasUniqueNameLayout579     bool hasUniqueName() const {
580       return Properties & uint16_t(ClassOptions::HasUniqueName);
581     }
582   };
583 
584   TypeIndex UnderlyingType;
585 };
586 
587 // LF_BITFIELD
588 class BitFieldRecord : public TypeRecord {
589 public:
BitFieldRecord(TypeIndex Type,uint8_t BitSize,uint8_t BitOffset)590   BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset)
591       : TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize),
592         BitOffset(BitOffset) {}
593 
594   /// Rewrite member type indices with IndexMap. Returns false if a type index
595   /// is not in the map.
596   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
597 
598   static ErrorOr<BitFieldRecord> deserialize(TypeRecordKind Kind,
599                                              ArrayRef<uint8_t> &Data);
600 
getType()601   TypeIndex getType() const { return Type; }
getBitOffset()602   uint8_t getBitOffset() const { return BitOffset; }
getBitSize()603   uint8_t getBitSize() const { return BitSize; }
604 
605 private:
606   struct Layout {
607     TypeIndex Type;
608     uint8_t BitSize;
609     uint8_t BitOffset;
610   };
611 
612   TypeIndex Type;
613   uint8_t BitSize;
614   uint8_t BitOffset;
615 };
616 
617 // LF_VTSHAPE
618 class VFTableShapeRecord : public TypeRecord {
619 public:
VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots)620   explicit VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots)
621       : TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {}
VFTableShapeRecord(std::vector<VFTableSlotKind> Slots)622   explicit VFTableShapeRecord(std::vector<VFTableSlotKind> Slots)
623       : TypeRecord(TypeRecordKind::VFTableShape), Slots(std::move(Slots)) {}
624 
625   /// Rewrite member type indices with IndexMap. Returns false if a type index
626   /// is not in the map.
627   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
628 
629   static ErrorOr<VFTableShapeRecord> deserialize(TypeRecordKind Kind,
630                                                  ArrayRef<uint8_t> &Data);
631 
getSlots()632   ArrayRef<VFTableSlotKind> getSlots() const {
633     if (!SlotsRef.empty())
634       return SlotsRef;
635     return Slots;
636   }
getEntryCount()637   uint32_t getEntryCount() const { return getSlots().size(); }
638 
639 private:
640   struct Layout {
641     // Number of vftable entries. Each method may have more than one entry due
642     // to
643     // things like covariant return types.
644     ulittle16_t VFEntryCount;
645     // Descriptors[]: 4-bit virtual method descriptors of type CV_VTS_desc_e.
646   };
647 
648 private:
649   ArrayRef<VFTableSlotKind> SlotsRef;
650   std::vector<VFTableSlotKind> Slots;
651 };
652 
653 // LF_TYPESERVER2
654 class TypeServer2Record : public TypeRecord {
655 public:
TypeServer2Record(StringRef Guid,uint32_t Age,StringRef Name)656   TypeServer2Record(StringRef Guid, uint32_t Age, StringRef Name)
657       : TypeRecord(TypeRecordKind::TypeServer2), Guid(Guid), Age(Age),
658         Name(Name) {}
659 
660   /// Rewrite member type indices with IndexMap. Returns false if a type index
661   /// is not in the map.
662   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
663 
664   static ErrorOr<TypeServer2Record> deserialize(TypeRecordKind Kind,
665                                                 ArrayRef<uint8_t> &Data);
666 
getGuid()667   StringRef getGuid() const { return Guid; }
668 
getAge()669   uint32_t getAge() const { return Age; }
670 
getName()671   StringRef getName() const { return Name; }
672 
673 private:
674   struct Layout {
675     char Guid[16]; // GUID
676     ulittle32_t Age;
677     // Name: Name of the PDB as a null-terminated string
678   };
679 
680   StringRef Guid;
681   uint32_t Age;
682   StringRef Name;
683 };
684 
685 // LF_STRING_ID
686 class StringIdRecord : public TypeRecord {
687 public:
StringIdRecord(TypeIndex Id,StringRef String)688   StringIdRecord(TypeIndex Id, StringRef String)
689       : TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {}
690 
691   /// Rewrite member type indices with IndexMap. Returns false if a type index
692   /// is not in the map.
693   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
694 
695   static ErrorOr<StringIdRecord> deserialize(TypeRecordKind Kind,
696                                              ArrayRef<uint8_t> &Data);
697 
getId()698   TypeIndex getId() const { return Id; }
699 
getString()700   StringRef getString() const { return String; }
701 
702 private:
703   struct Layout {
704     TypeIndex id;
705     // Name: Name of the PDB as a null-terminated string
706   };
707 
708   TypeIndex Id;
709   StringRef String;
710 };
711 
712 // LF_FUNC_ID
713 class FuncIdRecord : public TypeRecord {
714 public:
FuncIdRecord(TypeIndex ParentScope,TypeIndex FunctionType,StringRef Name)715   FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name)
716       : TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope),
717         FunctionType(FunctionType), Name(Name) {}
718 
719   /// Rewrite member type indices with IndexMap. Returns false if a type index
720   /// is not in the map.
721   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
722 
723   static ErrorOr<FuncIdRecord> deserialize(TypeRecordKind Kind,
724                                            ArrayRef<uint8_t> &Data);
725 
getParentScope()726   TypeIndex getParentScope() const { return ParentScope; }
727 
getFunctionType()728   TypeIndex getFunctionType() const { return FunctionType; }
729 
getName()730   StringRef getName() const { return Name; }
731 
732 private:
733   struct Layout {
734     TypeIndex ParentScope;
735     TypeIndex FunctionType;
736     // Name: The null-terminated name follows.
737   };
738 
739   TypeIndex ParentScope;
740   TypeIndex FunctionType;
741   StringRef Name;
742 };
743 
744 // LF_UDT_SRC_LINE
745 class UdtSourceLineRecord : public TypeRecord {
746 public:
UdtSourceLineRecord(TypeIndex UDT,TypeIndex SourceFile,uint32_t LineNumber)747   UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber)
748       : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
749         SourceFile(SourceFile), LineNumber(LineNumber) {}
750 
751   /// Rewrite member type indices with IndexMap. Returns false if a type index
752   /// is not in the map.
753   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
754 
755   static ErrorOr<UdtSourceLineRecord> deserialize(TypeRecordKind Kind,
756                                                   ArrayRef<uint8_t> &Data);
757 
getUDT()758   TypeIndex getUDT() const { return UDT; }
getSourceFile()759   TypeIndex getSourceFile() const { return SourceFile; }
getLineNumber()760   uint32_t getLineNumber() const { return LineNumber; }
761 
762 private:
763   struct Layout {
764     TypeIndex UDT;        // The user-defined type
765     TypeIndex SourceFile; // StringID containing the source filename
766     ulittle32_t LineNumber;
767   };
768 
769   TypeIndex UDT;
770   TypeIndex SourceFile;
771   uint32_t LineNumber;
772 };
773 
774 // LF_UDT_MOD_SRC_LINE
775 class UdtModSourceLineRecord : public TypeRecord {
776 public:
UdtModSourceLineRecord(TypeIndex UDT,TypeIndex SourceFile,uint32_t LineNumber,uint16_t Module)777   UdtModSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile,
778                          uint32_t LineNumber, uint16_t Module)
779       : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
780         SourceFile(SourceFile), LineNumber(LineNumber), Module(Module) {}
781 
782   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
783 
deserialize(TypeRecordKind Kind,ArrayRef<uint8_t> & Data)784   static ErrorOr<UdtModSourceLineRecord> deserialize(TypeRecordKind Kind,
785                                                      ArrayRef<uint8_t> &Data) {
786     const Layout *L = nullptr;
787     CV_DESERIALIZE(Data, L);
788 
789     return UdtModSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber,
790                                   L->Module);
791   }
792 
getUDT()793   TypeIndex getUDT() const { return UDT; }
getSourceFile()794   TypeIndex getSourceFile() const { return SourceFile; }
getLineNumber()795   uint32_t getLineNumber() const { return LineNumber; }
getModule()796   uint16_t getModule() const { return Module; }
797 
798 private:
799   struct Layout {
800     TypeIndex UDT;        // The user-defined type
801     TypeIndex SourceFile; // StringID containing the source filename
802     ulittle32_t LineNumber;
803     ulittle16_t Module; // Module that contributes this UDT definition
804   };
805 
806   TypeIndex UDT;
807   TypeIndex SourceFile;
808   uint32_t LineNumber;
809   uint16_t Module;
810 };
811 
812 // LF_BUILDINFO
813 class BuildInfoRecord : public TypeRecord {
814 public:
BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices)815   BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices)
816       : TypeRecord(TypeRecordKind::BuildInfo),
817         ArgIndices(ArgIndices.begin(), ArgIndices.end()) {}
818 
819   /// Rewrite member type indices with IndexMap. Returns false if a type index
820   /// is not in the map.
821   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
822 
823   static ErrorOr<BuildInfoRecord> deserialize(TypeRecordKind Kind,
824                                               ArrayRef<uint8_t> &Data);
825 
getArgs()826   ArrayRef<TypeIndex> getArgs() const { return ArgIndices; }
827 
828 private:
829   struct Layout {
830     ulittle16_t NumArgs; // Number of arguments
831                          // ArgTypes[]: Type indicies of arguments
832   };
833   SmallVector<TypeIndex, 4> ArgIndices;
834 };
835 
836 // LF_VFTABLE
837 class VFTableRecord : public TypeRecord {
838 public:
VFTableRecord(TypeIndex CompleteClass,TypeIndex OverriddenVFTable,uint32_t VFPtrOffset,StringRef Name,ArrayRef<StringRef> Methods)839   VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable,
840                 uint32_t VFPtrOffset, StringRef Name,
841                 ArrayRef<StringRef> Methods)
842       : TypeRecord(TypeRecordKind::VFTable),
843         CompleteClass(CompleteClass), OverriddenVFTable(OverriddenVFTable),
844         VFPtrOffset(VFPtrOffset), Name(Name), MethodNamesRef(Methods) {}
VFTableRecord(TypeIndex CompleteClass,TypeIndex OverriddenVFTable,uint32_t VFPtrOffset,StringRef Name,const std::vector<StringRef> & Methods)845   VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable,
846                 uint32_t VFPtrOffset, StringRef Name,
847                 const std::vector<StringRef> &Methods)
848       : TypeRecord(TypeRecordKind::VFTable),
849         CompleteClass(CompleteClass), OverriddenVFTable(OverriddenVFTable),
850         VFPtrOffset(VFPtrOffset), Name(Name), MethodNames(Methods) {}
851 
852   /// Rewrite member type indices with IndexMap. Returns false if a type index
853   /// is not in the map.
854   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
855 
856   static ErrorOr<VFTableRecord> deserialize(TypeRecordKind Kind,
857                                             ArrayRef<uint8_t> &Data);
858 
getCompleteClass()859   TypeIndex getCompleteClass() const { return CompleteClass; }
getOverriddenVTable()860   TypeIndex getOverriddenVTable() const { return OverriddenVFTable; }
getVFPtrOffset()861   uint32_t getVFPtrOffset() const { return VFPtrOffset; }
getName()862   StringRef getName() const { return Name; }
getMethodNames()863   ArrayRef<StringRef> getMethodNames() const {
864     if (!MethodNamesRef.empty())
865       return MethodNamesRef;
866     return MethodNames;
867   }
868 
869 private:
870   struct Layout {
871     TypeIndex CompleteClass;     // Class that owns this vftable.
872     TypeIndex OverriddenVFTable; // VFTable that this overrides.
873     ulittle32_t VFPtrOffset;     // VFPtr offset in CompleteClass
874     ulittle32_t NamesLen;        // Length of subsequent names array in bytes.
875     // Names: A sequence of null-terminated strings. First string is vftable
876     // names.
877   };
878 
879   TypeIndex CompleteClass;
880   TypeIndex OverriddenVFTable;
881   ulittle32_t VFPtrOffset;
882   StringRef Name;
883   ArrayRef<StringRef> MethodNamesRef;
884   std::vector<StringRef> MethodNames;
885 };
886 
887 // LF_ONEMETHOD
888 class OneMethodRecord : public TypeRecord {
889 public:
OneMethodRecord(TypeIndex Type,MethodKind Kind,MethodOptions Options,MemberAccess Access,int32_t VFTableOffset,StringRef Name)890   OneMethodRecord(TypeIndex Type, MethodKind Kind, MethodOptions Options,
891                   MemberAccess Access, int32_t VFTableOffset, StringRef Name)
892       : TypeRecord(TypeRecordKind::OneMethod), Type(Type), Kind(Kind),
893         Options(Options), Access(Access), VFTableOffset(VFTableOffset),
894         Name(Name) {}
895 
896   /// Rewrite member type indices with IndexMap. Returns false if a type index
897   /// is not in the map.
898   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
899 
900   static ErrorOr<OneMethodRecord> deserialize(TypeRecordKind Kind,
901                                               ArrayRef<uint8_t> &Data);
902 
getType()903   TypeIndex getType() const { return Type; }
getKind()904   MethodKind getKind() const { return Kind; }
getOptions()905   MethodOptions getOptions() const { return Options; }
getAccess()906   MemberAccess getAccess() const { return Access; }
getVFTableOffset()907   int32_t getVFTableOffset() const { return VFTableOffset; }
getName()908   StringRef getName() const { return Name; }
909 
isIntroducingVirtual()910   bool isIntroducingVirtual() const {
911     return Kind == MethodKind::IntroducingVirtual ||
912            Kind == MethodKind::PureIntroducingVirtual;
913   }
914 
915 private:
916   struct Layout {
917     MemberAttributes Attrs;
918     TypeIndex Type;
919     // If is introduced virtual method:
920     //   VFTableOffset: int32_t offset in vftable
921     // Name: Null-terminated string
922   };
923 
924   TypeIndex Type;
925   MethodKind Kind;
926   MethodOptions Options;
927   MemberAccess Access;
928   int32_t VFTableOffset;
929   StringRef Name;
930 };
931 
932 // LF_METHODLIST
933 class MethodOverloadListRecord : public TypeRecord {
934 public:
MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods)935   MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods)
936       : TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {}
937 
938   /// Rewrite member type indices with IndexMap. Returns false if a type index
939   /// is not in the map.
940   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
941 
942   static ErrorOr<MethodOverloadListRecord> deserialize(TypeRecordKind Kind,
943                                                        ArrayRef<uint8_t> &Data);
944 
getMethods()945   ArrayRef<OneMethodRecord> getMethods() const { return Methods; }
946 
947 private:
948   struct Layout {
949     MemberAttributes Attrs;
950     ulittle16_t Padding;
951 
952     TypeIndex Type;
953     // If is introduced virtual method:
954     //   VFTableOffset: int32_t offset in vftable
955   };
956 
957   std::vector<OneMethodRecord> Methods;
958 };
959 
960 /// For method overload sets.  LF_METHOD
961 class OverloadedMethodRecord : public TypeRecord {
962 public:
OverloadedMethodRecord(uint16_t NumOverloads,TypeIndex MethodList,StringRef Name)963   OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList,
964                          StringRef Name)
965       : TypeRecord(TypeRecordKind::OverloadedMethod),
966         NumOverloads(NumOverloads), MethodList(MethodList), Name(Name) {}
967 
968   /// Rewrite member type indices with IndexMap. Returns false if a type index
969   /// is not in the map.
970   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
971 
972   static ErrorOr<OverloadedMethodRecord> deserialize(TypeRecordKind Kind,
973                                                      ArrayRef<uint8_t> &Data);
974 
getNumOverloads()975   uint16_t getNumOverloads() const { return NumOverloads; }
getMethodList()976   TypeIndex getMethodList() const { return MethodList; }
getName()977   StringRef getName() const { return Name; }
978 
979 private:
980   struct Layout {
981     ulittle16_t MethodCount; // Size of overload set
982     TypeIndex MethList;      // Type index of methods in overload set
983                              // Name: Null-terminated string
984   };
985 
986   uint16_t NumOverloads;
987   TypeIndex MethodList;
988   StringRef Name;
989 };
990 
991 // LF_MEMBER
992 class DataMemberRecord : public TypeRecord {
993 public:
DataMemberRecord(MemberAccess Access,TypeIndex Type,uint64_t Offset,StringRef Name)994   DataMemberRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset,
995                    StringRef Name)
996       : TypeRecord(TypeRecordKind::DataMember), Access(Access), Type(Type),
997         FieldOffset(Offset), Name(Name) {}
998 
999   /// Rewrite member type indices with IndexMap. Returns false if a type index
1000   /// is not in the map.
1001   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
1002 
1003   static ErrorOr<DataMemberRecord> deserialize(TypeRecordKind Kind,
1004                                                ArrayRef<uint8_t> &Data);
1005 
getAccess()1006   MemberAccess getAccess() const { return Access; }
getType()1007   TypeIndex getType() const { return Type; }
getFieldOffset()1008   uint64_t getFieldOffset() const { return FieldOffset; }
getName()1009   StringRef getName() const { return Name; }
1010 
1011 private:
1012   struct Layout {
1013     MemberAttributes Attrs; // Access control attributes, etc
1014     TypeIndex Type;
1015     // FieldOffset: LF_NUMERIC encoded byte offset
1016     // Name: Null-terminated string
1017   };
1018 
1019   MemberAccess Access;
1020   TypeIndex Type;
1021   uint64_t FieldOffset;
1022   StringRef Name;
1023 };
1024 
1025 // LF_STMEMBER
1026 class StaticDataMemberRecord : public TypeRecord {
1027 public:
StaticDataMemberRecord(MemberAccess Access,TypeIndex Type,StringRef Name)1028   StaticDataMemberRecord(MemberAccess Access, TypeIndex Type, StringRef Name)
1029       : TypeRecord(TypeRecordKind::StaticDataMember), Access(Access),
1030         Type(Type), Name(Name) {}
1031 
1032   /// Rewrite member type indices with IndexMap. Returns false if a type index
1033   /// is not in the map.
1034   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
1035 
1036   static ErrorOr<StaticDataMemberRecord> deserialize(TypeRecordKind Kind,
1037                                                      ArrayRef<uint8_t> &Data);
1038 
getAccess()1039   MemberAccess getAccess() const { return Access; }
getType()1040   TypeIndex getType() const { return Type; }
getName()1041   StringRef getName() const { return Name; }
1042 
1043 private:
1044   struct Layout {
1045     MemberAttributes Attrs; // Access control attributes, etc
1046     TypeIndex Type;
1047     // Name: Null-terminated string
1048   };
1049 
1050   MemberAccess Access;
1051   TypeIndex Type;
1052   StringRef Name;
1053 };
1054 
1055 // LF_ENUMERATE
1056 class EnumeratorRecord : public TypeRecord {
1057 public:
EnumeratorRecord(MemberAccess Access,APSInt Value,StringRef Name)1058   EnumeratorRecord(MemberAccess Access, APSInt Value, StringRef Name)
1059       : TypeRecord(TypeRecordKind::Enumerator), Access(Access),
1060         Value(std::move(Value)), Name(Name) {}
1061 
1062   /// Rewrite member type indices with IndexMap. Returns false if a type index
1063   /// is not in the map.
1064   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
1065 
1066   static ErrorOr<EnumeratorRecord> deserialize(TypeRecordKind Kind,
1067                                                ArrayRef<uint8_t> &Data);
1068 
getAccess()1069   MemberAccess getAccess() const { return Access; }
getValue()1070   APSInt getValue() const { return Value; }
getName()1071   StringRef getName() const { return Name; }
1072 
1073 private:
1074   struct Layout {
1075     MemberAttributes Attrs; // Access control attributes, etc
1076                             // EnumValue: LF_NUMERIC encoded enumerator value
1077                             // Name: Null-terminated string
1078   };
1079 
1080   MemberAccess Access;
1081   APSInt Value;
1082   StringRef Name;
1083 };
1084 
1085 // LF_VFUNCTAB
1086 class VFPtrRecord : public TypeRecord {
1087 public:
VFPtrRecord(TypeIndex Type)1088   VFPtrRecord(TypeIndex Type)
1089       : TypeRecord(TypeRecordKind::VFPtr), Type(Type) {}
1090 
1091   /// Rewrite member type indices with IndexMap. Returns false if a type index
1092   /// is not in the map.
1093   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
1094 
1095   static ErrorOr<VFPtrRecord> deserialize(TypeRecordKind Kind,
1096                                           ArrayRef<uint8_t> &Data);
1097 
getType()1098   TypeIndex getType() const { return Type; }
1099 
1100 private:
1101   struct Layout {
1102     ulittle16_t Pad0;
1103     TypeIndex Type; // Type of vfptr
1104   };
1105   TypeIndex Type;
1106 };
1107 
1108 // LF_BCLASS, LF_BINTERFACE
1109 class BaseClassRecord : public TypeRecord {
1110 public:
BaseClassRecord(MemberAccess Access,TypeIndex Type,uint64_t Offset)1111   BaseClassRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset)
1112       : TypeRecord(TypeRecordKind::BaseClass), Access(Access), Type(Type),
1113         Offset(Offset) {}
1114 
1115   /// Rewrite member type indices with IndexMap. Returns false if a type index
1116   /// is not in the map.
1117   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
1118 
1119   static ErrorOr<BaseClassRecord> deserialize(TypeRecordKind Kind,
1120                                               ArrayRef<uint8_t> &Data);
1121 
getAccess()1122   MemberAccess getAccess() const { return Access; }
getBaseType()1123   TypeIndex getBaseType() const { return Type; }
getBaseOffset()1124   uint64_t getBaseOffset() const { return Offset; }
1125 
1126 private:
1127   struct Layout {
1128     MemberAttributes Attrs; // Access control attributes, etc
1129     TypeIndex BaseType;     // Base class type
1130     // BaseOffset: LF_NUMERIC encoded byte offset of base from derived.
1131   };
1132   MemberAccess Access;
1133   TypeIndex Type;
1134   uint64_t Offset;
1135 };
1136 
1137 // LF_VBCLASS, LF_IVBCLASS
1138 class VirtualBaseClassRecord : public TypeRecord {
1139 public:
VirtualBaseClassRecord(MemberAccess Access,TypeIndex BaseType,TypeIndex VBPtrType,uint64_t Offset,uint64_t Index)1140   VirtualBaseClassRecord(MemberAccess Access, TypeIndex BaseType,
1141                          TypeIndex VBPtrType, uint64_t Offset, uint64_t Index)
1142       : TypeRecord(TypeRecordKind::VirtualBaseClass), Access(Access),
1143         BaseType(BaseType), VBPtrType(VBPtrType), VBPtrOffset(Offset),
1144         VTableIndex(Index) {}
1145 
1146   /// Rewrite member type indices with IndexMap. Returns false if a type index
1147   /// is not in the map.
1148   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
1149 
1150   static ErrorOr<VirtualBaseClassRecord> deserialize(TypeRecordKind Kind,
1151                                                      ArrayRef<uint8_t> &Data);
1152 
getAccess()1153   MemberAccess getAccess() const { return Access; }
getBaseType()1154   TypeIndex getBaseType() const { return BaseType; }
getVBPtrType()1155   TypeIndex getVBPtrType() const { return VBPtrType; }
getVBPtrOffset()1156   uint64_t getVBPtrOffset() const { return VBPtrOffset; }
getVTableIndex()1157   uint64_t getVTableIndex() const { return VTableIndex; }
1158 
1159 private:
1160   struct Layout {
1161     MemberAttributes Attrs; // Access control attributes, etc.
1162     TypeIndex BaseType;     // Base class type
1163     TypeIndex VBPtrType;    // Virtual base pointer type
1164     // VBPtrOffset: Offset of vbptr from vfptr encoded as LF_NUMERIC.
1165     // VBTableIndex: Index of vbase within vbtable encoded as LF_NUMERIC.
1166   };
1167   MemberAccess Access;
1168   TypeIndex BaseType;
1169   TypeIndex VBPtrType;
1170   uint64_t VBPtrOffset;
1171   uint64_t VTableIndex;
1172 };
1173 
1174 /// LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records
1175 /// together. The first will end in an LF_INDEX record that points to the next.
1176 class ListContinuationRecord : public TypeRecord {
1177 public:
ListContinuationRecord(TypeIndex ContinuationIndex)1178   ListContinuationRecord(TypeIndex ContinuationIndex)
1179       : TypeRecord(TypeRecordKind::ListContinuation),
1180         ContinuationIndex(ContinuationIndex) {}
1181 
getContinuationIndex()1182   TypeIndex getContinuationIndex() const { return ContinuationIndex; }
1183 
1184   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
1185 
1186   static ErrorOr<ListContinuationRecord> deserialize(TypeRecordKind Kind,
1187                                                      ArrayRef<uint8_t> &Data);
1188 
1189 private:
1190   struct Layout {
1191     ulittle16_t Pad0;
1192     TypeIndex ContinuationIndex;
1193   };
1194   TypeIndex ContinuationIndex;
1195 };
1196 
1197 typedef CVRecord<TypeLeafKind> CVType;
1198 typedef VarStreamArray<CVType> CVTypeArray;
1199 }
1200 }
1201 
1202 #endif
1203