blob: 3b6d1b0b1a70992f341c428759df33ff3cfd1828 [file] [log] [blame]
//===- 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/Optional.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 <algorithm>
#include <cstdint>
#include <vector>
namespace llvm {
namespace codeview {
using support::little32_t;
using support::ulittle16_t;
using support::ulittle32_t;
struct CVMemberRecord {
TypeLeafKind Kind;
ArrayRef<uint8_t> 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<uint16_t>(Access)) {}
MemberAttributes(MemberAccess Access, MethodKind Kind, MethodOptions Flags) {
Attrs = static_cast<uint16_t>(Access);
Attrs |= (static_cast<uint16_t>(Kind) << MethodKindShift);
Attrs |= static_cast<uint16_t>(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;
};
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;
FunctionOptions Options;
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;
FunctionOptions Options;
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;
};
// 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<TypeIndex> Indices)
: TypeRecord(Kind), ArgIndices(Indices) {}
ArrayRef<TypeIndex> getIndices() const { return ArgIndices; }
std::vector<TypeIndex> ArgIndices;
};
// LF_SUBSTR_LIST
class StringListRecord : public TypeRecord {
public:
StringListRecord() = default;
explicit StringListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
StringListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
: TypeRecord(Kind), StringIndices(Indices) {}
ArrayRef<TypeIndex> getIndices() const { return StringIndices; }
std::vector<TypeIndex> 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<PointerKind>((Attrs >> PointerKindShift) &
PointerKindMask);
}
PointerMode getMode() const {
return static_cast<PointerMode>((Attrs >> PointerModeShift) &
PointerModeMask);
}
PointerOptions getOptions() const {
return static_cast<PointerOptions>(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;
Optional<MemberPointerInfo> 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<uint32_t>(PK);
A |= static_cast<uint32_t>(PO);
A |= (static_cast<uint32_t>(PM) << PointerModeShift);
A |= (static_cast<uint32_t>(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<uint8_t> Data)
: TypeRecord(TypeRecordKind::FieldList), Data(Data) {}
ArrayRef<uint8_t> 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;
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<uint16_t>(Options);
Value = (Value & HfaKindMask) >> HfaKindShift;
return static_cast<HfaKind>(Value);
}
WindowsRTClassKind getWinRTKind() const {
uint16_t Value = static_cast<uint16_t>(Options);
Value = (Value & WinRTKindMask) >> WinRTKindShift;
return static_cast<WindowsRTClassKind>(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<uint16_t>(Options);
Value = (Value & HfaKindMask) >> HfaKindShift;
return static_cast<HfaKind>(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<VFTableSlotKind> Slots)
: TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {}
explicit VFTableShapeRecord(std::vector<VFTableSlotKind> Slots)
: TypeRecord(TypeRecordKind::VFTableShape), Slots(std::move(Slots)) {}
ArrayRef<VFTableSlotKind> getSlots() const {
if (!SlotsRef.empty())
return SlotsRef;
return Slots;
}
uint32_t getEntryCount() const { return getSlots().size(); }
ArrayRef<VFTableSlotKind> SlotsRef;
std::vector<VFTableSlotKind> 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<TypeIndex> ArgIndices)
: TypeRecord(TypeRecordKind::BuildInfo),
ArgIndices(ArgIndices.begin(), ArgIndices.end()) {}
ArrayRef<TypeIndex> 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<TypeIndex, MaxArgs> 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<StringRef> 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 makeArrayRef(MethodNames).front(); }
ArrayRef<StringRef> getMethodNames() const {
return makeArrayRef(MethodNames).drop_front();
}
TypeIndex CompleteClass;
TypeIndex OverriddenVFTable;
uint32_t VFPtrOffset = 0;
std::vector<StringRef> 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<OneMethodRecord> Methods)
: TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {}
ArrayRef<OneMethodRecord> getMethods() const { return Methods; }
std::vector<OneMethodRecord> 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