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