summaryrefslogtreecommitdiff
path: root/lib/DebugInfo/PDB/Native
diff options
context:
space:
mode:
Diffstat (limited to 'lib/DebugInfo/PDB/Native')
-rw-r--r--lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp32
-rw-r--r--lib/DebugInfo/PDB/Native/DbiStream.cpp2
-rw-r--r--lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp45
-rw-r--r--lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp53
-rw-r--r--lib/DebugInfo/PDB/Native/GlobalsStream.cpp68
-rw-r--r--lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp11
-rw-r--r--lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp20
-rw-r--r--lib/DebugInfo/PDB/Native/NativeBuiltinSymbol.cpp47
-rw-r--r--lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp19
-rw-r--r--lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp55
-rw-r--r--lib/DebugInfo/PDB/Native/NativeEnumModules.cpp23
-rw-r--r--lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp108
-rw-r--r--lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp62
-rw-r--r--lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp60
-rw-r--r--lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp96
-rw-r--r--lib/DebugInfo/PDB/Native/NativeSession.cpp140
-rw-r--r--lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp123
-rw-r--r--lib/DebugInfo/PDB/Native/NativeTypeArray.cpp67
-rw-r--r--lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp47
-rw-r--r--lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp382
-rw-r--r--lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp200
-rw-r--r--lib/DebugInfo/PDB/Native/NativeTypePointer.cpp194
-rw-r--r--lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp27
-rw-r--r--lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp221
-rw-r--r--lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp35
-rw-r--r--lib/DebugInfo/PDB/Native/PDBFile.cpp6
-rw-r--r--lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp34
-rw-r--r--lib/DebugInfo/PDB/Native/RawError.cpp30
-rw-r--r--lib/DebugInfo/PDB/Native/SymbolCache.cpp299
-rw-r--r--lib/DebugInfo/PDB/Native/TpiHashing.cpp43
-rw-r--r--lib/DebugInfo/PDB/Native/TpiStream.cpp85
31 files changed, 2171 insertions, 463 deletions
diff --git a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
index b97f1e90bcf83..ab93efc839a9a 100644
--- a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
@@ -19,7 +19,6 @@
#include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
-#include "llvm/Support/BinaryItemStream.h"
#include "llvm/Support/BinaryStreamWriter.h"
using namespace llvm;
@@ -66,12 +65,22 @@ void DbiModuleDescriptorBuilder::setFirstSectionContrib(
}
void DbiModuleDescriptorBuilder::addSymbol(CVSymbol Symbol) {
- Symbols.push_back(Symbol);
- // Symbols written to a PDB file are required to be 4 byte aligned. The same
+ // Defer to the bulk API. It does the same thing.
+ addSymbolsInBulk(Symbol.data());
+}
+
+void DbiModuleDescriptorBuilder::addSymbolsInBulk(
+ ArrayRef<uint8_t> BulkSymbols) {
+ // Do nothing for empty runs of symbols.
+ if (BulkSymbols.empty())
+ return;
+
+ Symbols.push_back(BulkSymbols);
+ // Symbols written to a PDB file are required to be 4 byte aligned. The same
// is not true of object files.
- assert(Symbol.length() % alignOf(CodeViewContainer::Pdb) == 0 &&
+ assert(BulkSymbols.size() % alignOf(CodeViewContainer::Pdb) == 0 &&
"Invalid Symbol alignment!");
- SymbolByteSize += Symbol.length();
+ SymbolByteSize += BulkSymbols.size();
}
void DbiModuleDescriptorBuilder::addSourceFile(StringRef Path) {
@@ -145,16 +154,13 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter,
if (auto EC =
SymbolWriter.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC))
return EC;
- BinaryItemStream<CVSymbol> Records(llvm::support::endianness::little);
- Records.setItems(Symbols);
- BinaryStreamRef RecordsRef(Records);
- if (auto EC = SymbolWriter.writeStreamRef(RecordsRef))
- return EC;
- if (auto EC = SymbolWriter.padToAlignment(4))
- return EC;
- // TODO: Write C11 Line data
+ for (ArrayRef<uint8_t> Syms : Symbols) {
+ if (auto EC = SymbolWriter.writeBytes(Syms))
+ return EC;
+ }
assert(SymbolWriter.getOffset() % alignOf(CodeViewContainer::Pdb) == 0 &&
"Invalid debug section alignment!");
+ // TODO: Write C11 Line data
for (const auto &Builder : C13Builders) {
assert(Builder && "Empty C13 Fragment Builder!");
if (auto EC = Builder->commit(SymbolWriter))
diff --git a/lib/DebugInfo/PDB/Native/DbiStream.cpp b/lib/DebugInfo/PDB/Native/DbiStream.cpp
index edaa783398cae..60ac17b655a7b 100644
--- a/lib/DebugInfo/PDB/Native/DbiStream.cpp
+++ b/lib/DebugInfo/PDB/Native/DbiStream.cpp
@@ -197,7 +197,7 @@ PDB_Machine DbiStream::getMachineType() const {
return static_cast<PDB_Machine>(Machine);
}
-FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() {
+FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() const {
return SectionHeaders;
}
diff --git a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
index f6043bfd7cf94..094216ea800a0 100644
--- a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
@@ -11,6 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
@@ -74,10 +75,27 @@ void DbiStreamBuilder::setPublicsStreamIndex(uint32_t Index) {
PublicsStreamIndex = Index;
}
+void DbiStreamBuilder::addNewFpoData(const codeview::FrameData &FD) {
+ if (!NewFpoData.hasValue())
+ NewFpoData.emplace(false);
+
+ NewFpoData->addFrameData(FD);
+}
+
+void DbiStreamBuilder::addOldFpoData(const object::FpoData &FD) {
+ OldFpoData.push_back(FD);
+}
+
Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type,
ArrayRef<uint8_t> Data) {
+ assert(Type != DbgHeaderType::NewFPO &&
+ "NewFPO data should be written via addFrameData()!");
+
DbgStreams[(int)Type].emplace();
- DbgStreams[(int)Type]->Data = Data;
+ DbgStreams[(int)Type]->Size = Data.size();
+ DbgStreams[(int)Type]->WriteFn = [Data](BinaryStreamWriter &Writer) {
+ return Writer.writeArray(Data);
+ };
return Error::success();
}
@@ -272,10 +290,30 @@ Error DbiStreamBuilder::finalize() {
}
Error DbiStreamBuilder::finalizeMsfLayout() {
+ if (NewFpoData.hasValue()) {
+ DbgStreams[(int)DbgHeaderType::NewFPO].emplace();
+ DbgStreams[(int)DbgHeaderType::NewFPO]->Size =
+ NewFpoData->calculateSerializedSize();
+ DbgStreams[(int)DbgHeaderType::NewFPO]->WriteFn =
+ [this](BinaryStreamWriter &Writer) {
+ return NewFpoData->commit(Writer);
+ };
+ }
+
+ if (!OldFpoData.empty()) {
+ DbgStreams[(int)DbgHeaderType::FPO].emplace();
+ DbgStreams[(int)DbgHeaderType::FPO]->Size =
+ sizeof(object::FpoData) * OldFpoData.size();
+ DbgStreams[(int)DbgHeaderType::FPO]->WriteFn =
+ [this](BinaryStreamWriter &Writer) {
+ return Writer.writeArray(makeArrayRef(OldFpoData));
+ };
+ }
+
for (auto &S : DbgStreams) {
if (!S.hasValue())
continue;
- auto ExpectedIndex = Msf.addStream(S->Data.size());
+ auto ExpectedIndex = Msf.addStream(S->Size);
if (!ExpectedIndex)
return ExpectedIndex.takeError();
S->StreamNumber = *ExpectedIndex;
@@ -406,7 +444,8 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
auto WritableStream = WritableMappedBlockStream::createIndexedStream(
Layout, MsfBuffer, Stream->StreamNumber, Allocator);
BinaryStreamWriter DbgStreamWriter(*WritableStream);
- if (auto EC = DbgStreamWriter.writeArray(Stream->Data))
+
+ if (auto EC = Stream->WriteFn(DbgStreamWriter))
return EC;
}
diff --git a/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
index 58efc2256ae12..57da7003da2b8 100644
--- a/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
@@ -9,6 +9,7 @@
#include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/DebugInfo/CodeView/RecordName.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
@@ -20,6 +21,7 @@
#include "llvm/DebugInfo/PDB/Native/Hash.h"
#include "llvm/Support/BinaryItemStream.h"
#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/xxhash.h"
#include <algorithm>
#include <vector>
@@ -29,8 +31,27 @@ using namespace llvm::pdb;
using namespace llvm::codeview;
struct llvm::pdb::GSIHashStreamBuilder {
+ struct UdtDenseMapInfo {
+ static inline CVSymbol getEmptyKey() {
+ static CVSymbol Empty;
+ return Empty;
+ }
+ static inline CVSymbol getTombstoneKey() {
+ static CVSymbol Tombstone(static_cast<SymbolKind>(-1),
+ ArrayRef<uint8_t>());
+ return Tombstone;
+ }
+ static unsigned getHashValue(const CVSymbol &Val) {
+ return xxHash64(Val.RecordData);
+ }
+ static bool isEqual(const CVSymbol &LHS, const CVSymbol &RHS) {
+ return LHS.RecordData == RHS.RecordData;
+ }
+ };
+
std::vector<CVSymbol> Records;
uint32_t StreamIndex;
+ llvm::DenseSet<CVSymbol, UdtDenseMapInfo> UdtHashes;
std::vector<PSHashRecord> HashRecords;
std::array<support::ulittle32_t, (IPHR_HASH + 32) / 32> HashBitmap;
std::vector<support::ulittle32_t> HashBuckets;
@@ -42,10 +63,18 @@ struct llvm::pdb::GSIHashStreamBuilder {
template <typename T> void addSymbol(const T &Symbol, MSFBuilder &Msf) {
T Copy(Symbol);
- Records.push_back(SymbolSerializer::writeOneSymbol(Copy, Msf.getAllocator(),
- CodeViewContainer::Pdb));
+ addSymbol(SymbolSerializer::writeOneSymbol(Copy, Msf.getAllocator(),
+ CodeViewContainer::Pdb));
+ }
+ void addSymbol(const CVSymbol &Symbol) {
+ if (Symbol.kind() == S_UDT) {
+ auto Iter = UdtHashes.insert(Symbol);
+ if (!Iter.second)
+ return;
+ }
+
+ Records.push_back(Symbol);
}
- void addSymbol(const CVSymbol &Symbol) { Records.push_back(Symbol); }
};
uint32_t GSIHashStreamBuilder::calculateSerializedLength() const {
@@ -144,11 +173,10 @@ void GSIHashStreamBuilder::finalizeBuckets(uint32_t RecordZeroOffset) {
// can properly early-out when it detects the record won't be found. The
// algorithm used here corredsponds to the function
// caseInsensitiveComparePchPchCchCch in the reference implementation.
- llvm::sort(Bucket.begin(), Bucket.end(),
- [](const std::pair<StringRef, PSHashRecord> &Left,
- const std::pair<StringRef, PSHashRecord> &Right) {
- return gsiRecordLess(Left.first, Right.first);
- });
+ llvm::sort(Bucket, [](const std::pair<StringRef, PSHashRecord> &Left,
+ const std::pair<StringRef, PSHashRecord> &Right) {
+ return gsiRecordLess(Left.first, Right.first);
+ });
for (const auto &Entry : Bucket)
HashRecords.push_back(Entry.second);
@@ -273,10 +301,6 @@ void GSIStreamBuilder::addGlobalSymbol(const ConstantSym &Sym) {
GSH->addSymbol(Sym, Msf);
}
-void GSIStreamBuilder::addGlobalSymbol(const UDTSym &Sym) {
- GSH->addSymbol(Sym, Msf);
-}
-
void GSIStreamBuilder::addGlobalSymbol(const codeview::CVSymbol &Sym) {
GSH->addSymbol(Sym);
}
@@ -310,13 +334,14 @@ Error GSIStreamBuilder::commitPublicsHashStream(
PublicsStreamHeader Header;
// FIXME: Fill these in. They are for incremental linking.
+ Header.SymHash = PSH->calculateSerializedLength();
+ Header.AddrMap = PSH->Records.size() * 4;
Header.NumThunks = 0;
Header.SizeOfThunk = 0;
Header.ISectThunkTable = 0;
+ memset(Header.Padding, 0, sizeof(Header.Padding));
Header.OffThunkTable = 0;
Header.NumSections = 0;
- Header.SymHash = PSH->calculateSerializedLength();
- Header.AddrMap = PSH->Records.size() * 4;
if (auto EC = Writer.writeObject(Header))
return EC;
diff --git a/lib/DebugInfo/PDB/Native/GlobalsStream.cpp b/lib/DebugInfo/PDB/Native/GlobalsStream.cpp
index 36076f436ad0a..e363195668219 100644
--- a/lib/DebugInfo/PDB/Native/GlobalsStream.cpp
+++ b/lib/DebugInfo/PDB/Native/GlobalsStream.cpp
@@ -20,7 +20,11 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+
+#include "llvm/DebugInfo/CodeView/RecordName.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/Error.h"
#include <algorithm>
@@ -41,6 +45,43 @@ Error GlobalsStream::reload() {
return Error::success();
}
+std::vector<std::pair<uint32_t, codeview::CVSymbol>>
+GlobalsStream::findRecordsByName(StringRef Name,
+ const SymbolStream &Symbols) const {
+ std::vector<std::pair<uint32_t, codeview::CVSymbol>> Result;
+
+ // Hash the name to figure out which bucket this goes into.
+ size_t ExpandedBucketIndex = hashStringV1(Name) % IPHR_HASH;
+ int32_t CompressedBucketIndex = GlobalsTable.BucketMap[ExpandedBucketIndex];
+ if (CompressedBucketIndex == -1)
+ return Result;
+
+ uint32_t LastBucketIndex = GlobalsTable.HashBuckets.size() - 1;
+ uint32_t StartRecordIndex =
+ GlobalsTable.HashBuckets[CompressedBucketIndex] / 12;
+ uint32_t EndRecordIndex = 0;
+ if (LLVM_LIKELY(uint32_t(CompressedBucketIndex) < LastBucketIndex)) {
+ EndRecordIndex = GlobalsTable.HashBuckets[CompressedBucketIndex + 1];
+ } else {
+ // If this is the last bucket, it consists of all hash records until the end
+ // of the HashRecords array.
+ EndRecordIndex = GlobalsTable.HashRecords.size() * 12;
+ }
+
+ EndRecordIndex /= 12;
+
+ assert(EndRecordIndex <= GlobalsTable.HashRecords.size());
+ while (StartRecordIndex < EndRecordIndex) {
+ PSHashRecord PSH = GlobalsTable.HashRecords[StartRecordIndex];
+ uint32_t Off = PSH.Off - 1;
+ codeview::CVSymbol Record = Symbols.readRecord(Off);
+ if (codeview::getSymbolName(Record) == Name)
+ Result.push_back(std::make_pair(Off, std::move(Record)));
+ ++StartRecordIndex;
+ }
+ return Result;
+}
+
static Error checkHashHdrVersion(const GSIHashHeader *HashHdr) {
if (HashHdr->VerHdr != GSIHashHeader::HdrVersion)
return make_error<RawError>(
@@ -86,7 +127,9 @@ static Error readGSIHashRecords(FixedStreamArray<PSHashRecord> &HashRecords,
static Error
readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets,
- ArrayRef<uint8_t> &HashBitmap, const GSIHashHeader *HashHdr,
+ FixedStreamArray<support::ulittle32_t> &HashBitmap,
+ const GSIHashHeader *HashHdr,
+ MutableArrayRef<int32_t> BucketMap,
BinaryStreamReader &Reader) {
if (auto EC = checkHashHdrVersion(HashHdr))
return EC;
@@ -94,13 +137,27 @@ readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets,
// Before the actual hash buckets, there is a bitmap of length determined by
// IPHR_HASH.
size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32);
- uint32_t NumBitmapEntries = BitmapSizeInBits / 8;
- if (auto EC = Reader.readBytes(HashBitmap, NumBitmapEntries))
+ uint32_t NumBitmapEntries = BitmapSizeInBits / 32;
+ if (auto EC = Reader.readArray(HashBitmap, NumBitmapEntries))
return joinErrors(std::move(EC),
make_error<RawError>(raw_error_code::corrupt_file,
"Could not read a bitmap."));
+ uint32_t NumBuckets1 = 0;
+ uint32_t CompressedBucketIdx = 0;
+ for (uint32_t I = 0; I <= IPHR_HASH; ++I) {
+ uint8_t WordIdx = I / 32;
+ uint8_t BitIdx = I % 32;
+ bool IsSet = HashBitmap[WordIdx] & (1U << BitIdx);
+ if (IsSet) {
+ ++NumBuckets1;
+ BucketMap[I] = CompressedBucketIdx++;
+ } else {
+ BucketMap[I] = -1;
+ }
+ }
+
uint32_t NumBuckets = 0;
- for (uint8_t B : HashBitmap)
+ for (uint32_t B : HashBitmap)
NumBuckets += countPopulation(B);
// Hash buckets follow.
@@ -118,7 +175,8 @@ Error GSIHashTable::read(BinaryStreamReader &Reader) {
if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader))
return EC;
if (HashHdr->HrSize > 0)
- if (auto EC = readGSIHashBuckets(HashBuckets, HashBitmap, HashHdr, Reader))
+ if (auto EC = readGSIHashBuckets(HashBuckets, HashBitmap, HashHdr,
+ BucketMap, Reader))
return EC;
return Error::success();
}
diff --git a/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
index 54d6835f11215..3b5a2accdba65 100644
--- a/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
@@ -32,15 +32,20 @@ InfoStreamBuilder::InfoStreamBuilder(msf::MSFBuilder &Msf,
void InfoStreamBuilder::setVersion(PdbRaw_ImplVer V) { Ver = V; }
+void InfoStreamBuilder::addFeature(PdbRaw_FeatureSig Sig) {
+ Features.push_back(Sig);
+}
+
+void InfoStreamBuilder::setHashPDBContentsToGUID(bool B) {
+ HashPDBContentsToGUID = B;
+}
+
void InfoStreamBuilder::setAge(uint32_t A) { Age = A; }
void InfoStreamBuilder::setSignature(uint32_t S) { Signature = S; }
void InfoStreamBuilder::setGuid(GUID G) { Guid = G; }
-void InfoStreamBuilder::addFeature(PdbRaw_FeatureSig Sig) {
- Features.push_back(Sig);
-}
Error InfoStreamBuilder::finalizeMsfLayout() {
uint32_t Length = sizeof(InfoStreamHeader) +
diff --git a/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp b/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp
index 2e1f61c7a25dc..8c97f4a012f03 100644
--- a/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp
+++ b/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp
@@ -11,7 +11,9 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
#include "llvm/Support/BinaryStreamReader.h"
@@ -47,7 +49,8 @@ Error ModuleDebugStreamRef::reload() {
if (auto EC = Reader.readInteger(Signature))
return EC;
- if (auto EC = Reader.readSubstream(SymbolsSubstream, SymbolSize - 4))
+ Reader.setOffset(0);
+ if (auto EC = Reader.readSubstream(SymbolsSubstream, SymbolSize))
return EC;
if (auto EC = Reader.readSubstream(C11LinesSubstream, C11Size))
return EC;
@@ -55,8 +58,8 @@ Error ModuleDebugStreamRef::reload() {
return EC;
BinaryStreamReader SymbolReader(SymbolsSubstream.StreamData);
- if (auto EC =
- SymbolReader.readArray(SymbolArray, SymbolReader.bytesRemaining()))
+ if (auto EC = SymbolReader.readArray(
+ SymbolArray, SymbolReader.bytesRemaining(), sizeof(uint32_t)))
return EC;
BinaryStreamReader SubsectionsReader(C13LinesSubstream.StreamData);
@@ -76,6 +79,11 @@ Error ModuleDebugStreamRef::reload() {
return Error::success();
}
+const codeview::CVSymbolArray
+ModuleDebugStreamRef::getSymbolArrayForScope(uint32_t ScopeBegin) const {
+ return limitSymbolArrayToScope(SymbolArray, ScopeBegin);
+}
+
BinarySubstreamRef ModuleDebugStreamRef::getSymbolsSubstream() const {
return SymbolsSubstream;
}
@@ -97,6 +105,12 @@ ModuleDebugStreamRef::symbols(bool *HadError) const {
return make_range(SymbolArray.begin(HadError), SymbolArray.end());
}
+CVSymbol ModuleDebugStreamRef::readSymbolAtOffset(uint32_t Offset) const {
+ auto Iter = SymbolArray.at(Offset);
+ assert(Iter != SymbolArray.end());
+ return *Iter;
+}
+
iterator_range<ModuleDebugStreamRef::DebugSubsectionIterator>
ModuleDebugStreamRef::subsections() const {
return make_range(Subsections.begin(), Subsections.end());
diff --git a/lib/DebugInfo/PDB/Native/NativeBuiltinSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeBuiltinSymbol.cpp
deleted file mode 100644
index 4644ddcf24e39..0000000000000
--- a/lib/DebugInfo/PDB/Native/NativeBuiltinSymbol.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-//===- NativeBuiltinSymbol.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/PDB/Native/NativeBuiltinSymbol.h"
-
-
-namespace llvm {
-namespace pdb {
-
-NativeBuiltinSymbol::NativeBuiltinSymbol(NativeSession &PDBSession,
- SymIndexId Id, PDB_BuiltinType T,
- uint64_t L)
- : NativeRawSymbol(PDBSession, Id), Session(PDBSession), Type(T), Length(L) {
-}
-
-NativeBuiltinSymbol::~NativeBuiltinSymbol() {}
-
-std::unique_ptr<NativeRawSymbol> NativeBuiltinSymbol::clone() const {
- return llvm::make_unique<NativeBuiltinSymbol>(Session, SymbolId, Type, Length);
-}
-
-void NativeBuiltinSymbol::dump(raw_ostream &OS, int Indent) const {
- // TODO: Apparently nothing needs this yet.
-}
-
-PDB_SymType NativeBuiltinSymbol::getSymTag() const {
- return PDB_SymType::BuiltinType;
-}
-
-PDB_BuiltinType NativeBuiltinSymbol::getBuiltinType() const { return Type; }
-
-bool NativeBuiltinSymbol::isConstType() const { return false; }
-
-uint64_t NativeBuiltinSymbol::getLength() const { return Length; }
-
-bool NativeBuiltinSymbol::isUnalignedType() const { return false; }
-
-bool NativeBuiltinSymbol::isVolatileType() const { return false; }
-
-} // namespace pdb
-} // namespace llvm
diff --git a/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp
index 7132a99a9f160..efa70b0e7bd8b 100644
--- a/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp
+++ b/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/ADT/STLExtras.h"
@@ -17,21 +18,31 @@ namespace pdb {
NativeCompilandSymbol::NativeCompilandSymbol(NativeSession &Session,
SymIndexId SymbolId,
DbiModuleDescriptor MI)
- : NativeRawSymbol(Session, SymbolId), Module(MI) {}
+ : NativeRawSymbol(Session, PDB_SymType::Compiland, SymbolId), Module(MI) {}
PDB_SymType NativeCompilandSymbol::getSymTag() const {
return PDB_SymType::Compiland;
}
-std::unique_ptr<NativeRawSymbol> NativeCompilandSymbol::clone() const {
- return llvm::make_unique<NativeCompilandSymbol>(Session, SymbolId, Module);
+void NativeCompilandSymbol::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+ PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolField(OS, "libraryName", getLibraryName(), Indent);
+ dumpSymbolField(OS, "name", getName(), Indent);
+ dumpSymbolField(OS, "editAndContinueEnabled", isEditAndContinueEnabled(),
+ Indent);
}
bool NativeCompilandSymbol::isEditAndContinueEnabled() const {
return Module.hasECInfo();
}
-uint32_t NativeCompilandSymbol::getLexicalParentId() const { return 0; }
+SymIndexId NativeCompilandSymbol::getLexicalParentId() const { return 0; }
// The usage of getObjFileName for getLibraryName and getModuleName for getName
// may seem backwards, but it is consistent with DIA, which is what this API
diff --git a/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp b/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp
new file mode 100644
index 0000000000000..6eece3df2db34
--- /dev/null
+++ b/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp
@@ -0,0 +1,55 @@
+//==- NativeEnumGlobals.cpp - Native Global 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/NativeEnumGlobals.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeEnumGlobals::NativeEnumGlobals(NativeSession &PDBSession,
+ std::vector<codeview::SymbolKind> Kinds)
+ : Index(0), Session(PDBSession) {
+ GlobalsStream &GS = cantFail(Session.getPDBFile().getPDBGlobalsStream());
+ SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());
+ for (uint32_t Off : GS.getGlobalsTable()) {
+ CVSymbol S = SS.readRecord(Off);
+ if (!llvm::is_contained(Kinds, S.kind()))
+ continue;
+ MatchOffsets.push_back(Off);
+ }
+}
+
+uint32_t NativeEnumGlobals::getChildCount() const {
+ return static_cast<uint32_t>(MatchOffsets.size());
+}
+
+std::unique_ptr<PDBSymbol>
+NativeEnumGlobals::getChildAtIndex(uint32_t N) const {
+ if (N >= MatchOffsets.size())
+ return nullptr;
+
+ SymIndexId Id =
+ Session.getSymbolCache().getOrCreateGlobalSymbolByOffset(MatchOffsets[N]);
+ return Session.getSymbolCache().getSymbolById(Id);
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumGlobals::getNext() {
+ return getChildAtIndex(Index++);
+}
+
+void NativeEnumGlobals::reset() { Index = 0; }
diff --git a/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp b/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp
index a65782e2d4fc6..6e4d56443a072 100644
--- a/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp
+++ b/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp
@@ -10,42 +10,35 @@
#include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
-#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
namespace llvm {
namespace pdb {
-NativeEnumModules::NativeEnumModules(NativeSession &PDBSession,
- const DbiModuleList &Modules,
- uint32_t Index)
- : Session(PDBSession), Modules(Modules), Index(Index) {}
+NativeEnumModules::NativeEnumModules(NativeSession &PDBSession, uint32_t Index)
+ : Session(PDBSession), Index(Index) {}
uint32_t NativeEnumModules::getChildCount() const {
- return static_cast<uint32_t>(Modules.getModuleCount());
+ return Session.getSymbolCache().getNumCompilands();
}
std::unique_ptr<PDBSymbol>
-NativeEnumModules::getChildAtIndex(uint32_t Index) const {
- if (Index >= Modules.getModuleCount())
- return nullptr;
- return Session.createCompilandSymbol(Modules.getModuleDescriptor(Index));
+NativeEnumModules::getChildAtIndex(uint32_t N) const {
+ return Session.getSymbolCache().getOrCreateCompiland(N);
}
std::unique_ptr<PDBSymbol> NativeEnumModules::getNext() {
- if (Index >= Modules.getModuleCount())
+ if (Index >= getChildCount())
return nullptr;
return getChildAtIndex(Index++);
}
void NativeEnumModules::reset() { Index = 0; }
-NativeEnumModules *NativeEnumModules::clone() const {
- return new NativeEnumModules(Session, Modules, Index);
-}
-
}
}
diff --git a/lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp
deleted file mode 100644
index 38d65917306a7..0000000000000
--- a/lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-//===- 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());
-}
diff --git a/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp b/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp
index 36a68a1c62de4..288a9128147ab 100644
--- a/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp
+++ b/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp
@@ -9,39 +9,58 @@
#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/NativeEnumSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
-namespace llvm {
-namespace pdb {
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::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());
+ LazyRandomTypeCollection &Types,
+ 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 (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);
+ }
+ }
+ TI = Types.getNext(*TI);
}
}
-NativeEnumTypes::NativeEnumTypes(
- NativeSession &PDBSession, const std::vector<codeview::TypeIndex> &Matches,
- codeview::TypeLeafKind Kind)
- : Matches(Matches), Index(0), Session(PDBSession), Kind(Kind) {}
+NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
+ std::vector<codeview::TypeIndex> Indices)
+ : Matches(std::move(Indices)), Index(0), Session(PDBSession) {}
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]);
+std::unique_ptr<PDBSymbol> NativeEnumTypes::getChildAtIndex(uint32_t N) const {
+ if (N < Matches.size()) {
+ SymIndexId Id = Session.getSymbolCache().findSymbolByTypeIndex(Matches[N]);
+ return Session.getSymbolCache().getSymbolById(Id);
+ }
return nullptr;
}
@@ -50,10 +69,3 @@ std::unique_ptr<PDBSymbol> NativeEnumTypes::getNext() {
}
void NativeEnumTypes::reset() { Index = 0; }
-
-NativeEnumTypes *NativeEnumTypes::clone() const {
- return new NativeEnumTypes(Session, Matches, Kind);
-}
-
-} // namespace pdb
-} // namespace llvm
diff --git a/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
index e8b06065fc607..6dde5d08a500b 100644
--- a/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
+++ b/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
@@ -12,34 +12,53 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
-namespace llvm {
-namespace pdb {
+using namespace llvm;
+using namespace llvm::pdb;
-NativeExeSymbol::NativeExeSymbol(NativeSession &Session, SymIndexId SymbolId)
- : NativeRawSymbol(Session, SymbolId), File(Session.getPDBFile()) {}
+static DbiStream *getDbiStreamPtr(NativeSession &Session) {
+ Expected<DbiStream &> DbiS = Session.getPDBFile().getPDBDbiStream();
+ if (DbiS)
+ return &DbiS.get();
-std::unique_ptr<NativeRawSymbol> NativeExeSymbol::clone() const {
- return llvm::make_unique<NativeExeSymbol>(Session, SymbolId);
+ consumeError(DbiS.takeError());
+ return nullptr;
}
+NativeExeSymbol::NativeExeSymbol(NativeSession &Session, SymIndexId SymbolId)
+ : NativeRawSymbol(Session, PDB_SymType::Exe, SymbolId),
+ Dbi(getDbiStreamPtr(Session)) {}
+
std::unique_ptr<IPDBEnumSymbols>
NativeExeSymbol::findChildren(PDB_SymType Type) const {
switch (Type) {
case PDB_SymType::Compiland: {
- auto Dbi = File.getPDBDbiStream();
- if (Dbi) {
- const DbiModuleList &Modules = Dbi->modules();
- return std::unique_ptr<IPDBEnumSymbols>(
- new NativeEnumModules(Session, Modules));
- }
- consumeError(Dbi.takeError());
+ return std::unique_ptr<IPDBEnumSymbols>(new NativeEnumModules(Session));
break;
}
+ case PDB_SymType::ArrayType:
+ return Session.getSymbolCache().createTypeEnumerator(codeview::LF_ARRAY);
case PDB_SymType::Enum:
- return Session.createTypeEnumerator(codeview::LF_ENUM);
+ 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});
+ case PDB_SymType::VTableShape:
+ return Session.getSymbolCache().createTypeEnumerator(codeview::LF_VTSHAPE);
+ case PDB_SymType::FunctionSig:
+ return Session.getSymbolCache().createTypeEnumerator(
+ {codeview::LF_PROCEDURE, codeview::LF_MFUNCTION});
+ case PDB_SymType::Typedef:
+ return Session.getSymbolCache().createGlobalsEnumerator(codeview::S_UDT);
+
default:
break;
}
@@ -47,7 +66,7 @@ NativeExeSymbol::findChildren(PDB_SymType Type) const {
}
uint32_t NativeExeSymbol::getAge() const {
- auto IS = File.getPDBInfoStream();
+ auto IS = Session.getPDBFile().getPDBInfoStream();
if (IS)
return IS->getAge();
consumeError(IS.takeError());
@@ -55,11 +74,11 @@ uint32_t NativeExeSymbol::getAge() const {
}
std::string NativeExeSymbol::getSymbolsFileName() const {
- return File.getFilePath();
+ return Session.getPDBFile().getFilePath();
}
codeview::GUID NativeExeSymbol::getGuid() const {
- auto IS = File.getPDBInfoStream();
+ auto IS = Session.getPDBFile().getPDBInfoStream();
if (IS)
return IS->getGuid();
consumeError(IS.takeError());
@@ -67,7 +86,7 @@ codeview::GUID NativeExeSymbol::getGuid() const {
}
bool NativeExeSymbol::hasCTypes() const {
- auto Dbi = File.getPDBDbiStream();
+ auto Dbi = Session.getPDBFile().getPDBDbiStream();
if (Dbi)
return Dbi->hasCTypes();
consumeError(Dbi.takeError());
@@ -75,12 +94,9 @@ bool NativeExeSymbol::hasCTypes() const {
}
bool NativeExeSymbol::hasPrivateSymbols() const {
- auto Dbi = File.getPDBDbiStream();
+ auto Dbi = Session.getPDBFile().getPDBDbiStream();
if (Dbi)
return !Dbi->isStripped();
consumeError(Dbi.takeError());
return false;
}
-
-} // namespace pdb
-} // namespace llvm
diff --git a/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
index a4b0295963145..62950cb3e52a6 100644
--- a/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
+++ b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
@@ -7,82 +7,92 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/Support/FormatVariadic.h"
using namespace llvm;
using namespace llvm::pdb;
-NativeRawSymbol::NativeRawSymbol(NativeSession &PDBSession, SymIndexId SymbolId)
- : Session(PDBSession), SymbolId(SymbolId) {}
+NativeRawSymbol::NativeRawSymbol(NativeSession &PDBSession, PDB_SymType Tag,
+ SymIndexId SymbolId)
+ : Session(PDBSession), Tag(Tag), SymbolId(SymbolId) {}
-void NativeRawSymbol::dump(raw_ostream &OS, int Indent) const {}
+void NativeRawSymbol::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ dumpSymbolIdField(OS, "symIndexId", SymbolId, Indent, Session,
+ PdbSymbolIdField::SymIndexId, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolField(OS, "symTag", Tag, 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 {
@@ -105,9 +115,7 @@ uint32_t NativeRawSymbol::getAge() const {
return 0;
}
-uint32_t NativeRawSymbol::getArrayIndexTypeId() const {
- return 0;
-}
+SymIndexId NativeRawSymbol::getArrayIndexTypeId() const { return 0; }
void NativeRawSymbol::getBackEndVersion(VersionInfo &Version) const {
Version.Major = 0;
@@ -124,9 +132,7 @@ uint32_t NativeRawSymbol::getBaseDataSlot() const {
return 0;
}
-uint32_t NativeRawSymbol::getBaseSymbolId() const {
- return 0;
-}
+SymIndexId NativeRawSymbol::getBaseSymbolId() const { return 0; }
PDB_BuiltinType NativeRawSymbol::getBuiltinType() const {
return PDB_BuiltinType::None;
@@ -140,9 +146,7 @@ PDB_CallingConv NativeRawSymbol::getCallingConvention() const {
return PDB_CallingConv::FarStdCall;
}
-uint32_t NativeRawSymbol::getClassParentId() const {
- return 0;
-}
+SymIndexId NativeRawSymbol::getClassParentId() const { return 0; }
std::string NativeRawSymbol::getCompilerName() const {
return {};
@@ -167,9 +171,7 @@ PDB_Lang NativeRawSymbol::getLanguage() const {
return PDB_Lang::Cobol;
}
-uint32_t NativeRawSymbol::getLexicalParentId() const {
- return 0;
-}
+SymIndexId NativeRawSymbol::getLexicalParentId() const { return 0; }
std::string NativeRawSymbol::getLibraryName() const {
return {};
@@ -188,12 +190,10 @@ uint32_t NativeRawSymbol::getLiveRangeStartRelativeVirtualAddress() const {
}
codeview::RegisterId NativeRawSymbol::getLocalBasePointerRegisterId() const {
- return codeview::RegisterId::CVRegEAX;
+ return codeview::RegisterId::EAX;
}
-uint32_t NativeRawSymbol::getLowerBoundId() const {
- return 0;
-}
+SymIndexId NativeRawSymbol::getLowerBoundId() const { return 0; }
uint32_t NativeRawSymbol::getMemorySpaceKind() const {
return 0;
@@ -231,9 +231,7 @@ uint32_t NativeRawSymbol::getOemId() const {
return 0;
}
-uint32_t NativeRawSymbol::getOemSymbolId() const {
- return 0;
-}
+SymIndexId NativeRawSymbol::getOemSymbolId() const { return 0; }
uint32_t NativeRawSymbol::getOffsetInUdt() const {
return 0;
@@ -248,7 +246,7 @@ uint32_t NativeRawSymbol::getRank() const {
}
codeview::RegisterId NativeRawSymbol::getRegisterId() const {
- return codeview::RegisterId::CVRegEAX;
+ return codeview::RegisterId::EAX;
}
uint32_t NativeRawSymbol::getRegisterType() const {
@@ -288,13 +286,11 @@ uint32_t NativeRawSymbol::getStride() const {
return 0;
}
-uint32_t NativeRawSymbol::getSubTypeId() const {
- return 0;
-}
+SymIndexId NativeRawSymbol::getSubTypeId() const { return 0; }
std::string NativeRawSymbol::getSymbolsFileName() const { return {}; }
-uint32_t NativeRawSymbol::getSymIndexId() const { return SymbolId; }
+SymIndexId NativeRawSymbol::getSymIndexId() const { return SymbolId; }
uint32_t NativeRawSymbol::getTargetOffset() const {
return 0;
@@ -324,9 +320,7 @@ uint32_t NativeRawSymbol::getToken() const {
return 0;
}
-uint32_t NativeRawSymbol::getTypeId() const {
- return 0;
-}
+SymIndexId NativeRawSymbol::getTypeId() const { return 0; }
uint32_t NativeRawSymbol::getUavSlot() const {
return 0;
@@ -341,13 +335,9 @@ std::string NativeRawSymbol::getUndecoratedNameEx(
return {};
}
-uint32_t NativeRawSymbol::getUnmodifiedTypeId() const {
- return 0;
-}
+SymIndexId NativeRawSymbol::getUnmodifiedTypeId() const { return 0; }
-uint32_t NativeRawSymbol::getUpperBoundId() const {
- return 0;
-}
+SymIndexId NativeRawSymbol::getUpperBoundId() const { return 0; }
Variant NativeRawSymbol::getValue() const {
return Variant();
@@ -361,9 +351,7 @@ uint32_t NativeRawSymbol::getVirtualBaseOffset() const {
return 0;
}
-uint32_t NativeRawSymbol::getVirtualTableShapeId() const {
- return 0;
-}
+SymIndexId NativeRawSymbol::getVirtualTableShapeId() const { return 0; }
std::unique_ptr<PDBSymbolTypeBuiltin>
NativeRawSymbol::getVirtualBaseTableType() const {
@@ -374,9 +362,7 @@ PDB_DataKind NativeRawSymbol::getDataKind() const {
return PDB_DataKind::Unknown;
}
-PDB_SymType NativeRawSymbol::getSymTag() const {
- return PDB_SymType::None;
-}
+PDB_SymType NativeRawSymbol::getSymTag() const { return Tag; }
codeview::GUID NativeRawSymbol::getGuid() const { return codeview::GUID{{0}}; }
diff --git a/lib/DebugInfo/PDB/Native/NativeSession.cpp b/lib/DebugInfo/PDB/Native/NativeSession.cpp
index 086da13135c59..7807e312365c9 100644
--- a/lib/DebugInfo/PDB/Native/NativeSession.cpp
+++ b/lib/DebugInfo/PDB/Native/NativeSession.cpp
@@ -11,16 +11,16 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#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/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
@@ -40,31 +40,19 @@ using namespace llvm;
using namespace llvm::msf;
using namespace llvm::pdb;
-namespace {
-// Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
-// to instantiate a NativeBuiltinSymbol for that type.
-static const struct BuiltinTypeEntry {
- codeview::SimpleTypeKind Kind;
- PDB_BuiltinType Type;
- uint32_t Size;
-} BuiltinTypes[] = {
- {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
- {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
- {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
- {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
- {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
- {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
- {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
- {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
- {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1}
- // This table can be grown as necessary, but these are the only types we've
- // needed so far.
-};
-} // namespace
+static DbiStream *getDbiStreamPtr(PDBFile &File) {
+ Expected<DbiStream &> DbiS = File.getPDBDbiStream();
+ if (DbiS)
+ return &DbiS.get();
+
+ consumeError(DbiS.takeError());
+ return nullptr;
+}
NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile,
std::unique_ptr<BumpPtrAllocator> Allocator)
- : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)) {}
+ : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)),
+ Cache(*this, getDbiStreamPtr(*Pdb)) {}
NativeSession::~NativeSession() = default;
@@ -92,97 +80,17 @@ Error NativeSession::createFromExe(StringRef Path,
return make_error<RawError>(raw_error_code::feature_unsupported);
}
-std::unique_ptr<PDBSymbolCompiland>
-NativeSession::createCompilandSymbol(DbiModuleDescriptor MI) {
- const auto Id = static_cast<SymIndexId>(SymbolCache.size());
- SymbolCache.push_back(
- llvm::make_unique<NativeCompilandSymbol>(*this, Id, MI));
- return llvm::make_unique<PDBSymbolCompiland>(
- *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);
- if (Entry != TypeIndexToSymbolId.end())
- return Entry->second;
-
- // Symbols for built-in types are created on the fly.
- if (Index.isSimple()) {
- // FIXME: We will eventually need to handle pointers to other simple types,
- // which are still simple types in the world of CodeView TypeIndexes.
- if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
- return 0;
- const auto Kind = Index.getSimpleKind();
- const auto It =
- std::find_if(std::begin(BuiltinTypes), std::end(BuiltinTypes),
- [Kind](const BuiltinTypeEntry &Builtin) {
- return Builtin.Kind == Kind;
- });
- if (It == std::end(BuiltinTypes))
- return 0;
- SymIndexId Id = SymbolCache.size();
- SymbolCache.emplace_back(
- llvm::make_unique<NativeBuiltinSymbol>(*this, Id, It->Type, It->Size));
- TypeIndexToSymbolId[Index] = Id;
- return Id;
- }
-
- // 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; }
bool NativeSession::setLoadAddress(uint64_t Address) { return false; }
std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() {
- const auto Id = static_cast<SymIndexId>(SymbolCache.size());
- SymbolCache.push_back(llvm::make_unique<NativeExeSymbol>(*this, Id));
- auto RawSymbol = SymbolCache[Id]->clone();
- auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
- std::unique_ptr<PDBSymbolExe> ExeSymbol(
- static_cast<PDBSymbolExe *>(PdbSymbol.release()));
- return ExeSymbol;
+ return PDBSymbol::createAs<PDBSymbolExe>(*this, getNativeGlobalScope());
}
std::unique_ptr<PDBSymbol>
-NativeSession::getSymbolById(uint32_t SymbolId) const {
- // If the caller has a SymbolId, it'd better be in our SymbolCache.
- return SymbolId < SymbolCache.size()
- ? PDBSymbol::create(*this, SymbolCache[SymbolId]->clone())
- : nullptr;
+NativeSession::getSymbolById(SymIndexId SymbolId) const {
+ return Cache.getSymbolById(SymbolId);
}
bool NativeSession::addressForVA(uint64_t VA, uint32_t &Section,
@@ -291,3 +199,19 @@ std::unique_ptr<IPDBEnumSectionContribs>
NativeSession::getSectionContribs() const {
return nullptr;
}
+
+std::unique_ptr<IPDBEnumFrameData>
+NativeSession::getFrameData() const {
+ return nullptr;
+}
+
+void NativeSession::initializeExeSymbol() {
+ if (ExeSymbol == 0)
+ ExeSymbol = Cache.createSymbol<NativeExeSymbol>();
+}
+
+NativeExeSymbol &NativeSession::getNativeGlobalScope() const {
+ const_cast<NativeSession &>(*this).initializeExeSymbol();
+
+ return Cache.getNativeSymbolById<NativeExeSymbol>(ExeSymbol);
+}
diff --git a/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp b/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp
new file mode 100644
index 0000000000000..6ebb8cae3a656
--- /dev/null
+++ b/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp
@@ -0,0 +1,123 @@
+//===- NativeSymbolEnumerator.cpp - info about enumerators ------*- 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/NativeSymbolEnumerator.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeSymbolEnumerator::NativeSymbolEnumerator(
+ NativeSession &Session, SymIndexId Id, const NativeTypeEnum &Parent,
+ codeview::EnumeratorRecord Record)
+ : NativeRawSymbol(Session, PDB_SymType::Data, Id), Parent(Parent),
+ Record(std::move(Record)) {}
+
+NativeSymbolEnumerator::~NativeSymbolEnumerator() {}
+
+void NativeSymbolEnumerator::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+ dumpSymbolIdField(OS, "classParentId", getClassParentId(), Indent, Session,
+ PdbSymbolIdField::ClassParent, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolIdField(OS, "lexicalParentId", getLexicalParentId(), Indent,
+ Session, PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolField(OS, "name", getName(), Indent);
+ dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+ PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+ dumpSymbolField(OS, "dataKind", getDataKind(), Indent);
+ dumpSymbolField(OS, "locationType", getLocationType(), Indent);
+ dumpSymbolField(OS, "constType", isConstType(), Indent);
+ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+ dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+ dumpSymbolField(OS, "value", getValue(), Indent);
+}
+
+SymIndexId NativeSymbolEnumerator::getClassParentId() const {
+ return Parent.getSymIndexId();
+}
+
+SymIndexId NativeSymbolEnumerator::getLexicalParentId() const { return 0; }
+
+std::string NativeSymbolEnumerator::getName() const { return Record.Name; }
+
+SymIndexId NativeSymbolEnumerator::getTypeId() const {
+ return Parent.getTypeId();
+}
+
+PDB_DataKind NativeSymbolEnumerator::getDataKind() const {
+ return PDB_DataKind::Constant;
+}
+
+PDB_LocType NativeSymbolEnumerator::getLocationType() const {
+ return PDB_LocType::Constant;
+}
+
+bool NativeSymbolEnumerator::isConstType() const { return false; }
+
+bool NativeSymbolEnumerator::isVolatileType() const { return false; }
+
+bool NativeSymbolEnumerator::isUnalignedType() const { return false; }
+
+Variant NativeSymbolEnumerator::getValue() const {
+ const NativeTypeBuiltin &BT = Parent.getUnderlyingBuiltinType();
+
+ switch (BT.getBuiltinType()) {
+ case PDB_BuiltinType::Int:
+ case PDB_BuiltinType::Long:
+ case PDB_BuiltinType::Char: {
+ assert(Record.Value.isSignedIntN(BT.getLength() * 8));
+ int64_t N = Record.Value.getSExtValue();
+ switch (BT.getLength()) {
+ case 1:
+ return Variant{static_cast<int8_t>(N)};
+ case 2:
+ return Variant{static_cast<int16_t>(N)};
+ case 4:
+ return Variant{static_cast<int32_t>(N)};
+ case 8:
+ return Variant{static_cast<int64_t>(N)};
+ }
+ break;
+ }
+ case PDB_BuiltinType::UInt:
+ case PDB_BuiltinType::ULong: {
+ assert(Record.Value.isIntN(BT.getLength() * 8));
+ uint64_t U = Record.Value.getZExtValue();
+ switch (BT.getLength()) {
+ case 1:
+ return Variant{static_cast<uint8_t>(U)};
+ case 2:
+ return Variant{static_cast<uint16_t>(U)};
+ case 4:
+ return Variant{static_cast<uint32_t>(U)};
+ case 8:
+ return Variant{static_cast<uint64_t>(U)};
+ }
+ break;
+ }
+ case PDB_BuiltinType::Bool: {
+ assert(Record.Value.isIntN(BT.getLength() * 8));
+ uint64_t U = Record.Value.getZExtValue();
+ return Variant{static_cast<bool>(U)};
+ }
+ default:
+ assert(false && "Invalid enumeration type");
+ break;
+ }
+
+ return Variant{Record.Value.getSExtValue()};
+}
diff --git a/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp b/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp
new file mode 100644
index 0000000000000..a52561728a98d
--- /dev/null
+++ b/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp
@@ -0,0 +1,67 @@
+//===- NativeTypeArray.cpp - info about arrays ------------------*- 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/NativeTypeArray.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypeArray::NativeTypeArray(NativeSession &Session, SymIndexId Id,
+ codeview::TypeIndex TI,
+ codeview::ArrayRecord Record)
+ : NativeRawSymbol(Session, PDB_SymType::ArrayType, Id), Record(Record),
+ Index(TI) {}
+NativeTypeArray::~NativeTypeArray() {}
+
+void NativeTypeArray::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolField(OS, "arrayIndexTypeId", getArrayIndexTypeId(), Indent);
+ dumpSymbolIdField(OS, "elementTypeId", getTypeId(), Indent, Session,
+ PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+ PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolField(OS, "length", getLength(), Indent);
+ dumpSymbolField(OS, "count", getCount(), Indent);
+ dumpSymbolField(OS, "constType", isConstType(), Indent);
+ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+ dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+SymIndexId NativeTypeArray::getArrayIndexTypeId() const {
+ return Session.getSymbolCache().findSymbolByTypeIndex(Record.getIndexType());
+}
+
+bool NativeTypeArray::isConstType() const { return false; }
+
+bool NativeTypeArray::isUnalignedType() const { return false; }
+
+bool NativeTypeArray::isVolatileType() const { return false; }
+
+uint32_t NativeTypeArray::getCount() const {
+ NativeRawSymbol &Element =
+ Session.getSymbolCache().getNativeSymbolById(getTypeId());
+ return getLength() / Element.getLength();
+}
+
+SymIndexId NativeTypeArray::getTypeId() const {
+ return Session.getSymbolCache().findSymbolByTypeIndex(
+ Record.getElementType());
+}
+
+uint64_t NativeTypeArray::getLength() const { return Record.Size; } \ No newline at end of file
diff --git a/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp b/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp
new file mode 100644
index 0000000000000..7b0f13f3c0750
--- /dev/null
+++ b/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp
@@ -0,0 +1,47 @@
+//===- NativeTypeBuiltin.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/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypeBuiltin::NativeTypeBuiltin(NativeSession &PDBSession, SymIndexId Id,
+ ModifierOptions Mods, PDB_BuiltinType T,
+ uint64_t L)
+ : NativeRawSymbol(PDBSession, PDB_SymType::BuiltinType, Id),
+ Session(PDBSession), Mods(Mods), Type(T), Length(L) {}
+
+NativeTypeBuiltin::~NativeTypeBuiltin() {}
+
+void NativeTypeBuiltin::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {}
+
+PDB_SymType NativeTypeBuiltin::getSymTag() const {
+ return PDB_SymType::BuiltinType;
+}
+
+PDB_BuiltinType NativeTypeBuiltin::getBuiltinType() const { return Type; }
+
+bool NativeTypeBuiltin::isConstType() const {
+ return (Mods & ModifierOptions::Const) != ModifierOptions::None;
+}
+
+uint64_t NativeTypeBuiltin::getLength() const { return Length; }
+
+bool NativeTypeBuiltin::isUnalignedType() const {
+ return (Mods & ModifierOptions::Unaligned) != ModifierOptions::None;
+}
+
+bool NativeTypeBuiltin::isVolatileType() const {
+ return (Mods & ModifierOptions::Volatile) != ModifierOptions::None;
+}
diff --git a/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp b/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
new file mode 100644
index 0000000000000..37176fe083b97
--- /dev/null
+++ b/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
@@ -0,0 +1,382 @@
+//===- NativeTypeEnum.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/NativeTypeEnum.h"
+
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+
+#include "llvm/Support/FormatVariadic.h"
+
+#include <cassert>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+namespace {
+// Yea, this is a pretty terrible class name. But if we have an enum:
+//
+// enum Foo {
+// A,
+// B
+// };
+//
+// then A and B are the "enumerators" of the "enum" Foo. And we need
+// to enumerate them.
+class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks {
+public:
+ NativeEnumEnumEnumerators(NativeSession &Session,
+ const NativeTypeEnum &ClassParent);
+
+ uint32_t getChildCount() const override;
+ std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
+ std::unique_ptr<PDBSymbol> getNext() override;
+ void reset() override;
+
+private:
+ Error visitKnownMember(CVMemberRecord &CVM,
+ EnumeratorRecord &Record) override;
+ Error visitKnownMember(CVMemberRecord &CVM,
+ ListContinuationRecord &Record) override;
+
+ NativeSession &Session;
+ const NativeTypeEnum &ClassParent;
+ std::vector<EnumeratorRecord> Enumerators;
+ Optional<TypeIndex> ContinuationIndex;
+ uint32_t Index = 0;
+};
+} // namespace
+
+NativeEnumEnumEnumerators::NativeEnumEnumEnumerators(
+ NativeSession &Session, const NativeTypeEnum &ClassParent)
+ : Session(Session), ClassParent(ClassParent) {
+ TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
+ LazyRandomTypeCollection &Types = Tpi.typeCollection();
+
+ ContinuationIndex = ClassParent.getEnumRecord().FieldList;
+ while (ContinuationIndex) {
+ CVType FieldList = Types.getType(*ContinuationIndex);
+ assert(FieldList.kind() == LF_FIELDLIST);
+ ContinuationIndex.reset();
+ cantFail(visitMemberRecordStream(FieldList.data(), *this));
+ }
+}
+
+Error NativeEnumEnumEnumerators::visitKnownMember(CVMemberRecord &CVM,
+ EnumeratorRecord &Record) {
+ Enumerators.push_back(Record);
+ return Error::success();
+}
+
+Error NativeEnumEnumEnumerators::visitKnownMember(
+ CVMemberRecord &CVM, ListContinuationRecord &Record) {
+ ContinuationIndex = Record.ContinuationIndex;
+ return Error::success();
+}
+
+uint32_t NativeEnumEnumEnumerators::getChildCount() const {
+ return Enumerators.size();
+}
+
+std::unique_ptr<PDBSymbol>
+NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const {
+ if (Index >= getChildCount())
+ return nullptr;
+
+ SymIndexId Id = Session.getSymbolCache()
+ .getOrCreateFieldListMember<NativeSymbolEnumerator>(
+ ClassParent.getEnumRecord().FieldList, Index,
+ ClassParent, Enumerators[Index]);
+ return Session.getSymbolCache().getSymbolById(Id);
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumEnumEnumerators::getNext() {
+ if (Index >= getChildCount())
+ return nullptr;
+
+ return getChildAtIndex(Index++);
+}
+
+void NativeEnumEnumEnumerators::reset() { Index = 0; }
+
+NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
+ TypeIndex Index, EnumRecord Record)
+ : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(Index),
+ Record(std::move(Record)) {}
+
+NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
+ NativeTypeEnum &UnmodifiedType,
+ codeview::ModifierRecord Modifier)
+ : NativeRawSymbol(Session, PDB_SymType::Enum, Id),
+ UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {}
+
+NativeTypeEnum::~NativeTypeEnum() {}
+
+void NativeTypeEnum::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolField(OS, "baseType", static_cast<uint32_t>(getBuiltinType()),
+ Indent);
+ dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+ PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolField(OS, "name", getName(), Indent);
+ dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+ PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+ if (Modifiers.hasValue())
+ dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent,
+ Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolField(OS, "length", getLength(), 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::unique_ptr<IPDBEnumSymbols>
+NativeTypeEnum::findChildren(PDB_SymType Type) const {
+ if (Type != PDB_SymType::Data)
+ return llvm::make_unique<NullEnumerator<PDBSymbol>>();
+
+ const NativeTypeEnum *ClassParent = nullptr;
+ if (!Modifiers)
+ ClassParent = this;
+ else
+ ClassParent = UnmodifiedType;
+ return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent);
+}
+
+PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; }
+
+PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getBuiltinType();
+
+ Session.getSymbolCache().findSymbolByTypeIndex(Record->getUnderlyingType());
+
+ codeview::TypeIndex Underlying = Record->getUnderlyingType();
+
+ // This indicates a corrupt record.
+ if (!Underlying.isSimple() ||
+ Underlying.getSimpleMode() != SimpleTypeMode::Direct) {
+ return PDB_BuiltinType::None;
+ }
+
+ switch (Underlying.getSimpleKind()) {
+ case SimpleTypeKind::Boolean128:
+ case SimpleTypeKind::Boolean64:
+ case SimpleTypeKind::Boolean32:
+ case SimpleTypeKind::Boolean16:
+ case SimpleTypeKind::Boolean8:
+ return PDB_BuiltinType::Bool;
+ case SimpleTypeKind::NarrowCharacter:
+ case SimpleTypeKind::UnsignedCharacter:
+ case SimpleTypeKind::SignedCharacter:
+ return PDB_BuiltinType::Char;
+ case SimpleTypeKind::WideCharacter:
+ return PDB_BuiltinType::WCharT;
+ case SimpleTypeKind::Character16:
+ return PDB_BuiltinType::Char16;
+ case SimpleTypeKind::Character32:
+ return PDB_BuiltinType::Char32;
+ case SimpleTypeKind::Int128:
+ case SimpleTypeKind::Int128Oct:
+ case SimpleTypeKind::Int16:
+ case SimpleTypeKind::Int16Short:
+ case SimpleTypeKind::Int32:
+ case SimpleTypeKind::Int32Long:
+ case SimpleTypeKind::Int64:
+ case SimpleTypeKind::Int64Quad:
+ return PDB_BuiltinType::Int;
+ case SimpleTypeKind::UInt128:
+ case SimpleTypeKind::UInt128Oct:
+ case SimpleTypeKind::UInt16:
+ case SimpleTypeKind::UInt16Short:
+ case SimpleTypeKind::UInt32:
+ case SimpleTypeKind::UInt32Long:
+ case SimpleTypeKind::UInt64:
+ case SimpleTypeKind::UInt64Quad:
+ return PDB_BuiltinType::UInt;
+ case SimpleTypeKind::HResult:
+ return PDB_BuiltinType::HResult;
+ case SimpleTypeKind::Complex16:
+ case SimpleTypeKind::Complex32:
+ case SimpleTypeKind::Complex32PartialPrecision:
+ case SimpleTypeKind::Complex64:
+ case SimpleTypeKind::Complex80:
+ case SimpleTypeKind::Complex128:
+ return PDB_BuiltinType::Complex;
+ case SimpleTypeKind::Float16:
+ case SimpleTypeKind::Float32:
+ case SimpleTypeKind::Float32PartialPrecision:
+ case SimpleTypeKind::Float48:
+ case SimpleTypeKind::Float64:
+ case SimpleTypeKind::Float80:
+ case SimpleTypeKind::Float128:
+ return PDB_BuiltinType::Float;
+ default:
+ return PDB_BuiltinType::None;
+ }
+ llvm_unreachable("Unreachable");
+}
+
+SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const {
+ return UnmodifiedType ? UnmodifiedType->getSymIndexId() : 0;
+}
+
+bool NativeTypeEnum::hasConstructor() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasConstructor();
+
+ return bool(Record->getOptions() &
+ codeview::ClassOptions::HasConstructorOrDestructor);
+}
+
+bool NativeTypeEnum::hasAssignmentOperator() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasAssignmentOperator();
+
+ return bool(Record->getOptions() &
+ codeview::ClassOptions::HasOverloadedAssignmentOperator);
+}
+
+bool NativeTypeEnum::hasNestedTypes() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasNestedTypes();
+
+ return bool(Record->getOptions() &
+ codeview::ClassOptions::ContainsNestedClass);
+}
+
+bool NativeTypeEnum::isIntrinsic() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->isIntrinsic();
+
+ return bool(Record->getOptions() & codeview::ClassOptions::Intrinsic);
+}
+
+bool NativeTypeEnum::hasCastOperator() const {
+ 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());
+ const auto UnderlyingType =
+ Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id);
+ return UnderlyingType ? UnderlyingType->getLength() : 0;
+}
+
+std::string NativeTypeEnum::getName() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getName();
+
+ return Record->getName();
+}
+
+bool NativeTypeEnum::isNested() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->isNested();
+
+ return bool(Record->getOptions() & codeview::ClassOptions::Nested);
+}
+
+bool NativeTypeEnum::hasOverloadedOperator() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasOverloadedOperator();
+
+ return bool(Record->getOptions() &
+ codeview::ClassOptions::HasOverloadedOperator);
+}
+
+bool NativeTypeEnum::isPacked() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->isPacked();
+
+ return bool(Record->getOptions() & codeview::ClassOptions::Packed);
+}
+
+bool NativeTypeEnum::isScoped() const {
+ 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());
+}
+
+bool NativeTypeEnum::isRefUdt() const { return false; }
+
+bool NativeTypeEnum::isValueUdt() const { return false; }
+
+bool NativeTypeEnum::isInterfaceUdt() const { return false; }
+
+bool NativeTypeEnum::isConstType() const {
+ if (!Modifiers)
+ return false;
+ return ((Modifiers->getModifiers() & ModifierOptions::Const) !=
+ ModifierOptions::None);
+}
+
+bool NativeTypeEnum::isVolatileType() const {
+ if (!Modifiers)
+ return false;
+ return ((Modifiers->getModifiers() & ModifierOptions::Volatile) !=
+ ModifierOptions::None);
+}
+
+bool NativeTypeEnum::isUnalignedType() const {
+ if (!Modifiers)
+ return false;
+ return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) !=
+ ModifierOptions::None);
+}
+
+const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getUnderlyingBuiltinType();
+
+ return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>(
+ getTypeId());
+}
diff --git a/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp b/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp
new file mode 100644
index 0000000000000..a9590fffdb87e
--- /dev/null
+++ b/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp
@@ -0,0 +1,200 @@
+//===- NativeTypeFunctionSig.cpp - info about function signature -*- 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/NativeTypeFunctionSig.h"
+
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+namespace {
+// This is kind of a silly class, hence why we keep it private to the file.
+// It's only purpose is to wrap the real type record. I guess this is so that
+// we can have the lexical parent point to the function instead of the global
+// scope.
+class NativeTypeFunctionArg : public NativeRawSymbol {
+public:
+ NativeTypeFunctionArg(NativeSession &Session,
+ std::unique_ptr<PDBSymbol> RealType)
+ : NativeRawSymbol(Session, PDB_SymType::FunctionArg, 0),
+ RealType(std::move(RealType)) {}
+
+ void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const override {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+ PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+ }
+
+ SymIndexId getTypeId() const override { return RealType->getSymIndexId(); }
+
+ std::unique_ptr<PDBSymbol> RealType;
+};
+
+class NativeEnumFunctionArgs : public IPDBEnumChildren<PDBSymbol> {
+public:
+ NativeEnumFunctionArgs(NativeSession &Session,
+ std::unique_ptr<NativeEnumTypes> TypeEnumerator)
+ : Session(Session), TypeEnumerator(std::move(TypeEnumerator)) {}
+
+ uint32_t getChildCount() const override {
+ return TypeEnumerator->getChildCount();
+ }
+ std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override {
+ return wrap(TypeEnumerator->getChildAtIndex(Index));
+ }
+ std::unique_ptr<PDBSymbol> getNext() override {
+ return wrap(TypeEnumerator->getNext());
+ }
+
+ void reset() override { TypeEnumerator->reset(); }
+
+private:
+ std::unique_ptr<PDBSymbol> wrap(std::unique_ptr<PDBSymbol> S) const {
+ if (!S)
+ return nullptr;
+ auto NTFA = llvm::make_unique<NativeTypeFunctionArg>(Session, std::move(S));
+ return PDBSymbol::create(Session, std::move(NTFA));
+ }
+ NativeSession &Session;
+ std::unique_ptr<NativeEnumTypes> TypeEnumerator;
+};
+} // namespace
+
+NativeTypeFunctionSig::NativeTypeFunctionSig(NativeSession &Session,
+ SymIndexId Id,
+ codeview::TypeIndex Index,
+ codeview::ProcedureRecord Proc)
+ : NativeRawSymbol(Session, PDB_SymType::FunctionSig, Id),
+ Proc(std::move(Proc)), Index(Index), IsMemberFunction(false) {}
+
+NativeTypeFunctionSig::NativeTypeFunctionSig(
+ NativeSession &Session, SymIndexId Id, codeview::TypeIndex Index,
+ codeview::MemberFunctionRecord MemberFunc)
+ : NativeRawSymbol(Session, PDB_SymType::FunctionSig, Id),
+ MemberFunc(std::move(MemberFunc)), Index(Index), IsMemberFunction(true) {}
+
+void NativeTypeFunctionSig::initialize() {
+ if (IsMemberFunction) {
+ ClassParentId =
+ Session.getSymbolCache().findSymbolByTypeIndex(MemberFunc.ClassType);
+ initializeArgList(MemberFunc.ArgumentList);
+ } else {
+ initializeArgList(Proc.ArgumentList);
+ }
+}
+
+NativeTypeFunctionSig::~NativeTypeFunctionSig() {}
+
+void NativeTypeFunctionSig::initializeArgList(codeview::TypeIndex ArgListTI) {
+ TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
+ CVType CVT = Tpi.typeCollection().getType(ArgListTI);
+
+ cantFail(TypeDeserializer::deserializeAs<ArgListRecord>(CVT, ArgList));
+}
+
+void NativeTypeFunctionSig::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+ PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+
+ dumpSymbolField(OS, "callingConvention", getCallingConvention(), Indent);
+ dumpSymbolField(OS, "count", getCount(), Indent);
+ dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+ PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+ if (IsMemberFunction)
+ dumpSymbolField(OS, "thisAdjust", getThisAdjust(), Indent);
+ dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
+ dumpSymbolField(OS, "constType", isConstType(), Indent);
+ dumpSymbolField(OS, "isConstructorVirtualBase", isConstructorVirtualBase(),
+ Indent);
+ dumpSymbolField(OS, "isCxxReturnUdt", isCxxReturnUdt(), Indent);
+ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+ dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeTypeFunctionSig::findChildren(PDB_SymType Type) const {
+ if (Type != PDB_SymType::FunctionArg)
+ return llvm::make_unique<NullEnumerator<PDBSymbol>>();
+
+ auto NET = llvm::make_unique<NativeEnumTypes>(Session,
+ /* copy */ ArgList.ArgIndices);
+ return std::unique_ptr<IPDBEnumSymbols>(
+ new NativeEnumFunctionArgs(Session, std::move(NET)));
+}
+
+SymIndexId NativeTypeFunctionSig::getClassParentId() const {
+ if (!IsMemberFunction)
+ return 0;
+
+ return ClassParentId;
+}
+
+PDB_CallingConv NativeTypeFunctionSig::getCallingConvention() const {
+ return IsMemberFunction ? MemberFunc.CallConv : Proc.CallConv;
+}
+
+uint32_t NativeTypeFunctionSig::getCount() const {
+ return IsMemberFunction ? (1 + MemberFunc.getParameterCount())
+ : Proc.getParameterCount();
+}
+
+SymIndexId NativeTypeFunctionSig::getTypeId() const {
+ TypeIndex ReturnTI =
+ IsMemberFunction ? MemberFunc.getReturnType() : Proc.getReturnType();
+
+ SymIndexId Result = Session.getSymbolCache().findSymbolByTypeIndex(ReturnTI);
+ return Result;
+}
+
+int32_t NativeTypeFunctionSig::getThisAdjust() const {
+ return IsMemberFunction ? MemberFunc.getThisPointerAdjustment() : 0;
+}
+
+bool NativeTypeFunctionSig::hasConstructor() const {
+ if (!IsMemberFunction)
+ return false;
+
+ return (MemberFunc.getOptions() & FunctionOptions::Constructor) !=
+ FunctionOptions::None;
+}
+
+bool NativeTypeFunctionSig::isConstType() const { return false; }
+
+bool NativeTypeFunctionSig::isConstructorVirtualBase() const {
+ if (!IsMemberFunction)
+ return false;
+
+ return (MemberFunc.getOptions() &
+ FunctionOptions::ConstructorWithVirtualBases) !=
+ FunctionOptions::None;
+}
+
+bool NativeTypeFunctionSig::isCxxReturnUdt() const {
+ FunctionOptions Options =
+ IsMemberFunction ? MemberFunc.getOptions() : Proc.getOptions();
+ return (Options & FunctionOptions::CxxReturnUdt) != FunctionOptions::None;
+}
+
+bool NativeTypeFunctionSig::isUnalignedType() const { return false; }
+
+bool NativeTypeFunctionSig::isVolatileType() const { return false; }
diff --git a/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp b/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp
new file mode 100644
index 0000000000000..bd8ecb6c4007b
--- /dev/null
+++ b/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp
@@ -0,0 +1,194 @@
+//===- NativeTypePointer.cpp - info about pointer 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/NativeTypePointer.h"
+
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+
+#include <cassert>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypePointer::NativeTypePointer(NativeSession &Session, SymIndexId Id,
+ codeview::TypeIndex TI)
+ : NativeRawSymbol(Session, PDB_SymType::PointerType, Id), TI(TI) {
+ assert(TI.isSimple());
+ assert(TI.getSimpleMode() != SimpleTypeMode::Direct);
+}
+
+NativeTypePointer::NativeTypePointer(NativeSession &Session, SymIndexId Id,
+ codeview::TypeIndex TI,
+ codeview::PointerRecord Record)
+ : NativeRawSymbol(Session, PDB_SymType::PointerType, Id), TI(TI),
+ Record(std::move(Record)) {}
+
+NativeTypePointer::~NativeTypePointer() {}
+
+void NativeTypePointer::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ if (isMemberPointer()) {
+ dumpSymbolIdField(OS, "classParentId", getClassParentId(), Indent, Session,
+ PdbSymbolIdField::ClassParent, ShowIdFields,
+ RecurseIdFields);
+ }
+ dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+ PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+ PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+ dumpSymbolField(OS, "length", getLength(), Indent);
+ dumpSymbolField(OS, "constType", isConstType(), Indent);
+ dumpSymbolField(OS, "isPointerToDataMember", isPointerToDataMember(), Indent);
+ dumpSymbolField(OS, "isPointerToMemberFunction", isPointerToMemberFunction(),
+ Indent);
+ dumpSymbolField(OS, "RValueReference", isRValueReference(), Indent);
+ dumpSymbolField(OS, "reference", isReference(), Indent);
+ dumpSymbolField(OS, "restrictedType", isRestrictedType(), Indent);
+ if (isMemberPointer()) {
+ if (isSingleInheritance())
+ dumpSymbolField(OS, "isSingleInheritance", 1, Indent);
+ else if (isMultipleInheritance())
+ dumpSymbolField(OS, "isMultipleInheritance", 1, Indent);
+ else if (isVirtualInheritance())
+ dumpSymbolField(OS, "isVirtualInheritance", 1, Indent);
+ }
+ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+ dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+SymIndexId NativeTypePointer::getClassParentId() const {
+ if (!isMemberPointer())
+ return 0;
+
+ assert(Record);
+ const MemberPointerInfo &MPI = Record->getMemberInfo();
+ return Session.getSymbolCache().findSymbolByTypeIndex(MPI.ContainingType);
+}
+
+uint64_t NativeTypePointer::getLength() const {
+ if (Record)
+ return Record->getSize();
+
+ switch (TI.getSimpleMode()) {
+ case SimpleTypeMode::NearPointer:
+ case SimpleTypeMode::FarPointer:
+ case SimpleTypeMode::HugePointer:
+ return 2;
+ case SimpleTypeMode::NearPointer32:
+ case SimpleTypeMode::FarPointer32:
+ return 4;
+ case SimpleTypeMode::NearPointer64:
+ return 8;
+ case SimpleTypeMode::NearPointer128:
+ return 16;
+ default:
+ assert(false && "invalid simple type mode!");
+ }
+ return 0;
+}
+
+SymIndexId NativeTypePointer::getTypeId() const {
+ // This is the pointee SymIndexId.
+ TypeIndex Referent = Record ? Record->ReferentType : TI.makeDirect();
+
+ return Session.getSymbolCache().findSymbolByTypeIndex(Referent);
+}
+
+bool NativeTypePointer::isReference() const {
+ if (!Record)
+ return false;
+ return Record->getMode() == PointerMode::LValueReference;
+}
+
+bool NativeTypePointer::isRValueReference() const {
+ if (!Record)
+ return false;
+ return Record->getMode() == PointerMode::RValueReference;
+}
+
+bool NativeTypePointer::isPointerToDataMember() const {
+ if (!Record)
+ return false;
+ return Record->getMode() == PointerMode::PointerToDataMember;
+}
+
+bool NativeTypePointer::isPointerToMemberFunction() const {
+ if (!Record)
+ return false;
+ return Record->getMode() == PointerMode::PointerToMemberFunction;
+}
+
+bool NativeTypePointer::isConstType() const {
+ if (!Record)
+ return false;
+ return (Record->getOptions() & PointerOptions::Const) != PointerOptions::None;
+}
+
+bool NativeTypePointer::isRestrictedType() const {
+ if (!Record)
+ return false;
+ return (Record->getOptions() & PointerOptions::Restrict) !=
+ PointerOptions::None;
+}
+
+bool NativeTypePointer::isVolatileType() const {
+ if (!Record)
+ return false;
+ return (Record->getOptions() & PointerOptions::Volatile) !=
+ PointerOptions::None;
+}
+
+bool NativeTypePointer::isUnalignedType() const {
+ if (!Record)
+ return false;
+ return (Record->getOptions() & PointerOptions::Unaligned) !=
+ PointerOptions::None;
+}
+
+static inline bool isInheritanceKind(const MemberPointerInfo &MPI,
+ PointerToMemberRepresentation P1,
+ PointerToMemberRepresentation P2) {
+ return (MPI.getRepresentation() == P1 || MPI.getRepresentation() == P2);
+}
+
+bool NativeTypePointer::isSingleInheritance() const {
+ if (!isMemberPointer())
+ return false;
+ return isInheritanceKind(
+ Record->getMemberInfo(),
+ PointerToMemberRepresentation::SingleInheritanceData,
+ PointerToMemberRepresentation::SingleInheritanceFunction);
+}
+
+bool NativeTypePointer::isMultipleInheritance() const {
+ if (!isMemberPointer())
+ return false;
+ return isInheritanceKind(
+ Record->getMemberInfo(),
+ PointerToMemberRepresentation::MultipleInheritanceData,
+ PointerToMemberRepresentation::MultipleInheritanceFunction);
+}
+
+bool NativeTypePointer::isVirtualInheritance() const {
+ if (!isMemberPointer())
+ return false;
+ return isInheritanceKind(
+ Record->getMemberInfo(),
+ PointerToMemberRepresentation::VirtualInheritanceData,
+ PointerToMemberRepresentation::VirtualInheritanceFunction);
+}
+
+bool NativeTypePointer::isMemberPointer() const {
+ return isPointerToDataMember() || isPointerToMemberFunction();
+}
diff --git a/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp b/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp
new file mode 100644
index 0000000000000..60b3732822670
--- /dev/null
+++ b/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp
@@ -0,0 +1,27 @@
+#include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypeTypedef::NativeTypeTypedef(NativeSession &Session, SymIndexId Id,
+ codeview::UDTSym Typedef)
+ : NativeRawSymbol(Session, PDB_SymType::Typedef, Id),
+ Record(std::move(Typedef)) {}
+
+NativeTypeTypedef::~NativeTypeTypedef() {}
+
+void NativeTypeTypedef::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+ dumpSymbolField(OS, "name", getName(), Indent);
+ dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+ PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+}
+
+std::string NativeTypeTypedef::getName() const { return Record.Name; }
+
+SymIndexId NativeTypeTypedef::getTypeId() const {
+ return Session.getSymbolCache().findSymbolByTypeIndex(Record.Type);
+}
diff --git a/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp b/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp
new file mode 100644
index 0000000000000..3abf91dcc6a38
--- /dev/null
+++ b/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/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp b/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp
new file mode 100644
index 0000000000000..837fe19ec88c0
--- /dev/null
+++ b/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp
@@ -0,0 +1,35 @@
+#include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+// Create a pointer record for a non-simple type.
+NativeTypeVTShape::NativeTypeVTShape(NativeSession &Session, SymIndexId Id,
+ codeview::TypeIndex TI,
+ codeview::VFTableShapeRecord SR)
+ : NativeRawSymbol(Session, PDB_SymType::VTableShape, Id), TI(TI),
+ Record(std::move(SR)) {}
+
+NativeTypeVTShape::~NativeTypeVTShape() {}
+
+void NativeTypeVTShape::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+ PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolField(OS, "count", getCount(), Indent);
+ dumpSymbolField(OS, "constType", isConstType(), Indent);
+ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+ dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+bool NativeTypeVTShape::isConstType() const { return false; }
+
+bool NativeTypeVTShape::isVolatileType() const { return false; }
+
+bool NativeTypeVTShape::isUnalignedType() const { return false; }
+
+uint32_t NativeTypeVTShape::getCount() const { return Record.Slots.size(); }
diff --git a/lib/DebugInfo/PDB/Native/PDBFile.cpp b/lib/DebugInfo/PDB/Native/PDBFile.cpp
index 78b11937f051d..a1f8786ff12fb 100644
--- a/lib/DebugInfo/PDB/Native/PDBFile.cpp
+++ b/lib/DebugInfo/PDB/Native/PDBFile.cpp
@@ -125,7 +125,7 @@ Error PDBFile::parseFileHeaders() {
if (auto EC = Reader.readObject(SB)) {
consumeError(std::move(EC));
return make_error<RawError>(raw_error_code::corrupt_file,
- "Does not contain superblock");
+ "MSF superblock is missing");
}
if (auto EC = msf::validateSuperBlock(*SB))
@@ -401,7 +401,9 @@ uint32_t PDBFile::getPointerSize() {
return 4;
}
-bool PDBFile::hasPDBDbiStream() const { return StreamDBI < getNumStreams(); }
+bool PDBFile::hasPDBDbiStream() const {
+ return StreamDBI < getNumStreams() && getStreamByteSize(StreamDBI) > 0;
+}
bool PDBFile::hasPDBGlobalsStream() {
auto DbiS = getPDBDbiStream();
diff --git a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
index e164e7cf1c52b..e0ceb7499ee53 100644
--- a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
@@ -12,7 +12,6 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
-#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
@@ -26,6 +25,7 @@
#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/JamCRC.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/xxhash.h"
using namespace llvm;
using namespace llvm::codeview;
@@ -262,13 +262,14 @@ void PDBFileBuilder::commitInjectedSources(WritableBinaryStream &MsfBuffer,
}
}
-Error PDBFileBuilder::commit(StringRef Filename) {
+Error PDBFileBuilder::commit(StringRef Filename, codeview::GUID *Guid) {
assert(!Filename.empty());
if (auto EC = finalizeMsfLayout())
return EC;
MSFLayout Layout;
- auto ExpectedMsfBuffer = Msf->commit(Filename, Layout);
+ Expected<FileBufferByteStream> ExpectedMsfBuffer =
+ Msf->commit(Filename, Layout);
if (!ExpectedMsfBuffer)
return ExpectedMsfBuffer.takeError();
FileBufferByteStream Buffer = std::move(*ExpectedMsfBuffer);
@@ -330,11 +331,28 @@ Error PDBFileBuilder::commit(StringRef Filename) {
// Set the build id at the very end, after every other byte of the PDB
// has been written.
- // FIXME: Use a hash of the PDB rather than time(nullptr) for the signature.
- H->Age = Info->getAge();
- H->Guid = Info->getGuid();
- Optional<uint32_t> Sig = Info->getSignature();
- H->Signature = Sig.hasValue() ? *Sig : time(nullptr);
+ if (Info->hashPDBContentsToGUID()) {
+ // Compute a hash of all sections of the output file.
+ uint64_t Digest =
+ xxHash64({Buffer.getBufferStart(), Buffer.getBufferEnd()});
+
+ H->Age = 1;
+
+ memcpy(H->Guid.Guid, &Digest, 8);
+ // xxhash only gives us 8 bytes, so put some fixed data in the other half.
+ memcpy(H->Guid.Guid + 8, "LLD PDB.", 8);
+
+ // Put the hash in the Signature field too.
+ H->Signature = static_cast<uint32_t>(Digest);
+
+ // Return GUID to caller.
+ memcpy(Guid, H->Guid.Guid, 16);
+ } else {
+ H->Age = Info->getAge();
+ H->Guid = Info->getGuid();
+ Optional<uint32_t> Sig = Info->getSignature();
+ H->Signature = Sig.hasValue() ? *Sig : time(nullptr);
+ }
return Buffer.commit();
}
diff --git a/lib/DebugInfo/PDB/Native/RawError.cpp b/lib/DebugInfo/PDB/Native/RawError.cpp
index 548289fff3dfe..dec9797088f23 100644
--- a/lib/DebugInfo/PDB/Native/RawError.cpp
+++ b/lib/DebugInfo/PDB/Native/RawError.cpp
@@ -5,14 +5,12 @@
using namespace llvm;
using namespace llvm::pdb;
-namespace {
// FIXME: This class is only here to support the transition to llvm::Error. It
// will be removed once this transition is complete. Clients should prefer to
// deal with the Error value directly, rather than converting to error_code.
class RawErrorCategory : public std::error_category {
public:
const char *name() const noexcept override { return "llvm.pdb.raw"; }
-
std::string message(int Condition) const override {
switch (static_cast<raw_error_code>(Condition)) {
case raw_error_code::unspecified:
@@ -46,30 +44,8 @@ public:
llvm_unreachable("Unrecognized raw_error_code");
}
};
-} // end anonymous namespace
-
-static ManagedStatic<RawErrorCategory> Category;
-
-char RawError::ID = 0;
-
-RawError::RawError(raw_error_code C) : RawError(C, "") {}
-
-RawError::RawError(const std::string &Context)
- : RawError(raw_error_code::unspecified, Context) {}
-
-RawError::RawError(raw_error_code C, const std::string &Context) : Code(C) {
- ErrMsg = "Native PDB Error: ";
- std::error_code EC = convertToErrorCode();
- if (Code != raw_error_code::unspecified)
- ErrMsg += EC.message() + " ";
- if (!Context.empty())
- ErrMsg += Context;
-}
-
-void RawError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; }
-const std::string &RawError::getErrorMessage() const { return ErrMsg; }
+static llvm::ManagedStatic<RawErrorCategory> RawCategory;
+const std::error_category &llvm::pdb::RawErrCategory() { return *RawCategory; }
-std::error_code RawError::convertToErrorCode() const {
- return std::error_code(static_cast<int>(Code), *Category);
-}
+char RawError::ID;
diff --git a/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/lib/DebugInfo/PDB/Native/SymbolCache.cpp
new file mode 100644
index 0000000000000..5cdd628312fe5
--- /dev/null
+++ b/lib/DebugInfo/PDB/Native/SymbolCache.cpp
@@ -0,0 +1,299 @@
+#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.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/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+// Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
+// to instantiate a NativeBuiltinSymbol for that type.
+static const struct BuiltinTypeEntry {
+ codeview::SimpleTypeKind Kind;
+ PDB_BuiltinType Type;
+ uint32_t Size;
+} BuiltinTypes[] = {
+ {codeview::SimpleTypeKind::None, PDB_BuiltinType::None, 0},
+ {codeview::SimpleTypeKind::Void, PDB_BuiltinType::Void, 0},
+ {codeview::SimpleTypeKind::HResult, PDB_BuiltinType::HResult, 4},
+ {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
+ {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
+ {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
+ {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
+ {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
+ {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
+ {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
+ {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
+ {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
+ {codeview::SimpleTypeKind::WideCharacter, PDB_BuiltinType::WCharT, 2},
+ {codeview::SimpleTypeKind::Character16, PDB_BuiltinType::Char16, 2},
+ {codeview::SimpleTypeKind::Character32, PDB_BuiltinType::Char32, 4},
+ {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
+ {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
+ {codeview::SimpleTypeKind::Float32, PDB_BuiltinType::Float, 4},
+ {codeview::SimpleTypeKind::Float64, PDB_BuiltinType::Float, 8},
+ {codeview::SimpleTypeKind::Float80, PDB_BuiltinType::Float, 10},
+ {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1},
+ // This table can be grown as necessary, but these are the only types we've
+ // needed so far.
+};
+
+SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
+ : Session(Session), Dbi(Dbi) {
+ // Id 0 is reserved for the invalid symbol.
+ Cache.push_back(nullptr);
+
+ if (Dbi)
+ Compilands.resize(Dbi->modules().getModuleCount());
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
+ return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
+ auto Tpi = Session.getPDBFile().getPDBTpiStream();
+ if (!Tpi) {
+ consumeError(Tpi.takeError());
+ return nullptr;
+ }
+ auto &Types = Tpi->typeCollection();
+ return std::unique_ptr<IPDBEnumSymbols>(
+ new NativeEnumTypes(Session, Types, std::move(Kinds)));
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {
+ return std::unique_ptr<IPDBEnumSymbols>(
+ new NativeEnumGlobals(Session, {Kind}));
+}
+
+SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
+ ModifierOptions Mods) {
+ if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
+ return createSymbol<NativeTypePointer>(Index);
+
+ const auto Kind = Index.getSimpleKind();
+ const auto It = std::find_if(
+ std::begin(BuiltinTypes), std::end(BuiltinTypes),
+ [Kind](const BuiltinTypeEntry &Builtin) { return Builtin.Kind == Kind; });
+ if (It == std::end(BuiltinTypes))
+ return 0;
+ return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
+}
+
+SymIndexId
+SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
+ codeview::CVType CVT) {
+ ModifierRecord Record;
+ if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
+ consumeError(std::move(EC));
+ return 0;
+ }
+
+ if (Record.ModifiedType.isSimple())
+ return createSimpleType(Record.ModifiedType, Record.Modifiers);
+
+ // 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 0;
+}
+
+SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
+ // First see if it's already in our cache.
+ const auto Entry = TypeIndexToSymbolId.find(Index);
+ if (Entry != TypeIndexToSymbolId.end())
+ return Entry->second;
+
+ // Symbols for built-in types are created on the fly.
+ if (Index.isSimple()) {
+ SymIndexId Result = createSimpleType(Index, ModifierOptions::None);
+ assert(TypeIndexToSymbolId.count(Index) == 0);
+ TypeIndexToSymbolId[Index] = Result;
+ return Result;
+ }
+
+ // We need to instantiate and cache the desired type symbol.
+ auto Tpi = Session.getPDBFile().getPDBTpiStream();
+ if (!Tpi) {
+ consumeError(Tpi.takeError());
+ return 0;
+ }
+ codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
+ codeview::CVType CVT = Types.getType(Index);
+
+ 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.
+ assert(TypeIndexToSymbolId.count(Index) == 0);
+ 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_ARRAY:
+ Id = createSymbolForType<NativeTypeArray, ArrayRecord>(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));
+ break;
+ case codeview::LF_MODIFIER:
+ Id = createSymbolForModifiedType(Index, std::move(CVT));
+ break;
+ case codeview::LF_PROCEDURE:
+ Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
+ Index, std::move(CVT));
+ break;
+ case codeview::LF_MFUNCTION:
+ Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
+ Index, std::move(CVT));
+ break;
+ case codeview::LF_VTSHAPE:
+ Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
+ Index, std::move(CVT));
+ break;
+ default:
+ Id = createSymbolPlaceholder();
+ break;
+ }
+ if (Id != 0) {
+ assert(TypeIndexToSymbolId.count(Index) == 0);
+ TypeIndexToSymbolId[Index] = Id;
+ }
+ return Id;
+}
+
+std::unique_ptr<PDBSymbol>
+SymbolCache::getSymbolById(SymIndexId SymbolId) const {
+ assert(SymbolId < Cache.size());
+
+ // Id 0 is reserved.
+ if (SymbolId == 0 || SymbolId >= Cache.size())
+ return nullptr;
+
+ // Make sure to handle the case where we've inserted a placeholder symbol
+ // for types we don't yet suppport.
+ NativeRawSymbol *NRS = Cache[SymbolId].get();
+ if (!NRS)
+ return nullptr;
+
+ return PDBSymbol::create(Session, *NRS);
+}
+
+NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
+ return *Cache[SymbolId];
+}
+
+uint32_t SymbolCache::getNumCompilands() const {
+ if (!Dbi)
+ return 0;
+
+ return Dbi->modules().getModuleCount();
+}
+
+SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
+ auto Iter = GlobalOffsetToSymbolId.find(Offset);
+ if (Iter != GlobalOffsetToSymbolId.end())
+ return Iter->second;
+
+ SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());
+ CVSymbol CVS = SS.readRecord(Offset);
+ SymIndexId Id = 0;
+ switch (CVS.kind()) {
+ case SymbolKind::S_UDT: {
+ UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));
+ Id = createSymbol<NativeTypeTypedef>(std::move(US));
+ break;
+ }
+ default:
+ Id = createSymbolPlaceholder();
+ break;
+ }
+ if (Id != 0) {
+ assert(GlobalOffsetToSymbolId.count(Offset) == 0);
+ GlobalOffsetToSymbolId[Offset] = Id;
+ }
+
+ return Id;
+}
+
+std::unique_ptr<PDBSymbolCompiland>
+SymbolCache::getOrCreateCompiland(uint32_t Index) {
+ if (!Dbi)
+ return nullptr;
+
+ if (Index >= Compilands.size())
+ return nullptr;
+
+ if (Compilands[Index] == 0) {
+ const DbiModuleList &Modules = Dbi->modules();
+ Compilands[Index] =
+ createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
+ }
+
+ return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
+}
diff --git a/lib/DebugInfo/PDB/Native/TpiHashing.cpp b/lib/DebugInfo/PDB/Native/TpiHashing.cpp
index 77a2d57a83698..18708826ffc78 100644
--- a/lib/DebugInfo/PDB/Native/TpiHashing.cpp
+++ b/lib/DebugInfo/PDB/Native/TpiHashing.cpp
@@ -50,6 +50,32 @@ static Expected<uint32_t> getHashForUdt(const CVType &Rec) {
}
template <typename T>
+static Expected<TagRecordHash> getTagRecordHashForUdt(const CVType &Rec) {
+ T Deserialized;
+ if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
+ Deserialized))
+ return std::move(E);
+
+ ClassOptions Opts = Deserialized.getOptions();
+
+ bool ForwardRef = bool(Opts & ClassOptions::ForwardReference);
+
+ uint32_t ThisRecordHash = getHashForUdt(Deserialized, Rec.data());
+
+ // If we don't have a forward ref we can't compute the hash of it from the
+ // full record because it requires hashing the entire buffer.
+ if (!ForwardRef)
+ return TagRecordHash{std::move(Deserialized), ThisRecordHash, 0};
+
+ bool Scoped = bool(Opts & ClassOptions::Scoped);
+
+ StringRef NameToHash =
+ Scoped ? Deserialized.getUniqueName() : Deserialized.getName();
+ uint32_t FullHash = hashStringV1(NameToHash);
+ return TagRecordHash{std::move(Deserialized), FullHash, ThisRecordHash};
+}
+
+template <typename T>
static Expected<uint32_t> getSourceLineHash(const CVType &Rec) {
T Deserialized;
if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
@@ -60,6 +86,23 @@ static Expected<uint32_t> getSourceLineHash(const CVType &Rec) {
return hashStringV1(StringRef(Buf, 4));
}
+Expected<TagRecordHash> llvm::pdb::hashTagRecord(const codeview::CVType &Type) {
+ switch (Type.kind()) {
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ case LF_INTERFACE:
+ return getTagRecordHashForUdt<ClassRecord>(Type);
+ case LF_UNION:
+ return getTagRecordHashForUdt<UnionRecord>(Type);
+ case LF_ENUM:
+ return getTagRecordHashForUdt<EnumRecord>(Type);
+ default:
+ assert(false && "Type is not a tag record!");
+ }
+ return make_error<StringError>("Invalid record type",
+ inconvertibleErrorCode());
+}
+
Expected<uint32_t> llvm::pdb::hashTypeRecord(const CVType &Rec) {
switch (Rec.kind()) {
case LF_CLASS:
diff --git a/lib/DebugInfo/PDB/Native/TpiStream.cpp b/lib/DebugInfo/PDB/Native/TpiStream.cpp
index 0680b673380a6..f234d446e6a09 100644
--- a/lib/DebugInfo/PDB/Native/TpiStream.cpp
+++ b/lib/DebugInfo/PDB/Native/TpiStream.cpp
@@ -11,8 +11,11 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/RecordName.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"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
@@ -140,6 +143,88 @@ uint16_t TpiStream::getTypeHashStreamAuxIndex() const {
uint32_t TpiStream::getNumHashBuckets() const { return Header->NumHashBuckets; }
uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; }
+void TpiStream::buildHashMap() {
+ if (!HashMap.empty())
+ return;
+ if (HashValues.empty())
+ return;
+
+ HashMap.resize(Header->NumHashBuckets);
+
+ TypeIndex TIB{Header->TypeIndexBegin};
+ TypeIndex TIE{Header->TypeIndexEnd};
+ while (TIB < TIE) {
+ uint32_t HV = HashValues[TIB.toArrayIndex()];
+ HashMap[HV].push_back(TIB++);
+ }
+}
+
+std::vector<TypeIndex> TpiStream::findRecordsByName(StringRef Name) const {
+ if (!supportsTypeLookup())
+ const_cast<TpiStream*>(this)->buildHashMap();
+
+ uint32_t Bucket = hashStringV1(Name) % Header->NumHashBuckets;
+ if (Bucket > HashMap.size())
+ return {};
+
+ std::vector<TypeIndex> Result;
+ for (TypeIndex TI : HashMap[Bucket]) {
+ std::string ThisName = computeTypeName(*Types, TI);
+ if (ThisName == Name)
+ Result.push_back(TI);
+ }
+ return Result;
+}
+
+bool TpiStream::supportsTypeLookup() const { return !HashMap.empty(); }
+
+Expected<TypeIndex>
+TpiStream::findFullDeclForForwardRef(TypeIndex ForwardRefTI) const {
+ if (!supportsTypeLookup())
+ const_cast<TpiStream*>(this)->buildHashMap();
+
+ CVType F = Types->getType(ForwardRefTI);
+ if (!isUdtForwardRef(F))
+ return ForwardRefTI;
+
+ Expected<TagRecordHash> ForwardTRH = hashTagRecord(F);
+ if (!ForwardTRH)
+ return ForwardTRH.takeError();
+
+ uint32_t BucketIdx = ForwardTRH->FullRecordHash % Header->NumHashBuckets;
+
+ for (TypeIndex TI : HashMap[BucketIdx]) {
+ CVType CVT = Types->getType(TI);
+ if (CVT.kind() != F.kind())
+ continue;
+
+ Expected<TagRecordHash> FullTRH = hashTagRecord(CVT);
+ if (!FullTRH)
+ return FullTRH.takeError();
+ if (ForwardTRH->FullRecordHash != FullTRH->FullRecordHash)
+ continue;
+ TagRecord &ForwardTR = ForwardTRH->getRecord();
+ TagRecord &FullTR = FullTRH->getRecord();
+
+ if (!ForwardTR.hasUniqueName()) {
+ if (ForwardTR.getName() == FullTR.getName())
+ return TI;
+ continue;
+ }
+
+ if (!FullTR.hasUniqueName())
+ continue;
+ if (ForwardTR.getUniqueName() == FullTR.getUniqueName())
+ return TI;
+ }
+ return ForwardRefTI;
+}
+
+codeview::CVType TpiStream::getType(codeview::TypeIndex Index) {
+ assert(!Index.isSimple());
+ return Types->getType(Index);
+}
+
BinarySubstreamRef TpiStream::getTypeRecordsSubstream() const {
return TypeRecordsSubstream;
}