//===- TypeRecord.h ---------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H #define LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/GUID.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/Endian.h" #include #include #include #include namespace llvm { namespace codeview { using support::little32_t; using support::ulittle16_t; using support::ulittle32_t; struct CVMemberRecord { TypeLeafKind Kind; ArrayRef Data; }; /// Equvalent to CV_fldattr_t in cvinfo.h. struct MemberAttributes { uint16_t Attrs = 0; enum { MethodKindShift = 2, }; MemberAttributes() = default; explicit MemberAttributes(MemberAccess Access) : Attrs(static_cast(Access)) {} MemberAttributes(MemberAccess Access, MethodKind Kind, MethodOptions Flags) { Attrs = static_cast(Access); Attrs |= (static_cast(Kind) << MethodKindShift); Attrs |= static_cast(Flags); } /// Get the access specifier. Valid for any kind of member. MemberAccess getAccess() const { return MemberAccess(unsigned(Attrs) & unsigned(MethodOptions::AccessMask)); } /// Indicates if a method is defined with friend, virtual, static, etc. MethodKind getMethodKind() const { return MethodKind( (unsigned(Attrs) & unsigned(MethodOptions::MethodKindMask)) >> MethodKindShift); } /// Get the flags that are not included in access control or method /// properties. MethodOptions getFlags() const { return MethodOptions( unsigned(Attrs) & ~unsigned(MethodOptions::AccessMask | MethodOptions::MethodKindMask)); } /// Is this method virtual. bool isVirtual() const { auto MP = getMethodKind(); return MP != MethodKind::Vanilla && MP != MethodKind::Friend && MP != MethodKind::Static; } /// Does this member introduce a new virtual method. bool isIntroducedVirtual() const { auto MP = getMethodKind(); return MP == MethodKind::IntroducingVirtual || MP == MethodKind::PureIntroducingVirtual; } /// Is this method static. bool isStatic() const { return getMethodKind() == MethodKind::Static; } }; // Does not correspond to any tag, this is the tail of an LF_POINTER record // if it represents a member pointer. class MemberPointerInfo { public: MemberPointerInfo() = default; MemberPointerInfo(TypeIndex ContainingType, PointerToMemberRepresentation Representation) : ContainingType(ContainingType), Representation(Representation) {} TypeIndex getContainingType() const { return ContainingType; } PointerToMemberRepresentation getRepresentation() const { return Representation; } TypeIndex ContainingType; PointerToMemberRepresentation Representation = PointerToMemberRepresentation::Unknown; }; class TypeRecord { protected: TypeRecord() = default; explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {} public: TypeRecordKind getKind() const { return Kind; } TypeRecordKind Kind; }; // LF_MODIFIER class ModifierRecord : public TypeRecord { public: ModifierRecord() = default; explicit ModifierRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers) : TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType), Modifiers(Modifiers) {} TypeIndex getModifiedType() const { return ModifiedType; } ModifierOptions getModifiers() const { return Modifiers; } TypeIndex ModifiedType; ModifierOptions Modifiers = ModifierOptions::None; }; // LF_PROCEDURE class ProcedureRecord : public TypeRecord { public: ProcedureRecord() = default; explicit ProcedureRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv, FunctionOptions Options, uint16_t ParameterCount, TypeIndex ArgumentList) : TypeRecord(TypeRecordKind::Procedure), ReturnType(ReturnType), CallConv(CallConv), Options(Options), ParameterCount(ParameterCount), ArgumentList(ArgumentList) {} TypeIndex getReturnType() const { return ReturnType; } CallingConvention getCallConv() const { return CallConv; } FunctionOptions getOptions() const { return Options; } uint16_t getParameterCount() const { return ParameterCount; } TypeIndex getArgumentList() const { return ArgumentList; } TypeIndex ReturnType; CallingConvention CallConv = CallingConvention::NearC; FunctionOptions Options = FunctionOptions::None; uint16_t ParameterCount = 0; TypeIndex ArgumentList; }; // LF_MFUNCTION class MemberFunctionRecord : public TypeRecord { public: MemberFunctionRecord() = default; explicit MemberFunctionRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType, TypeIndex ThisType, CallingConvention CallConv, FunctionOptions Options, uint16_t ParameterCount, TypeIndex ArgumentList, int32_t ThisPointerAdjustment) : TypeRecord(TypeRecordKind::MemberFunction), ReturnType(ReturnType), ClassType(ClassType), ThisType(ThisType), CallConv(CallConv), Options(Options), ParameterCount(ParameterCount), ArgumentList(ArgumentList), ThisPointerAdjustment(ThisPointerAdjustment) {} TypeIndex getReturnType() const { return ReturnType; } TypeIndex getClassType() const { return ClassType; } TypeIndex getThisType() const { return ThisType; } CallingConvention getCallConv() const { return CallConv; } FunctionOptions getOptions() const { return Options; } uint16_t getParameterCount() const { return ParameterCount; } TypeIndex getArgumentList() const { return ArgumentList; } int32_t getThisPointerAdjustment() const { return ThisPointerAdjustment; } TypeIndex ReturnType; TypeIndex ClassType; TypeIndex ThisType; CallingConvention CallConv = CallingConvention::NearC; FunctionOptions Options = FunctionOptions::None; uint16_t ParameterCount = 0; TypeIndex ArgumentList; int32_t ThisPointerAdjustment = 0; }; // LF_LABEL class LabelRecord : public TypeRecord { public: LabelRecord() = default; explicit LabelRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} LabelRecord(LabelType Mode) : TypeRecord(TypeRecordKind::Label), Mode(Mode) {} LabelType Mode = LabelType::Near; }; // LF_MFUNC_ID class MemberFuncIdRecord : public TypeRecord { public: MemberFuncIdRecord() = default; explicit MemberFuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} MemberFuncIdRecord(TypeIndex ClassType, TypeIndex FunctionType, StringRef Name) : TypeRecord(TypeRecordKind::MemberFuncId), ClassType(ClassType), FunctionType(FunctionType), Name(Name) {} TypeIndex getClassType() const { return ClassType; } TypeIndex getFunctionType() const { return FunctionType; } StringRef getName() const { return Name; } TypeIndex ClassType; TypeIndex FunctionType; StringRef Name; }; // LF_ARGLIST class ArgListRecord : public TypeRecord { public: ArgListRecord() = default; explicit ArgListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} ArgListRecord(TypeRecordKind Kind, ArrayRef Indices) : TypeRecord(Kind), ArgIndices(Indices) {} ArrayRef getIndices() const { return ArgIndices; } std::vector ArgIndices; }; // LF_SUBSTR_LIST class StringListRecord : public TypeRecord { public: StringListRecord() = default; explicit StringListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} StringListRecord(TypeRecordKind Kind, ArrayRef Indices) : TypeRecord(Kind), StringIndices(Indices) {} ArrayRef getIndices() const { return StringIndices; } std::vector StringIndices; }; // LF_POINTER class PointerRecord : public TypeRecord { public: // ---------------------------XXXXX static const uint32_t PointerKindShift = 0; static const uint32_t PointerKindMask = 0x1F; // ------------------------XXX----- static const uint32_t PointerModeShift = 5; static const uint32_t PointerModeMask = 0x07; // ----------XXX------XXXXX-------- static const uint32_t PointerOptionMask = 0x381f00; // -------------XXXXXX------------ static const uint32_t PointerSizeShift = 13; static const uint32_t PointerSizeMask = 0xFF; PointerRecord() = default; explicit PointerRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} PointerRecord(TypeIndex ReferentType, uint32_t Attrs) : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType), Attrs(Attrs) {} PointerRecord(TypeIndex ReferentType, PointerKind PK, PointerMode PM, PointerOptions PO, uint8_t Size) : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType), Attrs(calcAttrs(PK, PM, PO, Size)) {} PointerRecord(TypeIndex ReferentType, PointerKind PK, PointerMode PM, PointerOptions PO, uint8_t Size, const MemberPointerInfo &MPI) : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType), Attrs(calcAttrs(PK, PM, PO, Size)), MemberInfo(MPI) {} TypeIndex getReferentType() const { return ReferentType; } PointerKind getPointerKind() const { return static_cast((Attrs >> PointerKindShift) & PointerKindMask); } PointerMode getMode() const { return static_cast((Attrs >> PointerModeShift) & PointerModeMask); } PointerOptions getOptions() const { return static_cast(Attrs & PointerOptionMask); } uint8_t getSize() const { return (Attrs >> PointerSizeShift) & PointerSizeMask; } MemberPointerInfo getMemberInfo() const { return *MemberInfo; } bool isPointerToMember() const { return getMode() == PointerMode::PointerToDataMember || getMode() == PointerMode::PointerToMemberFunction; } bool isFlat() const { return !!(Attrs & uint32_t(PointerOptions::Flat32)); } bool isConst() const { return !!(Attrs & uint32_t(PointerOptions::Const)); } bool isVolatile() const { return !!(Attrs & uint32_t(PointerOptions::Volatile)); } bool isUnaligned() const { return !!(Attrs & uint32_t(PointerOptions::Unaligned)); } bool isRestrict() const { return !!(Attrs & uint32_t(PointerOptions::Restrict)); } bool isLValueReferenceThisPtr() const { return !!(Attrs & uint32_t(PointerOptions::LValueRefThisPointer)); } bool isRValueReferenceThisPtr() const { return !!(Attrs & uint32_t(PointerOptions::RValueRefThisPointer)); } TypeIndex ReferentType; uint32_t Attrs = 0; std::optional MemberInfo; void setAttrs(PointerKind PK, PointerMode PM, PointerOptions PO, uint8_t Size) { Attrs = calcAttrs(PK, PM, PO, Size); } private: static uint32_t calcAttrs(PointerKind PK, PointerMode PM, PointerOptions PO, uint8_t Size) { uint32_t A = 0; A |= static_cast(PK); A |= static_cast(PO); A |= (static_cast(PM) << PointerModeShift); A |= (static_cast(Size) << PointerSizeShift); return A; } }; // LF_NESTTYPE class NestedTypeRecord : public TypeRecord { public: NestedTypeRecord() = default; explicit NestedTypeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} NestedTypeRecord(TypeIndex Type, StringRef Name) : TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {} TypeIndex getNestedType() const { return Type; } StringRef getName() const { return Name; } TypeIndex Type; StringRef Name; }; // LF_FIELDLIST class FieldListRecord : public TypeRecord { public: FieldListRecord() = default; explicit FieldListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} explicit FieldListRecord(ArrayRef Data) : TypeRecord(TypeRecordKind::FieldList), Data(Data) {} ArrayRef Data; }; // LF_ARRAY class ArrayRecord : public TypeRecord { public: ArrayRecord() = default; explicit ArrayRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size, StringRef Name) : TypeRecord(TypeRecordKind::Array), ElementType(ElementType), IndexType(IndexType), Size(Size), Name(Name) {} TypeIndex getElementType() const { return ElementType; } TypeIndex getIndexType() const { return IndexType; } uint64_t getSize() const { return Size; } StringRef getName() const { return Name; } TypeIndex ElementType; TypeIndex IndexType; uint64_t Size = 0; StringRef Name; }; class TagRecord : public TypeRecord { protected: TagRecord() = default; explicit TagRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, StringRef Name, StringRef UniqueName) : TypeRecord(Kind), MemberCount(MemberCount), Options(Options), FieldList(FieldList), Name(Name), UniqueName(UniqueName) {} public: static const int HfaKindShift = 11; static const int HfaKindMask = 0x1800; static const int WinRTKindShift = 14; static const int WinRTKindMask = 0xC000; bool hasUniqueName() const { return (Options & ClassOptions::HasUniqueName) != ClassOptions::None; } bool isNested() const { return (Options & ClassOptions::Nested) != ClassOptions::None; } bool isForwardRef() const { return (Options & ClassOptions::ForwardReference) != ClassOptions::None; } bool containsNestedClass() const { return (Options & ClassOptions::ContainsNestedClass) != ClassOptions::None; } bool isScoped() const { return (Options & ClassOptions::Scoped) != ClassOptions::None; } uint16_t getMemberCount() const { return MemberCount; } ClassOptions getOptions() const { return Options; } TypeIndex getFieldList() const { return FieldList; } StringRef getName() const { return Name; } StringRef getUniqueName() const { return UniqueName; } uint16_t MemberCount = 0; ClassOptions Options = ClassOptions::None; TypeIndex FieldList; StringRef Name; StringRef UniqueName; }; // LF_CLASS, LF_STRUCTURE, LF_INTERFACE class ClassRecord : public TagRecord { public: ClassRecord() = default; 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) : TagRecord(Kind, MemberCount, Options, FieldList, Name, UniqueName), DerivationList(DerivationList), VTableShape(VTableShape), Size(Size) {} HfaKind getHfa() const { uint16_t Value = static_cast(Options); Value = (Value & HfaKindMask) >> HfaKindShift; return static_cast(Value); } WindowsRTClassKind getWinRTKind() const { uint16_t Value = static_cast(Options); Value = (Value & WinRTKindMask) >> WinRTKindShift; return static_cast(Value); } TypeIndex getDerivationList() const { return DerivationList; } TypeIndex getVTableShape() const { return VTableShape; } uint64_t getSize() const { return Size; } TypeIndex DerivationList; TypeIndex VTableShape; uint64_t Size = 0; }; // LF_UNION struct UnionRecord : public TagRecord { UnionRecord() = default; explicit UnionRecord(TypeRecordKind Kind) : TagRecord(Kind) {} UnionRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, uint64_t Size, StringRef Name, StringRef UniqueName) : TagRecord(TypeRecordKind::Union, MemberCount, Options, FieldList, Name, UniqueName), Size(Size) {} HfaKind getHfa() const { uint16_t Value = static_cast(Options); Value = (Value & HfaKindMask) >> HfaKindShift; return static_cast(Value); } uint64_t getSize() const { return Size; } uint64_t Size = 0; }; // LF_ENUM class EnumRecord : public TagRecord { public: EnumRecord() = default; explicit EnumRecord(TypeRecordKind Kind) : TagRecord(Kind) {} EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType) : TagRecord(TypeRecordKind::Enum, MemberCount, Options, FieldList, Name, UniqueName), UnderlyingType(UnderlyingType) {} TypeIndex getUnderlyingType() const { return UnderlyingType; } TypeIndex UnderlyingType; }; // LF_BITFIELD class BitFieldRecord : public TypeRecord { public: BitFieldRecord() = default; explicit BitFieldRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset) : TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize), BitOffset(BitOffset) {} TypeIndex getType() const { return Type; } uint8_t getBitOffset() const { return BitOffset; } uint8_t getBitSize() const { return BitSize; } TypeIndex Type; uint8_t BitSize = 0; uint8_t BitOffset = 0; }; // LF_VTSHAPE class VFTableShapeRecord : public TypeRecord { public: VFTableShapeRecord() = default; explicit VFTableShapeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} explicit VFTableShapeRecord(ArrayRef Slots) : TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {} explicit VFTableShapeRecord(std::vector Slots) : TypeRecord(TypeRecordKind::VFTableShape), Slots(std::move(Slots)) {} ArrayRef getSlots() const { if (!SlotsRef.empty()) return SlotsRef; return Slots; } uint32_t getEntryCount() const { return getSlots().size(); } ArrayRef SlotsRef; std::vector Slots; }; // LF_TYPESERVER2 class TypeServer2Record : public TypeRecord { public: TypeServer2Record() = default; explicit TypeServer2Record(TypeRecordKind Kind) : TypeRecord(Kind) {} TypeServer2Record(StringRef GuidStr, uint32_t Age, StringRef Name) : TypeRecord(TypeRecordKind::TypeServer2), Age(Age), Name(Name) { assert(GuidStr.size() == 16 && "guid isn't 16 bytes"); ::memcpy(Guid.Guid, GuidStr.data(), 16); } const GUID &getGuid() const { return Guid; } uint32_t getAge() const { return Age; } StringRef getName() const { return Name; } GUID Guid = {}; uint32_t Age = 0; StringRef Name; }; // LF_STRING_ID class StringIdRecord : public TypeRecord { public: StringIdRecord() = default; explicit StringIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} StringIdRecord(TypeIndex Id, StringRef String) : TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {} TypeIndex getId() const { return Id; } StringRef getString() const { return String; } TypeIndex Id; StringRef String; }; // LF_FUNC_ID class FuncIdRecord : public TypeRecord { public: FuncIdRecord() = default; explicit FuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name) : TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope), FunctionType(FunctionType), Name(Name) {} TypeIndex getParentScope() const { return ParentScope; } TypeIndex getFunctionType() const { return FunctionType; } StringRef getName() const { return Name; } TypeIndex ParentScope; TypeIndex FunctionType; StringRef Name; }; // LF_UDT_SRC_LINE class UdtSourceLineRecord : public TypeRecord { public: UdtSourceLineRecord() = default; explicit UdtSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber) : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT), SourceFile(SourceFile), LineNumber(LineNumber) {} TypeIndex getUDT() const { return UDT; } TypeIndex getSourceFile() const { return SourceFile; } uint32_t getLineNumber() const { return LineNumber; } TypeIndex UDT; TypeIndex SourceFile; uint32_t LineNumber = 0; }; // LF_UDT_MOD_SRC_LINE class UdtModSourceLineRecord : public TypeRecord { public: UdtModSourceLineRecord() = default; explicit UdtModSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} UdtModSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber, uint16_t Module) : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT), SourceFile(SourceFile), LineNumber(LineNumber), Module(Module) {} TypeIndex getUDT() const { return UDT; } TypeIndex getSourceFile() const { return SourceFile; } uint32_t getLineNumber() const { return LineNumber; } uint16_t getModule() const { return Module; } TypeIndex UDT; TypeIndex SourceFile; uint32_t LineNumber = 0; uint16_t Module = 0; }; // LF_BUILDINFO class BuildInfoRecord : public TypeRecord { public: BuildInfoRecord() = default; explicit BuildInfoRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} BuildInfoRecord(ArrayRef ArgIndices) : TypeRecord(TypeRecordKind::BuildInfo), ArgIndices(ArgIndices.begin(), ArgIndices.end()) {} ArrayRef getArgs() const { return ArgIndices; } /// Indices of known build info arguments. enum BuildInfoArg { CurrentDirectory, ///< Absolute CWD path BuildTool, ///< Absolute compiler path SourceFile, ///< Path to main source file, relative or absolute TypeServerPDB, ///< Absolute path of type server PDB (/Fd) CommandLine, ///< Full canonical command line (maybe -cc1) MaxArgs }; SmallVector ArgIndices; }; // LF_VFTABLE class VFTableRecord : public TypeRecord { public: VFTableRecord() = default; explicit VFTableRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable, uint32_t VFPtrOffset, StringRef Name, ArrayRef Methods) : TypeRecord(TypeRecordKind::VFTable), CompleteClass(CompleteClass), OverriddenVFTable(OverriddenVFTable), VFPtrOffset(VFPtrOffset) { MethodNames.push_back(Name); llvm::append_range(MethodNames, Methods); } TypeIndex getCompleteClass() const { return CompleteClass; } TypeIndex getOverriddenVTable() const { return OverriddenVFTable; } uint32_t getVFPtrOffset() const { return VFPtrOffset; } StringRef getName() const { return ArrayRef(MethodNames).front(); } ArrayRef getMethodNames() const { return ArrayRef(MethodNames).drop_front(); } TypeIndex CompleteClass; TypeIndex OverriddenVFTable; uint32_t VFPtrOffset = 0; std::vector MethodNames; }; // LF_ONEMETHOD class OneMethodRecord : public TypeRecord { public: OneMethodRecord() = default; explicit OneMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} OneMethodRecord(TypeIndex Type, MemberAttributes Attrs, int32_t VFTableOffset, StringRef Name) : TypeRecord(TypeRecordKind::OneMethod), Type(Type), Attrs(Attrs), VFTableOffset(VFTableOffset), Name(Name) {} OneMethodRecord(TypeIndex Type, MemberAccess Access, MethodKind MK, MethodOptions Options, int32_t VFTableOffset, StringRef Name) : TypeRecord(TypeRecordKind::OneMethod), Type(Type), Attrs(Access, MK, Options), VFTableOffset(VFTableOffset), Name(Name) {} TypeIndex getType() const { return Type; } MethodKind getMethodKind() const { return Attrs.getMethodKind(); } MethodOptions getOptions() const { return Attrs.getFlags(); } MemberAccess getAccess() const { return Attrs.getAccess(); } int32_t getVFTableOffset() const { return VFTableOffset; } StringRef getName() const { return Name; } bool isIntroducingVirtual() const { return getMethodKind() == MethodKind::IntroducingVirtual || getMethodKind() == MethodKind::PureIntroducingVirtual; } TypeIndex Type; MemberAttributes Attrs; int32_t VFTableOffset = 0; StringRef Name; }; // LF_METHODLIST class MethodOverloadListRecord : public TypeRecord { public: MethodOverloadListRecord() = default; explicit MethodOverloadListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} MethodOverloadListRecord(ArrayRef Methods) : TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {} ArrayRef getMethods() const { return Methods; } std::vector Methods; }; /// For method overload sets. LF_METHOD class OverloadedMethodRecord : public TypeRecord { public: OverloadedMethodRecord() = default; explicit OverloadedMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList, StringRef Name) : TypeRecord(TypeRecordKind::OverloadedMethod), NumOverloads(NumOverloads), MethodList(MethodList), Name(Name) {} uint16_t getNumOverloads() const { return NumOverloads; } TypeIndex getMethodList() const { return MethodList; } StringRef getName() const { return Name; } uint16_t NumOverloads = 0; TypeIndex MethodList; StringRef Name; }; // LF_MEMBER class DataMemberRecord : public TypeRecord { public: DataMemberRecord() = default; explicit DataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} DataMemberRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset, StringRef Name) : TypeRecord(TypeRecordKind::DataMember), Attrs(Attrs), Type(Type), FieldOffset(Offset), Name(Name) {} DataMemberRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset, StringRef Name) : TypeRecord(TypeRecordKind::DataMember), Attrs(Access), Type(Type), FieldOffset(Offset), Name(Name) {} MemberAccess getAccess() const { return Attrs.getAccess(); } TypeIndex getType() const { return Type; } uint64_t getFieldOffset() const { return FieldOffset; } StringRef getName() const { return Name; } MemberAttributes Attrs; TypeIndex Type; uint64_t FieldOffset = 0; StringRef Name; }; // LF_STMEMBER class StaticDataMemberRecord : public TypeRecord { public: StaticDataMemberRecord() = default; explicit StaticDataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} StaticDataMemberRecord(MemberAttributes Attrs, TypeIndex Type, StringRef Name) : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Attrs), Type(Type), Name(Name) {} StaticDataMemberRecord(MemberAccess Access, TypeIndex Type, StringRef Name) : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Access), Type(Type), Name(Name) {} MemberAccess getAccess() const { return Attrs.getAccess(); } TypeIndex getType() const { return Type; } StringRef getName() const { return Name; } MemberAttributes Attrs; TypeIndex Type; StringRef Name; }; // LF_ENUMERATE class EnumeratorRecord : public TypeRecord { public: EnumeratorRecord() = default; explicit EnumeratorRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} EnumeratorRecord(MemberAttributes Attrs, APSInt Value, StringRef Name) : TypeRecord(TypeRecordKind::Enumerator), Attrs(Attrs), Value(std::move(Value)), Name(Name) {} EnumeratorRecord(MemberAccess Access, APSInt Value, StringRef Name) : TypeRecord(TypeRecordKind::Enumerator), Attrs(Access), Value(std::move(Value)), Name(Name) {} MemberAccess getAccess() const { return Attrs.getAccess(); } APSInt getValue() const { return Value; } StringRef getName() const { return Name; } MemberAttributes Attrs; APSInt Value; StringRef Name; }; // LF_VFUNCTAB class VFPtrRecord : public TypeRecord { public: VFPtrRecord() = default; explicit VFPtrRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} VFPtrRecord(TypeIndex Type) : TypeRecord(TypeRecordKind::VFPtr), Type(Type) {} TypeIndex getType() const { return Type; } TypeIndex Type; }; // LF_BCLASS, LF_BINTERFACE class BaseClassRecord : public TypeRecord { public: BaseClassRecord() = default; explicit BaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} BaseClassRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset) : TypeRecord(TypeRecordKind::BaseClass), Attrs(Attrs), Type(Type), Offset(Offset) {} BaseClassRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset) : TypeRecord(TypeRecordKind::BaseClass), Attrs(Access), Type(Type), Offset(Offset) {} MemberAccess getAccess() const { return Attrs.getAccess(); } TypeIndex getBaseType() const { return Type; } uint64_t getBaseOffset() const { return Offset; } MemberAttributes Attrs; TypeIndex Type; uint64_t Offset = 0; }; // LF_VBCLASS, LF_IVBCLASS class VirtualBaseClassRecord : public TypeRecord { public: VirtualBaseClassRecord() = default; explicit VirtualBaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} VirtualBaseClassRecord(TypeRecordKind Kind, MemberAttributes Attrs, TypeIndex BaseType, TypeIndex VBPtrType, uint64_t Offset, uint64_t Index) : TypeRecord(Kind), Attrs(Attrs), BaseType(BaseType), VBPtrType(VBPtrType), VBPtrOffset(Offset), VTableIndex(Index) {} VirtualBaseClassRecord(TypeRecordKind Kind, MemberAccess Access, TypeIndex BaseType, TypeIndex VBPtrType, uint64_t Offset, uint64_t Index) : TypeRecord(Kind), Attrs(Access), BaseType(BaseType), VBPtrType(VBPtrType), VBPtrOffset(Offset), VTableIndex(Index) {} MemberAccess getAccess() const { return Attrs.getAccess(); } TypeIndex getBaseType() const { return BaseType; } TypeIndex getVBPtrType() const { return VBPtrType; } uint64_t getVBPtrOffset() const { return VBPtrOffset; } uint64_t getVTableIndex() const { return VTableIndex; } MemberAttributes Attrs; TypeIndex BaseType; TypeIndex VBPtrType; uint64_t VBPtrOffset = 0; uint64_t VTableIndex = 0; }; /// LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records /// together. The first will end in an LF_INDEX record that points to the next. class ListContinuationRecord : public TypeRecord { public: ListContinuationRecord() = default; explicit ListContinuationRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} ListContinuationRecord(TypeIndex ContinuationIndex) : TypeRecord(TypeRecordKind::ListContinuation), ContinuationIndex(ContinuationIndex) {} TypeIndex getContinuationIndex() const { return ContinuationIndex; } TypeIndex ContinuationIndex; }; // LF_PRECOMP class PrecompRecord : public TypeRecord { public: PrecompRecord() = default; explicit PrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} uint32_t getStartTypeIndex() const { return StartTypeIndex; } uint32_t getTypesCount() const { return TypesCount; } uint32_t getSignature() const { return Signature; } StringRef getPrecompFilePath() const { return PrecompFilePath; } uint32_t StartTypeIndex = 0; uint32_t TypesCount = 0; uint32_t Signature = 0; StringRef PrecompFilePath; }; // LF_ENDPRECOMP class EndPrecompRecord : public TypeRecord { public: EndPrecompRecord() = default; explicit EndPrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} uint32_t getSignature() const { return Signature; } uint32_t Signature = 0; }; } // end namespace codeview } // end namespace llvm #endif // LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H