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/StringRef.h" 16 #include "llvm/DebugInfo/CodeView/CVRecord.h" 17 #include "llvm/DebugInfo/CodeView/CodeView.h" 18 #include "llvm/DebugInfo/CodeView/TypeIndex.h" 19 #include "llvm/Support/ErrorOr.h" 20 #include <cinttypes> 21 #include <utility> 22 23 namespace llvm { 24 namespace codeview { 25 26 using llvm::support::little32_t; 27 using llvm::support::ulittle16_t; 28 using llvm::support::ulittle32_t; 29 30 /// Equvalent to CV_fldattr_t in cvinfo.h. 31 struct MemberAttributes { 32 ulittle16_t Attrs; 33 enum { 34 MethodKindShift = 2, 35 }; 36 37 /// Get the access specifier. Valid for any kind of member. getAccessMemberAttributes38 MemberAccess getAccess() const { 39 return MemberAccess(unsigned(Attrs) & unsigned(MethodOptions::AccessMask)); 40 } 41 42 /// Indicates if a method is defined with friend, virtual, static, etc. getMethodKindMemberAttributes43 MethodKind getMethodKind() const { 44 return MethodKind( 45 (unsigned(Attrs) & unsigned(MethodOptions::MethodKindMask)) >> 46 MethodKindShift); 47 } 48 49 /// Get the flags that are not included in access control or method 50 /// properties. getFlagsMemberAttributes51 MethodOptions getFlags() const { 52 return MethodOptions( 53 unsigned(Attrs) & 54 ~unsigned(MethodOptions::AccessMask | MethodOptions::MethodKindMask)); 55 } 56 57 /// Is this method virtual. isVirtualMemberAttributes58 bool isVirtual() const { 59 auto MP = getMethodKind(); 60 return MP != MethodKind::Vanilla && MP != MethodKind::Friend && 61 MP != MethodKind::Static; 62 } 63 64 /// Does this member introduce a new virtual method. isIntroducedVirtualMemberAttributes65 bool isIntroducedVirtual() const { 66 auto MP = getMethodKind(); 67 return MP == MethodKind::IntroducingVirtual || 68 MP == MethodKind::PureIntroducingVirtual; 69 } 70 }; 71 72 // Does not correspond to any tag, this is the tail of an LF_POINTER record 73 // if it represents a member pointer. 74 class MemberPointerInfo { 75 public: MemberPointerInfo()76 MemberPointerInfo() {} 77 MemberPointerInfo(TypeIndex ContainingType,PointerToMemberRepresentation Representation)78 MemberPointerInfo(TypeIndex ContainingType, 79 PointerToMemberRepresentation Representation) 80 : ContainingType(ContainingType), Representation(Representation) {} 81 82 /// Rewrite member type indices with IndexMap. Returns false if a type index 83 /// is not in the map. 84 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 85 86 static ErrorOr<MemberPointerInfo> deserialize(ArrayRef<uint8_t> &Data); 87 getContainingType()88 TypeIndex getContainingType() const { return ContainingType; } getRepresentation()89 PointerToMemberRepresentation getRepresentation() const { 90 return Representation; 91 } 92 93 private: 94 struct Layout { 95 TypeIndex ClassType; 96 ulittle16_t Representation; // PointerToMemberRepresentation 97 }; 98 99 TypeIndex ContainingType; 100 PointerToMemberRepresentation Representation; 101 }; 102 103 class TypeRecord { 104 protected: TypeRecord(TypeRecordKind Kind)105 explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {} 106 107 public: getKind()108 TypeRecordKind getKind() const { return Kind; } 109 110 private: 111 TypeRecordKind Kind; 112 }; 113 114 // LF_MODIFIER 115 class ModifierRecord : public TypeRecord { 116 public: ModifierRecord(TypeIndex ModifiedType,ModifierOptions Modifiers)117 ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers) 118 : TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType), 119 Modifiers(Modifiers) {} 120 121 /// Rewrite member type indices with IndexMap. Returns false if a type index 122 /// is not in the map. 123 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 124 125 static ErrorOr<ModifierRecord> deserialize(TypeRecordKind Kind, 126 ArrayRef<uint8_t> &Data); 127 getModifiedType()128 TypeIndex getModifiedType() const { return ModifiedType; } getModifiers()129 ModifierOptions getModifiers() const { return Modifiers; } 130 131 private: 132 struct Layout { 133 TypeIndex ModifiedType; 134 ulittle16_t Modifiers; // ModifierOptions 135 }; 136 137 TypeIndex ModifiedType; 138 ModifierOptions Modifiers; 139 }; 140 141 // LF_PROCEDURE 142 class ProcedureRecord : public TypeRecord { 143 public: ProcedureRecord(TypeIndex ReturnType,CallingConvention CallConv,FunctionOptions Options,uint16_t ParameterCount,TypeIndex ArgumentList)144 ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv, 145 FunctionOptions Options, uint16_t ParameterCount, 146 TypeIndex ArgumentList) 147 : TypeRecord(TypeRecordKind::Procedure), ReturnType(ReturnType), 148 CallConv(CallConv), Options(Options), ParameterCount(ParameterCount), 149 ArgumentList(ArgumentList) {} 150 151 /// Rewrite member type indices with IndexMap. Returns false if a type index 152 /// is not in the map. 153 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 154 155 static ErrorOr<ProcedureRecord> deserialize(TypeRecordKind Kind, 156 ArrayRef<uint8_t> &Data); 157 getLayoutSize()158 static uint32_t getLayoutSize() { return 2 + sizeof(Layout); } 159 getReturnType()160 TypeIndex getReturnType() const { return ReturnType; } getCallConv()161 CallingConvention getCallConv() const { return CallConv; } getOptions()162 FunctionOptions getOptions() const { return Options; } getParameterCount()163 uint16_t getParameterCount() const { return ParameterCount; } getArgumentList()164 TypeIndex getArgumentList() const { return ArgumentList; } 165 166 private: 167 struct Layout { 168 TypeIndex ReturnType; 169 CallingConvention CallConv; 170 FunctionOptions Options; 171 ulittle16_t NumParameters; 172 TypeIndex ArgListType; 173 }; 174 175 TypeIndex ReturnType; 176 CallingConvention CallConv; 177 FunctionOptions Options; 178 uint16_t ParameterCount; 179 TypeIndex ArgumentList; 180 }; 181 182 // LF_MFUNCTION 183 class MemberFunctionRecord : public TypeRecord { 184 public: MemberFunctionRecord(TypeIndex ReturnType,TypeIndex ClassType,TypeIndex ThisType,CallingConvention CallConv,FunctionOptions Options,uint16_t ParameterCount,TypeIndex ArgumentList,int32_t ThisPointerAdjustment)185 MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType, 186 TypeIndex ThisType, CallingConvention CallConv, 187 FunctionOptions Options, uint16_t ParameterCount, 188 TypeIndex ArgumentList, int32_t ThisPointerAdjustment) 189 : TypeRecord(TypeRecordKind::MemberFunction), ReturnType(ReturnType), 190 ClassType(ClassType), ThisType(ThisType), CallConv(CallConv), 191 Options(Options), ParameterCount(ParameterCount), 192 ArgumentList(ArgumentList), 193 ThisPointerAdjustment(ThisPointerAdjustment) {} 194 195 /// Rewrite member type indices with IndexMap. Returns false if a type index 196 /// is not in the map. 197 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 198 199 static ErrorOr<MemberFunctionRecord> deserialize(TypeRecordKind Kind, 200 ArrayRef<uint8_t> &Data); 201 getReturnType()202 TypeIndex getReturnType() const { return ReturnType; } getClassType()203 TypeIndex getClassType() const { return ClassType; } getThisType()204 TypeIndex getThisType() const { return ThisType; } getCallConv()205 CallingConvention getCallConv() const { return CallConv; } getOptions()206 FunctionOptions getOptions() const { return Options; } getParameterCount()207 uint16_t getParameterCount() const { return ParameterCount; } getArgumentList()208 TypeIndex getArgumentList() const { return ArgumentList; } getThisPointerAdjustment()209 int32_t getThisPointerAdjustment() const { return ThisPointerAdjustment; } 210 211 private: 212 struct Layout { 213 TypeIndex ReturnType; 214 TypeIndex ClassType; 215 TypeIndex ThisType; 216 CallingConvention CallConv; 217 FunctionOptions Options; 218 ulittle16_t NumParameters; 219 TypeIndex ArgListType; 220 little32_t ThisAdjustment; 221 }; 222 223 TypeIndex ReturnType; 224 TypeIndex ClassType; 225 TypeIndex ThisType; 226 CallingConvention CallConv; 227 FunctionOptions Options; 228 uint16_t ParameterCount; 229 TypeIndex ArgumentList; 230 int32_t ThisPointerAdjustment; 231 }; 232 233 // LF_MFUNC_ID 234 class MemberFuncIdRecord : public TypeRecord { 235 public: MemberFuncIdRecord(TypeIndex ClassType,TypeIndex FunctionType,StringRef Name)236 MemberFuncIdRecord(TypeIndex ClassType, TypeIndex FunctionType, 237 StringRef Name) 238 : TypeRecord(TypeRecordKind::MemberFuncId), ClassType(ClassType), 239 FunctionType(FunctionType), Name(Name) {} 240 241 /// Rewrite member type indices with IndexMap. Returns false if a type index 242 /// is not in the map. 243 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 244 245 static ErrorOr<MemberFuncIdRecord> deserialize(TypeRecordKind Kind, 246 ArrayRef<uint8_t> &Data); getClassType()247 TypeIndex getClassType() const { return ClassType; } getFunctionType()248 TypeIndex getFunctionType() const { return FunctionType; } getName()249 StringRef getName() const { return Name; } 250 251 private: 252 struct Layout { 253 TypeIndex ClassType; 254 TypeIndex FunctionType; 255 // Name: The null-terminated name follows. 256 }; 257 TypeIndex ClassType; 258 TypeIndex FunctionType; 259 StringRef Name; 260 }; 261 262 // LF_ARGLIST, LF_SUBSTR_LIST 263 class ArgListRecord : public TypeRecord { 264 public: ArgListRecord(TypeRecordKind Kind,ArrayRef<TypeIndex> Indices)265 ArgListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices) 266 : TypeRecord(Kind), StringIndices(Indices) {} 267 268 /// Rewrite member type indices with IndexMap. Returns false if a type index 269 /// is not in the map. 270 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 271 272 static ErrorOr<ArgListRecord> deserialize(TypeRecordKind Kind, 273 ArrayRef<uint8_t> &Data); 274 getIndices()275 ArrayRef<TypeIndex> getIndices() const { return StringIndices; } 276 getLayoutSize()277 static uint32_t getLayoutSize() { return 2 + sizeof(Layout); } 278 279 private: 280 struct Layout { 281 ulittle32_t NumArgs; // Number of arguments 282 // ArgTypes[]: Type indicies of arguments 283 }; 284 285 std::vector<TypeIndex> StringIndices; 286 }; 287 288 // LF_POINTER 289 class PointerRecord : public TypeRecord { 290 public: 291 static const uint32_t PointerKindShift = 0; 292 static const uint32_t PointerKindMask = 0x1F; 293 294 static const uint32_t PointerModeShift = 5; 295 static const uint32_t PointerModeMask = 0x07; 296 297 static const uint32_t PointerSizeShift = 13; 298 static const uint32_t PointerSizeMask = 0xFF; 299 PointerRecord(TypeIndex ReferentType,PointerKind Kind,PointerMode Mode,PointerOptions Options,uint8_t Size)300 PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode, 301 PointerOptions Options, uint8_t Size) 302 : PointerRecord(ReferentType, Kind, Mode, Options, Size, 303 MemberPointerInfo()) {} 304 PointerRecord(TypeIndex ReferentType,PointerKind Kind,PointerMode Mode,PointerOptions Options,uint8_t Size,const MemberPointerInfo & Member)305 PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode, 306 PointerOptions Options, uint8_t Size, 307 const MemberPointerInfo &Member) 308 : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType), 309 PtrKind(Kind), Mode(Mode), Options(Options), Size(Size), 310 MemberInfo(Member) {} 311 312 /// Rewrite member type indices with IndexMap. Returns false if a type index 313 /// is not in the map. 314 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 315 316 static ErrorOr<PointerRecord> deserialize(TypeRecordKind Kind, 317 ArrayRef<uint8_t> &Data); 318 getReferentType()319 TypeIndex getReferentType() const { return ReferentType; } getPointerKind()320 PointerKind getPointerKind() const { return PtrKind; } getMode()321 PointerMode getMode() const { return Mode; } getOptions()322 PointerOptions getOptions() const { return Options; } getSize()323 uint8_t getSize() const { return Size; } getMemberInfo()324 MemberPointerInfo getMemberInfo() const { return MemberInfo; } 325 isPointerToMember()326 bool isPointerToMember() const { 327 return Mode == PointerMode::PointerToDataMember || 328 Mode == PointerMode::PointerToMemberFunction; 329 } isFlat()330 bool isFlat() const { 331 return !!(uint32_t(Options) & uint32_t(PointerOptions::Flat32)); 332 } isConst()333 bool isConst() const { 334 return !!(uint32_t(Options) & uint32_t(PointerOptions::Const)); 335 } isVolatile()336 bool isVolatile() const { 337 return !!(uint32_t(Options) & uint32_t(PointerOptions::Volatile)); 338 } isUnaligned()339 bool isUnaligned() const { 340 return !!(uint32_t(Options) & uint32_t(PointerOptions::Unaligned)); 341 } 342 343 private: 344 struct Layout { 345 TypeIndex PointeeType; 346 ulittle32_t Attrs; // pointer attributes 347 // if pointer to member: 348 // PointerToMemberTail getPtrKindLayout349 PointerKind getPtrKind() const { 350 return PointerKind(Attrs & PointerKindMask); 351 } getPtrModeLayout352 PointerMode getPtrMode() const { 353 return PointerMode((Attrs >> PointerModeShift) & PointerModeMask); 354 } getPtrSizeLayout355 uint8_t getPtrSize() const { 356 return (Attrs >> PointerSizeShift) & PointerSizeMask; 357 } isFlatLayout358 bool isFlat() const { return Attrs & (1 << 8); } isVolatileLayout359 bool isVolatile() const { return Attrs & (1 << 9); } isConstLayout360 bool isConst() const { return Attrs & (1 << 10); } isUnalignedLayout361 bool isUnaligned() const { return Attrs & (1 << 11); } 362 isPointerToDataMemberLayout363 bool isPointerToDataMember() const { 364 return getPtrMode() == PointerMode::PointerToDataMember; 365 } isPointerToMemberFunctionLayout366 bool isPointerToMemberFunction() const { 367 return getPtrMode() == PointerMode::PointerToMemberFunction; 368 } isPointerToMemberLayout369 bool isPointerToMember() const { 370 return isPointerToMemberFunction() || isPointerToDataMember(); 371 } 372 }; 373 374 TypeIndex ReferentType; 375 PointerKind PtrKind; 376 PointerMode Mode; 377 PointerOptions Options; 378 uint8_t Size; 379 MemberPointerInfo MemberInfo; 380 }; 381 382 // LF_NESTTYPE 383 class NestedTypeRecord : public TypeRecord { 384 public: NestedTypeRecord(TypeIndex Type,StringRef Name)385 NestedTypeRecord(TypeIndex Type, StringRef Name) 386 : TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {} 387 388 /// Rewrite member type indices with IndexMap. Returns false if a type index 389 /// is not in the map. 390 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 391 392 static ErrorOr<NestedTypeRecord> deserialize(TypeRecordKind Kind, 393 ArrayRef<uint8_t> &Data); 394 getNestedType()395 TypeIndex getNestedType() const { return Type; } getName()396 StringRef getName() const { return Name; } 397 398 private: 399 struct Layout { 400 ulittle16_t Pad0; // Should be zero 401 TypeIndex Type; // Type index of nested type 402 // Name: Null-terminated string 403 }; 404 405 TypeIndex Type; 406 StringRef Name; 407 }; 408 409 // LF_ARRAY 410 class ArrayRecord : public TypeRecord { 411 public: ArrayRecord(TypeIndex ElementType,TypeIndex IndexType,uint64_t Size,StringRef Name)412 ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size, 413 StringRef Name) 414 : TypeRecord(TypeRecordKind::Array), ElementType(ElementType), 415 IndexType(IndexType), Size(Size), Name(Name) {} 416 417 /// Rewrite member type indices with IndexMap. Returns false if a type index 418 /// is not in the map. 419 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 420 421 static ErrorOr<ArrayRecord> deserialize(TypeRecordKind Kind, 422 ArrayRef<uint8_t> &Data); 423 getElementType()424 TypeIndex getElementType() const { return ElementType; } getIndexType()425 TypeIndex getIndexType() const { return IndexType; } getSize()426 uint64_t getSize() const { return Size; } getName()427 llvm::StringRef getName() const { return Name; } 428 429 private: 430 struct Layout { 431 TypeIndex ElementType; 432 TypeIndex IndexType; 433 // SizeOf: LF_NUMERIC encoded size in bytes. Not element count! 434 // Name: The null-terminated name follows. 435 }; 436 437 TypeIndex ElementType; 438 TypeIndex IndexType; 439 uint64_t Size; 440 llvm::StringRef Name; 441 }; 442 443 class TagRecord : public TypeRecord { 444 protected: TagRecord(TypeRecordKind Kind,uint16_t MemberCount,ClassOptions Options,TypeIndex FieldList,StringRef Name,StringRef UniqueName)445 TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options, 446 TypeIndex FieldList, StringRef Name, StringRef UniqueName) 447 : TypeRecord(Kind), MemberCount(MemberCount), Options(Options), 448 FieldList(FieldList), Name(Name), UniqueName(UniqueName) {} 449 450 public: 451 /// Rewrite member type indices with IndexMap. Returns false if a type index 452 /// is not in the map. 453 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 454 455 static const int HfaKindShift = 11; 456 static const int HfaKindMask = 0x1800; 457 static const int WinRTKindShift = 14; 458 static const int WinRTKindMask = 0xC000; 459 getMemberCount()460 uint16_t getMemberCount() const { return MemberCount; } getOptions()461 ClassOptions getOptions() const { return Options; } getFieldList()462 TypeIndex getFieldList() const { return FieldList; } getName()463 StringRef getName() const { return Name; } getUniqueName()464 StringRef getUniqueName() const { return UniqueName; } 465 466 private: 467 uint16_t MemberCount; 468 ClassOptions Options; 469 TypeIndex FieldList; 470 StringRef Name; 471 StringRef UniqueName; 472 }; 473 474 // LF_CLASS, LF_STRUCTURE, LF_INTERFACE 475 class ClassRecord : public TagRecord { 476 public: ClassRecord(TypeRecordKind Kind,uint16_t MemberCount,ClassOptions Options,HfaKind Hfa,WindowsRTClassKind WinRTKind,TypeIndex FieldList,TypeIndex DerivationList,TypeIndex VTableShape,uint64_t Size,StringRef Name,StringRef UniqueName)477 ClassRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options, 478 HfaKind Hfa, WindowsRTClassKind WinRTKind, TypeIndex FieldList, 479 TypeIndex DerivationList, TypeIndex VTableShape, uint64_t Size, 480 StringRef Name, StringRef UniqueName) 481 : TagRecord(Kind, MemberCount, Options, FieldList, Name, UniqueName), 482 Hfa(Hfa), WinRTKind(WinRTKind), DerivationList(DerivationList), 483 VTableShape(VTableShape), Size(Size) {} 484 485 /// Rewrite member type indices with IndexMap. Returns false if a type index 486 /// is not in the map. 487 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 488 489 static ErrorOr<ClassRecord> deserialize(TypeRecordKind Kind, 490 ArrayRef<uint8_t> &Data); 491 getHfa()492 HfaKind getHfa() const { return Hfa; } getWinRTKind()493 WindowsRTClassKind getWinRTKind() const { return WinRTKind; } getDerivationList()494 TypeIndex getDerivationList() const { return DerivationList; } getVTableShape()495 TypeIndex getVTableShape() const { return VTableShape; } getSize()496 uint64_t getSize() const { return Size; } 497 498 private: 499 struct Layout { 500 ulittle16_t MemberCount; // Number of members in FieldList. 501 ulittle16_t Properties; // ClassOptions bitset 502 TypeIndex FieldList; // LF_FIELDLIST: List of all kinds of members 503 TypeIndex DerivedFrom; // LF_DERIVED: List of known derived classes 504 TypeIndex VShape; // LF_VTSHAPE: Shape of the vftable 505 // SizeOf: The 'sizeof' the UDT in bytes is encoded as an LF_NUMERIC 506 // integer. 507 // Name: The null-terminated name follows. 508 hasUniqueNameLayout509 bool hasUniqueName() const { 510 return Properties & uint16_t(ClassOptions::HasUniqueName); 511 } 512 }; 513 514 HfaKind Hfa; 515 WindowsRTClassKind WinRTKind; 516 TypeIndex DerivationList; 517 TypeIndex VTableShape; 518 uint64_t Size; 519 }; 520 521 // LF_UNION 522 struct UnionRecord : public TagRecord { UnionRecordUnionRecord523 UnionRecord(uint16_t MemberCount, ClassOptions Options, HfaKind Hfa, 524 TypeIndex FieldList, uint64_t Size, StringRef Name, 525 StringRef UniqueName) 526 : TagRecord(TypeRecordKind::Union, MemberCount, Options, FieldList, Name, 527 UniqueName), 528 Hfa(Hfa), Size(Size) {} 529 530 static ErrorOr<UnionRecord> deserialize(TypeRecordKind Kind, 531 ArrayRef<uint8_t> &Data); 532 getHfaUnionRecord533 HfaKind getHfa() const { return Hfa; } getSizeUnionRecord534 uint64_t getSize() const { return Size; } 535 536 private: 537 struct Layout { 538 ulittle16_t MemberCount; // Number of members in FieldList. 539 ulittle16_t Properties; // ClassOptions bitset 540 TypeIndex FieldList; // LF_FIELDLIST: List of all kinds of members 541 // SizeOf: The 'sizeof' the UDT in bytes is encoded as an LF_NUMERIC 542 // integer. 543 // Name: The null-terminated name follows. 544 hasUniqueNameUnionRecord::Layout545 bool hasUniqueName() const { 546 return Properties & uint16_t(ClassOptions::HasUniqueName); 547 } 548 }; 549 550 HfaKind Hfa; 551 uint64_t Size; 552 }; 553 554 // LF_ENUM 555 class EnumRecord : public TagRecord { 556 public: EnumRecord(uint16_t MemberCount,ClassOptions Options,TypeIndex FieldList,StringRef Name,StringRef UniqueName,TypeIndex UnderlyingType)557 EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, 558 StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType) 559 : TagRecord(TypeRecordKind::Enum, MemberCount, Options, FieldList, Name, 560 UniqueName), 561 UnderlyingType(UnderlyingType) {} 562 563 /// Rewrite member type indices with IndexMap. Returns false if a type index is not in the map. 564 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 565 566 static ErrorOr<EnumRecord> deserialize(TypeRecordKind Kind, 567 ArrayRef<uint8_t> &Data); 568 getUnderlyingType()569 TypeIndex getUnderlyingType() const { return UnderlyingType; } 570 571 private: 572 struct Layout { 573 ulittle16_t NumEnumerators; // Number of enumerators 574 ulittle16_t Properties; 575 TypeIndex UnderlyingType; 576 TypeIndex FieldListType; 577 // Name: The null-terminated name follows. 578 hasUniqueNameLayout579 bool hasUniqueName() const { 580 return Properties & uint16_t(ClassOptions::HasUniqueName); 581 } 582 }; 583 584 TypeIndex UnderlyingType; 585 }; 586 587 // LF_BITFIELD 588 class BitFieldRecord : public TypeRecord { 589 public: BitFieldRecord(TypeIndex Type,uint8_t BitSize,uint8_t BitOffset)590 BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset) 591 : TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize), 592 BitOffset(BitOffset) {} 593 594 /// Rewrite member type indices with IndexMap. Returns false if a type index 595 /// is not in the map. 596 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 597 598 static ErrorOr<BitFieldRecord> deserialize(TypeRecordKind Kind, 599 ArrayRef<uint8_t> &Data); 600 getType()601 TypeIndex getType() const { return Type; } getBitOffset()602 uint8_t getBitOffset() const { return BitOffset; } getBitSize()603 uint8_t getBitSize() const { return BitSize; } 604 605 private: 606 struct Layout { 607 TypeIndex Type; 608 uint8_t BitSize; 609 uint8_t BitOffset; 610 }; 611 612 TypeIndex Type; 613 uint8_t BitSize; 614 uint8_t BitOffset; 615 }; 616 617 // LF_VTSHAPE 618 class VFTableShapeRecord : public TypeRecord { 619 public: VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots)620 explicit VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots) 621 : TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {} VFTableShapeRecord(std::vector<VFTableSlotKind> Slots)622 explicit VFTableShapeRecord(std::vector<VFTableSlotKind> Slots) 623 : TypeRecord(TypeRecordKind::VFTableShape), Slots(std::move(Slots)) {} 624 625 /// Rewrite member type indices with IndexMap. Returns false if a type index 626 /// is not in the map. 627 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 628 629 static ErrorOr<VFTableShapeRecord> deserialize(TypeRecordKind Kind, 630 ArrayRef<uint8_t> &Data); 631 getSlots()632 ArrayRef<VFTableSlotKind> getSlots() const { 633 if (!SlotsRef.empty()) 634 return SlotsRef; 635 return Slots; 636 } getEntryCount()637 uint32_t getEntryCount() const { return getSlots().size(); } 638 639 private: 640 struct Layout { 641 // Number of vftable entries. Each method may have more than one entry due 642 // to 643 // things like covariant return types. 644 ulittle16_t VFEntryCount; 645 // Descriptors[]: 4-bit virtual method descriptors of type CV_VTS_desc_e. 646 }; 647 648 private: 649 ArrayRef<VFTableSlotKind> SlotsRef; 650 std::vector<VFTableSlotKind> Slots; 651 }; 652 653 // LF_TYPESERVER2 654 class TypeServer2Record : public TypeRecord { 655 public: TypeServer2Record(StringRef Guid,uint32_t Age,StringRef Name)656 TypeServer2Record(StringRef Guid, uint32_t Age, StringRef Name) 657 : TypeRecord(TypeRecordKind::TypeServer2), Guid(Guid), Age(Age), 658 Name(Name) {} 659 660 /// Rewrite member type indices with IndexMap. Returns false if a type index 661 /// is not in the map. 662 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 663 664 static ErrorOr<TypeServer2Record> deserialize(TypeRecordKind Kind, 665 ArrayRef<uint8_t> &Data); 666 getGuid()667 StringRef getGuid() const { return Guid; } 668 getAge()669 uint32_t getAge() const { return Age; } 670 getName()671 StringRef getName() const { return Name; } 672 673 private: 674 struct Layout { 675 char Guid[16]; // GUID 676 ulittle32_t Age; 677 // Name: Name of the PDB as a null-terminated string 678 }; 679 680 StringRef Guid; 681 uint32_t Age; 682 StringRef Name; 683 }; 684 685 // LF_STRING_ID 686 class StringIdRecord : public TypeRecord { 687 public: StringIdRecord(TypeIndex Id,StringRef String)688 StringIdRecord(TypeIndex Id, StringRef String) 689 : TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {} 690 691 /// Rewrite member type indices with IndexMap. Returns false if a type index 692 /// is not in the map. 693 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 694 695 static ErrorOr<StringIdRecord> deserialize(TypeRecordKind Kind, 696 ArrayRef<uint8_t> &Data); 697 getId()698 TypeIndex getId() const { return Id; } 699 getString()700 StringRef getString() const { return String; } 701 702 private: 703 struct Layout { 704 TypeIndex id; 705 // Name: Name of the PDB as a null-terminated string 706 }; 707 708 TypeIndex Id; 709 StringRef String; 710 }; 711 712 // LF_FUNC_ID 713 class FuncIdRecord : public TypeRecord { 714 public: FuncIdRecord(TypeIndex ParentScope,TypeIndex FunctionType,StringRef Name)715 FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name) 716 : TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope), 717 FunctionType(FunctionType), Name(Name) {} 718 719 /// Rewrite member type indices with IndexMap. Returns false if a type index 720 /// is not in the map. 721 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 722 723 static ErrorOr<FuncIdRecord> deserialize(TypeRecordKind Kind, 724 ArrayRef<uint8_t> &Data); 725 getParentScope()726 TypeIndex getParentScope() const { return ParentScope; } 727 getFunctionType()728 TypeIndex getFunctionType() const { return FunctionType; } 729 getName()730 StringRef getName() const { return Name; } 731 732 private: 733 struct Layout { 734 TypeIndex ParentScope; 735 TypeIndex FunctionType; 736 // Name: The null-terminated name follows. 737 }; 738 739 TypeIndex ParentScope; 740 TypeIndex FunctionType; 741 StringRef Name; 742 }; 743 744 // LF_UDT_SRC_LINE 745 class UdtSourceLineRecord : public TypeRecord { 746 public: UdtSourceLineRecord(TypeIndex UDT,TypeIndex SourceFile,uint32_t LineNumber)747 UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber) 748 : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT), 749 SourceFile(SourceFile), LineNumber(LineNumber) {} 750 751 /// Rewrite member type indices with IndexMap. Returns false if a type index 752 /// is not in the map. 753 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 754 755 static ErrorOr<UdtSourceLineRecord> deserialize(TypeRecordKind Kind, 756 ArrayRef<uint8_t> &Data); 757 getUDT()758 TypeIndex getUDT() const { return UDT; } getSourceFile()759 TypeIndex getSourceFile() const { return SourceFile; } getLineNumber()760 uint32_t getLineNumber() const { return LineNumber; } 761 762 private: 763 struct Layout { 764 TypeIndex UDT; // The user-defined type 765 TypeIndex SourceFile; // StringID containing the source filename 766 ulittle32_t LineNumber; 767 }; 768 769 TypeIndex UDT; 770 TypeIndex SourceFile; 771 uint32_t LineNumber; 772 }; 773 774 // LF_UDT_MOD_SRC_LINE 775 class UdtModSourceLineRecord : public TypeRecord { 776 public: UdtModSourceLineRecord(TypeIndex UDT,TypeIndex SourceFile,uint32_t LineNumber,uint16_t Module)777 UdtModSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, 778 uint32_t LineNumber, uint16_t Module) 779 : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT), 780 SourceFile(SourceFile), LineNumber(LineNumber), Module(Module) {} 781 782 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 783 deserialize(TypeRecordKind Kind,ArrayRef<uint8_t> & Data)784 static ErrorOr<UdtModSourceLineRecord> deserialize(TypeRecordKind Kind, 785 ArrayRef<uint8_t> &Data) { 786 const Layout *L = nullptr; 787 CV_DESERIALIZE(Data, L); 788 789 return UdtModSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber, 790 L->Module); 791 } 792 getUDT()793 TypeIndex getUDT() const { return UDT; } getSourceFile()794 TypeIndex getSourceFile() const { return SourceFile; } getLineNumber()795 uint32_t getLineNumber() const { return LineNumber; } getModule()796 uint16_t getModule() const { return Module; } 797 798 private: 799 struct Layout { 800 TypeIndex UDT; // The user-defined type 801 TypeIndex SourceFile; // StringID containing the source filename 802 ulittle32_t LineNumber; 803 ulittle16_t Module; // Module that contributes this UDT definition 804 }; 805 806 TypeIndex UDT; 807 TypeIndex SourceFile; 808 uint32_t LineNumber; 809 uint16_t Module; 810 }; 811 812 // LF_BUILDINFO 813 class BuildInfoRecord : public TypeRecord { 814 public: BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices)815 BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices) 816 : TypeRecord(TypeRecordKind::BuildInfo), 817 ArgIndices(ArgIndices.begin(), ArgIndices.end()) {} 818 819 /// Rewrite member type indices with IndexMap. Returns false if a type index 820 /// is not in the map. 821 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 822 823 static ErrorOr<BuildInfoRecord> deserialize(TypeRecordKind Kind, 824 ArrayRef<uint8_t> &Data); 825 getArgs()826 ArrayRef<TypeIndex> getArgs() const { return ArgIndices; } 827 828 private: 829 struct Layout { 830 ulittle16_t NumArgs; // Number of arguments 831 // ArgTypes[]: Type indicies of arguments 832 }; 833 SmallVector<TypeIndex, 4> ArgIndices; 834 }; 835 836 // LF_VFTABLE 837 class VFTableRecord : public TypeRecord { 838 public: VFTableRecord(TypeIndex CompleteClass,TypeIndex OverriddenVFTable,uint32_t VFPtrOffset,StringRef Name,ArrayRef<StringRef> Methods)839 VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable, 840 uint32_t VFPtrOffset, StringRef Name, 841 ArrayRef<StringRef> Methods) 842 : TypeRecord(TypeRecordKind::VFTable), 843 CompleteClass(CompleteClass), OverriddenVFTable(OverriddenVFTable), 844 VFPtrOffset(VFPtrOffset), Name(Name), MethodNamesRef(Methods) {} VFTableRecord(TypeIndex CompleteClass,TypeIndex OverriddenVFTable,uint32_t VFPtrOffset,StringRef Name,const std::vector<StringRef> & Methods)845 VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable, 846 uint32_t VFPtrOffset, StringRef Name, 847 const std::vector<StringRef> &Methods) 848 : TypeRecord(TypeRecordKind::VFTable), 849 CompleteClass(CompleteClass), OverriddenVFTable(OverriddenVFTable), 850 VFPtrOffset(VFPtrOffset), Name(Name), MethodNames(Methods) {} 851 852 /// Rewrite member type indices with IndexMap. Returns false if a type index 853 /// is not in the map. 854 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 855 856 static ErrorOr<VFTableRecord> deserialize(TypeRecordKind Kind, 857 ArrayRef<uint8_t> &Data); 858 getCompleteClass()859 TypeIndex getCompleteClass() const { return CompleteClass; } getOverriddenVTable()860 TypeIndex getOverriddenVTable() const { return OverriddenVFTable; } getVFPtrOffset()861 uint32_t getVFPtrOffset() const { return VFPtrOffset; } getName()862 StringRef getName() const { return Name; } getMethodNames()863 ArrayRef<StringRef> getMethodNames() const { 864 if (!MethodNamesRef.empty()) 865 return MethodNamesRef; 866 return MethodNames; 867 } 868 869 private: 870 struct Layout { 871 TypeIndex CompleteClass; // Class that owns this vftable. 872 TypeIndex OverriddenVFTable; // VFTable that this overrides. 873 ulittle32_t VFPtrOffset; // VFPtr offset in CompleteClass 874 ulittle32_t NamesLen; // Length of subsequent names array in bytes. 875 // Names: A sequence of null-terminated strings. First string is vftable 876 // names. 877 }; 878 879 TypeIndex CompleteClass; 880 TypeIndex OverriddenVFTable; 881 ulittle32_t VFPtrOffset; 882 StringRef Name; 883 ArrayRef<StringRef> MethodNamesRef; 884 std::vector<StringRef> MethodNames; 885 }; 886 887 // LF_ONEMETHOD 888 class OneMethodRecord : public TypeRecord { 889 public: OneMethodRecord(TypeIndex Type,MethodKind Kind,MethodOptions Options,MemberAccess Access,int32_t VFTableOffset,StringRef Name)890 OneMethodRecord(TypeIndex Type, MethodKind Kind, MethodOptions Options, 891 MemberAccess Access, int32_t VFTableOffset, StringRef Name) 892 : TypeRecord(TypeRecordKind::OneMethod), Type(Type), Kind(Kind), 893 Options(Options), Access(Access), VFTableOffset(VFTableOffset), 894 Name(Name) {} 895 896 /// Rewrite member type indices with IndexMap. Returns false if a type index 897 /// is not in the map. 898 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 899 900 static ErrorOr<OneMethodRecord> deserialize(TypeRecordKind Kind, 901 ArrayRef<uint8_t> &Data); 902 getType()903 TypeIndex getType() const { return Type; } getKind()904 MethodKind getKind() const { return Kind; } getOptions()905 MethodOptions getOptions() const { return Options; } getAccess()906 MemberAccess getAccess() const { return Access; } getVFTableOffset()907 int32_t getVFTableOffset() const { return VFTableOffset; } getName()908 StringRef getName() const { return Name; } 909 isIntroducingVirtual()910 bool isIntroducingVirtual() const { 911 return Kind == MethodKind::IntroducingVirtual || 912 Kind == MethodKind::PureIntroducingVirtual; 913 } 914 915 private: 916 struct Layout { 917 MemberAttributes Attrs; 918 TypeIndex Type; 919 // If is introduced virtual method: 920 // VFTableOffset: int32_t offset in vftable 921 // Name: Null-terminated string 922 }; 923 924 TypeIndex Type; 925 MethodKind Kind; 926 MethodOptions Options; 927 MemberAccess Access; 928 int32_t VFTableOffset; 929 StringRef Name; 930 }; 931 932 // LF_METHODLIST 933 class MethodOverloadListRecord : public TypeRecord { 934 public: MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods)935 MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods) 936 : TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {} 937 938 /// Rewrite member type indices with IndexMap. Returns false if a type index 939 /// is not in the map. 940 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 941 942 static ErrorOr<MethodOverloadListRecord> deserialize(TypeRecordKind Kind, 943 ArrayRef<uint8_t> &Data); 944 getMethods()945 ArrayRef<OneMethodRecord> getMethods() const { return Methods; } 946 947 private: 948 struct Layout { 949 MemberAttributes Attrs; 950 ulittle16_t Padding; 951 952 TypeIndex Type; 953 // If is introduced virtual method: 954 // VFTableOffset: int32_t offset in vftable 955 }; 956 957 std::vector<OneMethodRecord> Methods; 958 }; 959 960 /// For method overload sets. LF_METHOD 961 class OverloadedMethodRecord : public TypeRecord { 962 public: OverloadedMethodRecord(uint16_t NumOverloads,TypeIndex MethodList,StringRef Name)963 OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList, 964 StringRef Name) 965 : TypeRecord(TypeRecordKind::OverloadedMethod), 966 NumOverloads(NumOverloads), MethodList(MethodList), Name(Name) {} 967 968 /// Rewrite member type indices with IndexMap. Returns false if a type index 969 /// is not in the map. 970 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 971 972 static ErrorOr<OverloadedMethodRecord> deserialize(TypeRecordKind Kind, 973 ArrayRef<uint8_t> &Data); 974 getNumOverloads()975 uint16_t getNumOverloads() const { return NumOverloads; } getMethodList()976 TypeIndex getMethodList() const { return MethodList; } getName()977 StringRef getName() const { return Name; } 978 979 private: 980 struct Layout { 981 ulittle16_t MethodCount; // Size of overload set 982 TypeIndex MethList; // Type index of methods in overload set 983 // Name: Null-terminated string 984 }; 985 986 uint16_t NumOverloads; 987 TypeIndex MethodList; 988 StringRef Name; 989 }; 990 991 // LF_MEMBER 992 class DataMemberRecord : public TypeRecord { 993 public: DataMemberRecord(MemberAccess Access,TypeIndex Type,uint64_t Offset,StringRef Name)994 DataMemberRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset, 995 StringRef Name) 996 : TypeRecord(TypeRecordKind::DataMember), Access(Access), Type(Type), 997 FieldOffset(Offset), Name(Name) {} 998 999 /// Rewrite member type indices with IndexMap. Returns false if a type index 1000 /// is not in the map. 1001 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 1002 1003 static ErrorOr<DataMemberRecord> deserialize(TypeRecordKind Kind, 1004 ArrayRef<uint8_t> &Data); 1005 getAccess()1006 MemberAccess getAccess() const { return Access; } getType()1007 TypeIndex getType() const { return Type; } getFieldOffset()1008 uint64_t getFieldOffset() const { return FieldOffset; } getName()1009 StringRef getName() const { return Name; } 1010 1011 private: 1012 struct Layout { 1013 MemberAttributes Attrs; // Access control attributes, etc 1014 TypeIndex Type; 1015 // FieldOffset: LF_NUMERIC encoded byte offset 1016 // Name: Null-terminated string 1017 }; 1018 1019 MemberAccess Access; 1020 TypeIndex Type; 1021 uint64_t FieldOffset; 1022 StringRef Name; 1023 }; 1024 1025 // LF_STMEMBER 1026 class StaticDataMemberRecord : public TypeRecord { 1027 public: StaticDataMemberRecord(MemberAccess Access,TypeIndex Type,StringRef Name)1028 StaticDataMemberRecord(MemberAccess Access, TypeIndex Type, StringRef Name) 1029 : TypeRecord(TypeRecordKind::StaticDataMember), Access(Access), 1030 Type(Type), Name(Name) {} 1031 1032 /// Rewrite member type indices with IndexMap. Returns false if a type index 1033 /// is not in the map. 1034 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 1035 1036 static ErrorOr<StaticDataMemberRecord> deserialize(TypeRecordKind Kind, 1037 ArrayRef<uint8_t> &Data); 1038 getAccess()1039 MemberAccess getAccess() const { return Access; } getType()1040 TypeIndex getType() const { return Type; } getName()1041 StringRef getName() const { return Name; } 1042 1043 private: 1044 struct Layout { 1045 MemberAttributes Attrs; // Access control attributes, etc 1046 TypeIndex Type; 1047 // Name: Null-terminated string 1048 }; 1049 1050 MemberAccess Access; 1051 TypeIndex Type; 1052 StringRef Name; 1053 }; 1054 1055 // LF_ENUMERATE 1056 class EnumeratorRecord : public TypeRecord { 1057 public: EnumeratorRecord(MemberAccess Access,APSInt Value,StringRef Name)1058 EnumeratorRecord(MemberAccess Access, APSInt Value, StringRef Name) 1059 : TypeRecord(TypeRecordKind::Enumerator), Access(Access), 1060 Value(std::move(Value)), Name(Name) {} 1061 1062 /// Rewrite member type indices with IndexMap. Returns false if a type index 1063 /// is not in the map. 1064 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 1065 1066 static ErrorOr<EnumeratorRecord> deserialize(TypeRecordKind Kind, 1067 ArrayRef<uint8_t> &Data); 1068 getAccess()1069 MemberAccess getAccess() const { return Access; } getValue()1070 APSInt getValue() const { return Value; } getName()1071 StringRef getName() const { return Name; } 1072 1073 private: 1074 struct Layout { 1075 MemberAttributes Attrs; // Access control attributes, etc 1076 // EnumValue: LF_NUMERIC encoded enumerator value 1077 // Name: Null-terminated string 1078 }; 1079 1080 MemberAccess Access; 1081 APSInt Value; 1082 StringRef Name; 1083 }; 1084 1085 // LF_VFUNCTAB 1086 class VFPtrRecord : public TypeRecord { 1087 public: VFPtrRecord(TypeIndex Type)1088 VFPtrRecord(TypeIndex Type) 1089 : TypeRecord(TypeRecordKind::VFPtr), Type(Type) {} 1090 1091 /// Rewrite member type indices with IndexMap. Returns false if a type index 1092 /// is not in the map. 1093 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 1094 1095 static ErrorOr<VFPtrRecord> deserialize(TypeRecordKind Kind, 1096 ArrayRef<uint8_t> &Data); 1097 getType()1098 TypeIndex getType() const { return Type; } 1099 1100 private: 1101 struct Layout { 1102 ulittle16_t Pad0; 1103 TypeIndex Type; // Type of vfptr 1104 }; 1105 TypeIndex Type; 1106 }; 1107 1108 // LF_BCLASS, LF_BINTERFACE 1109 class BaseClassRecord : public TypeRecord { 1110 public: BaseClassRecord(MemberAccess Access,TypeIndex Type,uint64_t Offset)1111 BaseClassRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset) 1112 : TypeRecord(TypeRecordKind::BaseClass), Access(Access), Type(Type), 1113 Offset(Offset) {} 1114 1115 /// Rewrite member type indices with IndexMap. Returns false if a type index 1116 /// is not in the map. 1117 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 1118 1119 static ErrorOr<BaseClassRecord> deserialize(TypeRecordKind Kind, 1120 ArrayRef<uint8_t> &Data); 1121 getAccess()1122 MemberAccess getAccess() const { return Access; } getBaseType()1123 TypeIndex getBaseType() const { return Type; } getBaseOffset()1124 uint64_t getBaseOffset() const { return Offset; } 1125 1126 private: 1127 struct Layout { 1128 MemberAttributes Attrs; // Access control attributes, etc 1129 TypeIndex BaseType; // Base class type 1130 // BaseOffset: LF_NUMERIC encoded byte offset of base from derived. 1131 }; 1132 MemberAccess Access; 1133 TypeIndex Type; 1134 uint64_t Offset; 1135 }; 1136 1137 // LF_VBCLASS, LF_IVBCLASS 1138 class VirtualBaseClassRecord : public TypeRecord { 1139 public: VirtualBaseClassRecord(MemberAccess Access,TypeIndex BaseType,TypeIndex VBPtrType,uint64_t Offset,uint64_t Index)1140 VirtualBaseClassRecord(MemberAccess Access, TypeIndex BaseType, 1141 TypeIndex VBPtrType, uint64_t Offset, uint64_t Index) 1142 : TypeRecord(TypeRecordKind::VirtualBaseClass), Access(Access), 1143 BaseType(BaseType), VBPtrType(VBPtrType), VBPtrOffset(Offset), 1144 VTableIndex(Index) {} 1145 1146 /// Rewrite member type indices with IndexMap. Returns false if a type index 1147 /// is not in the map. 1148 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 1149 1150 static ErrorOr<VirtualBaseClassRecord> deserialize(TypeRecordKind Kind, 1151 ArrayRef<uint8_t> &Data); 1152 getAccess()1153 MemberAccess getAccess() const { return Access; } getBaseType()1154 TypeIndex getBaseType() const { return BaseType; } getVBPtrType()1155 TypeIndex getVBPtrType() const { return VBPtrType; } getVBPtrOffset()1156 uint64_t getVBPtrOffset() const { return VBPtrOffset; } getVTableIndex()1157 uint64_t getVTableIndex() const { return VTableIndex; } 1158 1159 private: 1160 struct Layout { 1161 MemberAttributes Attrs; // Access control attributes, etc. 1162 TypeIndex BaseType; // Base class type 1163 TypeIndex VBPtrType; // Virtual base pointer type 1164 // VBPtrOffset: Offset of vbptr from vfptr encoded as LF_NUMERIC. 1165 // VBTableIndex: Index of vbase within vbtable encoded as LF_NUMERIC. 1166 }; 1167 MemberAccess Access; 1168 TypeIndex BaseType; 1169 TypeIndex VBPtrType; 1170 uint64_t VBPtrOffset; 1171 uint64_t VTableIndex; 1172 }; 1173 1174 /// LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records 1175 /// together. The first will end in an LF_INDEX record that points to the next. 1176 class ListContinuationRecord : public TypeRecord { 1177 public: ListContinuationRecord(TypeIndex ContinuationIndex)1178 ListContinuationRecord(TypeIndex ContinuationIndex) 1179 : TypeRecord(TypeRecordKind::ListContinuation), 1180 ContinuationIndex(ContinuationIndex) {} 1181 getContinuationIndex()1182 TypeIndex getContinuationIndex() const { return ContinuationIndex; } 1183 1184 bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 1185 1186 static ErrorOr<ListContinuationRecord> deserialize(TypeRecordKind Kind, 1187 ArrayRef<uint8_t> &Data); 1188 1189 private: 1190 struct Layout { 1191 ulittle16_t Pad0; 1192 TypeIndex ContinuationIndex; 1193 }; 1194 TypeIndex ContinuationIndex; 1195 }; 1196 1197 typedef CVRecord<TypeLeafKind> CVType; 1198 typedef VarStreamArray<CVType> CVTypeArray; 1199 } 1200 } 1201 1202 #endif 1203