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