[llvm] r268535 - [codeview] Add a type visitor to help abstract away type stream handling
Reid Kleckner via llvm-commits
llvm-commits at lists.llvm.org
Wed May 4 12:39:28 PDT 2016
Author: rnk
Date: Wed May 4 14:39:28 2016
New Revision: 268535
URL: http://llvm.org/viewvc/llvm-project?rev=268535&view=rev
Log:
[codeview] Add a type visitor to help abstract away type stream handling
Summary:
Port the dumper in llvm-readobj over to it.
I'm planning to use this visitor to power type stream merging.
While we're at it, try to switch from StringRef to ArrayRef<uint8_t> in some
places.
Reviewers: zturner, amccarth
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D19899
Added:
llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def
Modified:
llvm/trunk/include/llvm/DebugInfo/CodeView/CVLeafTypes.def
llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h
llvm/trunk/include/llvm/Support/ScopedPrinter.h
llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp
llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/CVLeafTypes.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/CVLeafTypes.def?rev=268535&r1=268534&r2=268535&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/CVLeafTypes.def (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/CVLeafTypes.def Wed May 4 14:39:28 2016
@@ -30,7 +30,7 @@ LEAF_TYPE(LF_UNION_16t, 0x0006)
LEAF_TYPE(LF_ENUM_16t, 0x0007)
LEAF_TYPE(LF_PROCEDURE_16t, 0x0008)
LEAF_TYPE(LF_MFUNCTION_16t, 0x0009)
-LEAF_TYPE(LF_VTSHAPE, 0x000a)
+KNOWN_TYPE(LF_VTSHAPE, 0x000a, VTableShape)
LEAF_TYPE(LF_COBOL0_16t, 0x000b)
LEAF_TYPE(LF_COBOL1, 0x000c)
LEAF_TYPE(LF_BARRAY_16t, 0x000d)
@@ -76,8 +76,8 @@ LEAF_TYPE(LF_VFUNCOFF_16t, 0x040d)
LEAF_TYPE(LF_TI16_MAX, 0x1000)
-LEAF_TYPE(LF_MODIFIER, 0x1001)
-LEAF_TYPE(LF_POINTER, 0x1002)
+KNOWN_TYPE(LF_MODIFIER, 0x1001, TypeModifier)
+KNOWN_TYPE(LF_POINTER, 0x1002, PointerType)
LEAF_TYPE(LF_ARRAY_ST, 0x1003)
LEAF_TYPE(LF_CLASS_ST, 0x1004)
LEAF_TYPE(LF_STRUCTURE_ST, 0x1005)
Added: llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h?rev=268535&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h Wed May 4 14:39:28 2016
@@ -0,0 +1,153 @@
+//===- CVTypeVisitor.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
+#define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeStream.h"
+
+namespace llvm {
+namespace codeview {
+
+template <typename Derived>
+class CVTypeVisitor {
+public:
+ CVTypeVisitor() {}
+
+ bool hadError() const { return HadError; }
+
+ template <typename T>
+ bool consumeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
+ if (Data.size() < sizeof(*Res)) {
+ HadError = true;
+ return false;
+ }
+ Res = reinterpret_cast<const T *>(Data.data());
+ Data = Data.drop_front(sizeof(*Res));
+ return true;
+ }
+
+ /// Actions to take on known types. By default, they do nothing. Visit methods
+ /// for member records take the FieldData by non-const reference and are
+ /// expected to consume the trailing bytes used by the field.
+ /// 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) {}
+#define TYPE_RECORD_ALIAS(ClassName, LeafEnum)
+#define MEMBER_RECORD(ClassName, LeafEnum) \
+ void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
+ ArrayRef<uint8_t> &FieldData) {}
+#define MEMBER_RECORD_ALIAS(ClassName, LeafEnum)
+#include "TypeRecords.def"
+
+ /// Visits the type records in Data and returns remaining data. Sets the
+ /// error flag on parse failures.
+ void visitTypeStream(ArrayRef<uint8_t> Data) {
+ for (const auto &I : makeTypeRange(Data)) {
+ ArrayRef<uint8_t> LeafData = I.LeafData;
+ ArrayRef<uint8_t> RecordData = LeafData;
+ auto *DerivedThis = static_cast<Derived *>(this);
+ DerivedThis->visitTypeBegin(I.Leaf, RecordData);
+ switch (I.Leaf) {
+ default:
+ DerivedThis->visitUnknownType(I.Leaf);
+ break;
+ case LF_FIELDLIST:
+ DerivedThis->visitFieldList(I.Leaf, LeafData);
+ break;
+ case LF_METHODLIST:
+ DerivedThis->visitMethodList(I.Leaf, LeafData);
+ break;
+#define TYPE_RECORD(ClassName, LeafEnum) \
+ case LeafEnum: { \
+ const ClassName *Rec; \
+ if (!CVTypeVisitor::consumeObject(LeafData, Rec)) \
+ return; \
+ DerivedThis->visit##ClassName(I.Leaf, Rec, LeafData); \
+ break; \
+ }
+#include "TypeRecords.def"
+ }
+ DerivedThis->visitTypeEnd(I.Leaf, RecordData);
+ }
+ }
+
+ /// Action to take on unknown types. By default, they are ignored.
+ void visitUnknownType(TypeLeafKind Leaf) {}
+
+ /// Paired begin/end actions for all types. Receives all record data,
+ /// including the fixed-length record prefix.
+ void visitTypeBegin(TypeLeafKind Leaf, ArrayRef<uint8_t> RecordData) {}
+ void visitTypeEnd(TypeLeafKind Leaf, ArrayRef<uint8_t> RecordData) {}
+
+ static ArrayRef<uint8_t> skipPadding(ArrayRef<uint8_t> Data) {
+ if (Data.empty())
+ return Data;
+ uint8_t Leaf = Data.front();
+ if (Leaf < LF_PAD0)
+ return Data;
+ // Leaf is greater than 0xf0. We should advance by the number of bytes in
+ // the low 4 bits.
+ return Data.drop_front(Leaf & 0x0F);
+ }
+
+ /// Visits individual member records of a field list record. Member records do
+ /// not describe their own length, and need special handling.
+ void visitFieldList(TypeLeafKind Leaf, ArrayRef<uint8_t> FieldData) {
+ while (!FieldData.empty()) {
+ const ulittle16_t *LeafPtr;
+ if (!CVTypeVisitor::consumeObject(FieldData, LeafPtr))
+ return;
+ TypeLeafKind Leaf = TypeLeafKind(unsigned(*LeafPtr));
+ switch (Leaf) {
+ default:
+ // Field list records do not describe their own length, so we cannot
+ // continue parsing past an unknown member type.
+ visitUnknownMember(Leaf);
+ HadError = true;
+ return;
+#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); \
+ break; \
+ }
+#include "TypeRecords.def"
+ }
+ FieldData = skipPadding(FieldData);
+ }
+ }
+
+ /// Action to take on method overload lists, which do not have a common record
+ /// prefix. The LeafData is composed of MethodListEntry objects, each of which
+ /// may have a trailing 32-bit vftable offset.
+ /// FIXME: Hoist this complexity into the visitor.
+ void visitMethodList(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData) {}
+
+ /// Action to take on unknown members. By default, they are ignored. Member
+ /// record parsing cannot recover from an unknown member record, so this
+ /// method is only called at most once per field list record.
+ void visitUnknownMember(TypeLeafKind Leaf) {}
+
+private:
+ /// Whether a type stream parsing error was encountered.
+ bool HadError = false;
+};
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
Added: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def?rev=268535&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def (added)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def Wed May 4 14:39:28 2016
@@ -0,0 +1,75 @@
+
+//===-- CVLeafTypes.def - All CodeView leaf types ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// See LEAF_ENUM_e in cvinfo.h. This should match the constants there.
+//
+//===----------------------------------------------------------------------===//
+
+// If the type is known, then we have a record describing it in TypeRecord.h.
+#ifndef TYPE_RECORD
+#define TYPE_RECORD(ClassName, LeafEnum)
+#endif
+
+#ifndef TYPE_RECORD_ALIAS
+#define TYPE_RECORD_ALIAS(ClassName, LeafEnum) TYPE_RECORD(ClassName, LeafEnum)
+#endif
+
+#ifndef MEMBER_RECORD
+#define MEMBER_RECORD(ClassName, LeafEnum) TYPE_RECORD(ClassName, LeafEnum)
+#endif
+
+#ifndef MEMBER_RECORD_ALIAS
+#define MEMBER_RECORD_ALIAS(ClassName, LeafEnum) MEMBER_RECORD(ClassName, LeafEnum)
+#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(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)
+
+// 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)
+
+// 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)
+
+#undef TYPE_RECORD
+#undef TYPE_RECORD_ALIAS
+#undef MEMBER_RECORD
+#undef MEMBER_RECORD_ALIAS
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h?rev=268535&r1=268534&r2=268535&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h Wed May 4 14:39:28 2016
@@ -49,10 +49,10 @@ public:
struct TypeRecord {
std::size_t Length;
TypeLeafKind Leaf;
- StringRef LeafData;
+ ArrayRef<uint8_t> LeafData;
};
- explicit TypeIterator(const StringRef &SectionData)
+ explicit TypeIterator(const ArrayRef<uint8_t> &SectionData)
: Data(SectionData), AtEnd(false) {
next(); // Prime the pump
}
@@ -99,12 +99,15 @@ private:
return;
}
- const TypeRecordPrefix *Rec;
- if (consumeObject(Data, Rec))
+ // FIXME: Use consumeObject when it deals in ArrayRef<uint8_t>.
+ if (Data.size() < sizeof(TypeRecordPrefix))
return;
+ const auto *Rec = reinterpret_cast<const TypeRecordPrefix *>(Data.data());
+ Data = Data.drop_front(sizeof(TypeRecordPrefix));
+
Current.Length = Rec->Len;
Current.Leaf = static_cast<TypeLeafKind>(uint16_t(Rec->Leaf));
- Current.LeafData = Data.substr(0, Current.Length - 2);
+ Current.LeafData = Data.slice(0, Current.Length - 2);
// The next record starts immediately after this one.
Data = Data.drop_front(Current.LeafData.size());
@@ -116,15 +119,16 @@ private:
return;
}
- StringRef Data;
+ ArrayRef<uint8_t> Data;
TypeRecord Current;
bool AtEnd;
};
-inline iterator_range<TypeIterator> makeTypeRange(StringRef Data) {
+inline iterator_range<TypeIterator> makeTypeRange(ArrayRef<uint8_t> Data) {
return make_range(TypeIterator(Data), TypeIterator());
}
-}
-}
+
+} // end namespace codeview
+} // end namespace llvm
#endif
Modified: llvm/trunk/include/llvm/Support/ScopedPrinter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ScopedPrinter.h?rev=268535&r1=268534&r2=268535&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/ScopedPrinter.h (original)
+++ llvm/trunk/include/llvm/Support/ScopedPrinter.h Wed May 4 14:39:28 2016
@@ -277,6 +277,10 @@ public:
printBinaryImpl(Label, StringRef(), V, false);
}
+ void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value) {
+ printBinaryImpl(Label, StringRef(), Value, true);
+ }
+
void printBinaryBlock(StringRef Label, StringRef Value) {
auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
Value.size());
Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp?rev=268535&r1=268534&r2=268535&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp Wed May 4 14:39:28 2016
@@ -116,5 +116,5 @@ uint32_t TpiStream::NumTypeRecords() con
}
iterator_range<codeview::TypeIterator> TpiStream::types() const {
- return codeview::makeTypeRange(RecordsBuffer.str());
+ return codeview::makeTypeRange(RecordsBuffer.data());
}
Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=268535&r1=268534&r2=268535&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Wed May 4 14:39:28 2016
@@ -23,6 +23,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
@@ -53,21 +54,53 @@ using namespace llvm::Win64EH;
namespace {
-class CVTypeDumper {
+class CVTypeDumper : public CVTypeVisitor<CVTypeDumper> {
public:
CVTypeDumper(ScopedPrinter &W) : W(W) {}
StringRef getTypeName(TypeIndex TI);
void printTypeIndex(StringRef FieldName, TypeIndex TI);
- void dump(StringRef Data);
+ void dump(ArrayRef<uint8_t> Data);
+
+ /// CVTypeVisitor overrides.
+#define TYPE_RECORD(ClassName, LeafEnum) \
+ void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
+ ArrayRef<uint8_t> LeafData);
+#define TYPE_RECORD_ALIAS(ClassName, LeafEnum)
+#define MEMBER_RECORD(ClassName, LeafEnum) \
+ void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
+ ArrayRef<uint8_t> &FieldData);
+#define MEMBER_RECORD_ALIAS(ClassName, LeafEnum)
+#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+
+ /// Method overload lists are a special case.
+ void visitMethodList(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData);
+
+ void visitUnknownMember(TypeLeafKind Leaf);
+
+ void visitTypeBegin(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData);
+ void visitTypeEnd(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData);
private:
- void printCodeViewFieldList(StringRef FieldData);
void printMemberAttributes(MemberAttributes Attrs);
+ /// 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;
+ }
+
ScopedPrinter &W;
+ /// Name of the current type. Only valid before visitTypeEnd.
+ StringRef Name;
+
/// All user defined type records in .debug$T live in here. Type indices
/// greater than 0x1000 are user defined. Subtract 0x1000 from the index to
/// index into this vector.
@@ -1181,7 +1214,8 @@ void COFFDumper::printCodeViewSymbolSect
}
}
-static std::error_code decodeNumerictLeaf(StringRef &Data, APSInt &Num) {
+static std::error_code decodeNumerictLeaf(ArrayRef<uint8_t> &Data,
+ APSInt &Num) {
// Used to avoid overload ambiguity on APInt construtor.
bool FalseVal = false;
if (Data.size() < 2)
@@ -1247,8 +1281,16 @@ static std::error_code decodeNumerictLea
return object_error::parse_failed;
}
+static std::error_code decodeNumerictLeaf(StringRef &Data, APSInt &Num) {
+ ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(Data.data()),
+ Data.size());
+ auto EC = decodeNumerictLeaf(Bytes, Num);
+ Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
+ return EC;
+}
+
/// Decode an unsigned integer numeric leaf value.
-std::error_code decodeUIntLeaf(StringRef &Data, uint64_t &Num) {
+std::error_code decodeUIntLeaf(ArrayRef<uint8_t> &Data, uint64_t &Num) {
APSInt N;
if (std::error_code err = decodeNumerictLeaf(Data, N))
return err;
@@ -1847,12 +1889,6 @@ void COFFDumper::printCodeViewInlineeLin
}
}
-StringRef getLeafDataBytesAsString(StringRef LeafData) {
- StringRef Leading;
- std::tie(Leading, std::ignore) = LeafData.split('\0');
- return Leading;
-}
-
StringRef CVTypeDumper::getTypeName(TypeIndex TI) {
if (TI.isNoType())
return "<no type>";
@@ -1945,7 +1981,6 @@ static StringRef getLeafTypeName(TypeLea
return "UnknownLeaf";
}
-
void COFFDumper::printCodeViewTypeSection(StringRef SectionName,
const SectionRef &Section) {
ListScope D(W, "CodeViewTypes");
@@ -1955,384 +1990,340 @@ void COFFDumper::printCodeViewTypeSectio
error(Section.getContents(Data));
if (opts::CodeViewSubsectionBytes)
W.printBinaryBlock("Data", Data);
- CVTD.dump(Data);
-}
-void CVTypeDumper::dump(StringRef Data) {
uint32_t Magic;
- if (consumeUInt32(Data, Magic))
- return;
- if (Magic != COFF::DEBUG_SECTION_MAGIC)
- return;
-
+ error(consumeUInt32(Data, Magic));
W.printHex("Magic", Magic);
- for (const auto &Record : makeTypeRange(Data)) {
- StringRef LeafData = Record.LeafData;
-
- // Find the name of this leaf type.
- StringRef LeafName = getLeafTypeName(Record.Leaf);
- DictScope S(W, LeafName);
- unsigned NextTypeIndex = 0x1000 + CVUDTNames.size();
- W.printEnum("TypeLeafKind", unsigned(Record.Leaf),
- makeArrayRef(LeafTypeNames));
- W.printHex("TypeIndex", NextTypeIndex);
-
- // Fill this in inside the switch to get something in CVUDTNames.
- StringRef Name;
-
- switch (Record.Leaf) {
- default: {
- W.printHex("Size", Record.Length);
- break;
- }
-
- case LF_STRING_ID: {
- const StringId *String;
- error(consumeObject(LeafData, String));
- W.printHex("Id", String->id.getIndex());
- StringRef StringData = getLeafDataBytesAsString(LeafData);
- W.printString("StringData", StringData);
- // Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE.
- Name = StringData;
- break;
- }
-
- case LF_FIELDLIST: {
- W.printHex("Size", Record.Length);
- // FieldList has no fixed prefix that can be described with a struct. All
- // the bytes must be interpreted as more records.
- printCodeViewFieldList(LeafData);
- break;
- }
-
- case LF_ARGLIST:
- case LF_SUBSTR_LIST: {
- const ArgList *Args;
- error(consumeObject(LeafData, Args));
- W.printNumber("NumArgs", Args->NumArgs);
- ListScope Arguments(W, "Arguments");
- SmallString<256> TypeName("(");
- for (uint32_t ArgI = 0; ArgI != Args->NumArgs; ++ArgI) {
- const TypeIndex *Type;
- error(consumeObject(LeafData, Type));
- printTypeIndex("ArgType", *Type);
- StringRef ArgTypeName = getTypeName(*Type);
- TypeName.append(ArgTypeName);
- if (ArgI + 1 != Args->NumArgs)
- TypeName.append(", ");
- }
- TypeName.push_back(')');
- Name = TypeNames.insert(TypeName).first->getKey();
- break;
- }
-
- case LF_CLASS:
- case LF_STRUCTURE:
- case LF_INTERFACE: {
- const ClassType *Class;
- error(consumeObject(LeafData, Class));
- W.printNumber("MemberCount", Class->MemberCount);
- uint16_t Props = Class->Properties;
- W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
- printTypeIndex("FieldList", Class->FieldList);
- printTypeIndex("DerivedFrom", Class->DerivedFrom);
- printTypeIndex("VShape", Class->VShape);
- uint64_t SizeOf;
- error(decodeUIntLeaf(LeafData, SizeOf));
- W.printNumber("SizeOf", SizeOf);
- StringRef LinkageName;
- std::tie(Name, LinkageName) = LeafData.split('\0');
- W.printString("Name", Name);
- if (Props & uint16_t(ClassOptions::HasUniqueName)) {
- LinkageName = getLeafDataBytesAsString(LinkageName);
- if (LinkageName.empty())
- return error(object_error::parse_failed);
- W.printString("LinkageName", LinkageName);
- }
- break;
- }
-
- case LF_UNION: {
- const UnionType *Union;
- error(consumeObject(LeafData, Union));
- W.printNumber("MemberCount", Union->MemberCount);
- uint16_t Props = Union->Properties;
- W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
- printTypeIndex("FieldList", Union->FieldList);
- uint64_t SizeOf;
- error(decodeUIntLeaf(LeafData, SizeOf));
- W.printNumber("SizeOf", SizeOf);
- StringRef LinkageName;
- std::tie(Name, LinkageName) = LeafData.split('\0');
- W.printString("Name", Name);
- if (Props & uint16_t(ClassOptions::HasUniqueName)) {
- LinkageName = getLeafDataBytesAsString(LinkageName);
- if (LinkageName.empty())
- return error(object_error::parse_failed);
- W.printString("LinkageName", LinkageName);
- }
- break;
- }
-
- case LF_ENUM: {
- const EnumType *Enum;
- error(consumeObject(LeafData, Enum));
- W.printNumber("NumEnumerators", Enum->NumEnumerators);
- W.printFlags("Properties", uint16_t(Enum->Properties),
- makeArrayRef(ClassOptionNames));
- printTypeIndex("UnderlyingType", Enum->UnderlyingType);
- printTypeIndex("FieldListType", Enum->FieldListType);
- Name = LeafData.split('\0').first;
- W.printString("Name", Name);
- break;
- }
-
- case LF_ARRAY: {
- const ArrayType *AT;
- error(consumeObject(LeafData, AT));
- printTypeIndex("ElementType", AT->ElementType);
- printTypeIndex("IndexType", AT->IndexType);
- uint64_t SizeOf;
- error(decodeUIntLeaf(LeafData, SizeOf));
- W.printNumber("SizeOf", SizeOf);
- Name = LeafData.split('\0').first;
- W.printString("Name", Name);
- break;
- }
-
- case LF_VFTABLE: {
- const VFTableType *VFT;
- error(consumeObject(LeafData, VFT));
- printTypeIndex("CompleteClass", VFT->CompleteClass);
- printTypeIndex("OverriddenVFTable", VFT->OverriddenVFTable);
- W.printHex("VFPtrOffset", VFT->VFPtrOffset);
- StringRef NamesData = LeafData.substr(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);
- }
- break;
- }
-
- case LF_MFUNC_ID: {
- const MemberFuncId *Id;
- error(consumeObject(LeafData, Id));
- printTypeIndex("ClassType", Id->ClassType);
- printTypeIndex("FunctionType", Id->FunctionType);
- Name = LeafData.split('\0').first;
- W.printString("Name", Name);
- break;
- }
-
- case LF_PROCEDURE: {
- const ProcedureType *Proc;
- error(consumeObject(LeafData, Proc));
- printTypeIndex("ReturnType", Proc->ReturnType);
- W.printEnum("CallingConvention", uint8_t(Proc->CallConv),
- makeArrayRef(CallingConventions));
- W.printFlags("FunctionOptions", uint8_t(Proc->Options),
- makeArrayRef(FunctionOptionEnum));
- W.printNumber("NumParameters", Proc->NumParameters);
- printTypeIndex("ArgListType", Proc->ArgListType);
-
- StringRef ReturnTypeName = getTypeName(Proc->ReturnType);
- StringRef ArgListTypeName = getTypeName(Proc->ArgListType);
- SmallString<256> TypeName(ReturnTypeName);
- TypeName.push_back(' ');
- TypeName.append(ArgListTypeName);
- Name = TypeNames.insert(TypeName).first->getKey();
- break;
- }
-
- case LF_MFUNCTION: {
- const MemberFunctionType *MemberFunc;
- error(consumeObject(LeafData, MemberFunc));
- printTypeIndex("ReturnType", MemberFunc->ReturnType);
- printTypeIndex("ClassType", MemberFunc->ClassType);
- printTypeIndex("ThisType", MemberFunc->ThisType);
- W.printEnum("CallingConvention", uint8_t(MemberFunc->CallConv),
- makeArrayRef(CallingConventions));
- W.printFlags("FunctionOptions", uint8_t(MemberFunc->Options),
- makeArrayRef(FunctionOptionEnum));
- W.printNumber("NumParameters", MemberFunc->NumParameters);
- printTypeIndex("ArgListType", MemberFunc->ArgListType);
- W.printNumber("ThisAdjustment", MemberFunc->ThisAdjustment);
-
- StringRef ReturnTypeName = getTypeName(MemberFunc->ReturnType);
- StringRef ClassTypeName = getTypeName(MemberFunc->ClassType);
- StringRef ArgListTypeName = getTypeName(MemberFunc->ArgListType);
- SmallString<256> TypeName(ReturnTypeName);
- TypeName.push_back(' ');
- TypeName.append(ClassTypeName);
- TypeName.append("::");
- TypeName.append(ArgListTypeName);
- Name = TypeNames.insert(TypeName).first->getKey();
- break;
- }
+ if (Magic != COFF::DEBUG_SECTION_MAGIC)
+ return error(object_error::parse_failed);
- case LF_METHODLIST: {
- while (!LeafData.empty()) {
- const MethodListEntry *Method;
- error(consumeObject(LeafData, Method));
- ListScope S(W, "Method");
- printMemberAttributes(Method->Attrs);
- printTypeIndex("Type", Method->Type);
- if (Method->isIntroducedVirtual()) {
- const little32_t *VFTOffsetPtr;
- error(consumeObject(LeafData, VFTOffsetPtr));
- W.printHex("VFTableOffset", *VFTOffsetPtr);
- }
- }
- break;
- }
+ ArrayRef<uint8_t> BinaryData(reinterpret_cast<const uint8_t *>(Data.data()),
+ Data.size());
+ CVTD.dump(BinaryData);
+}
- case LF_FUNC_ID: {
- const FuncId *Func;
- error(consumeObject(LeafData, Func));
- printTypeIndex("ParentScope", Func->ParentScope);
- printTypeIndex("FunctionType", Func->FunctionType);
- StringRef Null;
- std::tie(Name, Null) = LeafData.split('\0');
- W.printString("Name", Name);
- break;
- }
+void CVTypeDumper::dump(ArrayRef<uint8_t> Data) {
+ visitTypeStream(Data);
+ if (hadError())
+ error(object_error::parse_failed);
+}
- case LF_TYPESERVER2: {
- const TypeServer2 *TypeServer;
- error(consumeObject(LeafData, TypeServer));
- W.printBinary("Signature", StringRef(TypeServer->Signature, 16));
- W.printNumber("Age", TypeServer->Age);
- Name = LeafData.split('\0').first;
- W.printString("Name", Name);
- break;
- }
+void CVTypeDumper::visitTypeBegin(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData) {
+ // Reset Name to the empty string. If the visitor sets it, we know it.
+ Name = "";
+
+ W.startLine() << getLeafTypeName(Leaf) << " {\n";
+ W.indent();
+ unsigned NextTypeIndex = 0x1000 + CVUDTNames.size();
+ W.printEnum("TypeLeafKind", unsigned(Leaf), makeArrayRef(LeafTypeNames));
+ W.printHex("TypeIndex", NextTypeIndex);
+ W.flush();
+}
- case LF_POINTER: {
- const PointerType *Ptr;
- error(consumeObject(LeafData, Ptr));
- printTypeIndex("PointeeType", Ptr->PointeeType);
- W.printHex("PointerAttributes", Ptr->Attrs);
- W.printEnum("PtrType", unsigned(Ptr->getPtrKind()),
- 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());
-
- if (Ptr->isPointerToMember()) {
- const PointerToMemberTail *PMT;
- error(consumeObject(LeafData, PMT));
- printTypeIndex("ClassType", PMT->ClassType);
- W.printEnum("Representation", PMT->Representation,
- makeArrayRef(PtrMemberRepNames));
-
- StringRef PointeeName = getTypeName(Ptr->PointeeType);
- StringRef ClassName = getTypeName(PMT->ClassType);
- SmallString<256> TypeName(PointeeName);
- TypeName.push_back(' ');
- TypeName.append(ClassName);
- TypeName.append("::*");
- Name = TypeNames.insert(TypeName).first->getKey();
- } else {
- W.printBinaryBlock("TailData", LeafData);
-
- SmallString<256> TypeName;
- if (Ptr->isConst())
- TypeName.append("const ");
- if (Ptr->isVolatile())
- TypeName.append("volatile ");
- if (Ptr->isUnaligned())
- TypeName.append("__unaligned ");
-
- TypeName.append(getTypeName(Ptr->PointeeType));
-
- if (Ptr->getPtrMode() == PointerMode::LValueReference)
- TypeName.append("&");
- else if (Ptr->getPtrMode() == PointerMode::RValueReference)
- TypeName.append("&&");
- else if (Ptr->getPtrMode() == PointerMode::Pointer)
- TypeName.append("*");
+void CVTypeDumper::visitTypeEnd(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData) {
+ // Always record some name for every type, even if Name is empty, since
+ // CVUDTNames is indexed by TypeIndex.
+ CVUDTNames.push_back(Name);
- Name = TypeNames.insert(TypeName).first->getKey();
- }
- break;
- }
+ if (opts::CodeViewSubsectionBytes)
+ W.printBinaryBlock("LeafData", getBytesAsCharacters(LeafData));
- case LF_MODIFIER: {
- const TypeModifier *Mod;
- error(consumeObject(LeafData, Mod));
- printTypeIndex("ModifiedType", Mod->ModifiedType);
- W.printFlags("Modifiers", Mod->Modifiers,
- makeArrayRef(TypeModifierNames));
-
- StringRef ModifiedName = getTypeName(Mod->ModifiedType);
- SmallString<256> TypeName;
- if (Mod->Modifiers & uint16_t(ModifierOptions::Const))
- TypeName.append("const ");
- if (Mod->Modifiers & uint16_t(ModifierOptions::Volatile))
- TypeName.append("volatile ");
- if (Mod->Modifiers & uint16_t(ModifierOptions::Unaligned))
- TypeName.append("__unaligned ");
- TypeName.append(ModifiedName);
- Name = TypeNames.insert(TypeName).first->getKey();
- break;
- }
+ W.unindent();
+ W.startLine() << "}\n";
+ W.flush();
+}
- case LF_VTSHAPE: {
- const VTableShape *Shape;
- error(consumeObject(LeafData, Shape));
- 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.
- break;
- }
+void CVTypeDumper::visitStringId(TypeLeafKind Leaf, const StringId *String,
+ ArrayRef<uint8_t> LeafData) {
+ W.printHex("Id", String->id.getIndex());
+ StringRef StringData = getBytesAsCString(LeafData);
+ W.printString("StringData", StringData);
+ // Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE.
+ Name = StringData;
+}
+
+void CVTypeDumper::visitArgList(TypeLeafKind Leaf, const ArgList *Args,
+ ArrayRef<uint8_t> LeafData) {
+ W.printNumber("NumArgs", Args->NumArgs);
+ 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);
+ TypeName.append(ArgTypeName);
+ if (ArgI + 1 != Args->NumArgs)
+ TypeName.append(", ");
+ }
+ TypeName.push_back(')');
+ Name = TypeNames.insert(TypeName).first->getKey();
+}
+
+void CVTypeDumper::visitClassType(TypeLeafKind Leaf, const ClassType *Class,
+ ArrayRef<uint8_t> LeafData) {
+ W.printNumber("MemberCount", Class->MemberCount);
+ uint16_t Props = Class->Properties;
+ W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
+ printTypeIndex("FieldList", Class->FieldList);
+ printTypeIndex("DerivedFrom", Class->DerivedFrom);
+ printTypeIndex("VShape", Class->VShape);
+ uint64_t SizeOf;
+ error(decodeUIntLeaf(LeafData, SizeOf));
+ 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 error(object_error::parse_failed);
+ W.printString("LinkageName", LinkageName);
+ }
+}
- case LF_UDT_SRC_LINE: {
- const UDTSrcLine *Line;
- error(consumeObject(LeafData, Line));
- printTypeIndex("UDT", Line->UDT);
- printTypeIndex("SourceFile", Line->SourceFile);
- W.printNumber("LineNumber", Line->LineNumber);
- break;
- }
+void CVTypeDumper::visitUnionType(TypeLeafKind Leaf, const UnionType *Union,
+ ArrayRef<uint8_t> LeafData) {
+ W.printNumber("MemberCount", Union->MemberCount);
+ uint16_t Props = Union->Properties;
+ W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
+ printTypeIndex("FieldList", Union->FieldList);
+ uint64_t SizeOf;
+ error(decodeUIntLeaf(LeafData, SizeOf));
+ 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 error(object_error::parse_failed);
+ W.printString("LinkageName", LinkageName);
+ }
+}
- case LF_BUILDINFO: {
- const BuildInfo *Args;
- error(consumeObject(LeafData, Args));
- W.printNumber("NumArgs", Args->NumArgs);
-
- ListScope Arguments(W, "Arguments");
- for (uint32_t ArgI = 0; ArgI != Args->NumArgs; ++ArgI) {
- const TypeIndex *Type;
- error(consumeObject(LeafData, Type));
- printTypeIndex("ArgType", *Type);
- }
- break;
- }
+void CVTypeDumper::visitEnumType(TypeLeafKind Leaf, const EnumType *Enum,
+ ArrayRef<uint8_t> LeafData) {
+ W.printNumber("NumEnumerators", Enum->NumEnumerators);
+ W.printFlags("Properties", uint16_t(Enum->Properties),
+ makeArrayRef(ClassOptionNames));
+ printTypeIndex("UnderlyingType", Enum->UnderlyingType);
+ printTypeIndex("FieldListType", Enum->FieldListType);
+ Name = getBytesAsCString(LeafData);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumper::visitArrayType(TypeLeafKind Leaf, const ArrayType *AT,
+ ArrayRef<uint8_t> LeafData) {
+ printTypeIndex("ElementType", AT->ElementType);
+ printTypeIndex("IndexType", AT->IndexType);
+ uint64_t SizeOf;
+ error(decodeUIntLeaf(LeafData, SizeOf));
+ W.printNumber("SizeOf", SizeOf);
+ Name = getBytesAsCString(LeafData);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumper::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 CVTypeDumper::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 CVTypeDumper::visitProcedureType(TypeLeafKind Leaf,
+ const ProcedureType *Proc,
+ ArrayRef<uint8_t> LeafData) {
+ printTypeIndex("ReturnType", Proc->ReturnType);
+ W.printEnum("CallingConvention", uint8_t(Proc->CallConv),
+ makeArrayRef(CallingConventions));
+ W.printFlags("FunctionOptions", uint8_t(Proc->Options),
+ makeArrayRef(FunctionOptionEnum));
+ W.printNumber("NumParameters", Proc->NumParameters);
+ printTypeIndex("ArgListType", Proc->ArgListType);
+
+ StringRef ReturnTypeName = getTypeName(Proc->ReturnType);
+ StringRef ArgListTypeName = getTypeName(Proc->ArgListType);
+ SmallString<256> TypeName(ReturnTypeName);
+ TypeName.push_back(' ');
+ TypeName.append(ArgListTypeName);
+ Name = TypeNames.insert(TypeName).first->getKey();
+}
+
+void CVTypeDumper::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),
+ makeArrayRef(CallingConventions));
+ W.printFlags("FunctionOptions", uint8_t(MemberFunc->Options),
+ makeArrayRef(FunctionOptionEnum));
+ W.printNumber("NumParameters", MemberFunc->NumParameters);
+ printTypeIndex("ArgListType", MemberFunc->ArgListType);
+ W.printNumber("ThisAdjustment", MemberFunc->ThisAdjustment);
+
+ StringRef ReturnTypeName = getTypeName(MemberFunc->ReturnType);
+ StringRef ClassTypeName = getTypeName(MemberFunc->ClassType);
+ StringRef ArgListTypeName = getTypeName(MemberFunc->ArgListType);
+ SmallString<256> TypeName(ReturnTypeName);
+ TypeName.push_back(' ');
+ TypeName.append(ClassTypeName);
+ TypeName.append("::");
+ TypeName.append(ArgListTypeName);
+ Name = TypeNames.insert(TypeName).first->getKey();
+}
+
+void CVTypeDumper::visitMethodList(TypeLeafKind Leaf,
+ ArrayRef<uint8_t> LeafData) {
+ while (!LeafData.empty()) {
+ const MethodListEntry *Method;
+ if (!consumeObject(LeafData, Method))
+ return;
+ 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);
}
-
- if (opts::CodeViewSubsectionBytes)
- W.printBinaryBlock("LeafData", LeafData);
-
- CVUDTNames.push_back(Name);
}
}
-static StringRef skipPadding(StringRef Data) {
- if (Data.empty())
- return Data;
- uint8_t Leaf = Data.front();
- if (Leaf < LF_PAD0)
- return Data;
- // Leaf is greater than 0xf0. We should advance by the number of bytes in the
- // low 4 bits.
- return Data.drop_front(Leaf & 0x0F);
+void CVTypeDumper::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 CVTypeDumper::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 CVTypeDumper::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()),
+ 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());
+
+ if (Ptr->isPointerToMember()) {
+ const PointerToMemberTail *PMT;
+ if (!consumeObject(LeafData, PMT))
+ return;
+ printTypeIndex("ClassType", PMT->ClassType);
+ W.printEnum("Representation", PMT->Representation,
+ makeArrayRef(PtrMemberRepNames));
+
+ StringRef PointeeName = getTypeName(Ptr->PointeeType);
+ StringRef ClassName = getTypeName(PMT->ClassType);
+ SmallString<256> TypeName(PointeeName);
+ TypeName.push_back(' ');
+ TypeName.append(ClassName);
+ TypeName.append("::*");
+ Name = TypeNames.insert(TypeName).first->getKey();
+ } else {
+ W.printBinaryBlock("TailData", getBytesAsCharacters(LeafData));
+
+ SmallString<256> TypeName;
+ if (Ptr->isConst())
+ TypeName.append("const ");
+ if (Ptr->isVolatile())
+ TypeName.append("volatile ");
+ if (Ptr->isUnaligned())
+ TypeName.append("__unaligned ");
+
+ TypeName.append(getTypeName(Ptr->PointeeType));
+
+ if (Ptr->getPtrMode() == PointerMode::LValueReference)
+ TypeName.append("&");
+ else if (Ptr->getPtrMode() == PointerMode::RValueReference)
+ TypeName.append("&&");
+ else if (Ptr->getPtrMode() == PointerMode::Pointer)
+ TypeName.append("*");
+
+ Name = TypeNames.insert(TypeName).first->getKey();
+ }
+}
+
+void CVTypeDumper::visitTypeModifier(TypeLeafKind Leaf, const TypeModifier *Mod,
+ ArrayRef<uint8_t> LeafData) {
+ printTypeIndex("ModifiedType", Mod->ModifiedType);
+ W.printFlags("Modifiers", Mod->Modifiers, makeArrayRef(TypeModifierNames));
+
+ StringRef ModifiedName = getTypeName(Mod->ModifiedType);
+ SmallString<256> TypeName;
+ if (Mod->Modifiers & uint16_t(ModifierOptions::Const))
+ TypeName.append("const ");
+ if (Mod->Modifiers & uint16_t(ModifierOptions::Volatile))
+ TypeName.append("volatile ");
+ if (Mod->Modifiers & uint16_t(ModifierOptions::Unaligned))
+ TypeName.append("__unaligned ");
+ TypeName.append(ModifiedName);
+ Name = TypeNames.insert(TypeName).first->getKey();
+}
+
+void CVTypeDumper::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 CVTypeDumper::visitUDTSrcLine(TypeLeafKind Leaf, const UDTSrcLine *Line,
+ ArrayRef<uint8_t> LeafData) {
+ printTypeIndex("UDT", Line->UDT);
+ printTypeIndex("SourceFile", Line->SourceFile);
+ W.printNumber("LineNumber", Line->LineNumber);
+}
+
+void CVTypeDumper::visitBuildInfo(TypeLeafKind Leaf, const BuildInfo *Args,
+ ArrayRef<uint8_t> LeafData) {
+ W.printNumber("NumArgs", Args->NumArgs);
+
+ ListScope Arguments(W, "Arguments");
+ for (uint32_t ArgI = 0; ArgI != Args->NumArgs; ++ArgI) {
+ const TypeIndex *Type;
+ if (!consumeObject(LeafData, Type))
+ return;
+ printTypeIndex("ArgType", *Type);
+ }
}
void CVTypeDumper::printMemberAttributes(MemberAttributes Attrs) {
@@ -2348,140 +2339,112 @@ void CVTypeDumper::printMemberAttributes
}
}
-void CVTypeDumper::printCodeViewFieldList(StringRef FieldData) {
- while (!FieldData.empty()) {
- const ulittle16_t *LeafPtr;
- error(consumeObject(FieldData, LeafPtr));
- uint16_t Leaf = *LeafPtr;
- switch (Leaf) {
- default:
- W.printHex("UnknownMember", Leaf);
- // We can't advance once we hit an unknown field. The size is not encoded.
- return;
-
- case LF_NESTTYPE: {
- const NestedType *Nested;
- error(consumeObject(FieldData, Nested));
- DictScope S(W, "NestedType");
- printTypeIndex("Type", Nested->Type);
- StringRef Name;
- std::tie(Name, FieldData) = FieldData.split('\0');
- W.printString("Name", Name);
- break;
- }
-
- case LF_ONEMETHOD: {
- const OneMethod *Method;
- error(consumeObject(FieldData, Method));
- DictScope S(W, "OneMethod");
- printMemberAttributes(Method->Attrs);
- printTypeIndex("Type", Method->Type);
- // If virtual, then read the vftable offset.
- if (Method->isIntroducedVirtual()) {
- const little32_t *VFTOffsetPtr;
- error(consumeObject(FieldData, VFTOffsetPtr));
- W.printHex("VFTableOffset", *VFTOffsetPtr);
- }
- StringRef Name;
- std::tie(Name, FieldData) = FieldData.split('\0');
- W.printString("Name", Name);
- break;
- }
-
- case LF_METHOD: {
- const OverloadedMethod *Method;
- error(consumeObject(FieldData, Method));
- DictScope S(W, "OverloadedMethod");
- W.printHex("MethodCount", Method->MethodCount);
- W.printHex("MethodListIndex", Method->MethList.getIndex());
- StringRef Name;
- std::tie(Name, FieldData) = FieldData.split('\0');
- W.printString("Name", Name);
- break;
- }
-
- case LF_MEMBER: {
- const DataMember *Field;
- error(consumeObject(FieldData, Field));
- DictScope S(W, "DataMember");
- printMemberAttributes(Field->Attrs);
- printTypeIndex("Type", Field->Type);
- uint64_t FieldOffset;
- error(decodeUIntLeaf(FieldData, FieldOffset));
- W.printHex("FieldOffset", FieldOffset);
- StringRef Name;
- std::tie(Name, FieldData) = FieldData.split('\0');
- W.printString("Name", Name);
- break;
- }
-
- case LF_STMEMBER: {
- const StaticDataMember *Field;
- error(consumeObject(FieldData, Field));
- DictScope S(W, "StaticDataMember");
- printMemberAttributes(Field->Attrs);
- printTypeIndex("Type", Field->Type);
- StringRef Name;
- std::tie(Name, FieldData) = FieldData.split('\0');
- W.printString("Name", Name);
- break;
- }
-
- case LF_VFUNCTAB: {
- const VirtualFunctionPointer *VFTable;
- error(consumeObject(FieldData, VFTable));
- DictScope S(W, "VirtualFunctionPointer");
- printTypeIndex("Type", VFTable->Type);
- break;
- }
-
- case LF_ENUMERATE: {
- const Enumerator *Enum;
- error(consumeObject(FieldData, Enum));
- DictScope S(W, "Enumerator");
- printMemberAttributes(Enum->Attrs);
- APSInt EnumValue;
- error(decodeNumerictLeaf(FieldData, EnumValue));
- W.printNumber("EnumValue", EnumValue);
- StringRef Name;
- std::tie(Name, FieldData) = FieldData.split('\0');
- W.printString("Name", Name);
- break;
- }
-
- case LF_BCLASS:
- case LF_BINTERFACE: {
- const BaseClass *Base;
- error(consumeObject(FieldData, Base));
- DictScope S(W, "BaseClass");
- printMemberAttributes(Base->Attrs);
- printTypeIndex("BaseType", Base->BaseType);
- uint64_t BaseOffset;
- error(decodeUIntLeaf(FieldData, BaseOffset));
- W.printHex("BaseOffset", BaseOffset);
- break;
- }
-
- case LF_VBCLASS:
- case LF_IVBCLASS: {
- const VirtualBaseClass *Base;
- error(consumeObject(FieldData, Base));
- DictScope S(W, "VirtualBaseClass");
- printMemberAttributes(Base->Attrs);
- printTypeIndex("BaseType", Base->BaseType);
- printTypeIndex("VBPtrType", Base->VBPtrType);
- uint64_t VBPtrOffset, VBTableIndex;
- error(decodeUIntLeaf(FieldData, VBPtrOffset));
- error(decodeUIntLeaf(FieldData, VBTableIndex));
- W.printHex("VBPtrOffset", VBPtrOffset);
- W.printHex("VBTableIndex", VBTableIndex);
- break;
- }
- }
+void CVTypeDumper::visitUnknownMember(TypeLeafKind Leaf) {
+ W.printHex("UnknownMember", unsigned(Leaf));
+}
- // Handle padding.
- FieldData = skipPadding(FieldData);
+void CVTypeDumper::visitNestedType(TypeLeafKind Leaf, const NestedType *Nested,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "NestedType");
+ printTypeIndex("Type", Nested->Type);
+ StringRef Name = getBytesAsCString(FieldData);
+ FieldData = FieldData.drop_front(Name.size() + 1);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumper::visitOneMethod(TypeLeafKind Leaf, const OneMethod *Method,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "OneMethod");
+ printMemberAttributes(Method->Attrs);
+ printTypeIndex("Type", Method->Type);
+ // 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);
+}
+
+void CVTypeDumper::visitOverloadedMethod(TypeLeafKind Leaf,
+ const OverloadedMethod *Method,
+ ArrayRef<uint8_t> &FieldData) {
+ 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);
+}
+
+void CVTypeDumper::visitDataMember(TypeLeafKind Leaf, const DataMember *Field,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "DataMember");
+ printMemberAttributes(Field->Attrs);
+ printTypeIndex("Type", Field->Type);
+ uint64_t FieldOffset;
+ error(decodeUIntLeaf(FieldData, FieldOffset));
+ W.printHex("FieldOffset", FieldOffset);
+ StringRef Name = getBytesAsCString(FieldData);
+ FieldData = FieldData.drop_front(Name.size() + 1);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumper::visitStaticDataMember(TypeLeafKind Leaf,
+ const StaticDataMember *Field,
+ ArrayRef<uint8_t> &FieldData) {
+ 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);
+}
+
+void CVTypeDumper::visitVirtualFunctionPointer(
+ TypeLeafKind Leaf, const VirtualFunctionPointer *VFTable,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "VirtualFunctionPointer");
+ printTypeIndex("Type", VFTable->Type);
+}
+
+void CVTypeDumper::visitEnumerator(TypeLeafKind Leaf, const Enumerator *Enum,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "Enumerator");
+ printMemberAttributes(Enum->Attrs);
+ APSInt EnumValue;
+ error(decodeNumerictLeaf(FieldData, EnumValue));
+ W.printNumber("EnumValue", EnumValue);
+ StringRef Name = getBytesAsCString(FieldData);
+ FieldData = FieldData.drop_front(Name.size() + 1);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumper::visitBaseClass(TypeLeafKind Leaf, const BaseClass *Base,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "BaseClass");
+ printMemberAttributes(Base->Attrs);
+ printTypeIndex("BaseType", Base->BaseType);
+ uint64_t BaseOffset;
+ error(decodeUIntLeaf(FieldData, BaseOffset));
+ W.printHex("BaseOffset", BaseOffset);
+}
+
+void CVTypeDumper::visitVirtualBaseClass(TypeLeafKind Leaf,
+ const VirtualBaseClass *Base,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "VirtualBaseClass");
+ printMemberAttributes(Base->Attrs);
+ printTypeIndex("BaseType", Base->BaseType);
+ printTypeIndex("VBPtrType", Base->VBPtrType);
+ uint64_t VBPtrOffset, VBTableIndex;
+ error(decodeUIntLeaf(FieldData, VBPtrOffset));
+ error(decodeUIntLeaf(FieldData, VBTableIndex));
+ W.printHex("VBPtrOffset", VBPtrOffset);
+ W.printHex("VBTableIndex", VBTableIndex);
}
void COFFDumper::printSections() {
More information about the llvm-commits
mailing list