aboutsummaryrefslogtreecommitdiff
path: root/lld
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2020-06-03 18:08:55 -0700
committerReid Kleckner <rnk@google.com>2020-09-17 11:53:10 -0700
commit1e5b7e91aa64c267e495cb4bd8351b1840694437 (patch)
treed2e33ef91c7c2bfa15f874ec92176fed6e769430 /lld
parent7d5b10348371644c69041965b9864886e9961ddd (diff)
downloadllvm-1e5b7e91aa64c267e495cb4bd8351b1840694437.zip
llvm-1e5b7e91aa64c267e495cb4bd8351b1840694437.tar.gz
llvm-1e5b7e91aa64c267e495cb4bd8351b1840694437.tar.bz2
[PDB] Split TypeServerSource and extend type index map lifetime
Extending the lifetime of these type index mappings does increase memory usage (+2% in my case), but it decouples type merging from symbol merging. This is a pre-requisite for two changes that I have in mind: - parallel type merging: speeds up slow type merging - defered symbol merging: avoid heap allocating (relocating) all symbols This eliminates CVIndexMap and moves its data into TpiSource. The maps are also split into a SmallVector and ArrayRef component, so that the ipiMap can alias the tpiMap for /Z7 object files, and so that both maps can simply alias the PDB type server maps for /Zi files. Splitting TypeServerSource establishes that all input types to be merged can be identified with two 32-bit indices: - The index of the TpiSource object - The type index of the record This is useful, because this information can be stored in a single 64-bit atomic word to enable concurrent hashtable insertion. One last change is that now all object files with debugChunks get a TpiSource, even if they have no type info. This avoids some null checks and special cases. Differential Revision: https://reviews.llvm.org/D87736
Diffstat (limited to 'lld')
-rw-r--r--lld/COFF/DebugTypes.cpp141
-rw-r--r--lld/COFF/DebugTypes.h20
-rw-r--r--lld/COFF/InputFiles.cpp8
-rw-r--r--lld/COFF/PDB.cpp80
-rw-r--r--lld/COFF/TypeMerger.h9
5 files changed, 130 insertions, 128 deletions
diff --git a/lld/COFF/DebugTypes.cpp b/lld/COFF/DebugTypes.cpp
index 3a9bd83..4695933 100644
--- a/lld/COFF/DebugTypes.cpp
+++ b/lld/COFF/DebugTypes.cpp
@@ -29,6 +29,8 @@ using namespace lld;
using namespace lld::coff;
namespace {
+class TypeServerIpiSource;
+
// The TypeServerSource class represents a PDB type server, a file referenced by
// OBJ files compiled with MSVC /Zi. A single PDB can be shared by several OBJ
// files, therefore there must be only once instance per OBJ lot. The file path
@@ -49,20 +51,35 @@ public:
auto it = mappings.emplace(expectedInfo->getGuid(), this);
assert(it.second);
(void)it;
- tsIndexMap.isTypeServerMap = true;
}
- Expected<const CVIndexMap *> mergeDebugT(TypeMerger *m,
- CVIndexMap *indexMap) override;
+ Error mergeDebugT(TypeMerger *m) override;
bool isDependency() const override { return true; }
PDBInputFile *pdbInputFile = nullptr;
- CVIndexMap tsIndexMap;
+ // TpiSource for IPI stream.
+ TypeServerIpiSource *ipiSrc = nullptr;
static std::map<codeview::GUID, TypeServerSource *> mappings;
};
+// Companion to TypeServerSource. Stores the index map for the IPI stream in the
+// PDB. Modeling PDBs with two sources for TPI and IPI helps establish the
+// invariant of one type index space per source.
+class TypeServerIpiSource : public TpiSource {
+public:
+ explicit TypeServerIpiSource() : TpiSource(PDBIpi, nullptr) {}
+
+ friend class TypeServerSource;
+
+ // IPI merging is handled in TypeServerSource::mergeDebugT, since it depends
+ // directly on type merging.
+ Error mergeDebugT(TypeMerger *m) override { return Error::success(); }
+
+ bool isDependency() const override { return true; }
+};
+
// This class represents the debug type stream of an OBJ file that depends on a
// PDB type server (see TypeServerSource).
class UseTypeServerSource : public TpiSource {
@@ -70,8 +87,7 @@ public:
UseTypeServerSource(ObjFile *f, TypeServer2Record ts)
: TpiSource(UsingPDB, f), typeServerDependency(ts) {}
- Expected<const CVIndexMap *> mergeDebugT(TypeMerger *m,
- CVIndexMap *indexMap) override;
+ Error mergeDebugT(TypeMerger *m) override;
// Information about the PDB type server dependency, that needs to be loaded
// in before merging this OBJ.
@@ -92,15 +108,10 @@ public:
if (!it.second)
fatal("a PCH object with the same signature has already been provided (" +
toString(it.first->second->file) + " and " + toString(file) + ")");
- precompIndexMap.isPrecompiledTypeMap = true;
}
- Expected<const CVIndexMap *> mergeDebugT(TypeMerger *m,
- CVIndexMap *indexMap) override;
bool isDependency() const override { return true; }
- CVIndexMap precompIndexMap;
-
static std::map<uint32_t, PrecompSource *> mappings;
};
@@ -111,8 +122,7 @@ public:
UsePrecompSource(ObjFile *f, PrecompRecord precomp)
: TpiSource(UsingPCH, f), precompDependency(precomp) {}
- Expected<const CVIndexMap *> mergeDebugT(TypeMerger *m,
- CVIndexMap *indexMap) override;
+ Error mergeDebugT(TypeMerger *m) override;
// Information about the Precomp OBJ dependency, that needs to be loaded in
// before merging this OBJ.
@@ -134,7 +144,11 @@ TpiSource *lld::coff::makeTpiSource(ObjFile *file) {
}
TpiSource *lld::coff::makeTypeServerSource(PDBInputFile *pdbInputFile) {
- return make<TypeServerSource>(pdbInputFile);
+ // Type server sources come in pairs: the TPI stream, and the IPI stream.
+ auto *tpiSource = make<TypeServerSource>(pdbInputFile);
+ if (pdbInputFile->session->getPDBFile().hasPDBIpiStream())
+ tpiSource->ipiSrc = make<TypeServerIpiSource>();
+ return tpiSource;
}
TpiSource *lld::coff::makeUseTypeServerSource(ObjFile *file,
@@ -196,8 +210,7 @@ getHashesFromDebugH(ArrayRef<uint8_t> debugH) {
}
// Merge .debug$T for a generic object file.
-Expected<const CVIndexMap *> TpiSource::mergeDebugT(TypeMerger *m,
- CVIndexMap *indexMap) {
+Error TpiSource::mergeDebugT(TypeMerger *m) {
CVTypeArray types;
BinaryStreamReader reader(file->debugTypes, support::little);
cantFail(reader.readArray(types, reader.getLength()));
@@ -213,18 +226,22 @@ Expected<const CVIndexMap *> TpiSource::mergeDebugT(TypeMerger *m,
}
if (auto err = mergeTypeAndIdRecords(m->globalIDTable, m->globalTypeTable,
- indexMap->tpiMap, types, hashes,
+ indexMapStorage, types, hashes,
file->pchSignature))
fatal("codeview::mergeTypeAndIdRecords failed: " +
toString(std::move(err)));
} else {
if (auto err =
- mergeTypeAndIdRecords(m->idTable, m->typeTable, indexMap->tpiMap,
+ mergeTypeAndIdRecords(m->idTable, m->typeTable, indexMapStorage,
types, file->pchSignature))
fatal("codeview::mergeTypeAndIdRecords failed: " +
toString(std::move(err)));
}
+ // In an object, there is only one mapping for both types and items.
+ tpiMap = indexMapStorage;
+ ipiMap = indexMapStorage;
+
if (config->showSummary) {
// Count how many times we saw each type record in our input. This
// calculation requires a second pass over the type records to classify each
@@ -234,7 +251,7 @@ Expected<const CVIndexMap *> TpiSource::mergeDebugT(TypeMerger *m,
m->ipiCounts.resize(m->getIDTable().size());
uint32_t srcIdx = 0;
for (CVType &ty : types) {
- TypeIndex dstIdx = indexMap->tpiMap[srcIdx++];
+ TypeIndex dstIdx = tpiMap[srcIdx++];
// Type merging may fail, so a complex source type may become the simple
// NotTranslated type, which cannot be used as an array index.
if (dstIdx.isSimple())
@@ -245,12 +262,11 @@ Expected<const CVIndexMap *> TpiSource::mergeDebugT(TypeMerger *m,
}
}
- return indexMap;
+ return Error::success();
}
// Merge types from a type server PDB.
-Expected<const CVIndexMap *> TypeServerSource::mergeDebugT(TypeMerger *m,
- CVIndexMap *) {
+Error TypeServerSource::mergeDebugT(TypeMerger *m) {
pdb::PDBFile &pdbFile = pdbInputFile->session->getPDBFile();
Expected<pdb::TpiStream &> expectedTpi = pdbFile.getPDBTpiStream();
if (auto e = expectedTpi.takeError())
@@ -273,30 +289,34 @@ Expected<const CVIndexMap *> TypeServerSource::mergeDebugT(TypeMerger *m,
Optional<uint32_t> endPrecomp;
// Merge TPI first, because the IPI stream will reference type indices.
if (auto err =
- mergeTypeRecords(m->globalTypeTable, tsIndexMap.tpiMap,
+ mergeTypeRecords(m->globalTypeTable, indexMapStorage,
expectedTpi->typeArray(), tpiHashes, endPrecomp))
fatal("codeview::mergeTypeRecords failed: " + toString(std::move(err)));
+ tpiMap = indexMapStorage;
// Merge IPI.
if (maybeIpi) {
auto ipiHashes =
GloballyHashedType::hashIds(maybeIpi->typeArray(), tpiHashes);
- if (auto err = mergeIdRecords(m->globalIDTable, tsIndexMap.tpiMap,
- tsIndexMap.ipiMap, maybeIpi->typeArray(),
- ipiHashes))
+ if (auto err =
+ mergeIdRecords(m->globalIDTable, tpiMap, ipiSrc->indexMapStorage,
+ maybeIpi->typeArray(), ipiHashes))
fatal("codeview::mergeIdRecords failed: " + toString(std::move(err)));
+ ipiMap = ipiSrc->indexMapStorage;
}
} else {
// Merge TPI first, because the IPI stream will reference type indices.
- if (auto err = mergeTypeRecords(m->typeTable, tsIndexMap.tpiMap,
+ if (auto err = mergeTypeRecords(m->typeTable, indexMapStorage,
expectedTpi->typeArray()))
fatal("codeview::mergeTypeRecords failed: " + toString(std::move(err)));
+ tpiMap = indexMapStorage;
// Merge IPI.
if (maybeIpi) {
- if (auto err = mergeIdRecords(m->idTable, tsIndexMap.tpiMap,
- tsIndexMap.ipiMap, maybeIpi->typeArray()))
+ if (auto err = mergeIdRecords(m->idTable, tpiMap, ipiSrc->indexMapStorage,
+ maybeIpi->typeArray()))
fatal("codeview::mergeIdRecords failed: " + toString(std::move(err)));
+ ipiMap = ipiSrc->indexMapStorage;
}
}
@@ -306,19 +326,18 @@ Expected<const CVIndexMap *> TypeServerSource::mergeDebugT(TypeMerger *m,
// map, that means we saw it once in the input. Add it to our histogram.
m->tpiCounts.resize(m->getTypeTable().size());
m->ipiCounts.resize(m->getIDTable().size());
- for (TypeIndex ti : tsIndexMap.tpiMap)
+ for (TypeIndex ti : tpiMap)
if (!ti.isSimple())
++m->tpiCounts[ti.toArrayIndex()];
- for (TypeIndex ti : tsIndexMap.ipiMap)
+ for (TypeIndex ti : ipiMap)
if (!ti.isSimple())
++m->ipiCounts[ti.toArrayIndex()];
}
- return &tsIndexMap;
+ return Error::success();
}
-Expected<const CVIndexMap *>
-UseTypeServerSource::mergeDebugT(TypeMerger *m, CVIndexMap *indexMap) {
+Error UseTypeServerSource::mergeDebugT(TypeMerger *m) {
const codeview::GUID &tsId = typeServerDependency.getGuid();
StringRef tsPath = typeServerDependency.getName();
@@ -342,7 +361,7 @@ UseTypeServerSource::mergeDebugT(TypeMerger *m, CVIndexMap *indexMap) {
pdb::PDBFile &pdbSession = tsSrc->pdbInputFile->session->getPDBFile();
auto expectedInfo = pdbSession.getPDBInfoStream();
if (!expectedInfo)
- return &tsSrc->tsIndexMap;
+ return expectedInfo.takeError();
// Just because a file with a matching name was found and it was an actual
// PDB file doesn't mean it matches. For it to match the InfoStream's GUID
@@ -352,7 +371,10 @@ UseTypeServerSource::mergeDebugT(TypeMerger *m, CVIndexMap *indexMap) {
tsPath,
make_error<pdb::PDBError>(pdb::pdb_error_code::signature_out_of_date));
- return &tsSrc->tsIndexMap;
+ // Reuse the type index map of the type server.
+ tpiMap = tsSrc->tpiMap;
+ ipiMap = tsSrc->ipiMap;
+ return Error::success();
}
static bool equalsPath(StringRef path1, StringRef path2) {
@@ -377,8 +399,8 @@ static PrecompSource *findObjByName(StringRef fileNameOnly) {
return nullptr;
}
-static Expected<const CVIndexMap *> findPrecompMap(ObjFile *file,
- PrecompRecord &pr) {
+static Expected<PrecompSource *> findPrecompMap(ObjFile *file,
+ PrecompRecord &pr) {
// Cross-compile warning: given that Clang doesn't generate LF_PRECOMP
// records, we assume the OBJ comes from a Windows build of cl.exe. Thusly,
// the paths embedded in the OBJs are in the Windows format.
@@ -409,53 +431,42 @@ static Expected<const CVIndexMap *> findPrecompMap(ObjFile *file,
toString(precomp->file),
make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch));
- return &precomp->precompIndexMap;
+ return precomp;
}
/// Merges a precompiled headers TPI map into the current TPI map. The
/// precompiled headers object will also be loaded and remapped in the
/// process.
-static Expected<const CVIndexMap *>
-mergeInPrecompHeaderObj(ObjFile *file, CVIndexMap *indexMap,
+static Error
+mergeInPrecompHeaderObj(ObjFile *file,
+ SmallVectorImpl<TypeIndex> &indexMapStorage,
PrecompRecord &precomp) {
auto e = findPrecompMap(file, precomp);
if (!e)
return e.takeError();
- const CVIndexMap *precompIndexMap = *e;
- assert(precompIndexMap->isPrecompiledTypeMap);
-
- if (precompIndexMap->tpiMap.empty())
- return precompIndexMap;
+ PrecompSource *precompSrc = *e;
+ if (precompSrc->tpiMap.empty())
+ return Error::success();
assert(precomp.getStartTypeIndex() == TypeIndex::FirstNonSimpleIndex);
- assert(precomp.getTypesCount() <= precompIndexMap->tpiMap.size());
+ assert(precomp.getTypesCount() <= precompSrc->tpiMap.size());
// Use the previously remapped index map from the precompiled headers.
- indexMap->tpiMap.append(precompIndexMap->tpiMap.begin(),
- precompIndexMap->tpiMap.begin() +
- precomp.getTypesCount());
- return indexMap;
+ indexMapStorage.append(precompSrc->tpiMap.begin(),
+ precompSrc->tpiMap.begin() + precomp.getTypesCount());
+ return Error::success();
}
-Expected<const CVIndexMap *>
-UsePrecompSource::mergeDebugT(TypeMerger *m, CVIndexMap *indexMap) {
+Error UsePrecompSource::mergeDebugT(TypeMerger *m) {
// This object was compiled with /Yu, so process the corresponding
// precompiled headers object (/Yc) first. Some type indices in the current
// object are referencing data in the precompiled headers object, so we need
// both to be loaded.
- auto e = mergeInPrecompHeaderObj(file, indexMap, precompDependency);
- if (!e)
- return e.takeError();
-
- return TpiSource::mergeDebugT(m, indexMap);
-}
+ if (Error e =
+ mergeInPrecompHeaderObj(file, indexMapStorage, precompDependency))
+ return e;
-Expected<const CVIndexMap *> PrecompSource::mergeDebugT(TypeMerger *m,
- CVIndexMap *) {
- // Note that we're not using the provided CVIndexMap. Instead, we use our
- // local one. Precompiled headers objects need to save the index map for
- // further reference by other objects which use the precompiled headers.
- return TpiSource::mergeDebugT(m, &precompIndexMap);
+ return TpiSource::mergeDebugT(m);
}
uint32_t TpiSource::countTypeServerPDBs() {
diff --git a/lld/COFF/DebugTypes.h b/lld/COFF/DebugTypes.h
index 24d79d8..f97c0f7 100644
--- a/lld/COFF/DebugTypes.h
+++ b/lld/COFF/DebugTypes.h
@@ -9,6 +9,8 @@
#ifndef LLD_COFF_DEBUGTYPES_H
#define LLD_COFF_DEBUGTYPES_H
+#include "lld/Common/LLVM.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -25,14 +27,15 @@ class NativeSession;
namespace lld {
namespace coff {
+using llvm::codeview::TypeIndex;
+
class ObjFile;
class PDBInputFile;
-struct CVIndexMap;
class TypeMerger;
class TpiSource {
public:
- enum TpiKind { Regular, PCH, UsingPCH, PDB, UsingPDB };
+ enum TpiKind { Regular, PCH, UsingPCH, PDB, PDBIpi, UsingPDB };
TpiSource(TpiKind k, ObjFile *f);
virtual ~TpiSource();
@@ -48,8 +51,8 @@ public:
/// If the object does not use a type server PDB (compiled with /Z7), we merge
/// all the type and item records from the .debug$S stream and fill in the
/// caller-provided ObjectIndexMap.
- virtual llvm::Expected<const CVIndexMap *> mergeDebugT(TypeMerger *m,
- CVIndexMap *indexMap);
+ virtual Error mergeDebugT(TypeMerger *m);
+
/// Is this a dependent file that needs to be processed first, before other
/// OBJs?
virtual bool isDependency() const { return false; }
@@ -64,6 +67,15 @@ public:
const TpiKind kind;
ObjFile *file;
+
+ // Storage for tpiMap or ipiMap, depending on the kind of source.
+ llvm::SmallVector<TypeIndex, 0> indexMapStorage;
+
+ // Source type index to PDB type index mapping for type and item records.
+ // These mappings will be the same for /Z7 objects, and distinct for /Zi
+ // objects.
+ llvm::ArrayRef<TypeIndex> tpiMap;
+ llvm::ArrayRef<TypeIndex> ipiMap;
};
TpiSource *makeTpiSource(ObjFile *file);
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index 6522d68..aaa00d0 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -785,8 +785,14 @@ void ObjFile::initializeDependencies() {
else
data = getDebugSection(".debug$T");
- if (data.empty())
+ // Don't make a TpiSource for objects with no debug info. If the object has
+ // symbols but no types, make a plain, empty TpiSource anyway, because it
+ // simplifies adding the symbols later.
+ if (data.empty()) {
+ if (!debugChunks.empty())
+ debugTypesObj = makeTpiSource(this);
return;
+ }
// Get the first type record. It will indicate if this object uses a type
// server (/Zi) or a PCH file (/Yu).
diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp
index 49d04ad..bfa7bd8 100644
--- a/lld/COFF/PDB.cpp
+++ b/lld/COFF/PDB.cpp
@@ -112,11 +112,11 @@ public:
/// externally.
void addDebug(TpiSource *source);
- const CVIndexMap *mergeTypeRecords(TpiSource *source, CVIndexMap *localMap);
+ bool mergeTypeRecords(TpiSource *source);
- void addDebugSymbols(ObjFile *file, const CVIndexMap *indexMap);
+ void addDebugSymbols(TpiSource *source);
- void mergeSymbolRecords(ObjFile *file, const CVIndexMap &indexMap,
+ void mergeSymbolRecords(TpiSource *source,
std::vector<ulittle32_t *> &stringTableRefs,
BinaryStreamRef symData);
@@ -156,7 +156,7 @@ class DebugSHandler {
ObjFile &file;
/// The result of merging type indices.
- const CVIndexMap *indexMap;
+ TpiSource *source;
/// The DEBUG_S_STRINGTABLE subsection. These strings are referred to by
/// index from other records in the .debug$S section. All of these strings
@@ -188,8 +188,8 @@ class DebugSHandler {
void mergeInlineeLines(const DebugSubsectionRecord &inlineeLines);
public:
- DebugSHandler(PDBLinker &linker, ObjFile &file, const CVIndexMap *indexMap)
- : linker(linker), file(file), indexMap(indexMap) {}
+ DebugSHandler(PDBLinker &linker, ObjFile &file, TpiSource *source)
+ : linker(linker), file(file), source(source) {}
void handleDebugS(ArrayRef<uint8_t> relocatedDebugContents);
@@ -261,7 +261,7 @@ static bool remapTypeIndex(TypeIndex &ti, ArrayRef<TypeIndex> typeIndexMap) {
static void remapTypesInSymbolRecord(ObjFile *file, SymbolKind symKind,
MutableArrayRef<uint8_t> recordBytes,
- const CVIndexMap &indexMap,
+ TpiSource *source,
ArrayRef<TiReference> typeRefs) {
MutableArrayRef<uint8_t> contents =
recordBytes.drop_front(sizeof(RecordPrefix));
@@ -271,10 +271,9 @@ static void remapTypesInSymbolRecord(ObjFile *file, SymbolKind symKind,
fatal("symbol record too short");
// This can be an item index or a type index. Choose the appropriate map.
- ArrayRef<TypeIndex> typeOrItemMap = indexMap.tpiMap;
bool isItemIndex = ref.Kind == TiRefKind::IndexRef;
- if (isItemIndex && indexMap.isTypeServerMap)
- typeOrItemMap = indexMap.ipiMap;
+ ArrayRef<TypeIndex> typeOrItemMap =
+ isItemIndex ? source->ipiMap : source->tpiMap;
MutableArrayRef<TypeIndex> tIs(
reinterpret_cast<TypeIndex *>(contents.data() + ref.Offset), ref.Count);
@@ -505,9 +504,10 @@ static void addGlobalSymbol(pdb::GSIStreamBuilder &builder, uint16_t modIndex,
}
}
-void PDBLinker::mergeSymbolRecords(ObjFile *file, const CVIndexMap &indexMap,
+void PDBLinker::mergeSymbolRecords(TpiSource *source,
std::vector<ulittle32_t *> &stringTableRefs,
BinaryStreamRef symData) {
+ ObjFile *file = source->file;
ArrayRef<uint8_t> symsBuffer;
cantFail(symData.readBytes(0, symData.getLength(), symsBuffer));
SmallVector<SymbolScope, 4> scopes;
@@ -571,7 +571,7 @@ void PDBLinker::mergeSymbolRecords(ObjFile *file, const CVIndexMap &indexMap,
}
// Re-map all the type index references.
- remapTypesInSymbolRecord(file, sym.kind(), recordBytes, indexMap,
+ remapTypesInSymbolRecord(file, sym.kind(), recordBytes, source,
typeRefs);
// An object file may have S_xxx_ID symbols, but these get converted to
@@ -665,11 +665,6 @@ void DebugSHandler::handleDebugS(ArrayRef<uint8_t> relocatedDebugContents) {
BinaryStreamReader reader(relocatedDebugContents, support::little);
exitOnErr(reader.readArray(subsections, relocatedDebugContents.size()));
- // If there is no index map, use an empty one.
- CVIndexMap tempIndexMap;
- if (!indexMap)
- indexMap = &tempIndexMap;
-
for (const DebugSubsectionRecord &ss : subsections) {
// Ignore subsections with the 'ignore' bit. Some versions of the Visual C++
// runtime have subsections with this bit set.
@@ -709,7 +704,7 @@ void DebugSHandler::handleDebugS(ArrayRef<uint8_t> relocatedDebugContents) {
break;
}
case DebugSubsectionKind::Symbols: {
- linker.mergeSymbolRecords(&file, *indexMap, stringTableReferences,
+ linker.mergeSymbolRecords(source, stringTableReferences,
ss.getRecordData());
break;
}
@@ -757,9 +752,7 @@ void DebugSHandler::mergeInlineeLines(
// Remap type indices in inlinee line records in place.
for (const InlineeSourceLine &line : inlineeLines) {
TypeIndex &inlinee = *const_cast<TypeIndex *>(&line.Header->Inlinee);
- ArrayRef<TypeIndex> typeOrItemMap =
- indexMap->isTypeServerMap ? indexMap->ipiMap : indexMap->tpiMap;
- if (!remapTypeIndex(inlinee, typeOrItemMap)) {
+ if (!remapTypeIndex(inlinee, source->ipiMap)) {
log("bad inlinee line record in " + file.getName() +
" with bad inlinee index 0x" + utohexstr(inlinee.getIndex()));
}
@@ -834,21 +827,18 @@ static void warnUnusable(InputFile *f, Error e) {
warn(msg);
}
-const CVIndexMap *PDBLinker::mergeTypeRecords(TpiSource *source,
- CVIndexMap *localMap) {
+bool PDBLinker::mergeTypeRecords(TpiSource *source) {
ScopedTimer t(typeMergingTimer);
// Before we can process symbol substreams from .debug$S, we need to process
// type information, file checksums, and the string table. Add type info to
// the PDB first, so that we can get the map from object file type and item
// indices to PDB type and item indices.
- Expected<const CVIndexMap *> r = source->mergeDebugT(&tMerger, localMap);
-
- // If the .debug$T sections fail to merge, assume there is no debug info.
- if (!r) {
- warnUnusable(source->file, r.takeError());
- return nullptr;
+ if (Error e = source->mergeDebugT(&tMerger)) {
+ // If the .debug$T sections fail to merge, assume there is no debug info.
+ warnUnusable(source->file, std::move(e));
+ return false;
}
- return *r;
+ return true;
}
// Allocate memory for a .debug$S / .debug$F section and relocate it.
@@ -860,12 +850,17 @@ static ArrayRef<uint8_t> relocateDebugChunk(SectionChunk &debugChunk) {
return makeArrayRef(buffer, debugChunk.getSize());
}
-void PDBLinker::addDebugSymbols(ObjFile *file, const CVIndexMap *indexMap) {
+void PDBLinker::addDebugSymbols(TpiSource *source) {
+ // If this TpiSource doesn't have an object file, it must be from a type
+ // server PDB. Type server PDBs do not contain symbols, so stop here.
+ if (!source->file)
+ return;
+
ScopedTimer t(symbolMergingTimer);
pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder();
- DebugSHandler dsh(*this, *file, indexMap);
+ DebugSHandler dsh(*this, *source->file, source);
// Now do all live .debug$S and .debug$F sections.
- for (SectionChunk *debugChunk : file->getDebugChunks()) {
+ for (SectionChunk *debugChunk : source->file->getDebugChunks()) {
if (!debugChunk->live || debugChunk->getSize() == 0)
continue;
@@ -925,13 +920,9 @@ static void createModuleDBI(pdb::PDBFileBuilder &builder, ObjFile *file) {
}
void PDBLinker::addDebug(TpiSource *source) {
- CVIndexMap localMap;
- const CVIndexMap *indexMap = mergeTypeRecords(source, &localMap);
-
- if (source->kind == TpiSource::PDB)
- return; // No symbols in TypeServer PDBs
-
- addDebugSymbols(source->file, indexMap);
+ // If type merging failed, ignore the symbols.
+ if (mergeTypeRecords(source))
+ addDebugSymbols(source);
}
static pdb::BulkPublic createPublic(Defined *def) {
@@ -964,15 +955,6 @@ void PDBLinker::addObjectsToPDB() {
for_each(ObjFile::instances,
[&](ObjFile *obj) { createModuleDBI(builder, obj); });
- // Merge OBJs that do not have debug types
- for_each(ObjFile::instances, [&](ObjFile *obj) {
- if (obj->debugTypesObj)
- return;
- // Even if there're no types, still merge non-symbol .Debug$S and .Debug$F
- // sections
- addDebugSymbols(obj, nullptr);
- });
-
// Merge dependencies
TpiSource::forEachSource([&](TpiSource *source) {
if (source->isDependency())
diff --git a/lld/COFF/TypeMerger.h b/lld/COFF/TypeMerger.h
index 858f55b..d3184a7 100644
--- a/lld/COFF/TypeMerger.h
+++ b/lld/COFF/TypeMerger.h
@@ -55,15 +55,6 @@ public:
SmallVector<uint32_t, 0> ipiCounts;
};
-/// Map from type index and item index in a type server PDB to the
-/// corresponding index in the destination PDB.
-struct CVIndexMap {
- llvm::SmallVector<llvm::codeview::TypeIndex, 0> tpiMap;
- llvm::SmallVector<llvm::codeview::TypeIndex, 0> ipiMap;
- bool isTypeServerMap = false;
- bool isPrecompiledTypeMap = false;
-};
-
} // namespace coff
} // namespace lld