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