forked from OSchip/llvm-project
Refactor CodeView type records to use common code.
Differential Revision: http://reviews.llvm.org/D20138 Reviewed By: rnk llvm-svn: 269216
This commit is contained in:
parent
c200ad7e3b
commit
ae3882a19a
|
@ -14,6 +14,7 @@
|
|||
#include "llvm/DebugInfo/CodeView/RecordIterator.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
@ -42,12 +43,10 @@ public:
|
|||
/// FIXME: Make the visitor interpret the trailing bytes so that clients don't
|
||||
/// need to.
|
||||
#define TYPE_RECORD(ClassName, LeafEnum) \
|
||||
void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
|
||||
ArrayRef<uint8_t> LeafData) {}
|
||||
void visit##ClassName(TypeLeafKind LeafType, ClassName &Record) {}
|
||||
#define TYPE_RECORD_ALIAS(ClassName, LeafEnum)
|
||||
#define MEMBER_RECORD(ClassName, LeafEnum) \
|
||||
void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
|
||||
ArrayRef<uint8_t> &FieldData) {}
|
||||
void visit##ClassName(TypeLeafKind LeafType, ClassName &Record) {}
|
||||
#define MEMBER_RECORD_ALIAS(ClassName, LeafEnum)
|
||||
#include "TypeRecords.def"
|
||||
|
||||
|
@ -68,10 +67,11 @@ public:
|
|||
break;
|
||||
#define TYPE_RECORD(ClassName, LeafEnum) \
|
||||
case LeafEnum: { \
|
||||
const ClassName *Rec; \
|
||||
if (!CVTypeVisitor::consumeObject(LeafData, Rec)) \
|
||||
return; \
|
||||
DerivedThis->visit##ClassName(Record.Type, Rec, LeafData); \
|
||||
TypeRecordKind RK = static_cast<TypeRecordKind>(LeafEnum); \
|
||||
auto Result = ClassName::deserialize(RK, LeafData); \
|
||||
if (Result.getError()) \
|
||||
return parseError(); \
|
||||
DerivedThis->visit##ClassName(Record.Type, *Result); \
|
||||
break; \
|
||||
}
|
||||
#include "TypeRecords.def"
|
||||
|
@ -120,10 +120,11 @@ public:
|
|||
return parseError();
|
||||
#define MEMBER_RECORD(ClassName, LeafEnum) \
|
||||
case LeafEnum: { \
|
||||
const ClassName *Rec; \
|
||||
if (!CVTypeVisitor::consumeObject(FieldData, Rec)) \
|
||||
return; \
|
||||
static_cast<Derived *>(this)->visit##ClassName(Leaf, Rec, FieldData); \
|
||||
TypeRecordKind RK = static_cast<TypeRecordKind>(LeafEnum); \
|
||||
auto Result = ClassName::deserialize(RK, FieldData); \
|
||||
if (Result.getError()) \
|
||||
return parseError(); \
|
||||
static_cast<Derived *>(this)->visit##ClassName(Leaf, *Result); \
|
||||
break; \
|
||||
}
|
||||
#include "TypeRecords.def"
|
||||
|
|
|
@ -423,9 +423,10 @@ enum class TypeRecordKind : uint16_t {
|
|||
Alias = 0x150a,
|
||||
Member = 0x150d,
|
||||
StaticMember = 0x150e,
|
||||
Method = 0x150f,
|
||||
OverloadedMethod = 0x150f,
|
||||
NestedType = 0x1510,
|
||||
OneMethod = 0x1511,
|
||||
TypeServer2 = 0x1515,
|
||||
VirtualFunctionTable = 0x151d,
|
||||
|
||||
FunctionId = 0x1601,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -30,44 +30,44 @@
|
|||
#endif
|
||||
|
||||
|
||||
TYPE_RECORD(PointerType, LF_POINTER)
|
||||
TYPE_RECORD(TypeModifier, LF_MODIFIER)
|
||||
TYPE_RECORD(ProcedureType, LF_PROCEDURE)
|
||||
TYPE_RECORD(MemberFunctionType, LF_MFUNCTION)
|
||||
TYPE_RECORD(ArgList, LF_ARGLIST)
|
||||
TYPE_RECORD(PointerRecord, LF_POINTER)
|
||||
TYPE_RECORD(ModifierRecord, LF_MODIFIER)
|
||||
TYPE_RECORD(ProcedureRecord, LF_PROCEDURE)
|
||||
TYPE_RECORD(MemberFunctionRecord, LF_MFUNCTION)
|
||||
TYPE_RECORD(StringListRecord, LF_ARGLIST)
|
||||
|
||||
TYPE_RECORD(ArrayType, LF_ARRAY)
|
||||
TYPE_RECORD(ClassType, LF_CLASS)
|
||||
TYPE_RECORD_ALIAS(ClassType, LF_STRUCTURE)
|
||||
TYPE_RECORD_ALIAS(ClassType, LF_INTERFACE)
|
||||
TYPE_RECORD(UnionType, LF_UNION)
|
||||
TYPE_RECORD(EnumType, LF_ENUM)
|
||||
TYPE_RECORD(TypeServer2, LF_TYPESERVER2)
|
||||
TYPE_RECORD(VFTableType, LF_VFTABLE)
|
||||
TYPE_RECORD(VTableShape, LF_VTSHAPE)
|
||||
TYPE_RECORD(ArrayRecord, LF_ARRAY)
|
||||
TYPE_RECORD(ClassRecord, LF_CLASS)
|
||||
TYPE_RECORD_ALIAS(ClassRecord, LF_STRUCTURE)
|
||||
TYPE_RECORD_ALIAS(ClassRecord, LF_INTERFACE)
|
||||
TYPE_RECORD(UnionRecord, LF_UNION)
|
||||
TYPE_RECORD(EnumRecord, LF_ENUM)
|
||||
TYPE_RECORD(TypeServer2Record, LF_TYPESERVER2)
|
||||
TYPE_RECORD(VirtualTableRecord, LF_VFTABLE)
|
||||
TYPE_RECORD(VirtualTableShapeRecord, LF_VTSHAPE)
|
||||
|
||||
// Member type records. These are generally not length prefixed, and appear
|
||||
// inside of a field list record.
|
||||
MEMBER_RECORD(BaseClass, LF_BCLASS)
|
||||
MEMBER_RECORD_ALIAS(BaseClass, LF_BINTERFACE)
|
||||
MEMBER_RECORD(VirtualBaseClass, LF_VBCLASS)
|
||||
MEMBER_RECORD_ALIAS(VirtualBaseClass, LF_IVBCLASS)
|
||||
MEMBER_RECORD(VirtualFunctionPointer, LF_VFUNCTAB)
|
||||
MEMBER_RECORD(StaticDataMember, LF_STMEMBER)
|
||||
MEMBER_RECORD(OverloadedMethod, LF_METHOD)
|
||||
MEMBER_RECORD(DataMember, LF_MEMBER)
|
||||
MEMBER_RECORD(NestedType, LF_NESTTYPE)
|
||||
MEMBER_RECORD(OneMethod, LF_ONEMETHOD)
|
||||
MEMBER_RECORD(Enumerator, LF_ENUMERATE)
|
||||
MEMBER_RECORD(BaseClassRecord, LF_BCLASS)
|
||||
MEMBER_RECORD_ALIAS(BaseClassRecord, LF_BINTERFACE)
|
||||
MEMBER_RECORD(VirtualBaseClassRecord, LF_VBCLASS)
|
||||
MEMBER_RECORD_ALIAS(VirtualBaseClassRecord, LF_IVBCLASS)
|
||||
MEMBER_RECORD(VirtualFunctionPointerRecord, LF_VFUNCTAB)
|
||||
MEMBER_RECORD(StaticDataMemberRecord, LF_STMEMBER)
|
||||
MEMBER_RECORD(OverloadedMethodRecord, LF_METHOD)
|
||||
MEMBER_RECORD(DataMemberRecord, LF_MEMBER)
|
||||
MEMBER_RECORD(NestedTypeRecord, LF_NESTTYPE)
|
||||
MEMBER_RECORD(OneMethodRecord, LF_ONEMETHOD)
|
||||
MEMBER_RECORD(EnumeratorRecord, LF_ENUMERATE)
|
||||
|
||||
// ID leaf records. Subsequent leaf types may be referenced from .debug$S.
|
||||
|
||||
TYPE_RECORD(FuncId, LF_FUNC_ID)
|
||||
TYPE_RECORD(MemberFuncId, LF_MFUNC_ID)
|
||||
TYPE_RECORD(BuildInfo, LF_BUILDINFO)
|
||||
TYPE_RECORD_ALIAS(ArgList, LF_SUBSTR_LIST)
|
||||
TYPE_RECORD(StringId, LF_STRING_ID)
|
||||
TYPE_RECORD(UDTSrcLine, LF_UDT_SRC_LINE)
|
||||
TYPE_RECORD(FuncIdRecord, LF_FUNC_ID)
|
||||
TYPE_RECORD(MemberFunctionIdRecord, LF_MFUNC_ID)
|
||||
TYPE_RECORD(BuildInfoRecord, LF_BUILDINFO)
|
||||
TYPE_RECORD_ALIAS(StringListRecord, LF_SUBSTR_LIST)
|
||||
TYPE_RECORD(StringIdRecord, LF_STRING_ID)
|
||||
TYPE_RECORD(UdtSourceLineRecord, LF_UDT_SRC_LINE)
|
||||
|
||||
#undef TYPE_RECORD
|
||||
#undef TYPE_RECORD_ALIAS
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/RecordIterator.h"
|
||||
#include "llvm/Object/Error.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include <cstdint>
|
||||
#include <system_error>
|
||||
|
@ -26,43 +25,6 @@ class APSInt;
|
|||
|
||||
namespace codeview {
|
||||
|
||||
/// Consumes sizeof(T) bytes from the given byte sequence. Returns an error if
|
||||
/// there are not enough bytes remaining. Reinterprets the consumed bytes as a
|
||||
/// T object and points 'Res' at them.
|
||||
template <typename T>
|
||||
inline std::error_code consumeObject(StringRef &Data, const T *&Res) {
|
||||
if (Data.size() < sizeof(*Res))
|
||||
return object::object_error::parse_failed;
|
||||
Res = reinterpret_cast<const T *>(Data.data());
|
||||
Data = Data.drop_front(sizeof(*Res));
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
inline std::error_code consumeUInt32(StringRef &Data, uint32_t &Res) {
|
||||
const support::ulittle32_t *IntPtr;
|
||||
if (auto EC = consumeObject(Data, IntPtr))
|
||||
return EC;
|
||||
Res = *IntPtr;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
/// Decodes a numeric "leaf" value. These are integer literals encountered in
|
||||
/// the type stream. If the value is positive and less than LF_NUMERIC (1 <<
|
||||
/// 15), it is emitted directly in Data. Otherwise, it has a tag like LF_CHAR
|
||||
/// that indicates the bitwidth and sign of the numeric data.
|
||||
bool decodeNumericLeaf(ArrayRef<uint8_t> &Data, APSInt &Num);
|
||||
|
||||
inline bool decodeNumericLeaf(StringRef &Data, APSInt &Num) {
|
||||
ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(Data.data()),
|
||||
Data.size());
|
||||
bool Success = decodeNumericLeaf(Bytes, Num);
|
||||
Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
|
||||
return Success;
|
||||
}
|
||||
|
||||
/// Decode a numeric leaf value that is known to be a uint32_t.
|
||||
bool decodeUIntLeaf(ArrayRef<uint8_t> &Data, uint64_t &Num);
|
||||
|
||||
typedef RecordIterator<TypeLeafKind> TypeIterator;
|
||||
|
||||
inline iterator_range<TypeIterator> makeTypeRange(ArrayRef<uint8_t> Data) {
|
||||
|
|
|
@ -40,12 +40,11 @@ public:
|
|||
TypeIndex writeModifier(const ModifierRecord &Record);
|
||||
TypeIndex writeProcedure(const ProcedureRecord &Record);
|
||||
TypeIndex writeMemberFunction(const MemberFunctionRecord &Record);
|
||||
TypeIndex writeArgumentList(const ArgumentListRecord &Record);
|
||||
TypeIndex writeArgumentList(const StringListRecord &Record);
|
||||
TypeIndex writeRecord(TypeRecordBuilder &builder);
|
||||
TypeIndex writePointer(const PointerRecord &Record);
|
||||
TypeIndex writePointerToMember(const PointerToMemberRecord &Record);
|
||||
TypeIndex writeArray(const ArrayRecord &Record);
|
||||
TypeIndex writeAggregate(const AggregateRecord &Record);
|
||||
TypeIndex writeClass(const ClassRecord &Record);
|
||||
TypeIndex writeEnum(const EnumRecord &Record);
|
||||
TypeIndex writeBitField(const BitFieldRecord &Record);
|
||||
TypeIndex writeVirtualTableShape(const VirtualTableShapeRecord &Record);
|
||||
|
|
|
@ -263,7 +263,7 @@ void CodeViewDebug::emitTypeInformation() {
|
|||
// type here.
|
||||
unsigned ArgListIndex = getNextTypeIndex();
|
||||
OS.AddComment("Type record length");
|
||||
OS.EmitIntValue(2 + sizeof(ArgList), 2);
|
||||
OS.EmitIntValue(StringListRecord::getLayoutSize(), 2);
|
||||
OS.AddComment("Leaf type: LF_ARGLIST");
|
||||
OS.EmitIntValue(LF_ARGLIST, 2);
|
||||
OS.AddComment("Number of arguments");
|
||||
|
@ -271,7 +271,7 @@ void CodeViewDebug::emitTypeInformation() {
|
|||
|
||||
unsigned VoidFnTyIdx = getNextTypeIndex();
|
||||
OS.AddComment("Type record length");
|
||||
OS.EmitIntValue(2 + sizeof(ProcedureType), 2);
|
||||
OS.EmitIntValue(ProcedureRecord::getLayoutSize(), 2);
|
||||
OS.AddComment("Leaf type: LF_PROCEDURE");
|
||||
OS.EmitIntValue(LF_PROCEDURE, 2);
|
||||
OS.AddComment("Return type index");
|
||||
|
|
|
@ -56,7 +56,7 @@ void FieldListRecordBuilder::writeMethod(uint16_t OverloadCount,
|
|||
TypeIndex MethodList, StringRef Name) {
|
||||
TypeRecordBuilder &Builder = getBuilder();
|
||||
|
||||
Builder.writeTypeRecordKind(TypeRecordKind::Method);
|
||||
Builder.writeTypeRecordKind(TypeRecordKind::OverloadedMethod);
|
||||
Builder.writeUInt16(OverloadCount);
|
||||
Builder.writeTypeIndex(MethodList);
|
||||
Builder.writeNullTerminatedString(Name);
|
||||
|
|
|
@ -201,12 +201,10 @@ public:
|
|||
|
||||
/// CVTypeVisitor overrides.
|
||||
#define TYPE_RECORD(ClassName, LeafEnum) \
|
||||
void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
|
||||
ArrayRef<uint8_t> LeafData);
|
||||
void visit##ClassName(TypeLeafKind LeafType, ClassName &Record);
|
||||
#define TYPE_RECORD_ALIAS(ClassName, LeafEnum)
|
||||
#define MEMBER_RECORD(ClassName, LeafEnum) \
|
||||
void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
|
||||
ArrayRef<uint8_t> &FieldData);
|
||||
void visit##ClassName(TypeLeafKind LeafType, ClassName &Record);
|
||||
#define MEMBER_RECORD_ALIAS(ClassName, LeafEnum)
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
|
||||
|
||||
|
@ -219,6 +217,8 @@ public:
|
|||
void visitTypeEnd(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData);
|
||||
|
||||
void printMemberAttributes(MemberAttributes Attrs);
|
||||
void printMemberAttributes(MemberAccess Access, MethodKind Kind,
|
||||
MethodOptions Options);
|
||||
|
||||
private:
|
||||
/// Forwards to the dumper, which holds the persistent state from visitation.
|
||||
|
@ -240,17 +240,6 @@ private:
|
|||
|
||||
} // end anonymous namespace
|
||||
|
||||
/// Reinterpret a byte array as an array of characters. Does not interpret as
|
||||
/// a C string, as StringRef has several helpers (split) that make that easy.
|
||||
static StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {
|
||||
return StringRef(reinterpret_cast<const char *>(LeafData.data()),
|
||||
LeafData.size());
|
||||
}
|
||||
|
||||
static StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData) {
|
||||
return getBytesAsCharacters(LeafData).split('\0').first;
|
||||
}
|
||||
|
||||
static StringRef getLeafTypeName(TypeLeafKind LT) {
|
||||
switch (LT) {
|
||||
#define KNOWN_TYPE(LeafName, Value, ClassName) \
|
||||
|
@ -286,164 +275,128 @@ void CVTypeDumperImpl::visitTypeEnd(TypeLeafKind Leaf,
|
|||
W.startLine() << "}\n";
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitStringId(TypeLeafKind Leaf, const StringId *String,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
W.printHex("Id", String->id.getIndex());
|
||||
StringRef StringData = getBytesAsCString(LeafData);
|
||||
W.printString("StringData", StringData);
|
||||
void CVTypeDumperImpl::visitStringIdRecord(TypeLeafKind Leaf,
|
||||
StringIdRecord &String) {
|
||||
printTypeIndex("Id", String.getId());
|
||||
W.printString("StringData", String.getString());
|
||||
// Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE.
|
||||
Name = StringData;
|
||||
Name = String.getString();
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitArgList(TypeLeafKind Leaf, const ArgList *Args,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
W.printNumber("NumArgs", Args->NumArgs);
|
||||
void CVTypeDumperImpl::visitStringListRecord(TypeLeafKind Leaf,
|
||||
StringListRecord &Args) {
|
||||
auto Indices = Args.getIndices();
|
||||
uint32_t Size = Indices.size();
|
||||
W.printNumber("NumArgs", Size);
|
||||
ListScope Arguments(W, "Arguments");
|
||||
SmallString<256> TypeName("(");
|
||||
for (uint32_t ArgI = 0; ArgI != Args->NumArgs; ++ArgI) {
|
||||
const TypeIndex *Type;
|
||||
if (!consumeObject(LeafData, Type))
|
||||
return;
|
||||
printTypeIndex("ArgType", *Type);
|
||||
StringRef ArgTypeName = getTypeName(*Type);
|
||||
for (uint32_t I = 0; I < Size; ++I) {
|
||||
printTypeIndex("ArgType", Indices[I]);
|
||||
StringRef ArgTypeName = getTypeName(Indices[I]);
|
||||
TypeName.append(ArgTypeName);
|
||||
if (ArgI + 1 != Args->NumArgs)
|
||||
if (I + 1 != Size)
|
||||
TypeName.append(", ");
|
||||
}
|
||||
TypeName.push_back(')');
|
||||
Name = CVTD.saveName(TypeName);
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitClassType(TypeLeafKind Leaf, const ClassType *Class,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
W.printNumber("MemberCount", Class->MemberCount);
|
||||
uint16_t Props = Class->Properties;
|
||||
void CVTypeDumperImpl::visitClassRecord(TypeLeafKind Leaf, ClassRecord &Class) {
|
||||
uint16_t Props = static_cast<uint16_t>(Class.getOptions());
|
||||
W.printNumber("MemberCount", Class.getMemberCount());
|
||||
W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
|
||||
printTypeIndex("FieldList", Class->FieldList);
|
||||
printTypeIndex("DerivedFrom", Class->DerivedFrom);
|
||||
printTypeIndex("VShape", Class->VShape);
|
||||
uint64_t SizeOf;
|
||||
if (!decodeUIntLeaf(LeafData, SizeOf))
|
||||
return parseError();
|
||||
W.printNumber("SizeOf", SizeOf);
|
||||
StringRef LeafChars = getBytesAsCharacters(LeafData);
|
||||
StringRef LinkageName;
|
||||
std::tie(Name, LinkageName) = LeafChars.split('\0');
|
||||
W.printString("Name", Name);
|
||||
if (Props & uint16_t(ClassOptions::HasUniqueName)) {
|
||||
LinkageName = LinkageName.split('\0').first;
|
||||
if (LinkageName.empty())
|
||||
return parseError();
|
||||
W.printString("LinkageName", LinkageName);
|
||||
}
|
||||
printTypeIndex("FieldList", Class.getFieldList());
|
||||
printTypeIndex("DerivedFrom", Class.getDerivationList());
|
||||
printTypeIndex("VShape", Class.getVTableShape());
|
||||
W.printNumber("SizeOf", Class.getSize());
|
||||
W.printString("Name", Class.getName());
|
||||
if (Props & uint16_t(ClassOptions::HasUniqueName))
|
||||
W.printString("LinkageName", Class.getUniqueName());
|
||||
Name = Class.getName();
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitUnionType(TypeLeafKind Leaf, const UnionType *Union,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
W.printNumber("MemberCount", Union->MemberCount);
|
||||
uint16_t Props = Union->Properties;
|
||||
void CVTypeDumperImpl::visitUnionRecord(TypeLeafKind Leaf, UnionRecord &Union) {
|
||||
uint16_t Props = static_cast<uint16_t>(Union.getOptions());
|
||||
W.printNumber("MemberCount", Union.getMemberCount());
|
||||
W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
|
||||
printTypeIndex("FieldList", Union->FieldList);
|
||||
uint64_t SizeOf;
|
||||
if (!decodeUIntLeaf(LeafData, SizeOf))
|
||||
return parseError();
|
||||
W.printNumber("SizeOf", SizeOf);
|
||||
StringRef LeafChars = getBytesAsCharacters(LeafData);
|
||||
StringRef LinkageName;
|
||||
std::tie(Name, LinkageName) = LeafChars.split('\0');
|
||||
W.printString("Name", Name);
|
||||
if (Props & uint16_t(ClassOptions::HasUniqueName)) {
|
||||
LinkageName = LinkageName.split('\0').first;
|
||||
if (LinkageName.empty())
|
||||
return parseError();
|
||||
W.printString("LinkageName", LinkageName);
|
||||
}
|
||||
printTypeIndex("FieldList", Union.getFieldList());
|
||||
W.printNumber("SizeOf", Union.getSize());
|
||||
W.printString("Name", Union.getName());
|
||||
if (Props & uint16_t(ClassOptions::HasUniqueName))
|
||||
W.printString("LinkageName", Union.getUniqueName());
|
||||
Name = Union.getName();
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitEnumType(TypeLeafKind Leaf, const EnumType *Enum,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
W.printNumber("NumEnumerators", Enum->NumEnumerators);
|
||||
W.printFlags("Properties", uint16_t(Enum->Properties),
|
||||
void CVTypeDumperImpl::visitEnumRecord(TypeLeafKind Leaf, EnumRecord &Enum) {
|
||||
W.printNumber("NumEnumerators", Enum.getMemberCount());
|
||||
W.printFlags("Properties", uint16_t(Enum.getOptions()),
|
||||
makeArrayRef(ClassOptionNames));
|
||||
printTypeIndex("UnderlyingType", Enum->UnderlyingType);
|
||||
printTypeIndex("FieldListType", Enum->FieldListType);
|
||||
Name = getBytesAsCString(LeafData);
|
||||
W.printString("Name", Name);
|
||||
printTypeIndex("UnderlyingType", Enum.getUnderlyingType());
|
||||
printTypeIndex("FieldListType", Enum.getFieldList());
|
||||
W.printString("Name", Enum.getName());
|
||||
Name = Enum.getName();
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitArrayType(TypeLeafKind Leaf, const ArrayType *AT,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
printTypeIndex("ElementType", AT->ElementType);
|
||||
printTypeIndex("IndexType", AT->IndexType);
|
||||
uint64_t SizeOf;
|
||||
if (!decodeUIntLeaf(LeafData, SizeOf))
|
||||
return parseError();
|
||||
W.printNumber("SizeOf", SizeOf);
|
||||
Name = getBytesAsCString(LeafData);
|
||||
W.printString("Name", Name);
|
||||
void CVTypeDumperImpl::visitArrayRecord(TypeLeafKind Leaf, ArrayRecord &AT) {
|
||||
printTypeIndex("ElementType", AT.getElementType());
|
||||
printTypeIndex("IndexType", AT.getIndexType());
|
||||
W.printNumber("SizeOf", AT.getSize());
|
||||
W.printString("Name", AT.getName());
|
||||
Name = AT.getName();
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitVFTableType(TypeLeafKind Leaf,
|
||||
const VFTableType *VFT,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
printTypeIndex("CompleteClass", VFT->CompleteClass);
|
||||
printTypeIndex("OverriddenVFTable", VFT->OverriddenVFTable);
|
||||
W.printHex("VFPtrOffset", VFT->VFPtrOffset);
|
||||
StringRef NamesData = getBytesAsCharacters(LeafData.slice(0, VFT->NamesLen));
|
||||
std::tie(Name, NamesData) = NamesData.split('\0');
|
||||
W.printString("VFTableName", Name);
|
||||
while (!NamesData.empty()) {
|
||||
StringRef MethodName;
|
||||
std::tie(MethodName, NamesData) = NamesData.split('\0');
|
||||
W.printString("MethodName", MethodName);
|
||||
}
|
||||
void CVTypeDumperImpl::visitVirtualTableRecord(TypeLeafKind Leaf,
|
||||
VirtualTableRecord &VFT) {
|
||||
printTypeIndex("CompleteClass", VFT.getCompleteClass());
|
||||
printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable());
|
||||
W.printHex("VFPtrOffset", VFT.getVFPtrOffset());
|
||||
W.printString("VFTableName", VFT.getName());
|
||||
for (auto N : VFT.getMethodNames())
|
||||
W.printString("MethodName", N);
|
||||
Name = VFT.getName();
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitMemberFuncId(TypeLeafKind Leaf,
|
||||
const MemberFuncId *Id,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
printTypeIndex("ClassType", Id->ClassType);
|
||||
printTypeIndex("FunctionType", Id->FunctionType);
|
||||
Name = getBytesAsCString(LeafData);
|
||||
W.printString("Name", Name);
|
||||
void CVTypeDumperImpl::visitMemberFunctionIdRecord(TypeLeafKind Leaf,
|
||||
MemberFunctionIdRecord &Id) {
|
||||
printTypeIndex("ClassType", Id.getClassType());
|
||||
printTypeIndex("FunctionType", Id.getFunctionType());
|
||||
W.printString("Name", Id.getName());
|
||||
Name = Id.getName();
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitProcedureType(TypeLeafKind Leaf,
|
||||
const ProcedureType *Proc,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
printTypeIndex("ReturnType", Proc->ReturnType);
|
||||
W.printEnum("CallingConvention", uint8_t(Proc->CallConv),
|
||||
void CVTypeDumperImpl::visitProcedureRecord(TypeLeafKind Leaf,
|
||||
ProcedureRecord &Proc) {
|
||||
printTypeIndex("ReturnType", Proc.getReturnType());
|
||||
W.printEnum("CallingConvention", uint8_t(Proc.getCallConv()),
|
||||
makeArrayRef(CallingConventions));
|
||||
W.printFlags("FunctionOptions", uint8_t(Proc->Options),
|
||||
W.printFlags("FunctionOptions", uint8_t(Proc.getOptions()),
|
||||
makeArrayRef(FunctionOptionEnum));
|
||||
W.printNumber("NumParameters", Proc->NumParameters);
|
||||
printTypeIndex("ArgListType", Proc->ArgListType);
|
||||
W.printNumber("NumParameters", Proc.getParameterCount());
|
||||
printTypeIndex("ArgListType", Proc.getArgumentList());
|
||||
|
||||
StringRef ReturnTypeName = getTypeName(Proc->ReturnType);
|
||||
StringRef ArgListTypeName = getTypeName(Proc->ArgListType);
|
||||
StringRef ReturnTypeName = getTypeName(Proc.getReturnType());
|
||||
StringRef ArgListTypeName = getTypeName(Proc.getArgumentList());
|
||||
SmallString<256> TypeName(ReturnTypeName);
|
||||
TypeName.push_back(' ');
|
||||
TypeName.append(ArgListTypeName);
|
||||
Name = CVTD.saveName(TypeName);
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitMemberFunctionType(
|
||||
TypeLeafKind Leaf, const MemberFunctionType *MemberFunc,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
printTypeIndex("ReturnType", MemberFunc->ReturnType);
|
||||
printTypeIndex("ClassType", MemberFunc->ClassType);
|
||||
printTypeIndex("ThisType", MemberFunc->ThisType);
|
||||
W.printEnum("CallingConvention", uint8_t(MemberFunc->CallConv),
|
||||
void CVTypeDumperImpl::visitMemberFunctionRecord(TypeLeafKind Leaf,
|
||||
MemberFunctionRecord &MF) {
|
||||
printTypeIndex("ReturnType", MF.getReturnType());
|
||||
printTypeIndex("ClassType", MF.getClassType());
|
||||
printTypeIndex("ThisType", MF.getThisType());
|
||||
W.printEnum("CallingConvention", uint8_t(MF.getCallConv()),
|
||||
makeArrayRef(CallingConventions));
|
||||
W.printFlags("FunctionOptions", uint8_t(MemberFunc->Options),
|
||||
W.printFlags("FunctionOptions", uint8_t(MF.getOptions()),
|
||||
makeArrayRef(FunctionOptionEnum));
|
||||
W.printNumber("NumParameters", MemberFunc->NumParameters);
|
||||
printTypeIndex("ArgListType", MemberFunc->ArgListType);
|
||||
W.printNumber("ThisAdjustment", MemberFunc->ThisAdjustment);
|
||||
W.printNumber("NumParameters", MF.getParameterCount());
|
||||
printTypeIndex("ArgListType", MF.getArgumentList());
|
||||
W.printNumber("ThisAdjustment", MF.getThisPointerAdjustment());
|
||||
|
||||
StringRef ReturnTypeName = getTypeName(MemberFunc->ReturnType);
|
||||
StringRef ClassTypeName = getTypeName(MemberFunc->ClassType);
|
||||
StringRef ArgListTypeName = getTypeName(MemberFunc->ArgListType);
|
||||
StringRef ReturnTypeName = getTypeName(MF.getReturnType());
|
||||
StringRef ClassTypeName = getTypeName(MF.getClassType());
|
||||
StringRef ArgListTypeName = getTypeName(MF.getArgumentList());
|
||||
SmallString<256> TypeName(ReturnTypeName);
|
||||
TypeName.push_back(' ');
|
||||
TypeName.append(ClassTypeName);
|
||||
|
@ -455,148 +408,141 @@ void CVTypeDumperImpl::visitMemberFunctionType(
|
|||
void CVTypeDumperImpl::visitMethodList(TypeLeafKind Leaf,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
while (!LeafData.empty()) {
|
||||
const MethodListEntry *Method;
|
||||
if (!consumeObject(LeafData, Method))
|
||||
auto Method =
|
||||
MethodListRecord::deserialize(TypeRecordKind::MethodList, LeafData);
|
||||
if (Method)
|
||||
return;
|
||||
const MethodListRecord &M = *Method;
|
||||
|
||||
ListScope S(W, "Method");
|
||||
printMemberAttributes(Method->Attrs);
|
||||
printTypeIndex("Type", Method->Type);
|
||||
if (Method->isIntroducedVirtual()) {
|
||||
const little32_t *VFTOffsetPtr;
|
||||
if (!consumeObject(LeafData, VFTOffsetPtr))
|
||||
return;
|
||||
W.printHex("VFTableOffset", *VFTOffsetPtr);
|
||||
}
|
||||
printMemberAttributes(M.getAccess(), M.getMethodKind(), M.getOptions());
|
||||
printTypeIndex("Type", Method->getType());
|
||||
if (Method->getMethodKind() == MethodKind::IntroducingVirtual ||
|
||||
Method->getMethodKind() == MethodKind::PureIntroducingVirtual)
|
||||
W.printHex("VFTableOffset", Method->getVFTableOffset());
|
||||
}
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitFuncId(TypeLeafKind Leaf, const FuncId *Func,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
printTypeIndex("ParentScope", Func->ParentScope);
|
||||
printTypeIndex("FunctionType", Func->FunctionType);
|
||||
Name = getBytesAsCString(LeafData);
|
||||
W.printString("Name", Name);
|
||||
void CVTypeDumperImpl::visitFuncIdRecord(TypeLeafKind Leaf,
|
||||
FuncIdRecord &Func) {
|
||||
printTypeIndex("ParentScope", Func.getParentScope());
|
||||
printTypeIndex("FunctionType", Func.getFunctionType());
|
||||
W.printString("Name", Func.getName());
|
||||
Name = Func.getName();
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitTypeServer2(TypeLeafKind Leaf,
|
||||
const TypeServer2 *TypeServer,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
W.printBinary("Signature", StringRef(TypeServer->Signature, 16));
|
||||
W.printNumber("Age", TypeServer->Age);
|
||||
Name = getBytesAsCString(LeafData);
|
||||
W.printString("Name", Name);
|
||||
void CVTypeDumperImpl::visitTypeServer2Record(TypeLeafKind Leaf,
|
||||
TypeServer2Record &TS) {
|
||||
W.printBinary("Signature", TS.getGuid());
|
||||
W.printNumber("Age", TS.getAge());
|
||||
W.printString("Name", TS.getName());
|
||||
Name = TS.getName();
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitPointerType(TypeLeafKind Leaf,
|
||||
const PointerType *Ptr,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
printTypeIndex("PointeeType", Ptr->PointeeType);
|
||||
W.printHex("PointerAttributes", Ptr->Attrs);
|
||||
W.printEnum("PtrType", unsigned(Ptr->getPtrKind()),
|
||||
void CVTypeDumperImpl::visitPointerRecord(TypeLeafKind Leaf,
|
||||
PointerRecord &Ptr) {
|
||||
printTypeIndex("PointeeType", Ptr.getReferentType());
|
||||
W.printHex("PointerAttributes", uint32_t(Ptr.getOptions()));
|
||||
W.printEnum("PtrType", unsigned(Ptr.getPointerKind()),
|
||||
makeArrayRef(PtrKindNames));
|
||||
W.printEnum("PtrMode", unsigned(Ptr->getPtrMode()),
|
||||
makeArrayRef(PtrModeNames));
|
||||
W.printNumber("IsFlat", Ptr->isFlat());
|
||||
W.printNumber("IsConst", Ptr->isConst());
|
||||
W.printNumber("IsVolatile", Ptr->isVolatile());
|
||||
W.printNumber("IsUnaligned", Ptr->isUnaligned());
|
||||
W.printEnum("PtrMode", unsigned(Ptr.getMode()), makeArrayRef(PtrModeNames));
|
||||
|
||||
if (Ptr->isPointerToMember()) {
|
||||
const PointerToMemberTail *PMT;
|
||||
if (!consumeObject(LeafData, PMT))
|
||||
return;
|
||||
printTypeIndex("ClassType", PMT->ClassType);
|
||||
W.printEnum("Representation", PMT->Representation,
|
||||
W.printNumber("IsFlat", Ptr.isFlat());
|
||||
W.printNumber("IsConst", Ptr.isConst());
|
||||
W.printNumber("IsVolatile", Ptr.isVolatile());
|
||||
W.printNumber("IsUnaligned", Ptr.isUnaligned());
|
||||
|
||||
if (Ptr.isPointerToMember()) {
|
||||
const MemberPointerInfo &MI = Ptr.getMemberInfo();
|
||||
|
||||
printTypeIndex("ClassType", MI.getContainingType());
|
||||
W.printEnum("Representation", uint16_t(MI.getRepresentation()),
|
||||
makeArrayRef(PtrMemberRepNames));
|
||||
|
||||
StringRef PointeeName = getTypeName(Ptr->PointeeType);
|
||||
StringRef ClassName = getTypeName(PMT->ClassType);
|
||||
StringRef PointeeName = getTypeName(Ptr.getReferentType());
|
||||
StringRef ClassName = getTypeName(MI.getContainingType());
|
||||
SmallString<256> TypeName(PointeeName);
|
||||
TypeName.push_back(' ');
|
||||
TypeName.append(ClassName);
|
||||
TypeName.append("::*");
|
||||
Name = CVTD.saveName(TypeName);
|
||||
} else {
|
||||
W.printBinaryBlock("TailData", getBytesAsCharacters(LeafData));
|
||||
|
||||
SmallString<256> TypeName;
|
||||
if (Ptr->isConst())
|
||||
if (Ptr.isConst())
|
||||
TypeName.append("const ");
|
||||
if (Ptr->isVolatile())
|
||||
if (Ptr.isVolatile())
|
||||
TypeName.append("volatile ");
|
||||
if (Ptr->isUnaligned())
|
||||
if (Ptr.isUnaligned())
|
||||
TypeName.append("__unaligned ");
|
||||
|
||||
TypeName.append(getTypeName(Ptr->PointeeType));
|
||||
TypeName.append(getTypeName(Ptr.getReferentType()));
|
||||
|
||||
if (Ptr->getPtrMode() == PointerMode::LValueReference)
|
||||
if (Ptr.getMode() == PointerMode::LValueReference)
|
||||
TypeName.append("&");
|
||||
else if (Ptr->getPtrMode() == PointerMode::RValueReference)
|
||||
else if (Ptr.getMode() == PointerMode::RValueReference)
|
||||
TypeName.append("&&");
|
||||
else if (Ptr->getPtrMode() == PointerMode::Pointer)
|
||||
else if (Ptr.getMode() == PointerMode::Pointer)
|
||||
TypeName.append("*");
|
||||
|
||||
Name = CVTD.saveName(TypeName);
|
||||
}
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitTypeModifier(TypeLeafKind Leaf,
|
||||
const TypeModifier *Mod,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
printTypeIndex("ModifiedType", Mod->ModifiedType);
|
||||
W.printFlags("Modifiers", Mod->Modifiers, makeArrayRef(TypeModifierNames));
|
||||
void CVTypeDumperImpl::visitModifierRecord(TypeLeafKind Leaf,
|
||||
ModifierRecord &Mod) {
|
||||
uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
|
||||
printTypeIndex("ModifiedType", Mod.getModifiedType());
|
||||
W.printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames));
|
||||
|
||||
StringRef ModifiedName = getTypeName(Mod->ModifiedType);
|
||||
StringRef ModifiedName = getTypeName(Mod.getModifiedType());
|
||||
SmallString<256> TypeName;
|
||||
if (Mod->Modifiers & uint16_t(ModifierOptions::Const))
|
||||
if (Mods & uint16_t(ModifierOptions::Const))
|
||||
TypeName.append("const ");
|
||||
if (Mod->Modifiers & uint16_t(ModifierOptions::Volatile))
|
||||
if (Mods & uint16_t(ModifierOptions::Volatile))
|
||||
TypeName.append("volatile ");
|
||||
if (Mod->Modifiers & uint16_t(ModifierOptions::Unaligned))
|
||||
if (Mods & uint16_t(ModifierOptions::Unaligned))
|
||||
TypeName.append("__unaligned ");
|
||||
TypeName.append(ModifiedName);
|
||||
Name = CVTD.saveName(TypeName);
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitVTableShape(TypeLeafKind Leaf,
|
||||
const VTableShape *Shape,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
unsigned VFEntryCount = Shape->VFEntryCount;
|
||||
W.printNumber("VFEntryCount", VFEntryCount);
|
||||
// We could print out whether the methods are near or far, but in practice
|
||||
// today everything is CV_VTS_near32, so it's just noise.
|
||||
void CVTypeDumperImpl::visitVirtualTableShapeRecord(
|
||||
TypeLeafKind Leaf, VirtualTableShapeRecord &Shape) {
|
||||
W.printNumber("VFEntryCount", Shape.getEntryCount());
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitUDTSrcLine(TypeLeafKind Leaf,
|
||||
const UDTSrcLine *Line,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
printTypeIndex("UDT", Line->UDT);
|
||||
printTypeIndex("SourceFile", Line->SourceFile);
|
||||
W.printNumber("LineNumber", Line->LineNumber);
|
||||
void CVTypeDumperImpl::visitUdtSourceLineRecord(TypeLeafKind Leaf,
|
||||
UdtSourceLineRecord &Line) {
|
||||
printTypeIndex("UDT", Line.getUDT());
|
||||
printTypeIndex("SourceFile", Line.getSourceFile());
|
||||
W.printNumber("LineNumber", Line.getLineNumber());
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitBuildInfo(TypeLeafKind Leaf, const BuildInfo *Args,
|
||||
ArrayRef<uint8_t> LeafData) {
|
||||
W.printNumber("NumArgs", Args->NumArgs);
|
||||
void CVTypeDumperImpl::visitBuildInfoRecord(TypeLeafKind Leaf,
|
||||
BuildInfoRecord &Args) {
|
||||
W.printNumber("NumArgs", Args.getArgs().size());
|
||||
|
||||
ListScope Arguments(W, "Arguments");
|
||||
for (uint32_t ArgI = 0; ArgI != Args->NumArgs; ++ArgI) {
|
||||
const TypeIndex *Type;
|
||||
if (!consumeObject(LeafData, Type))
|
||||
return;
|
||||
printTypeIndex("ArgType", *Type);
|
||||
for (auto Arg : Args.getArgs()) {
|
||||
printTypeIndex("ArgType", Arg);
|
||||
}
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::printMemberAttributes(MemberAttributes Attrs) {
|
||||
W.printEnum("AccessSpecifier", uint8_t(Attrs.getAccess()),
|
||||
return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(),
|
||||
Attrs.getFlags());
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::printMemberAttributes(MemberAccess Access,
|
||||
MethodKind Kind,
|
||||
MethodOptions Options) {
|
||||
W.printEnum("AccessSpecifier", uint8_t(Access),
|
||||
makeArrayRef(MemberAccessNames));
|
||||
auto MK = Attrs.getMethodKind();
|
||||
// Data members will be vanilla. Don't try to print a method kind for them.
|
||||
if (MK != MethodKind::Vanilla)
|
||||
W.printEnum("MethodKind", unsigned(MK), makeArrayRef(MemberKindNames));
|
||||
if (Attrs.getFlags() != MethodOptions::None) {
|
||||
W.printFlags("MethodOptions", unsigned(Attrs.getFlags()),
|
||||
if (Kind != MethodKind::Vanilla)
|
||||
W.printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames));
|
||||
if (Options != MethodOptions::None) {
|
||||
W.printFlags("MethodOptions", unsigned(Options),
|
||||
makeArrayRef(MethodOptionNames));
|
||||
}
|
||||
}
|
||||
|
@ -605,117 +551,91 @@ void CVTypeDumperImpl::visitUnknownMember(TypeLeafKind Leaf) {
|
|||
W.printHex("UnknownMember", unsigned(Leaf));
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitNestedType(TypeLeafKind Leaf,
|
||||
const NestedType *Nested,
|
||||
ArrayRef<uint8_t> &FieldData) {
|
||||
void CVTypeDumperImpl::visitNestedTypeRecord(TypeLeafKind Leaf,
|
||||
NestedTypeRecord &Nested) {
|
||||
DictScope S(W, "NestedType");
|
||||
printTypeIndex("Type", Nested->Type);
|
||||
StringRef Name = getBytesAsCString(FieldData);
|
||||
FieldData = FieldData.drop_front(Name.size() + 1);
|
||||
W.printString("Name", Name);
|
||||
printTypeIndex("Type", Nested.getNestedType());
|
||||
W.printString("Name", Nested.getName());
|
||||
Name = Nested.getName();
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitOneMethod(TypeLeafKind Leaf,
|
||||
const OneMethod *Method,
|
||||
ArrayRef<uint8_t> &FieldData) {
|
||||
void CVTypeDumperImpl::visitOneMethodRecord(TypeLeafKind Leaf,
|
||||
OneMethodRecord &Method) {
|
||||
DictScope S(W, "OneMethod");
|
||||
printMemberAttributes(Method->Attrs);
|
||||
printTypeIndex("Type", Method->Type);
|
||||
MethodKind K = Method.getKind();
|
||||
printMemberAttributes(Method.getAccess(), K, Method.getOptions());
|
||||
printTypeIndex("Type", Method.getType());
|
||||
// If virtual, then read the vftable offset.
|
||||
if (Method->isIntroducedVirtual()) {
|
||||
const little32_t *VFTOffsetPtr;
|
||||
if (!consumeObject(FieldData, VFTOffsetPtr))
|
||||
return;
|
||||
W.printHex("VFTableOffset", *VFTOffsetPtr);
|
||||
}
|
||||
StringRef Name = getBytesAsCString(FieldData);
|
||||
FieldData = FieldData.drop_front(Name.size() + 1);
|
||||
W.printString("Name", Name);
|
||||
if (Method.isIntroducingVirtual())
|
||||
W.printHex("VFTableOffset", Method.getVFTableOffset());
|
||||
W.printString("Name", Method.getName());
|
||||
Name = Method.getName();
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitOverloadedMethod(TypeLeafKind Leaf,
|
||||
const OverloadedMethod *Method,
|
||||
ArrayRef<uint8_t> &FieldData) {
|
||||
void CVTypeDumperImpl::visitOverloadedMethodRecord(
|
||||
TypeLeafKind Leaf, OverloadedMethodRecord &Method) {
|
||||
DictScope S(W, "OverloadedMethod");
|
||||
W.printHex("MethodCount", Method->MethodCount);
|
||||
W.printHex("MethodListIndex", Method->MethList.getIndex());
|
||||
StringRef Name = getBytesAsCString(FieldData);
|
||||
FieldData = FieldData.drop_front(Name.size() + 1);
|
||||
W.printString("Name", Name);
|
||||
W.printHex("MethodCount", Method.getNumOverloads());
|
||||
printTypeIndex("MethodListIndex", Method.getMethodList());
|
||||
W.printString("Name", Method.getName());
|
||||
Name = Method.getName();
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitDataMember(TypeLeafKind Leaf,
|
||||
const DataMember *Field,
|
||||
ArrayRef<uint8_t> &FieldData) {
|
||||
void CVTypeDumperImpl::visitDataMemberRecord(TypeLeafKind Leaf,
|
||||
DataMemberRecord &Field) {
|
||||
DictScope S(W, "DataMember");
|
||||
printMemberAttributes(Field->Attrs);
|
||||
printTypeIndex("Type", Field->Type);
|
||||
uint64_t FieldOffset;
|
||||
if (!decodeUIntLeaf(FieldData, FieldOffset))
|
||||
return parseError();
|
||||
W.printHex("FieldOffset", FieldOffset);
|
||||
StringRef Name = getBytesAsCString(FieldData);
|
||||
FieldData = FieldData.drop_front(Name.size() + 1);
|
||||
W.printString("Name", Name);
|
||||
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
|
||||
MethodOptions::None);
|
||||
printTypeIndex("Type", Field.getType());
|
||||
W.printHex("FieldOffset", Field.getFieldOffset());
|
||||
W.printString("Name", Field.getName());
|
||||
Name = Field.getName();
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitStaticDataMember(TypeLeafKind Leaf,
|
||||
const StaticDataMember *Field,
|
||||
ArrayRef<uint8_t> &FieldData) {
|
||||
void CVTypeDumperImpl::visitStaticDataMemberRecord(
|
||||
TypeLeafKind Leaf, StaticDataMemberRecord &Field) {
|
||||
DictScope S(W, "StaticDataMember");
|
||||
printMemberAttributes(Field->Attrs);
|
||||
printTypeIndex("Type", Field->Type);
|
||||
StringRef Name = getBytesAsCString(FieldData);
|
||||
FieldData = FieldData.drop_front(Name.size() + 1);
|
||||
W.printString("Name", Name);
|
||||
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
|
||||
MethodOptions::None);
|
||||
printTypeIndex("Type", Field.getType());
|
||||
W.printString("Name", Field.getName());
|
||||
Name = Field.getName();
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitVirtualFunctionPointer(
|
||||
TypeLeafKind Leaf, const VirtualFunctionPointer *VFTable,
|
||||
ArrayRef<uint8_t> &FieldData) {
|
||||
void CVTypeDumperImpl::visitVirtualFunctionPointerRecord(
|
||||
TypeLeafKind Leaf, VirtualFunctionPointerRecord &VFTable) {
|
||||
DictScope S(W, "VirtualFunctionPointer");
|
||||
printTypeIndex("Type", VFTable->Type);
|
||||
printTypeIndex("Type", VFTable.getType());
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitEnumerator(TypeLeafKind Leaf,
|
||||
const Enumerator *Enum,
|
||||
ArrayRef<uint8_t> &FieldData) {
|
||||
void CVTypeDumperImpl::visitEnumeratorRecord(TypeLeafKind Leaf,
|
||||
EnumeratorRecord &Enum) {
|
||||
DictScope S(W, "Enumerator");
|
||||
printMemberAttributes(Enum->Attrs);
|
||||
APSInt EnumValue;
|
||||
if (!decodeNumericLeaf(FieldData, EnumValue))
|
||||
return parseError();
|
||||
W.printNumber("EnumValue", EnumValue);
|
||||
StringRef Name = getBytesAsCString(FieldData);
|
||||
FieldData = FieldData.drop_front(Name.size() + 1);
|
||||
W.printString("Name", Name);
|
||||
printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
|
||||
MethodOptions::None);
|
||||
W.printNumber("EnumValue", Enum.getValue());
|
||||
W.printString("Name", Enum.getName());
|
||||
Name = Enum.getName();
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitBaseClass(TypeLeafKind Leaf, const BaseClass *Base,
|
||||
ArrayRef<uint8_t> &FieldData) {
|
||||
void CVTypeDumperImpl::visitBaseClassRecord(TypeLeafKind Leaf,
|
||||
BaseClassRecord &Base) {
|
||||
DictScope S(W, "BaseClass");
|
||||
printMemberAttributes(Base->Attrs);
|
||||
printTypeIndex("BaseType", Base->BaseType);
|
||||
uint64_t BaseOffset;
|
||||
if (!decodeUIntLeaf(FieldData, BaseOffset))
|
||||
return parseError();
|
||||
W.printHex("BaseOffset", BaseOffset);
|
||||
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
|
||||
MethodOptions::None);
|
||||
printTypeIndex("BaseType", Base.getBaseType());
|
||||
W.printHex("BaseOffset", Base.getBaseOffset());
|
||||
}
|
||||
|
||||
void CVTypeDumperImpl::visitVirtualBaseClass(TypeLeafKind Leaf,
|
||||
const VirtualBaseClass *Base,
|
||||
ArrayRef<uint8_t> &FieldData) {
|
||||
void CVTypeDumperImpl::visitVirtualBaseClassRecord(
|
||||
TypeLeafKind Leaf, VirtualBaseClassRecord &Base) {
|
||||
DictScope S(W, "VirtualBaseClass");
|
||||
printMemberAttributes(Base->Attrs);
|
||||
printTypeIndex("BaseType", Base->BaseType);
|
||||
printTypeIndex("VBPtrType", Base->VBPtrType);
|
||||
uint64_t VBPtrOffset, VBTableIndex;
|
||||
if (!decodeUIntLeaf(FieldData, VBPtrOffset))
|
||||
return parseError();
|
||||
if (!decodeUIntLeaf(FieldData, VBTableIndex))
|
||||
return parseError();
|
||||
W.printHex("VBPtrOffset", VBPtrOffset);
|
||||
W.printHex("VBTableIndex", VBTableIndex);
|
||||
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
|
||||
MethodOptions::None);
|
||||
printTypeIndex("BaseType", Base.getBaseType());
|
||||
printTypeIndex("VBPtrType", Base.getVBPtrType());
|
||||
W.printHex("VBPtrOffset", Base.getVBPtrOffset());
|
||||
W.printHex("VBTableIndex", Base.getVTableIndex());
|
||||
}
|
||||
|
||||
StringRef CVTypeDumper::getTypeName(TypeIndex TI) {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeStream.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
|
|
@ -17,27 +17,6 @@
|
|||
using namespace llvm;
|
||||
using namespace codeview;
|
||||
|
||||
namespace {
|
||||
|
||||
const int PointerKindShift = 0;
|
||||
const int PointerModeShift = 5;
|
||||
const int PointerSizeShift = 13;
|
||||
|
||||
const int ClassHfaKindShift = 11;
|
||||
const int ClassWindowsRTClassKindShift = 14;
|
||||
|
||||
void writePointerBase(TypeRecordBuilder &Builder,
|
||||
const PointerRecordBase &Record) {
|
||||
Builder.writeTypeIndex(Record.getReferentType());
|
||||
uint32_t flags =
|
||||
static_cast<uint32_t>(Record.getOptions()) |
|
||||
(Record.getSize() << PointerSizeShift) |
|
||||
(static_cast<uint32_t>(Record.getMode()) << PointerModeShift) |
|
||||
(static_cast<uint32_t>(Record.getPointerKind()) << PointerKindShift);
|
||||
Builder.writeUInt32(flags);
|
||||
}
|
||||
}
|
||||
|
||||
TypeTableBuilder::TypeTableBuilder() {}
|
||||
|
||||
TypeTableBuilder::~TypeTableBuilder() {}
|
||||
|
@ -46,7 +25,7 @@ TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) {
|
|||
TypeRecordBuilder Builder(TypeRecordKind::Modifier);
|
||||
|
||||
Builder.writeTypeIndex(Record.getModifiedType());
|
||||
Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));
|
||||
Builder.writeUInt16(static_cast<uint16_t>(Record.getModifiers()));
|
||||
|
||||
return writeRecord(Builder);
|
||||
}
|
||||
|
@ -79,12 +58,11 @@ TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) {
|
|||
return writeRecord(Builder);
|
||||
}
|
||||
|
||||
TypeIndex
|
||||
TypeTableBuilder::writeArgumentList(const ArgumentListRecord &Record) {
|
||||
TypeIndex TypeTableBuilder::writeArgumentList(const StringListRecord &Record) {
|
||||
TypeRecordBuilder Builder(TypeRecordKind::ArgumentList);
|
||||
|
||||
Builder.writeUInt32(Record.getArgumentTypes().size());
|
||||
for (TypeIndex TI : Record.getArgumentTypes()) {
|
||||
Builder.writeUInt32(Record.getIndices().size());
|
||||
for (TypeIndex TI : Record.getIndices()) {
|
||||
Builder.writeTypeIndex(TI);
|
||||
}
|
||||
|
||||
|
@ -94,19 +72,20 @@ TypeTableBuilder::writeArgumentList(const ArgumentListRecord &Record) {
|
|||
TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) {
|
||||
TypeRecordBuilder Builder(TypeRecordKind::Pointer);
|
||||
|
||||
writePointerBase(Builder, Record);
|
||||
Builder.writeTypeIndex(Record.getReferentType());
|
||||
uint32_t flags = static_cast<uint32_t>(Record.getOptions()) |
|
||||
(Record.getSize() << PointerRecord::PointerSizeShift) |
|
||||
(static_cast<uint32_t>(Record.getMode())
|
||||
<< PointerRecord::PointerModeShift) |
|
||||
(static_cast<uint32_t>(Record.getPointerKind())
|
||||
<< PointerRecord::PointerKindShift);
|
||||
Builder.writeUInt32(flags);
|
||||
|
||||
return writeRecord(Builder);
|
||||
}
|
||||
|
||||
TypeIndex
|
||||
TypeTableBuilder::writePointerToMember(const PointerToMemberRecord &Record) {
|
||||
TypeRecordBuilder Builder(TypeRecordKind::Pointer);
|
||||
|
||||
writePointerBase(Builder, Record);
|
||||
|
||||
Builder.writeTypeIndex(Record.getContainingType());
|
||||
Builder.writeUInt16(static_cast<uint16_t>(Record.getRepresentation()));
|
||||
if (Record.isPointerToMember()) {
|
||||
const MemberPointerInfo &M = Record.getMemberInfo();
|
||||
Builder.writeTypeIndex(M.getContainingType());
|
||||
Builder.writeUInt16(static_cast<uint16_t>(M.getRepresentation()));
|
||||
}
|
||||
|
||||
return writeRecord(Builder);
|
||||
}
|
||||
|
@ -122,7 +101,7 @@ TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) {
|
|||
return writeRecord(Builder);
|
||||
}
|
||||
|
||||
TypeIndex TypeTableBuilder::writeAggregate(const AggregateRecord &Record) {
|
||||
TypeIndex TypeTableBuilder::writeClass(const ClassRecord &Record) {
|
||||
assert((Record.getKind() == TypeRecordKind::Structure) ||
|
||||
(Record.getKind() == TypeRecordKind::Class) ||
|
||||
(Record.getKind() == TypeRecordKind::Union));
|
||||
|
@ -132,18 +111,13 @@ TypeIndex TypeTableBuilder::writeAggregate(const AggregateRecord &Record) {
|
|||
Builder.writeUInt16(Record.getMemberCount());
|
||||
uint16_t Flags =
|
||||
static_cast<uint16_t>(Record.getOptions()) |
|
||||
(static_cast<uint16_t>(Record.getHfa()) << ClassHfaKindShift) |
|
||||
(static_cast<uint16_t>(Record.getHfa()) << ClassRecord::HfaKindShift) |
|
||||
(static_cast<uint16_t>(Record.getWinRTKind())
|
||||
<< ClassWindowsRTClassKindShift);
|
||||
<< ClassRecord::WinRTKindShift);
|
||||
Builder.writeUInt16(Flags);
|
||||
Builder.writeTypeIndex(Record.getFieldList());
|
||||
if (Record.getKind() != TypeRecordKind::Union) {
|
||||
Builder.writeTypeIndex(Record.getDerivationList());
|
||||
Builder.writeTypeIndex(Record.getVTableShape());
|
||||
} else {
|
||||
assert(Record.getDerivationList() == TypeIndex());
|
||||
assert(Record.getVTableShape() == TypeIndex());
|
||||
}
|
||||
Builder.writeTypeIndex(Record.getDerivationList());
|
||||
Builder.writeTypeIndex(Record.getVTableShape());
|
||||
Builder.writeEncodedUnsignedInteger(Record.getSize());
|
||||
Builder.writeNullTerminatedString(Record.getName());
|
||||
if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
|
||||
|
|
Loading…
Reference in New Issue