summaryrefslogtreecommitdiffstats
path: root/llvm/lib/DebugInfo
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/DebugInfo')
-rw-r--r--llvm/lib/DebugInfo/CodeView/CMakeLists.txt1
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp53
-rw-r--r--llvm/lib/DebugInfo/PDB/CMakeLists.txt1
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp29
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp4
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp24
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp117
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp221
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp80
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp32
10 files changed, 431 insertions, 131 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt
index 0515788d85e..e1bdffd30ee 100644
--- a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt
@@ -34,6 +34,7 @@ add_llvm_library(LLVMDebugInfoCodeView
TypeIndex.cpp
TypeIndexDiscovery.cpp
TypeHashing.cpp
+ TypeRecordHelpers.cpp
TypeRecordMapping.cpp
TypeStreamMerger.cpp
TypeTableCollection.cpp
diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp
new file mode 100644
index 00000000000..2a66474cf5b
--- /dev/null
+++ b/llvm/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp
@@ -0,0 +1,53 @@
+//===- TypeRecordHelpers.cpp ------------------------------------*- 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/TypeRecordHelpers.h"
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+template <typename RecordT> static ClassOptions getUdtOptions(CVType CVT) {
+ RecordT Record;
+ if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) {
+ consumeError(std::move(EC));
+ return ClassOptions::None;
+ }
+ return Record.getOptions();
+}
+
+bool llvm::codeview::isUdtForwardRef(CVType CVT) {
+ ClassOptions UdtOptions = ClassOptions::None;
+ switch (CVT.kind()) {
+ case LF_STRUCTURE:
+ case LF_CLASS:
+ case LF_INTERFACE:
+ UdtOptions = getUdtOptions<ClassRecord>(std::move(CVT));
+ break;
+ case LF_ENUM:
+ UdtOptions = getUdtOptions<EnumRecord>(std::move(CVT));
+ break;
+ case LF_UNION:
+ UdtOptions = getUdtOptions<UnionRecord>(std::move(CVT));
+ break;
+ default:
+ return false;
+ }
+ return (UdtOptions & ClassOptions::ForwardReference) != ClassOptions::None;
+}
+
+TypeIndex llvm::codeview::getModifiedType(const CVType &CVT) {
+ assert(CVT.kind() == LF_MODIFIER);
+ SmallVector<TypeIndex, 1> Refs;
+ discoverTypeIndices(CVT, Refs);
+ return Refs.front();
+}
diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
index 8bf16c505cb..db39ba3b0ee 100644
--- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
@@ -55,6 +55,7 @@ add_pdb_impl_folder(Native
Native/NativeTypeBuiltin.cpp
Native/NativeTypeEnum.cpp
Native/NativeTypePointer.cpp
+ Native/NativeTypeUDT.cpp
Native/NamedStreamMap.cpp
Native/NativeSession.cpp
Native/PDBFile.cpp
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp
index 97348a55d61..f16b776dc65 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp
@@ -10,6 +10,7 @@
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
@@ -22,21 +23,24 @@ using namespace llvm::pdb;
NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
LazyRandomTypeCollection &Types,
- TypeLeafKind Kind)
+ std::vector<codeview::TypeLeafKind> Kinds)
: Matches(), Index(0), Session(PDBSession) {
Optional<TypeIndex> TI = Types.getFirst();
while (TI) {
CVType CVT = Types.getType(*TI);
TypeLeafKind K = CVT.kind();
- if (K == Kind)
- Matches.push_back(*TI);
- else if (K == TypeLeafKind::LF_MODIFIER) {
- ModifierRecord MR;
- if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, MR)) {
- consumeError(std::move(EC));
- } else if (!MR.ModifiedType.isSimple()) {
- CVType UnmodifiedCVT = Types.getType(MR.ModifiedType);
- if (UnmodifiedCVT.kind() == Kind)
+ if (llvm::is_contained(Kinds, K)) {
+ // Don't add forward refs, we'll find those later while enumerating.
+ if (!isUdtForwardRef(CVT))
+ Matches.push_back(*TI);
+ } else if (K == TypeLeafKind::LF_MODIFIER) {
+ TypeIndex ModifiedTI = getModifiedType(CVT);
+ if (!ModifiedTI.isSimple()) {
+ CVType UnmodifiedCVT = Types.getType(ModifiedTI);
+ // LF_MODIFIERs point to forward refs, but don't worry about that
+ // here. We're pushing the TypeIndex of the LF_MODIFIER itself,
+ // so we'll worry about resolving forward refs later.
+ if (llvm::is_contained(Kinds, UnmodifiedCVT.kind()))
Matches.push_back(*TI);
}
}
@@ -44,11 +48,6 @@ NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
}
}
-NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
- const std::vector<TypeIndex> &Matches,
- TypeLeafKind Kind)
- : Matches(Matches), Index(0), Session(PDBSession) {}
-
uint32_t NativeEnumTypes::getChildCount() const {
return static_cast<uint32_t>(Matches.size());
}
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
index 97d20d4d3bb..ca173808358 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
@@ -45,6 +45,10 @@ NativeExeSymbol::findChildren(PDB_SymType Type) const {
return Session.getSymbolCache().createTypeEnumerator(codeview::LF_ENUM);
case PDB_SymType::PointerType:
return Session.getSymbolCache().createTypeEnumerator(codeview::LF_POINTER);
+ case PDB_SymType::UDT:
+ return Session.getSymbolCache().createTypeEnumerator(
+ {codeview::LF_STRUCTURE, codeview::LF_CLASS, codeview::LF_UNION,
+ codeview::LF_INTERFACE});
default:
break;
}
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
index 1a8c75db998..62950cb3e52 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
@@ -31,68 +31,68 @@ void NativeRawSymbol::dump(raw_ostream &OS, int Indent,
std::unique_ptr<IPDBEnumSymbols>
NativeRawSymbol::findChildren(PDB_SymType Type) const {
- return nullptr;
+ return llvm::make_unique<NullEnumerator<PDBSymbol>>();
}
std::unique_ptr<IPDBEnumSymbols>
NativeRawSymbol::findChildren(PDB_SymType Type, StringRef Name,
PDB_NameSearchFlags Flags) const {
- return nullptr;
+ return llvm::make_unique<NullEnumerator<PDBSymbol>>();
}
std::unique_ptr<IPDBEnumSymbols>
NativeRawSymbol::findChildrenByAddr(PDB_SymType Type, StringRef Name,
PDB_NameSearchFlags Flags, uint32_t Section, uint32_t Offset) const {
- return nullptr;
+ return llvm::make_unique<NullEnumerator<PDBSymbol>>();
}
std::unique_ptr<IPDBEnumSymbols>
NativeRawSymbol::findChildrenByVA(PDB_SymType Type, StringRef Name,
PDB_NameSearchFlags Flags, uint64_t VA) const {
- return nullptr;
+ return llvm::make_unique<NullEnumerator<PDBSymbol>>();
}
std::unique_ptr<IPDBEnumSymbols>
NativeRawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name,
PDB_NameSearchFlags Flags, uint32_t RVA) const {
- return nullptr;
+ return llvm::make_unique<NullEnumerator<PDBSymbol>>();
}
std::unique_ptr<IPDBEnumSymbols>
NativeRawSymbol::findInlineFramesByAddr(uint32_t Section,
uint32_t Offset) const {
- return nullptr;
+ return llvm::make_unique<NullEnumerator<PDBSymbol>>();
}
std::unique_ptr<IPDBEnumSymbols>
NativeRawSymbol::findInlineFramesByRVA(uint32_t RVA) const {
- return nullptr;
+ return llvm::make_unique<NullEnumerator<PDBSymbol>>();
}
std::unique_ptr<IPDBEnumSymbols>
NativeRawSymbol::findInlineFramesByVA(uint64_t VA) const {
- return nullptr;
+ return llvm::make_unique<NullEnumerator<PDBSymbol>>();
}
std::unique_ptr<IPDBEnumLineNumbers>
NativeRawSymbol::findInlineeLines() const {
- return nullptr;
+ return llvm::make_unique<NullEnumerator<IPDBLineNumber>>();
}
std::unique_ptr<IPDBEnumLineNumbers>
NativeRawSymbol::findInlineeLinesByAddr(uint32_t Section, uint32_t Offset,
uint32_t Length) const {
- return nullptr;
+ return llvm::make_unique<NullEnumerator<IPDBLineNumber>>();
}
std::unique_ptr<IPDBEnumLineNumbers>
NativeRawSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const {
- return nullptr;
+ return llvm::make_unique<NullEnumerator<IPDBLineNumber>>();
}
std::unique_ptr<IPDBEnumLineNumbers>
NativeRawSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const {
- return nullptr;
+ return llvm::make_unique<NullEnumerator<IPDBLineNumber>>();
}
void NativeRawSymbol::getDataBytes(SmallVector<uint8_t, 32> &bytes) const {
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
index 0994be4af42..37176fe083b 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
@@ -40,8 +40,7 @@ namespace {
class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks {
public:
NativeEnumEnumEnumerators(NativeSession &Session,
- const NativeTypeEnum &ClassParent,
- const codeview::EnumRecord &CVEnum);
+ const NativeTypeEnum &ClassParent);
uint32_t getChildCount() const override;
std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
@@ -56,7 +55,6 @@ private:
NativeSession &Session;
const NativeTypeEnum &ClassParent;
- const codeview::EnumRecord &CVEnum;
std::vector<EnumeratorRecord> Enumerators;
Optional<TypeIndex> ContinuationIndex;
uint32_t Index = 0;
@@ -64,13 +62,12 @@ private:
} // namespace
NativeEnumEnumEnumerators::NativeEnumEnumEnumerators(
- NativeSession &Session, const NativeTypeEnum &ClassParent,
- const codeview::EnumRecord &CVEnum)
- : Session(Session), ClassParent(ClassParent), CVEnum(CVEnum) {
+ NativeSession &Session, const NativeTypeEnum &ClassParent)
+ : Session(Session), ClassParent(ClassParent) {
TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
LazyRandomTypeCollection &Types = Tpi.typeCollection();
- ContinuationIndex = CVEnum.FieldList;
+ ContinuationIndex = ClassParent.getEnumRecord().FieldList;
while (ContinuationIndex) {
CVType FieldList = Types.getType(*ContinuationIndex);
assert(FieldList.kind() == LF_FIELDLIST);
@@ -100,10 +97,10 @@ NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const {
if (Index >= getChildCount())
return nullptr;
- SymIndexId Id =
- Session.getSymbolCache()
- .getOrCreateFieldListMember<NativeSymbolEnumerator>(
- CVEnum.FieldList, Index, ClassParent, Enumerators[Index]);
+ SymIndexId Id = Session.getSymbolCache()
+ .getOrCreateFieldListMember<NativeSymbolEnumerator>(
+ ClassParent.getEnumRecord().FieldList, Index,
+ ClassParent, Enumerators[Index]);
return Session.getSymbolCache().getSymbolById(Id);
}
@@ -122,11 +119,10 @@ NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
Record(std::move(Record)) {}
NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
- codeview::TypeIndex ModifierTI,
- codeview::ModifierRecord Modifier,
- codeview::EnumRecord EnumRecord)
- : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(ModifierTI),
- Record(std::move(EnumRecord)), Modifiers(std::move(Modifier)) {}
+ NativeTypeEnum &UnmodifiedType,
+ codeview::ModifierRecord Modifier)
+ : NativeRawSymbol(Session, PDB_SymType::Enum, Id),
+ UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {}
NativeTypeEnum::~NativeTypeEnum() {}
@@ -173,22 +169,20 @@ NativeTypeEnum::findChildren(PDB_SymType Type) const {
const NativeTypeEnum *ClassParent = nullptr;
if (!Modifiers)
ClassParent = this;
- else {
- NativeRawSymbol &NRS =
- Session.getSymbolCache().getNativeSymbolById(getUnmodifiedTypeId());
- assert(NRS.getSymTag() == PDB_SymType::Enum);
- ClassParent = static_cast<NativeTypeEnum *>(&NRS);
- }
- return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent,
- Record);
+ else
+ ClassParent = UnmodifiedType;
+ return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent);
}
PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; }
PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
- Session.getSymbolCache().findSymbolByTypeIndex(Record.getUnderlyingType());
+ if (UnmodifiedType)
+ return UnmodifiedType->getBuiltinType();
+
+ Session.getSymbolCache().findSymbolByTypeIndex(Record->getUnderlyingType());
- codeview::TypeIndex Underlying = Record.getUnderlyingType();
+ codeview::TypeIndex Underlying = Record->getUnderlyingType();
// This indicates a corrupt record.
if (!Underlying.isSimple() ||
@@ -255,67 +249,101 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
}
SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const {
- if (!Modifiers)
- return 0;
-
- return Session.getSymbolCache().findSymbolByTypeIndex(
- Modifiers->ModifiedType);
+ return UnmodifiedType ? UnmodifiedType->getSymIndexId() : 0;
}
bool NativeTypeEnum::hasConstructor() const {
- return bool(Record.getOptions() &
+ if (UnmodifiedType)
+ return UnmodifiedType->hasConstructor();
+
+ return bool(Record->getOptions() &
codeview::ClassOptions::HasConstructorOrDestructor);
}
bool NativeTypeEnum::hasAssignmentOperator() const {
- return bool(Record.getOptions() &
+ if (UnmodifiedType)
+ return UnmodifiedType->hasAssignmentOperator();
+
+ return bool(Record->getOptions() &
codeview::ClassOptions::HasOverloadedAssignmentOperator);
}
bool NativeTypeEnum::hasNestedTypes() const {
- return bool(Record.getOptions() &
+ if (UnmodifiedType)
+ return UnmodifiedType->hasNestedTypes();
+
+ return bool(Record->getOptions() &
codeview::ClassOptions::ContainsNestedClass);
}
bool NativeTypeEnum::isIntrinsic() const {
- return bool(Record.getOptions() & codeview::ClassOptions::Intrinsic);
+ if (UnmodifiedType)
+ return UnmodifiedType->isIntrinsic();
+
+ return bool(Record->getOptions() & codeview::ClassOptions::Intrinsic);
}
bool NativeTypeEnum::hasCastOperator() const {
- return bool(Record.getOptions() &
+ if (UnmodifiedType)
+ return UnmodifiedType->hasCastOperator();
+
+ return bool(Record->getOptions() &
codeview::ClassOptions::HasConversionOperator);
}
uint64_t NativeTypeEnum::getLength() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getLength();
+
const auto Id = Session.getSymbolCache().findSymbolByTypeIndex(
- Record.getUnderlyingType());
+ Record->getUnderlyingType());
const auto UnderlyingType =
Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id);
return UnderlyingType ? UnderlyingType->getLength() : 0;
}
-std::string NativeTypeEnum::getName() const { return Record.getName(); }
+std::string NativeTypeEnum::getName() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getName();
+
+ return Record->getName();
+}
bool NativeTypeEnum::isNested() const {
- return bool(Record.getOptions() & codeview::ClassOptions::Nested);
+ if (UnmodifiedType)
+ return UnmodifiedType->isNested();
+
+ return bool(Record->getOptions() & codeview::ClassOptions::Nested);
}
bool NativeTypeEnum::hasOverloadedOperator() const {
- return bool(Record.getOptions() &
+ if (UnmodifiedType)
+ return UnmodifiedType->hasOverloadedOperator();
+
+ return bool(Record->getOptions() &
codeview::ClassOptions::HasOverloadedOperator);
}
bool NativeTypeEnum::isPacked() const {
- return bool(Record.getOptions() & codeview::ClassOptions::Packed);
+ if (UnmodifiedType)
+ return UnmodifiedType->isPacked();
+
+ return bool(Record->getOptions() & codeview::ClassOptions::Packed);
}
bool NativeTypeEnum::isScoped() const {
- return bool(Record.getOptions() & codeview::ClassOptions::Scoped);
+ if (UnmodifiedType)
+ return UnmodifiedType->isScoped();
+
+ return bool(Record->getOptions() & codeview::ClassOptions::Scoped);
}
SymIndexId NativeTypeEnum::getTypeId() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getTypeId();
+
return Session.getSymbolCache().findSymbolByTypeIndex(
- Record.getUnderlyingType());
+ Record->getUnderlyingType());
}
bool NativeTypeEnum::isRefUdt() const { return false; }
@@ -346,6 +374,9 @@ bool NativeTypeEnum::isUnalignedType() const {
}
const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getUnderlyingBuiltinType();
+
return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>(
getTypeId());
}
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp
new file mode 100644
index 00000000000..3abf91dcc6a
--- /dev/null
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp
@@ -0,0 +1,221 @@
+//===- NativeTypeUDT.cpp - info about class/struct 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/NativeTypeUDT.h"
+
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+
+#include <cassert>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id,
+ codeview::TypeIndex TI, codeview::ClassRecord CR)
+ : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI),
+ Class(std::move(CR)), Tag(Class.getPointer()) {}
+
+NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id,
+ codeview::TypeIndex TI, codeview::UnionRecord UR)
+ : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI),
+ Union(std::move(UR)), Tag(Union.getPointer()) {}
+
+NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id,
+ NativeTypeUDT &UnmodifiedType,
+ codeview::ModifierRecord Modifier)
+ : NativeRawSymbol(Session, PDB_SymType::UDT, Id),
+ UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {}
+
+NativeTypeUDT::~NativeTypeUDT() {}
+
+void NativeTypeUDT::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolField(OS, "name", getName(), Indent);
+ dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+ PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+ if (Modifiers.hasValue())
+ dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent,
+ Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields,
+ RecurseIdFields);
+ if (getUdtKind() != PDB_UdtType::Union)
+ dumpSymbolField(OS, "virtualTableShapeId", getVirtualTableShapeId(),
+ Indent);
+ dumpSymbolField(OS, "length", getLength(), Indent);
+ dumpSymbolField(OS, "udtKind", getUdtKind(), Indent);
+ dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
+ dumpSymbolField(OS, "constType", isConstType(), Indent);
+ dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent);
+ dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent);
+ dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent);
+ dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent);
+ dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent);
+ dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent);
+ dumpSymbolField(OS, "nested", isNested(), Indent);
+ dumpSymbolField(OS, "packed", isPacked(), Indent);
+ dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent);
+ dumpSymbolField(OS, "scoped", isScoped(), Indent);
+ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+ dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent);
+ dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+std::string NativeTypeUDT::getName() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getName();
+
+ return Tag->getName();
+}
+
+SymIndexId NativeTypeUDT::getLexicalParentId() const { return 0; }
+
+SymIndexId NativeTypeUDT::getUnmodifiedTypeId() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getSymIndexId();
+
+ return 0;
+}
+
+SymIndexId NativeTypeUDT::getVirtualTableShapeId() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getVirtualTableShapeId();
+
+ if (Class)
+ return Session.getSymbolCache().findSymbolByTypeIndex(Class->VTableShape);
+
+ return 0;
+}
+
+uint64_t NativeTypeUDT::getLength() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getLength();
+
+ if (Class)
+ return Class->getSize();
+
+ return Union->getSize();
+}
+
+PDB_UdtType NativeTypeUDT::getUdtKind() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getUdtKind();
+
+ switch (Tag->Kind) {
+ case TypeRecordKind::Class:
+ return PDB_UdtType::Class;
+ case TypeRecordKind::Union:
+ return PDB_UdtType::Union;
+ case TypeRecordKind::Struct:
+ return PDB_UdtType::Struct;
+ case TypeRecordKind::Interface:
+ return PDB_UdtType::Interface;
+ default:
+ llvm_unreachable("Unexected udt kind");
+ }
+}
+
+bool NativeTypeUDT::hasConstructor() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasConstructor();
+
+ return (Tag->Options & ClassOptions::HasConstructorOrDestructor) !=
+ ClassOptions::None;
+}
+
+bool NativeTypeUDT::isConstType() const {
+ if (!Modifiers)
+ return false;
+ return (Modifiers->Modifiers & ModifierOptions::Const) !=
+ ModifierOptions::None;
+}
+
+bool NativeTypeUDT::hasAssignmentOperator() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasAssignmentOperator();
+
+ return (Tag->Options & ClassOptions::HasOverloadedAssignmentOperator) !=
+ ClassOptions::None;
+}
+
+bool NativeTypeUDT::hasCastOperator() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasCastOperator();
+
+ return (Tag->Options & ClassOptions::HasConversionOperator) !=
+ ClassOptions::None;
+}
+
+bool NativeTypeUDT::hasNestedTypes() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasNestedTypes();
+
+ return (Tag->Options & ClassOptions::ContainsNestedClass) !=
+ ClassOptions::None;
+}
+
+bool NativeTypeUDT::hasOverloadedOperator() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasOverloadedOperator();
+
+ return (Tag->Options & ClassOptions::HasOverloadedOperator) !=
+ ClassOptions::None;
+}
+
+bool NativeTypeUDT::isInterfaceUdt() const { return false; }
+
+bool NativeTypeUDT::isIntrinsic() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->isIntrinsic();
+
+ return (Tag->Options & ClassOptions::Intrinsic) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isNested() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->isNested();
+
+ return (Tag->Options & ClassOptions::Nested) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isPacked() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->isPacked();
+
+ return (Tag->Options & ClassOptions::Packed) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isRefUdt() const { return false; }
+
+bool NativeTypeUDT::isScoped() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->isScoped();
+
+ return (Tag->Options & ClassOptions::Scoped) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isValueUdt() const { return false; }
+
+bool NativeTypeUDT::isUnalignedType() const {
+ if (!Modifiers)
+ return false;
+ return (Modifiers->Modifiers & ModifierOptions::Unaligned) !=
+ ModifierOptions::None;
+}
+
+bool NativeTypeUDT::isVolatileType() const {
+ if (!Modifiers)
+ return false;
+ return (Modifiers->Modifiers & ModifierOptions::Volatile) !=
+ ModifierOptions::None;
+}
diff --git a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
index d714177509d..4fd7adf1632 100644
--- a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
@@ -1,6 +1,7 @@
#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
@@ -9,6 +10,7 @@
#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
@@ -50,10 +52,18 @@ SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
if (Dbi)
Compilands.resize(Dbi->modules().getModuleCount());
+
+ auto &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
+ Tpi.buildHashMap();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
+ return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
}
std::unique_ptr<IPDBEnumSymbols>
-SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) {
+SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
auto Tpi = Session.getPDBFile().getPDBTpiStream();
if (!Tpi) {
consumeError(Tpi.takeError());
@@ -61,7 +71,7 @@ SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) {
}
auto &Types = Tpi->typeCollection();
return std::unique_ptr<IPDBEnumSymbols>(
- new NativeEnumTypes(Session, Types, Kind));
+ new NativeEnumTypes(Session, Types, std::move(Kinds)));
}
SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
@@ -98,38 +108,24 @@ SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
if (Record.ModifiedType.isSimple())
return createSimpleType(Record.ModifiedType, Record.Modifiers);
- auto Tpi = Session.getPDBFile().getPDBTpiStream();
- if (!Tpi) {
- consumeError(Tpi.takeError());
- return 0;
- }
- codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
-
- codeview::CVType UnmodifiedType = Types.getType(Record.ModifiedType);
-
- switch (UnmodifiedType.kind()) {
- case LF_ENUM: {
- EnumRecord ER;
- if (auto EC =
- TypeDeserializer::deserializeAs<EnumRecord>(UnmodifiedType, ER)) {
- consumeError(std::move(EC));
- return 0;
- }
- return createSymbol<NativeTypeEnum>(Record.ModifiedType, std::move(Record),
- std::move(ER));
- }
- case LF_STRUCTURE:
- case LF_UNION:
- case LF_CLASS:
- // FIXME: Handle these
- break;
+ // Make sure we create and cache a record for the unmodified type.
+ SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
+ NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
+
+ switch (UnmodifiedNRS.getSymTag()) {
+ case PDB_SymType::Enum:
+ return createSymbol<NativeTypeEnum>(
+ static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));
+ case PDB_SymType::UDT:
+ return createSymbol<NativeTypeUDT>(
+ static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record));
default:
// No other types can be modified. (LF_POINTER, for example, records
// its modifiers a different way.
assert(false && "Invalid LF_MODIFIER record");
break;
}
- return createSymbolPlaceholder();
+ return 0;
}
SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
@@ -150,13 +146,37 @@ SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
}
codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
codeview::CVType CVT = Types.getType(Index);
- // TODO(amccarth): Make this handle all types.
- SymIndexId Id = 0;
+ if (isUdtForwardRef(CVT)) {
+ Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index);
+
+ if (!EFD)
+ consumeError(EFD.takeError());
+ else if (*EFD != Index) {
+ assert(!isUdtForwardRef(Types.getType(*EFD)));
+ SymIndexId Result = findSymbolByTypeIndex(*EFD);
+ // Record a mapping from ForwardRef -> SymIndex of complete type so that
+ // we'll take the fast path next time.
+ TypeIndexToSymbolId[Index] = Result;
+ return Result;
+ }
+ }
+
+ // At this point if we still have a forward ref udt it means the full decl was
+ // not in the PDB. We just have to deal with it and use the forward ref.
+ SymIndexId Id = 0;
switch (CVT.kind()) {
case codeview::LF_ENUM:
Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
break;
+ case codeview::LF_CLASS:
+ case codeview::LF_STRUCTURE:
+ case codeview::LF_INTERFACE:
+ Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
+ break;
+ case codeview::LF_UNION:
+ Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
+ break;
case codeview::LF_POINTER:
Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
std::move(CVT));
diff --git a/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp b/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp
index 311c3859acf..96221f7d6ec 100644
--- a/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp
@@ -11,9 +11,8 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
-#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
-#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Native/Hash.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
@@ -161,35 +160,6 @@ void TpiStream::buildHashMap() {
bool TpiStream::supportsTypeLookup() const { return !HashMap.empty(); }
-template <typename RecordT> static ClassOptions getUdtOptions(CVType CVT) {
- RecordT Record;
- if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) {
- consumeError(std::move(EC));
- return ClassOptions::None;
- }
- return Record.getOptions();
-}
-
-static bool isUdtForwardRef(CVType CVT) {
- ClassOptions UdtOptions = ClassOptions::None;
- switch (CVT.kind()) {
- case LF_STRUCTURE:
- case LF_CLASS:
- case LF_INTERFACE:
- UdtOptions = getUdtOptions<ClassRecord>(std::move(CVT));
- break;
- case LF_ENUM:
- UdtOptions = getUdtOptions<EnumRecord>(std::move(CVT));
- break;
- case LF_UNION:
- UdtOptions = getUdtOptions<UnionRecord>(std::move(CVT));
- break;
- default:
- return false;
- }
- return (UdtOptions & ClassOptions::ForwardReference) != ClassOptions::None;
-}
-
Expected<TypeIndex>
TpiStream::findFullDeclForForwardRef(TypeIndex ForwardRefTI) const {
CVType F = Types->getType(ForwardRefTI);
OpenPOWER on IntegriCloud