--- /dev/null
+//===- 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<NativeRawSymbol> clone() const override;
+
+ std::unique_ptr<IPDBEnumSymbols>
+ 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
--- /dev/null
+//==- 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/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <vector>
+
+namespace llvm {
+namespace pdb {
+
+class NativeSession;
+
+class NativeEnumTypes : public IPDBEnumChildren<PDBSymbol> {
+public:
+ NativeEnumTypes(NativeSession &Session,
+ codeview::LazyRandomTypeCollection &TypeCollection,
+ codeview::TypeLeafKind Kind);
+
+ uint32_t getChildCount() const override;
+ std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
+ std::unique_ptr<PDBSymbol> getNext() override;
+ void reset() override;
+ NativeEnumTypes *clone() const override;
+
+private:
+ NativeEnumTypes(NativeSession &Session,
+ const std::vector<codeview::TypeIndex> &Matches,
+ codeview::TypeLeafKind Kind);
+
+ std::vector<codeview::TypeIndex> Matches;
+ uint32_t Index;
+ NativeSession &Session;
+ codeview::TypeLeafKind Kind;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif
std::unique_ptr<PDBSymbolCompiland>
createCompilandSymbol(DbiModuleDescriptor MI);
+ std::unique_ptr<PDBSymbolTypeEnum>
+ createEnumSymbol(codeview::TypeIndex Index);
+
+ std::unique_ptr<IPDBEnumSymbols>
+ createTypeEnumerator(codeview::TypeLeafKind Kind);
+
SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI);
uint64_t getLoadAddress() const override;
//
//===----------------------------------------------------------------------===//
-#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"
Native/NativeBuiltinSymbol.cpp
Native/NativeCompilandSymbol.cpp
Native/NativeEnumModules.cpp
+ Native/NativeEnumSymbol.cpp
+ Native/NativeEnumTypes.cpp
Native/NativeExeSymbol.cpp
Native/NativeRawSymbol.cpp
Native/NamedStreamMap.cpp
--- /dev/null
+//===- 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"
+
+#include <cassert>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+NativeEnumSymbol::NativeEnumSymbol(NativeSession &Session, SymIndexId Id,
+ const codeview::CVType &CVT)
+ : NativeRawSymbol(Session, Id), CV(CVT),
+ Record(codeview::TypeRecordKind::Enum) {
+ assert(CV.kind() == codeview::TypeLeafKind::LF_ENUM);
+ cantFail(visitTypeRecord(CV, *this));
+}
+
+NativeEnumSymbol::~NativeEnumSymbol() {}
+
+std::unique_ptr<NativeRawSymbol> NativeEnumSymbol::clone() const {
+ return llvm::make_unique<NativeEnumSymbol>(Session, SymbolId, CV);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeEnumSymbol::findChildren(PDB_SymType Type) const {
+ switch (Type) {
+ case PDB_SymType::Data: {
+ // TODO(amccarth): Provide an actual implementation.
+ return nullptr;
+ }
+ 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<PDBSymbolTypeBuiltin>(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());
+}
--- /dev/null
+//==- 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::LazyRandomTypeCollection &Types,
+ codeview::TypeLeafKind Kind)
+ : Matches(), Index(0), Session(PDBSession), Kind(Kind) {
+ for (auto Index = Types.getFirst(); Index;
+ Index = Types.getNext(Index.getValue())) {
+ if (Types.getType(Index.getValue()).kind() == Kind)
+ Matches.push_back(Index.getValue());
+ }
+}
+
+NativeEnumTypes::NativeEnumTypes(
+ NativeSession &PDBSession, const std::vector<codeview::TypeIndex> &Matches,
+ codeview::TypeLeafKind Kind)
+ : Matches(Matches), Index(0), Session(PDBSession), Kind(Kind) {}
+
+uint32_t NativeEnumTypes::getChildCount() const {
+ return static_cast<uint32_t>(Matches.size());
+}
+
+std::unique_ptr<PDBSymbol>
+NativeEnumTypes::getChildAtIndex(uint32_t Index) const {
+ if (Index < Matches.size())
+ return Session.createEnumSymbol(Matches[Index]);
+ return nullptr;
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumTypes::getNext() {
+ return getChildAtIndex(Index++);
+}
+
+void NativeEnumTypes::reset() { Index = 0; }
+
+NativeEnumTypes *NativeEnumTypes::clone() const {
+ return new NativeEnumTypes(Session, Matches, Kind);
+}
+
+} // namespace pdb
+} // namespace llvm
#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 {
consumeError(Dbi.takeError());
break;
}
+ case PDB_SymType::Enum:
+ return Session.createTypeEnumerator(codeview::LF_ENUM);
default:
break;
}
#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/NativeEnumTypes.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/Native/TpiStream.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"
#include "llvm/Support/MemoryBuffer.h"
#include <algorithm>
+#include <cassert>
#include <memory>
#include <utility>
*this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone()));
}
+std::unique_ptr<PDBSymbolTypeEnum>
+NativeSession::createEnumSymbol(codeview::TypeIndex Index) {
+ const auto Id = findSymbolByTypeIndex(Index);
+ return llvm::make_unique<PDBSymbolTypeEnum>(
+ *this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone()));
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeSession::createTypeEnumerator(codeview::TypeLeafKind Kind) {
+ auto Tpi = Pdb->getPDBTpiStream();
+ if (!Tpi) {
+ consumeError(Tpi.takeError());
+ return nullptr;
+ }
+ auto &Types = Tpi->typeCollection();
+ return std::unique_ptr<IPDBEnumSymbols>(
+ new NativeEnumTypes(*this, Types, codeview::LF_ENUM));
+}
+
SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) {
// First see if it's already in our cache.
const auto Entry = TypeIndexToSymbolId.find(Index);
return Id;
}
- // TODO: Look up PDB type by type index
-
- return 0;
+ // We need to instantiate and cache the desired type symbol.
+ auto Tpi = Pdb->getPDBTpiStream();
+ if (!Tpi) {
+ consumeError(Tpi.takeError());
+ return 0;
+ }
+ auto &Types = Tpi->typeCollection();
+ const auto &I = Types.getType(Index);
+ const auto Id = static_cast<SymIndexId>(SymbolCache.size());
+ // TODO(amccarth): Make this handle all types, not just LF_ENUMs.
+ assert(I.kind() == codeview::LF_ENUM);
+ SymbolCache.emplace_back(llvm::make_unique<NativeEnumSymbol>(*this, Id, I));
+ TypeIndexToSymbolId[Index] = Id;
+ return Id;
}
uint64_t NativeSession::getLoadAddress() const { return 0; }
--- /dev/null
+; 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: }
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<PDBSymbolData>();
Printer << " {";
Printer.Indent();
- auto EnumValues = Symbol.findAllChildren<PDBSymbolData>();
- while (auto EnumValue = EnumValues->getNext()) {
- if (EnumValue->getDataKind() != PDB_DataKind::Constant)
- continue;
- Printer.NewLine();
- WithColor(Printer, PDB_ColorItem::Identifier).get()
- << EnumValue->getName();
- Printer << " = ";
- WithColor(Printer, PDB_ColorItem::LiteralValue).get()
- << EnumValue->getValue();
+ if (EnumValues && EnumValues->getChildCount() > 0) {
+ while (auto EnumValue = EnumValues->getNext()) {
+ if (EnumValue->getDataKind() != PDB_DataKind::Constant)
+ continue;
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get()
+ << EnumValue->getName();
+ Printer << " = ";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get()
+ << EnumValue->getValue();
+ }
}
Printer.Unindent();
Printer.NewLine();