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