Index: llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h =================================================================== --- /dev/null +++ llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h @@ -0,0 +1,60 @@ +//===- NativeEnumSymbol.h - info about enum type ----------------*- 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_PDB_NATIVE_NATIVEENUMSYMBOL_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOL_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeEnumSymbol : public NativeRawSymbol, + public codeview::TypeVisitorCallbacks { +public: + NativeEnumSymbol(NativeSession &Session, SymIndexId Id, + const codeview::CVType &CV); + ~NativeEnumSymbol() override; + + std::unique_ptr clone() const override; + + std::unique_ptr + findChildren(PDB_SymType Type) const override; + + Error visitKnownRecord(codeview::CVType &CVR, + codeview::EnumRecord &Record) override; + Error visitKnownMember(codeview::CVMemberRecord &CVM, + codeview::EnumeratorRecord &Record) override; + + PDB_SymType getSymTag() const override; + uint32_t getClassParentId() const override; + uint32_t getUnmodifiedTypeId() const override; + bool hasConstructor() const override; + bool hasAssignmentOperator() const override; + bool hasCastOperator() const override; + uint64_t getLength() const override; + std::string getName() const override; + bool isNested() const override; + bool hasOverloadedOperator() const override; + bool isPacked() const override; + bool isScoped() const override; + uint32_t getTypeId() const override; + +protected: + codeview::CVType CV; + codeview::EnumRecord Record; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOL_H Index: llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h =================================================================== --- /dev/null +++ llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h @@ -0,0 +1,47 @@ +//==- NativeEnumTypes.h - Native Type Enumerator impl ------------*- 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_PDB_NATIVE_NATIVEENUMTYPES_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMTYPES_H + +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" + +#include + +namespace llvm { +namespace pdb { + +class NativeSession; + +class NativeEnumTypes : public IPDBEnumChildren { +public: + NativeEnumTypes(NativeSession &Session, codeview::CVTypeRange Range, + codeview::TypeLeafKind Kind); + + uint32_t getChildCount() const override; + std::unique_ptr getChildAtIndex(uint32_t Index) const override; + std::unique_ptr getNext() override; + void reset() override; + NativeEnumTypes *clone() const override; + +private: + std::vector Types; + uint32_t Index; + NativeSession &Session; + codeview::CVTypeRange Range; + codeview::TypeLeafKind Kind; + // codeview::CVTypeArray::Iterator I; +}; + +} // namespace pdb +} // namespace llvm + +#endif Index: llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h =================================================================== --- llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h +++ llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h @@ -39,6 +39,9 @@ std::unique_ptr createCompilandSymbol(DbiModuleDescriptor MI); + std::unique_ptr + createEnumSymbol(const codeview::CVType &E); + SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI); uint64_t getLoadAddress() const override; Index: llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h =================================================================== --- llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h +++ llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H -#define LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOL_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOL_H #include "ConcreteSymbolEnumerator.h" #include "IPDBRawSymbol.h" Index: llvm/lib/DebugInfo/PDB/CMakeLists.txt =================================================================== --- llvm/lib/DebugInfo/PDB/CMakeLists.txt +++ llvm/lib/DebugInfo/PDB/CMakeLists.txt @@ -43,6 +43,8 @@ Native/NativeBuiltinSymbol.cpp Native/NativeCompilandSymbol.cpp Native/NativeEnumModules.cpp + Native/NativeEnumSymbol.cpp + Native/NativeEnumTypes.cpp Native/NativeExeSymbol.cpp Native/NativeRawSymbol.cpp Native/NamedStreamMap.cpp Index: llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp =================================================================== --- /dev/null +++ llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp @@ -0,0 +1,111 @@ +//===- NativeEnumSymbol.cpp - info about enum type --------------*- 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/PDB/Native/NativeEnumSymbol.h" + +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" + +namespace llvm { +namespace pdb { + +NativeEnumSymbol::NativeEnumSymbol(NativeSession &Session, SymIndexId Id, + const codeview::CVType &fooCV) + : NativeRawSymbol(Session, Id), CV(fooCV), + Record(codeview::TypeRecordKind::Enum) { + cantFail(visitTypeRecord(CV, *this)); +} + +NativeEnumSymbol::~NativeEnumSymbol() {} + +std::unique_ptr NativeEnumSymbol::clone() const { + return llvm::make_unique(Session, SymbolId, CV); +} + +std::unique_ptr +NativeEnumSymbol::findChildren(PDB_SymType Type) const { + switch (Type) { + case PDB_SymType::Data: { + // TODO(amccarth): Provide an actual implementation. + codeview::CVTypeArray Array; + codeview::CVTypeRange Types(Array); + return std::unique_ptr( + new NativeEnumTypes(Session, Types, codeview::LF_ENUMERATE)); + } + default: + return nullptr; + } +} + +Error NativeEnumSymbol::visitKnownRecord(codeview::CVType &CVR, + codeview::EnumRecord &ER) { + Record = ER; + return Error::success(); +} + +Error NativeEnumSymbol::visitKnownMember(codeview::CVMemberRecord &CVM, + codeview::EnumeratorRecord &R) { + return Error::success(); +} + +PDB_SymType NativeEnumSymbol::getSymTag() const { return PDB_SymType::Enum; } + +uint32_t NativeEnumSymbol::getClassParentId() const { return 0xFFFFFFFF; } + +uint32_t NativeEnumSymbol::getUnmodifiedTypeId() const { return 0; } + +bool NativeEnumSymbol::hasConstructor() const { + return bool(Record.getOptions() & + codeview::ClassOptions::HasConstructorOrDestructor); +} + +bool NativeEnumSymbol::hasAssignmentOperator() const { + return bool(Record.getOptions() & + codeview::ClassOptions::HasOverloadedAssignmentOperator); +} + +bool NativeEnumSymbol::hasCastOperator() const { + return bool(Record.getOptions() & + codeview::ClassOptions::HasConversionOperator); +} + +uint64_t NativeEnumSymbol::getLength() const { + const auto Id = Session.findSymbolByTypeIndex(Record.getUnderlyingType()); + const auto UnderlyingType = + Session.getConcreteSymbolById(Id); + return UnderlyingType ? UnderlyingType->getLength() : 0; +} + +std::string NativeEnumSymbol::getName() const { return Record.getName(); } + +bool NativeEnumSymbol::isNested() const { + return bool(Record.getOptions() & codeview::ClassOptions::Nested); +} + +bool NativeEnumSymbol::hasOverloadedOperator() const { + return bool(Record.getOptions() & + codeview::ClassOptions::HasOverloadedOperator); +} + +bool NativeEnumSymbol::isPacked() const { + return bool(Record.getOptions() & codeview::ClassOptions::Packed); +} + +bool NativeEnumSymbol::isScoped() const { + return bool(Record.getOptions() & codeview::ClassOptions::Scoped); +} + +uint32_t NativeEnumSymbol::getTypeId() const { + return Session.findSymbolByTypeIndex(Record.getUnderlyingType()); +} + +} // namespace pdb +} // namespace llvm Index: llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp =================================================================== --- /dev/null +++ llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp @@ -0,0 +1,54 @@ +//==- NativeEnumTypes.cpp - Native Type Enumerator impl ----------*- 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/PDB/Native/NativeEnumTypes.h" + +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" + +namespace llvm { +namespace pdb { + +NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession, + codeview::CVTypeRange Range, + codeview::TypeLeafKind Kind) + : Types(), Index(0), Session(PDBSession), Range(Range), Kind(Kind) { + // Scan the range to find the types we're supposed to enumerate. + for (const auto &I : Range) { + if (I.kind() == Kind) + Types.push_back(I); + } +} + +uint32_t NativeEnumTypes::getChildCount() const { + return static_cast(Types.size()); +} + +std::unique_ptr +NativeEnumTypes::getChildAtIndex(uint32_t Index) const { + if (Index < Types.size()) + return Session.createEnumSymbol(Types[Index]); + return nullptr; +} + +std::unique_ptr NativeEnumTypes::getNext() { + return getChildAtIndex(Index++); +} + +void NativeEnumTypes::reset() { Index = 0; } + +NativeEnumTypes *NativeEnumTypes::clone() const { + return new NativeEnumTypes(Session, Range, Kind); +} + +} // namespace pdb +} // namespace llvm Index: llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp =================================================================== --- llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp +++ llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp @@ -13,7 +13,9 @@ #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" namespace llvm { namespace pdb { @@ -38,6 +40,19 @@ consumeError(Dbi.takeError()); break; } + case PDB_SymType::Enum: { + auto Tpi = File.getPDBTpiStream(); + if (Tpi) { + bool HadError = false; + const auto &Types = Tpi->types(&HadError); + if (HadError) + return nullptr; + return std::unique_ptr( + new NativeEnumTypes(Session, Types, llvm::codeview::LF_ENUM)); + } + consumeError(Tpi.takeError()); + break; + } default: break; } Index: llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp =================================================================== --- llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -16,11 +16,13 @@ #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" #include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/BinaryByteStream.h" #include "llvm/Support/Error.h" @@ -28,6 +30,7 @@ #include "llvm/Support/MemoryBuffer.h" #include +#include #include #include @@ -102,6 +105,15 @@ *this, std::unique_ptr(SymbolCache[Id]->clone())); } +std::unique_ptr +NativeSession::createEnumSymbol(const codeview::CVType &I) { + assert(I.kind() == codeview::LF_ENUM); + const auto Id = static_cast(SymbolCache.size()); + SymbolCache.push_back(llvm::make_unique(*this, Id, I)); + return llvm::make_unique( + *this, std::unique_ptr(SymbolCache[Id]->clone())); +} + SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) { // First see if it's already in our cache. const auto Entry = TypeIndexToSymbolId.find(Index); @@ -129,7 +141,7 @@ return Id; } - // TODO: Look up PDB type by type index + // TODO(amccarth): Look up PDB type by type index return 0; } Index: llvm/test/DebugInfo/PDB/Native/pdb-native-enums.test =================================================================== --- /dev/null +++ llvm/test/DebugInfo/PDB/Native/pdb-native-enums.test @@ -0,0 +1,6 @@ +; Test that the native PDB reader can enumerate the enum types. +; RUN: llvm-pdbutil pretty -native -enums %p/../Inputs/every-type.pdb \ +; RUN: | FileCheck -check-prefix=ENUMS %s + +ENUMS: enum FooClass::NestedEnum { +ENUMS-NEXT: } Index: llvm/tools/llvm-pdbutil/PrettyEnumDumper.cpp =================================================================== --- llvm/tools/llvm-pdbutil/PrettyEnumDumper.cpp +++ llvm/tools/llvm-pdbutil/PrettyEnumDumper.cpp @@ -26,16 +26,18 @@ WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum "; WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); if (!opts::pretty::NoEnumDefs) { - auto BuiltinType = Symbol.getUnderlyingType(); - if (BuiltinType->getBuiltinType() != PDB_BuiltinType::Int || - BuiltinType->getLength() != 4) { + auto UnderlyingType = Symbol.getUnderlyingType(); + if (!UnderlyingType) + return; + if (UnderlyingType->getBuiltinType() != PDB_BuiltinType::Int || + UnderlyingType->getLength() != 4) { Printer << " : "; BuiltinDumper Dumper(Printer); - Dumper.start(*BuiltinType); + Dumper.start(*UnderlyingType); } + auto EnumValues = Symbol.findAllChildren(); Printer << " {"; Printer.Indent(); - auto EnumValues = Symbol.findAllChildren(); while (auto EnumValue = EnumValues->getNext()) { if (EnumValue->getDataKind() != PDB_DataKind::Constant) continue;