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