diff options
author | Zachary Turner <zturner@google.com> | 2017-01-11 23:24:22 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2017-01-11 23:24:22 +0000 |
commit | 629cb7d8cc333c26f3b3b6b373c98221fcf54b28 (patch) | |
tree | a9bdc827c75b0e1bab2e3e590f51e6d9e655526e /llvm/lib/DebugInfo/CodeView | |
parent | 7e35ee4b8b06e9fc695b46d39e8a7597abd44859 (diff) | |
download | bcm5719-llvm-629cb7d8cc333c26f3b3b6b373c98221fcf54b28.tar.gz bcm5719-llvm-629cb7d8cc333c26f3b3b6b373c98221fcf54b28.zip |
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
Diffstat (limited to 'llvm/lib/DebugInfo/CodeView')
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp | 538 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp | 39 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp | 532 |
4 files changed, 571 insertions, 539 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt index 32a73fc6742..f9bff86b41c 100644 --- a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt @@ -13,6 +13,7 @@ add_llvm_library(LLVMDebugInfoCodeView SymbolDumper.cpp TypeDatabase.cpp TypeDatabaseVisitor.cpp + TypeDumpVisitor.cpp TypeRecord.cpp TypeRecordMapping.cpp TypeSerializer.cpp diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp index a652d3b983a..fcd239cce0d 100644 --- a/llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp +++ b/llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp @@ -8,536 +8,24 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/CVTypeDumper.h" -#include "llvm/ADT/SmallString.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/TypeDatabase.h" #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" -#include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" #include "llvm/DebugInfo/MSF/ByteStream.h" -#include "llvm/Support/ScopedPrinter.h" using namespace llvm; using namespace llvm::codeview; -static const EnumEntry<TypeLeafKind> LeafTypeNames[] = { -#define CV_TYPE(enum, val) {#enum, enum}, -#include "llvm/DebugInfo/CodeView/TypeRecords.def" -}; - -#define ENUM_ENTRY(enum_class, enum) \ - { #enum, std::underlying_type < enum_class > ::type(enum_class::enum) } - -static const EnumEntry<uint16_t> ClassOptionNames[] = { - ENUM_ENTRY(ClassOptions, Packed), - ENUM_ENTRY(ClassOptions, HasConstructorOrDestructor), - ENUM_ENTRY(ClassOptions, HasOverloadedOperator), - ENUM_ENTRY(ClassOptions, Nested), - ENUM_ENTRY(ClassOptions, ContainsNestedClass), - ENUM_ENTRY(ClassOptions, HasOverloadedAssignmentOperator), - ENUM_ENTRY(ClassOptions, HasConversionOperator), - ENUM_ENTRY(ClassOptions, ForwardReference), - ENUM_ENTRY(ClassOptions, Scoped), - ENUM_ENTRY(ClassOptions, HasUniqueName), - ENUM_ENTRY(ClassOptions, Sealed), - ENUM_ENTRY(ClassOptions, Intrinsic), -}; - -static const EnumEntry<uint8_t> MemberAccessNames[] = { - ENUM_ENTRY(MemberAccess, None), ENUM_ENTRY(MemberAccess, Private), - ENUM_ENTRY(MemberAccess, Protected), ENUM_ENTRY(MemberAccess, Public), -}; - -static const EnumEntry<uint16_t> MethodOptionNames[] = { - ENUM_ENTRY(MethodOptions, Pseudo), - ENUM_ENTRY(MethodOptions, NoInherit), - ENUM_ENTRY(MethodOptions, NoConstruct), - ENUM_ENTRY(MethodOptions, CompilerGenerated), - ENUM_ENTRY(MethodOptions, Sealed), -}; - -static const EnumEntry<uint16_t> MemberKindNames[] = { - ENUM_ENTRY(MethodKind, Vanilla), - ENUM_ENTRY(MethodKind, Virtual), - ENUM_ENTRY(MethodKind, Static), - ENUM_ENTRY(MethodKind, Friend), - ENUM_ENTRY(MethodKind, IntroducingVirtual), - ENUM_ENTRY(MethodKind, PureVirtual), - ENUM_ENTRY(MethodKind, PureIntroducingVirtual), -}; - -static const EnumEntry<uint8_t> PtrKindNames[] = { - ENUM_ENTRY(PointerKind, Near16), - ENUM_ENTRY(PointerKind, Far16), - ENUM_ENTRY(PointerKind, Huge16), - ENUM_ENTRY(PointerKind, BasedOnSegment), - ENUM_ENTRY(PointerKind, BasedOnValue), - ENUM_ENTRY(PointerKind, BasedOnSegmentValue), - ENUM_ENTRY(PointerKind, BasedOnAddress), - ENUM_ENTRY(PointerKind, BasedOnSegmentAddress), - ENUM_ENTRY(PointerKind, BasedOnType), - ENUM_ENTRY(PointerKind, BasedOnSelf), - ENUM_ENTRY(PointerKind, Near32), - ENUM_ENTRY(PointerKind, Far32), - ENUM_ENTRY(PointerKind, Near64), -}; - -static const EnumEntry<uint8_t> PtrModeNames[] = { - ENUM_ENTRY(PointerMode, Pointer), - ENUM_ENTRY(PointerMode, LValueReference), - ENUM_ENTRY(PointerMode, PointerToDataMember), - ENUM_ENTRY(PointerMode, PointerToMemberFunction), - ENUM_ENTRY(PointerMode, RValueReference), -}; - -static const EnumEntry<uint16_t> PtrMemberRepNames[] = { - ENUM_ENTRY(PointerToMemberRepresentation, Unknown), - ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceData), - ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceData), - ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceData), - ENUM_ENTRY(PointerToMemberRepresentation, GeneralData), - ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceFunction), - ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceFunction), - ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceFunction), - ENUM_ENTRY(PointerToMemberRepresentation, GeneralFunction), -}; - -static const EnumEntry<uint16_t> TypeModifierNames[] = { - ENUM_ENTRY(ModifierOptions, Const), ENUM_ENTRY(ModifierOptions, Volatile), - ENUM_ENTRY(ModifierOptions, Unaligned), -}; - -static const EnumEntry<uint8_t> CallingConventions[] = { - ENUM_ENTRY(CallingConvention, NearC), - ENUM_ENTRY(CallingConvention, FarC), - ENUM_ENTRY(CallingConvention, NearPascal), - ENUM_ENTRY(CallingConvention, FarPascal), - ENUM_ENTRY(CallingConvention, NearFast), - ENUM_ENTRY(CallingConvention, FarFast), - ENUM_ENTRY(CallingConvention, NearStdCall), - ENUM_ENTRY(CallingConvention, FarStdCall), - ENUM_ENTRY(CallingConvention, NearSysCall), - ENUM_ENTRY(CallingConvention, FarSysCall), - ENUM_ENTRY(CallingConvention, ThisCall), - ENUM_ENTRY(CallingConvention, MipsCall), - ENUM_ENTRY(CallingConvention, Generic), - ENUM_ENTRY(CallingConvention, AlphaCall), - ENUM_ENTRY(CallingConvention, PpcCall), - ENUM_ENTRY(CallingConvention, SHCall), - ENUM_ENTRY(CallingConvention, ArmCall), - ENUM_ENTRY(CallingConvention, AM33Call), - ENUM_ENTRY(CallingConvention, TriCall), - ENUM_ENTRY(CallingConvention, SH5Call), - ENUM_ENTRY(CallingConvention, M32RCall), - ENUM_ENTRY(CallingConvention, ClrCall), - ENUM_ENTRY(CallingConvention, Inline), - ENUM_ENTRY(CallingConvention, NearVector), -}; - -static const EnumEntry<uint8_t> FunctionOptionEnum[] = { - ENUM_ENTRY(FunctionOptions, CxxReturnUdt), - ENUM_ENTRY(FunctionOptions, Constructor), - ENUM_ENTRY(FunctionOptions, ConstructorWithVirtualBases), -}; - -#undef ENUM_ENTRY - -static StringRef getLeafTypeName(TypeLeafKind LT) { - switch (LT) { -#define TYPE_RECORD(ename, value, name) \ - case ename: \ - return #name; -#include "llvm/DebugInfo/CodeView/TypeRecords.def" - default: - break; - } - return "UnknownLeaf"; -} - -Error CVTypeDumper::visitTypeBegin(CVType &Record) { - W->startLine() << getLeafTypeName(Record.Type); - W->getOStream() << " (" << HexNumber(TypeDB.getNextTypeIndex().getIndex()) - << ")"; - W->getOStream() << " {\n"; - W->indent(); - W->printEnum("TypeLeafKind", unsigned(Record.Type), - makeArrayRef(LeafTypeNames)); - return Error::success(); -} - -Error CVTypeDumper::visitTypeEnd(CVType &Record) { - if (PrintRecordBytes) - W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.content())); - - W->unindent(); - W->startLine() << "}\n"; - return Error::success(); -} - -Error CVTypeDumper::visitMemberBegin(CVMemberRecord &Record) { - W->startLine() << getLeafTypeName(Record.Kind); - W->getOStream() << " {\n"; - W->indent(); - W->printEnum("TypeLeafKind", unsigned(Record.Kind), - makeArrayRef(LeafTypeNames)); - return Error::success(); -} - -Error CVTypeDumper::visitMemberEnd(CVMemberRecord &Record) { - if (PrintRecordBytes) - W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data)); - - W->unindent(); - W->startLine() << "}\n"; - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, FieldListRecord &FieldList) { - CVTypeVisitor Visitor(*this); - if (auto EC = Visitor.visitFieldListMemberStream(FieldList.Data)) - return EC; - - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, StringIdRecord &String) { - printTypeIndex("Id", String.getId()); - W->printString("StringData", String.getString()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, ArgListRecord &Args) { - auto Indices = Args.getIndices(); - uint32_t Size = Indices.size(); - W->printNumber("NumArgs", Size); - ListScope Arguments(*W, "Arguments"); - for (uint32_t I = 0; I < Size; ++I) { - printTypeIndex("ArgType", Indices[I]); - } - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, 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.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()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, 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.getFieldList()); - W->printNumber("SizeOf", Union.getSize()); - W->printString("Name", Union.getName()); - if (Props & uint16_t(ClassOptions::HasUniqueName)) - W->printString("LinkageName", Union.getUniqueName()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, EnumRecord &Enum) { - uint16_t Props = static_cast<uint16_t>(Enum.getOptions()); - W->printNumber("NumEnumerators", Enum.getMemberCount()); - W->printFlags("Properties", uint16_t(Enum.getOptions()), - makeArrayRef(ClassOptionNames)); - printTypeIndex("UnderlyingType", Enum.getUnderlyingType()); - printTypeIndex("FieldListType", Enum.getFieldList()); - W->printString("Name", Enum.getName()); - if (Props & uint16_t(ClassOptions::HasUniqueName)) - W->printString("LinkageName", Enum.getUniqueName()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, ArrayRecord &AT) { - printTypeIndex("ElementType", AT.getElementType()); - printTypeIndex("IndexType", AT.getIndexType()); - W->printNumber("SizeOf", AT.getSize()); - W->printString("Name", AT.getName()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, VFTableRecord &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); - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) { - printTypeIndex("ClassType", Id.getClassType()); - printTypeIndex("FunctionType", Id.getFunctionType()); - W->printString("Name", Id.getName()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) { - printTypeIndex("ReturnType", Proc.getReturnType()); - W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()), - makeArrayRef(CallingConventions)); - W->printFlags("FunctionOptions", uint8_t(Proc.getOptions()), - makeArrayRef(FunctionOptionEnum)); - W->printNumber("NumParameters", Proc.getParameterCount()); - printTypeIndex("ArgListType", Proc.getArgumentList()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, 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(MF.getOptions()), - makeArrayRef(FunctionOptionEnum)); - W->printNumber("NumParameters", MF.getParameterCount()); - printTypeIndex("ArgListType", MF.getArgumentList()); - W->printNumber("ThisAdjustment", MF.getThisPointerAdjustment()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, - MethodOverloadListRecord &MethodList) { - for (auto &M : MethodList.getMethods()) { - ListScope S(*W, "Method"); - printMemberAttributes(M.getAccess(), M.getMethodKind(), M.getOptions()); - printTypeIndex("Type", M.getType()); - if (M.isIntroducingVirtual()) - W->printHex("VFTableOffset", M.getVFTableOffset()); - } - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) { - printTypeIndex("ParentScope", Func.getParentScope()); - printTypeIndex("FunctionType", Func.getFunctionType()); - W->printString("Name", Func.getName()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) { - W->printBinary("Signature", TS.getGuid()); - W->printNumber("Age", TS.getAge()); - W->printString("Name", TS.getName()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, 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.getMode()), makeArrayRef(PtrModeNames)); - - W->printNumber("IsFlat", Ptr.isFlat()); - W->printNumber("IsConst", Ptr.isConst()); - W->printNumber("IsVolatile", Ptr.isVolatile()); - W->printNumber("IsUnaligned", Ptr.isUnaligned()); - W->printNumber("SizeOf", Ptr.getSize()); - - if (Ptr.isPointerToMember()) { - const MemberPointerInfo &MI = Ptr.getMemberInfo(); - - printTypeIndex("ClassType", MI.getContainingType()); - W->printEnum("Representation", uint16_t(MI.getRepresentation()), - makeArrayRef(PtrMemberRepNames)); - } - - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) { - uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers()); - printTypeIndex("ModifiedType", Mod.getModifiedType()); - W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames)); - - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, BitFieldRecord &BitField) { - printTypeIndex("Type", BitField.getType()); - W->printNumber("BitSize", BitField.getBitSize()); - W->printNumber("BitOffset", BitField.getBitOffset()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, VFTableShapeRecord &Shape) { - W->printNumber("VFEntryCount", Shape.getEntryCount()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, UdtSourceLineRecord &Line) { - printTypeIndex("UDT", Line.getUDT()); - printTypeIndex("SourceFile", Line.getSourceFile()); - W->printNumber("LineNumber", Line.getLineNumber()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, - UdtModSourceLineRecord &Line) { - printTypeIndex("UDT", Line.getUDT()); - printTypeIndex("SourceFile", Line.getSourceFile()); - W->printNumber("LineNumber", Line.getLineNumber()); - W->printNumber("Module", Line.getModule()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownRecord(CVType &CVR, BuildInfoRecord &Args) { - W->printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size())); - - ListScope Arguments(*W, "Arguments"); - for (auto Arg : Args.getArgs()) { - printTypeIndex("ArgType", Arg); - } - return Error::success(); -} - -void CVTypeDumper::printMemberAttributes(MemberAttributes Attrs) { - return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(), - Attrs.getFlags()); -} - -void CVTypeDumper::printMemberAttributes(MemberAccess Access, MethodKind Kind, - MethodOptions Options) { - W->printEnum("AccessSpecifier", uint8_t(Access), - makeArrayRef(MemberAccessNames)); - // Data members will be vanilla. Don't try to print a method kind for them. - if (Kind != MethodKind::Vanilla) - W->printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames)); - if (Options != MethodOptions::None) { - W->printFlags("MethodOptions", unsigned(Options), - makeArrayRef(MethodOptionNames)); - } -} - -Error CVTypeDumper::visitUnknownMember(CVMemberRecord &Record) { - W->printHex("UnknownMember", unsigned(Record.Kind)); - return Error::success(); -} - -Error CVTypeDumper::visitUnknownType(CVType &Record) { - W->printEnum("Kind", uint16_t(Record.kind()), makeArrayRef(LeafTypeNames)); - W->printNumber("Length", uint32_t(Record.content().size())); - return Error::success(); -} - -Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR, - NestedTypeRecord &Nested) { - printTypeIndex("Type", Nested.getNestedType()); - W->printString("Name", Nested.getName()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR, - OneMethodRecord &Method) { - MethodKind K = Method.getMethodKind(); - printMemberAttributes(Method.getAccess(), K, Method.getOptions()); - printTypeIndex("Type", Method.getType()); - // If virtual, then read the vftable offset. - if (Method.isIntroducingVirtual()) - W->printHex("VFTableOffset", Method.getVFTableOffset()); - W->printString("Name", Method.getName()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR, - OverloadedMethodRecord &Method) { - W->printHex("MethodCount", Method.getNumOverloads()); - printTypeIndex("MethodListIndex", Method.getMethodList()); - W->printString("Name", Method.getName()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR, - DataMemberRecord &Field) { - printMemberAttributes(Field.getAccess(), MethodKind::Vanilla, - MethodOptions::None); - printTypeIndex("Type", Field.getType()); - W->printHex("FieldOffset", Field.getFieldOffset()); - W->printString("Name", Field.getName()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR, - StaticDataMemberRecord &Field) { - printMemberAttributes(Field.getAccess(), MethodKind::Vanilla, - MethodOptions::None); - printTypeIndex("Type", Field.getType()); - W->printString("Name", Field.getName()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR, - VFPtrRecord &VFTable) { - printTypeIndex("Type", VFTable.getType()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR, - EnumeratorRecord &Enum) { - printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla, - MethodOptions::None); - W->printNumber("EnumValue", Enum.getValue()); - W->printString("Name", Enum.getName()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR, - BaseClassRecord &Base) { - printMemberAttributes(Base.getAccess(), MethodKind::Vanilla, - MethodOptions::None); - printTypeIndex("BaseType", Base.getBaseType()); - W->printHex("BaseOffset", Base.getBaseOffset()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR, - VirtualBaseClassRecord &Base) { - 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()); - return Error::success(); -} - -Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR, - ListContinuationRecord &Cont) { - printTypeIndex("ContinuationIndex", Cont.getContinuationIndex()); - return Error::success(); -} - -void CVTypeDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) { - StringRef TypeName; - if (!TI.isNoneType()) - TypeName = TypeDB.getTypeName(TI); - if (!TypeName.empty()) - W->printHex(FieldName, TypeName, TI.getIndex()); - else - W->printHex(FieldName, TI.getIndex()); -} - -Error CVTypeDumper::dump(const CVType &Record) { - assert(W && "printer should not be null"); +Error CVTypeDumper::dump(const CVType &Record, TypeVisitorCallbacks &Dumper) { TypeDatabaseVisitor DBV(TypeDB); TypeDeserializer Deserializer; TypeVisitorCallbackPipeline Pipeline; Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(DBV); - Pipeline.addCallbackToPipeline(*this); + Pipeline.addCallbackToPipeline(Dumper); CVTypeVisitor Visitor(Pipeline); @@ -547,14 +35,14 @@ Error CVTypeDumper::dump(const CVType &Record) { return Error::success(); } -Error CVTypeDumper::dump(const CVTypeArray &Types) { - assert(W && "printer should not be null"); +Error CVTypeDumper::dump(const CVTypeArray &Types, + TypeVisitorCallbacks &Dumper) { TypeDatabaseVisitor DBV(TypeDB); TypeDeserializer Deserializer; TypeVisitorCallbackPipeline Pipeline; Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(DBV); - Pipeline.addCallbackToPipeline(*this); + Pipeline.addCallbackToPipeline(Dumper); CVTypeVisitor Visitor(Pipeline); @@ -563,17 +51,23 @@ Error CVTypeDumper::dump(const CVTypeArray &Types) { return Error::success(); } -Error CVTypeDumper::dump(ArrayRef<uint8_t> Data) { +Error CVTypeDumper::dump(ArrayRef<uint8_t> Data, TypeVisitorCallbacks &Dumper) { msf::ByteStream Stream(Data); CVTypeArray Types; msf::StreamReader Reader(Stream); if (auto EC = Reader.readArray(Types, Reader.getLength())) return EC; - return dump(Types); + return dump(Types, Dumper); } -void CVTypeDumper::setPrinter(ScopedPrinter *P) { - static ScopedPrinter NullP(llvm::nulls()); - W = P ? P : &NullP; +void CVTypeDumper::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, + TypeIndex TI, TypeDatabase &DB) { + StringRef TypeName; + if (!TI.isNoneType()) + TypeName = DB.getTypeName(TI); + if (!TypeName.empty()) + Printer.printHex(FieldName, TypeName, TI.getIndex()); + else + Printer.printHex(FieldName, TI.getIndex()); } diff --git a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp index c17112884cb..fd54fba13c7 100644 --- a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -32,9 +32,9 @@ namespace { /// the visitor out of SymbolDumper.h. class CVSymbolDumperImpl : public SymbolVisitorCallbacks { public: - CVSymbolDumperImpl(CVTypeDumper &CVTD, SymbolDumpDelegate *ObjDelegate, + CVSymbolDumperImpl(TypeDatabase &TypeDB, SymbolDumpDelegate *ObjDelegate, ScopedPrinter &W, bool PrintRecordBytes) - : CVTD(CVTD), ObjDelegate(ObjDelegate), W(W), + : TypeDB(TypeDB), ObjDelegate(ObjDelegate), W(W), PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {} /// CVSymbolVisitor overrides. @@ -51,8 +51,9 @@ private: void printLocalVariableAddrRange(const LocalVariableAddrRange &Range, uint32_t RelocationOffset); void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps); + void printTypeIndex(StringRef FieldName, TypeIndex TI); - CVTypeDumper &CVTD; + TypeDatabase &TypeDB; SymbolDumpDelegate *ObjDelegate; ScopedPrinter &W; @@ -80,6 +81,10 @@ void CVSymbolDumperImpl::printLocalVariableAddrGap( } } +void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName, TypeIndex TI) { + CVTypeDumper::printTypeIndex(W, FieldName, TI, TypeDB); +} + Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) { return Error::success(); } @@ -163,7 +168,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, DictScope S(W, "BPRelativeSym"); W.printNumber("Offset", BPRel.Offset); - CVTD.printTypeIndex("Type", BPRel.Type); + printTypeIndex("Type", BPRel.Type); W.printString("VarName", BPRel.Name); return Error::success(); } @@ -187,7 +192,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, CallSiteInfo.CodeOffset, &LinkageName); } W.printHex("Segment", CallSiteInfo.Segment); - CVTD.printTypeIndex("Type", CallSiteInfo.Type); + printTypeIndex("Type", CallSiteInfo.Type); if (!LinkageName.empty()) W.printString("LinkageName", LinkageName); return Error::success(); @@ -278,7 +283,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ConstantSym &Constant) { DictScope S(W, "Constant"); - CVTD.printTypeIndex("Type", Constant.Type); + printTypeIndex("Type", Constant.Type); W.printNumber("Value", Constant.Value); W.printString("Name", Constant.Name); return Error::success(); @@ -293,7 +298,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, DataSym &Data) { ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(), Data.DataOffset, &LinkageName); } - CVTD.printTypeIndex("Type", Data.Type); + printTypeIndex("Type", Data.Type); W.printString("DisplayName", Data.Name); if (!LinkageName.empty()) W.printString("LinkageName", LinkageName); @@ -445,7 +450,7 @@ Error CVSymbolDumperImpl::visitKnownRecord( } W.printHex("Segment", HeapAllocSite.Segment); W.printHex("CallInstructionSize", HeapAllocSite.CallInstructionSize); - CVTD.printTypeIndex("Type", HeapAllocSite.Type); + printTypeIndex("Type", HeapAllocSite.Type); if (!LinkageName.empty()) W.printString("LinkageName", LinkageName); return Error::success(); @@ -457,7 +462,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, W.printHex("PtrParent", InlineSite.Parent); W.printHex("PtrEnd", InlineSite.End); - CVTD.printTypeIndex("Inlinee", InlineSite.Inlinee); + printTypeIndex("Inlinee", InlineSite.Inlinee); ListScope BinaryAnnotations(W, "BinaryAnnotations"); for (auto &Annotation : InlineSite.annotations()) { @@ -555,7 +560,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) { Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) { DictScope S(W, "Local"); - CVTD.printTypeIndex("Type", Local.Type); + printTypeIndex("Type", Local.Type); W.printFlags("Flags", uint16_t(Local.Flags), getLocalFlagNames()); W.printString("VarName", Local.Name); return Error::success(); @@ -586,7 +591,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) { W.printHex("CodeSize", Proc.CodeSize); W.printHex("DbgStart", Proc.DbgStart); W.printHex("DbgEnd", Proc.DbgEnd); - CVTD.printTypeIndex("FunctionType", Proc.FunctionType); + printTypeIndex("FunctionType", Proc.FunctionType); if (ObjDelegate) { ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(), Proc.CodeOffset, &LinkageName); @@ -616,7 +621,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) { ListScope S(W, CVR.kind() == S_CALLEES ? "Callees" : "Callers"); for (auto FuncID : Caller.Indices) - CVTD.printTypeIndex("FuncID", FuncID); + printTypeIndex("FuncID", FuncID); return Error::success(); } @@ -625,7 +630,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, DictScope S(W, "RegRelativeSym"); W.printHex("Offset", RegRel.Offset); - CVTD.printTypeIndex("Type", RegRel.Type); + printTypeIndex("Type", RegRel.Type); W.printHex("Register", RegRel.Register); W.printString("VarName", RegRel.Name); return Error::success(); @@ -640,7 +645,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(), Data.DataOffset, &LinkageName); } - CVTD.printTypeIndex("Type", Data.Type); + printTypeIndex("Type", Data.Type); W.printString("DisplayName", Data.Name); if (!LinkageName.empty()) W.printString("LinkageName", LinkageName); @@ -649,7 +654,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) { DictScope S(W, "UDT"); - CVTD.printTypeIndex("Type", UDT.Type); + printTypeIndex("Type", UDT.Type); W.printString("UDTName", UDT.Name); return Error::success(); } @@ -664,7 +669,7 @@ Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) { Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) { SymbolVisitorCallbackPipeline Pipeline; SymbolDeserializer Deserializer(ObjDelegate.get()); - CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes); + CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes); Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Dumper); @@ -675,7 +680,7 @@ Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) { Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) { SymbolVisitorCallbackPipeline Pipeline; SymbolDeserializer Deserializer(ObjDelegate.get()); - CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes); + CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes); Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Dumper); diff --git a/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp b/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp new file mode 100644 index 00000000000..033585ba8cc --- /dev/null +++ b/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp @@ -0,0 +1,532 @@ +//===-- TypeDumpVisitor.cpp - CodeView type info dumper -----------*- C++ +//-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" + +#include "llvm/ADT/SmallString.h" +#include "llvm/DebugInfo/CodeView/CVTypeDumper.h" +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" +#include "llvm/DebugInfo/MSF/ByteStream.h" +#include "llvm/Support/ScopedPrinter.h" + +using namespace llvm; +using namespace llvm::codeview; + +static const EnumEntry<TypeLeafKind> LeafTypeNames[] = { +#define CV_TYPE(enum, val) {#enum, enum}, +#include "llvm/DebugInfo/CodeView/TypeRecords.def" +}; + +#define ENUM_ENTRY(enum_class, enum) \ + { #enum, std::underlying_type < enum_class > ::type(enum_class::enum) } + +static const EnumEntry<uint16_t> ClassOptionNames[] = { + ENUM_ENTRY(ClassOptions, Packed), + ENUM_ENTRY(ClassOptions, HasConstructorOrDestructor), + ENUM_ENTRY(ClassOptions, HasOverloadedOperator), + ENUM_ENTRY(ClassOptions, Nested), + ENUM_ENTRY(ClassOptions, ContainsNestedClass), + ENUM_ENTRY(ClassOptions, HasOverloadedAssignmentOperator), + ENUM_ENTRY(ClassOptions, HasConversionOperator), + ENUM_ENTRY(ClassOptions, ForwardReference), + ENUM_ENTRY(ClassOptions, Scoped), + ENUM_ENTRY(ClassOptions, HasUniqueName), + ENUM_ENTRY(ClassOptions, Sealed), + ENUM_ENTRY(ClassOptions, Intrinsic), +}; + +static const EnumEntry<uint8_t> MemberAccessNames[] = { + ENUM_ENTRY(MemberAccess, None), ENUM_ENTRY(MemberAccess, Private), + ENUM_ENTRY(MemberAccess, Protected), ENUM_ENTRY(MemberAccess, Public), +}; + +static const EnumEntry<uint16_t> MethodOptionNames[] = { + ENUM_ENTRY(MethodOptions, Pseudo), + ENUM_ENTRY(MethodOptions, NoInherit), + ENUM_ENTRY(MethodOptions, NoConstruct), + ENUM_ENTRY(MethodOptions, CompilerGenerated), + ENUM_ENTRY(MethodOptions, Sealed), +}; + +static const EnumEntry<uint16_t> MemberKindNames[] = { + ENUM_ENTRY(MethodKind, Vanilla), + ENUM_ENTRY(MethodKind, Virtual), + ENUM_ENTRY(MethodKind, Static), + ENUM_ENTRY(MethodKind, Friend), + ENUM_ENTRY(MethodKind, IntroducingVirtual), + ENUM_ENTRY(MethodKind, PureVirtual), + ENUM_ENTRY(MethodKind, PureIntroducingVirtual), +}; + +static const EnumEntry<uint8_t> PtrKindNames[] = { + ENUM_ENTRY(PointerKind, Near16), + ENUM_ENTRY(PointerKind, Far16), + ENUM_ENTRY(PointerKind, Huge16), + ENUM_ENTRY(PointerKind, BasedOnSegment), + ENUM_ENTRY(PointerKind, BasedOnValue), + ENUM_ENTRY(PointerKind, BasedOnSegmentValue), + ENUM_ENTRY(PointerKind, BasedOnAddress), + ENUM_ENTRY(PointerKind, BasedOnSegmentAddress), + ENUM_ENTRY(PointerKind, BasedOnType), + ENUM_ENTRY(PointerKind, BasedOnSelf), + ENUM_ENTRY(PointerKind, Near32), + ENUM_ENTRY(PointerKind, Far32), + ENUM_ENTRY(PointerKind, Near64), +}; + +static const EnumEntry<uint8_t> PtrModeNames[] = { + ENUM_ENTRY(PointerMode, Pointer), + ENUM_ENTRY(PointerMode, LValueReference), + ENUM_ENTRY(PointerMode, PointerToDataMember), + ENUM_ENTRY(PointerMode, PointerToMemberFunction), + ENUM_ENTRY(PointerMode, RValueReference), +}; + +static const EnumEntry<uint16_t> PtrMemberRepNames[] = { + ENUM_ENTRY(PointerToMemberRepresentation, Unknown), + ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceData), + ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceData), + ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceData), + ENUM_ENTRY(PointerToMemberRepresentation, GeneralData), + ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceFunction), + ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceFunction), + ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceFunction), + ENUM_ENTRY(PointerToMemberRepresentation, GeneralFunction), +}; + +static const EnumEntry<uint16_t> TypeModifierNames[] = { + ENUM_ENTRY(ModifierOptions, Const), ENUM_ENTRY(ModifierOptions, Volatile), + ENUM_ENTRY(ModifierOptions, Unaligned), +}; + +static const EnumEntry<uint8_t> CallingConventions[] = { + ENUM_ENTRY(CallingConvention, NearC), + ENUM_ENTRY(CallingConvention, FarC), + ENUM_ENTRY(CallingConvention, NearPascal), + ENUM_ENTRY(CallingConvention, FarPascal), + ENUM_ENTRY(CallingConvention, NearFast), + ENUM_ENTRY(CallingConvention, FarFast), + ENUM_ENTRY(CallingConvention, NearStdCall), + ENUM_ENTRY(CallingConvention, FarStdCall), + ENUM_ENTRY(CallingConvention, NearSysCall), + ENUM_ENTRY(CallingConvention, FarSysCall), + ENUM_ENTRY(CallingConvention, ThisCall), + ENUM_ENTRY(CallingConvention, MipsCall), + ENUM_ENTRY(CallingConvention, Generic), + ENUM_ENTRY(CallingConvention, AlphaCall), + ENUM_ENTRY(CallingConvention, PpcCall), + ENUM_ENTRY(CallingConvention, SHCall), + ENUM_ENTRY(CallingConvention, ArmCall), + ENUM_ENTRY(CallingConvention, AM33Call), + ENUM_ENTRY(CallingConvention, TriCall), + ENUM_ENTRY(CallingConvention, SH5Call), + ENUM_ENTRY(CallingConvention, M32RCall), + ENUM_ENTRY(CallingConvention, ClrCall), + ENUM_ENTRY(CallingConvention, Inline), + ENUM_ENTRY(CallingConvention, NearVector), +}; + +static const EnumEntry<uint8_t> FunctionOptionEnum[] = { + ENUM_ENTRY(FunctionOptions, CxxReturnUdt), + ENUM_ENTRY(FunctionOptions, Constructor), + ENUM_ENTRY(FunctionOptions, ConstructorWithVirtualBases), +}; + +#undef ENUM_ENTRY + +static StringRef getLeafTypeName(TypeLeafKind LT) { + switch (LT) { +#define TYPE_RECORD(ename, value, name) \ + case ename: \ + return #name; +#include "llvm/DebugInfo/CodeView/TypeRecords.def" + default: + break; + } + return "UnknownLeaf"; +} + +void TypeDumpVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const { + CVTypeDumper::printTypeIndex(*W, FieldName, TI, TypeDB); +} + +Error TypeDumpVisitor::visitTypeBegin(CVType &Record) { + W->startLine() << getLeafTypeName(Record.Type); + W->getOStream() << " (" << HexNumber(TypeDB.getNextTypeIndex().getIndex()) + << ")"; + W->getOStream() << " {\n"; + W->indent(); + W->printEnum("TypeLeafKind", unsigned(Record.Type), + makeArrayRef(LeafTypeNames)); + return Error::success(); +} + +Error TypeDumpVisitor::visitTypeEnd(CVType &Record) { + if (PrintRecordBytes) + W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.content())); + + W->unindent(); + W->startLine() << "}\n"; + return Error::success(); +} + +Error TypeDumpVisitor::visitMemberBegin(CVMemberRecord &Record) { + W->startLine() << getLeafTypeName(Record.Kind); + W->getOStream() << " {\n"; + W->indent(); + W->printEnum("TypeLeafKind", unsigned(Record.Kind), + makeArrayRef(LeafTypeNames)); + return Error::success(); +} + +Error TypeDumpVisitor::visitMemberEnd(CVMemberRecord &Record) { + if (PrintRecordBytes) + W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data)); + + W->unindent(); + W->startLine() << "}\n"; + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, + FieldListRecord &FieldList) { + CVTypeVisitor Visitor(*this); + if (auto EC = Visitor.visitFieldListMemberStream(FieldList.Data)) + return EC; + + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, StringIdRecord &String) { + printTypeIndex("Id", String.getId()); + W->printString("StringData", String.getString()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ArgListRecord &Args) { + auto Indices = Args.getIndices(); + uint32_t Size = Indices.size(); + W->printNumber("NumArgs", Size); + ListScope Arguments(*W, "Arguments"); + for (uint32_t I = 0; I < Size; ++I) { + printTypeIndex("ArgType", Indices[I]); + } + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, 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.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()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, 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.getFieldList()); + W->printNumber("SizeOf", Union.getSize()); + W->printString("Name", Union.getName()); + if (Props & uint16_t(ClassOptions::HasUniqueName)) + W->printString("LinkageName", Union.getUniqueName()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) { + uint16_t Props = static_cast<uint16_t>(Enum.getOptions()); + W->printNumber("NumEnumerators", Enum.getMemberCount()); + W->printFlags("Properties", uint16_t(Enum.getOptions()), + makeArrayRef(ClassOptionNames)); + printTypeIndex("UnderlyingType", Enum.getUnderlyingType()); + printTypeIndex("FieldListType", Enum.getFieldList()); + W->printString("Name", Enum.getName()); + if (Props & uint16_t(ClassOptions::HasUniqueName)) + W->printString("LinkageName", Enum.getUniqueName()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) { + printTypeIndex("ElementType", AT.getElementType()); + printTypeIndex("IndexType", AT.getIndexType()); + W->printNumber("SizeOf", AT.getSize()); + W->printString("Name", AT.getName()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, VFTableRecord &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); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) { + printTypeIndex("ClassType", Id.getClassType()); + printTypeIndex("FunctionType", Id.getFunctionType()); + W->printString("Name", Id.getName()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) { + printTypeIndex("ReturnType", Proc.getReturnType()); + W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()), + makeArrayRef(CallingConventions)); + W->printFlags("FunctionOptions", uint8_t(Proc.getOptions()), + makeArrayRef(FunctionOptionEnum)); + W->printNumber("NumParameters", Proc.getParameterCount()); + printTypeIndex("ArgListType", Proc.getArgumentList()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, 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(MF.getOptions()), + makeArrayRef(FunctionOptionEnum)); + W->printNumber("NumParameters", MF.getParameterCount()); + printTypeIndex("ArgListType", MF.getArgumentList()); + W->printNumber("ThisAdjustment", MF.getThisPointerAdjustment()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, + MethodOverloadListRecord &MethodList) { + for (auto &M : MethodList.getMethods()) { + ListScope S(*W, "Method"); + printMemberAttributes(M.getAccess(), M.getMethodKind(), M.getOptions()); + printTypeIndex("Type", M.getType()); + if (M.isIntroducingVirtual()) + W->printHex("VFTableOffset", M.getVFTableOffset()); + } + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) { + printTypeIndex("ParentScope", Func.getParentScope()); + printTypeIndex("FunctionType", Func.getFunctionType()); + W->printString("Name", Func.getName()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) { + W->printBinary("Signature", TS.getGuid()); + W->printNumber("Age", TS.getAge()); + W->printString("Name", TS.getName()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, 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.getMode()), makeArrayRef(PtrModeNames)); + + W->printNumber("IsFlat", Ptr.isFlat()); + W->printNumber("IsConst", Ptr.isConst()); + W->printNumber("IsVolatile", Ptr.isVolatile()); + W->printNumber("IsUnaligned", Ptr.isUnaligned()); + W->printNumber("SizeOf", Ptr.getSize()); + + if (Ptr.isPointerToMember()) { + const MemberPointerInfo &MI = Ptr.getMemberInfo(); + + printTypeIndex("ClassType", MI.getContainingType()); + W->printEnum("Representation", uint16_t(MI.getRepresentation()), + makeArrayRef(PtrMemberRepNames)); + } + + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) { + uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers()); + printTypeIndex("ModifiedType", Mod.getModifiedType()); + W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames)); + + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BitFieldRecord &BitField) { + printTypeIndex("Type", BitField.getType()); + W->printNumber("BitSize", BitField.getBitSize()); + W->printNumber("BitOffset", BitField.getBitOffset()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, + VFTableShapeRecord &Shape) { + W->printNumber("VFEntryCount", Shape.getEntryCount()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, + UdtSourceLineRecord &Line) { + printTypeIndex("UDT", Line.getUDT()); + printTypeIndex("SourceFile", Line.getSourceFile()); + W->printNumber("LineNumber", Line.getLineNumber()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, + UdtModSourceLineRecord &Line) { + printTypeIndex("UDT", Line.getUDT()); + printTypeIndex("SourceFile", Line.getSourceFile()); + W->printNumber("LineNumber", Line.getLineNumber()); + W->printNumber("Module", Line.getModule()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &Args) { + W->printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size())); + + ListScope Arguments(*W, "Arguments"); + for (auto Arg : Args.getArgs()) { + printTypeIndex("ArgType", Arg); + } + return Error::success(); +} + +void TypeDumpVisitor::printMemberAttributes(MemberAttributes Attrs) { + return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(), + Attrs.getFlags()); +} + +void TypeDumpVisitor::printMemberAttributes(MemberAccess Access, + MethodKind Kind, + MethodOptions Options) { + W->printEnum("AccessSpecifier", uint8_t(Access), + makeArrayRef(MemberAccessNames)); + // Data members will be vanilla. Don't try to print a method kind for them. + if (Kind != MethodKind::Vanilla) + W->printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames)); + if (Options != MethodOptions::None) { + W->printFlags("MethodOptions", unsigned(Options), + makeArrayRef(MethodOptionNames)); + } +} + +Error TypeDumpVisitor::visitUnknownMember(CVMemberRecord &Record) { + W->printHex("UnknownMember", unsigned(Record.Kind)); + return Error::success(); +} + +Error TypeDumpVisitor::visitUnknownType(CVType &Record) { + W->printEnum("Kind", uint16_t(Record.kind()), makeArrayRef(LeafTypeNames)); + W->printNumber("Length", uint32_t(Record.content().size())); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, + NestedTypeRecord &Nested) { + printTypeIndex("Type", Nested.getNestedType()); + W->printString("Name", Nested.getName()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, + OneMethodRecord &Method) { + MethodKind K = Method.getMethodKind(); + printMemberAttributes(Method.getAccess(), K, Method.getOptions()); + printTypeIndex("Type", Method.getType()); + // If virtual, then read the vftable offset. + if (Method.isIntroducingVirtual()) + W->printHex("VFTableOffset", Method.getVFTableOffset()); + W->printString("Name", Method.getName()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, + OverloadedMethodRecord &Method) { + W->printHex("MethodCount", Method.getNumOverloads()); + printTypeIndex("MethodListIndex", Method.getMethodList()); + W->printString("Name", Method.getName()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, + DataMemberRecord &Field) { + printMemberAttributes(Field.getAccess(), MethodKind::Vanilla, + MethodOptions::None); + printTypeIndex("Type", Field.getType()); + W->printHex("FieldOffset", Field.getFieldOffset()); + W->printString("Name", Field.getName()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, + StaticDataMemberRecord &Field) { + printMemberAttributes(Field.getAccess(), MethodKind::Vanilla, + MethodOptions::None); + printTypeIndex("Type", Field.getType()); + W->printString("Name", Field.getName()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, + VFPtrRecord &VFTable) { + printTypeIndex("Type", VFTable.getType()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, + EnumeratorRecord &Enum) { + printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla, + MethodOptions::None); + W->printNumber("EnumValue", Enum.getValue()); + W->printString("Name", Enum.getName()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, + BaseClassRecord &Base) { + printMemberAttributes(Base.getAccess(), MethodKind::Vanilla, + MethodOptions::None); + printTypeIndex("BaseType", Base.getBaseType()); + W->printHex("BaseOffset", Base.getBaseOffset()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, + VirtualBaseClassRecord &Base) { + 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()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, + ListContinuationRecord &Cont) { + printTypeIndex("ContinuationIndex", Cont.getContinuationIndex()); + return Error::success(); +} |