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