llvm-project
1236 строк · 46.3 Кб
1//===- DebugTypes.cpp -----------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "DebugTypes.h"
10#include "COFFLinkerContext.h"
11#include "Chunks.h"
12#include "Driver.h"
13#include "InputFiles.h"
14#include "PDB.h"
15#include "TypeMerger.h"
16#include "lld/Common/ErrorHandler.h"
17#include "lld/Common/Memory.h"
18#include "llvm/ADT/StringExtras.h"
19#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
20#include "llvm/DebugInfo/CodeView/TypeRecord.h"
21#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
22#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
23#include "llvm/DebugInfo/PDB/GenericError.h"
24#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
25#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
26#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
27#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
28#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
29#include "llvm/Support/FormatVariadic.h"
30#include "llvm/Support/Parallel.h"
31#include "llvm/Support/Path.h"
32#include "llvm/Support/TimeProfiler.h"
33
34using namespace llvm;
35using namespace llvm::codeview;
36using namespace lld;
37using namespace lld::coff;
38
39namespace {
40class TypeServerIpiSource;
41
42// The TypeServerSource class represents a PDB type server, a file referenced by
43// OBJ files compiled with MSVC /Zi. A single PDB can be shared by several OBJ
44// files, therefore there must be only once instance per OBJ lot. The file path
45// is discovered from the dependent OBJ's debug type stream. The
46// TypeServerSource object is then queued and loaded by the COFF Driver. The
47// debug type stream for such PDB files will be merged first in the final PDB,
48// before any dependent OBJ.
49class TypeServerSource : public TpiSource {
50public:
51explicit TypeServerSource(COFFLinkerContext &ctx, PDBInputFile *f)
52: TpiSource(ctx, PDB, nullptr), pdbInputFile(f) {
53if (f->loadErrorStr)
54return;
55pdb::PDBFile &file = f->session->getPDBFile();
56auto expectedInfo = file.getPDBInfoStream();
57if (!expectedInfo)
58return;
59Guid = expectedInfo->getGuid();
60auto it = ctx.typeServerSourceMappings.emplace(Guid, this);
61if (!it.second) {
62// If we hit here we have collision on Guid's in two PDB files.
63// This can happen if the PDB Guid is invalid or if we are really
64// unlucky. This should fall back on stright file-system lookup.
65it.first->second = nullptr;
66}
67}
68
69Error mergeDebugT(TypeMerger *m) override;
70
71void loadGHashes() override;
72void remapTpiWithGHashes(GHashState *g) override;
73
74bool isDependency() const override { return true; }
75
76PDBInputFile *pdbInputFile = nullptr;
77
78// TpiSource for IPI stream.
79TypeServerIpiSource *ipiSrc = nullptr;
80
81// The PDB signature GUID.
82codeview::GUID Guid;
83};
84
85// Companion to TypeServerSource. Stores the index map for the IPI stream in the
86// PDB. Modeling PDBs with two sources for TPI and IPI helps establish the
87// invariant of one type index space per source.
88class TypeServerIpiSource : public TpiSource {
89public:
90explicit TypeServerIpiSource(COFFLinkerContext &ctx)
91: TpiSource(ctx, PDBIpi, nullptr) {}
92
93friend class TypeServerSource;
94
95// All of the TpiSource methods are no-ops. The parent TypeServerSource
96// handles both TPI and IPI.
97Error mergeDebugT(TypeMerger *m) override { return Error::success(); }
98void loadGHashes() override {}
99void remapTpiWithGHashes(GHashState *g) override {}
100bool isDependency() const override { return true; }
101};
102
103// This class represents the debug type stream of an OBJ file that depends on a
104// PDB type server (see TypeServerSource).
105class UseTypeServerSource : public TpiSource {
106Expected<TypeServerSource *> getTypeServerSource();
107
108public:
109UseTypeServerSource(COFFLinkerContext &ctx, ObjFile *f, TypeServer2Record ts)
110: TpiSource(ctx, UsingPDB, f), typeServerDependency(ts) {}
111
112Error mergeDebugT(TypeMerger *m) override;
113
114// No need to load ghashes from /Zi objects.
115void loadGHashes() override {}
116void remapTpiWithGHashes(GHashState *g) override;
117
118// Information about the PDB type server dependency, that needs to be loaded
119// in before merging this OBJ.
120TypeServer2Record typeServerDependency;
121};
122
123// This class represents the debug type stream of a Microsoft precompiled
124// headers OBJ (PCH OBJ). This OBJ kind needs to be merged first in the output
125// PDB, before any other OBJs that depend on this. Note that only MSVC generate
126// such files, clang does not.
127class PrecompSource : public TpiSource {
128public:
129PrecompSource(COFFLinkerContext &ctx, ObjFile *f) : TpiSource(ctx, PCH, f) {
130// If the S_OBJNAME record contains the PCH signature, we'll register this
131// source file right away.
132registerMapping();
133}
134
135Error mergeDebugT(TypeMerger *m) override;
136
137void loadGHashes() override;
138
139bool isDependency() const override { return true; }
140
141private:
142void registerMapping();
143
144// Whether this precomp OBJ was recorded in the precompSourceMappings map.
145// Only happens if the file->pchSignature is valid.
146bool registered = false;
147};
148
149// This class represents the debug type stream of an OBJ file that depends on a
150// Microsoft precompiled headers OBJ (see PrecompSource).
151class UsePrecompSource : public TpiSource {
152public:
153UsePrecompSource(COFFLinkerContext &ctx, ObjFile *f, PrecompRecord precomp)
154: TpiSource(ctx, UsingPCH, f), precompDependency(precomp) {}
155
156Error mergeDebugT(TypeMerger *m) override;
157
158void loadGHashes() override;
159void remapTpiWithGHashes(GHashState *g) override;
160
161private:
162Error mergeInPrecompHeaderObj();
163
164PrecompSource *findObjByName(StringRef fileNameOnly);
165PrecompSource *findPrecompSource(ObjFile *file, PrecompRecord &pr);
166Expected<PrecompSource *> findPrecompMap(ObjFile *file, PrecompRecord &pr);
167
168public:
169// Information about the Precomp OBJ dependency, that needs to be loaded in
170// before merging this OBJ.
171PrecompRecord precompDependency;
172};
173} // namespace
174
175TpiSource::TpiSource(COFFLinkerContext &ctx, TpiKind k, ObjFile *f)
176: ctx(ctx), kind(k), tpiSrcIdx(ctx.tpiSourceList.size()), file(f) {
177ctx.addTpiSource(this);
178}
179
180// Vtable key method.
181TpiSource::~TpiSource() {
182// Silence any assertions about unchecked errors.
183consumeError(std::move(typeMergingError));
184}
185
186TpiSource *lld::coff::makeTpiSource(COFFLinkerContext &ctx, ObjFile *file) {
187return make<TpiSource>(ctx, TpiSource::Regular, file);
188}
189
190TpiSource *lld::coff::makeTypeServerSource(COFFLinkerContext &ctx,
191PDBInputFile *pdbInputFile) {
192// Type server sources come in pairs: the TPI stream, and the IPI stream.
193auto *tpiSource = make<TypeServerSource>(ctx, pdbInputFile);
194if (pdbInputFile->session->getPDBFile().hasPDBIpiStream())
195tpiSource->ipiSrc = make<TypeServerIpiSource>(ctx);
196return tpiSource;
197}
198
199TpiSource *lld::coff::makeUseTypeServerSource(COFFLinkerContext &ctx,
200ObjFile *file,
201TypeServer2Record ts) {
202return make<UseTypeServerSource>(ctx, file, ts);
203}
204
205TpiSource *lld::coff::makePrecompSource(COFFLinkerContext &ctx, ObjFile *file) {
206return make<PrecompSource>(ctx, file);
207}
208
209TpiSource *lld::coff::makeUsePrecompSource(COFFLinkerContext &ctx,
210ObjFile *file,
211PrecompRecord precomp) {
212return make<UsePrecompSource>(ctx, file, precomp);
213}
214
215bool TpiSource::remapTypeIndex(TypeIndex &ti, TiRefKind refKind) const {
216if (ti.isSimple())
217return true;
218
219// This can be an item index or a type index. Choose the appropriate map.
220ArrayRef<TypeIndex> tpiOrIpiMap =
221(refKind == TiRefKind::IndexRef) ? ipiMap : tpiMap;
222if (ti.toArrayIndex() >= tpiOrIpiMap.size())
223return false;
224ti = tpiOrIpiMap[ti.toArrayIndex()];
225return true;
226}
227
228void TpiSource::remapRecord(MutableArrayRef<uint8_t> rec,
229ArrayRef<TiReference> typeRefs) {
230MutableArrayRef<uint8_t> contents = rec.drop_front(sizeof(RecordPrefix));
231for (const TiReference &ref : typeRefs) {
232unsigned byteSize = ref.Count * sizeof(TypeIndex);
233if (contents.size() < ref.Offset + byteSize)
234fatal("symbol record too short");
235
236MutableArrayRef<TypeIndex> indices(
237reinterpret_cast<TypeIndex *>(contents.data() + ref.Offset), ref.Count);
238for (TypeIndex &ti : indices) {
239if (!remapTypeIndex(ti, ref.Kind)) {
240if (ctx.config.verbose) {
241uint16_t kind =
242reinterpret_cast<const RecordPrefix *>(rec.data())->RecordKind;
243StringRef fname = file ? file->getName() : "<unknown PDB>";
244log("failed to remap type index in record of kind 0x" +
245utohexstr(kind) + " in " + fname + " with bad " +
246(ref.Kind == TiRefKind::IndexRef ? "item" : "type") +
247" index 0x" + utohexstr(ti.getIndex()));
248}
249ti = TypeIndex(SimpleTypeKind::NotTranslated);
250continue;
251}
252}
253}
254}
255
256void TpiSource::remapTypesInTypeRecord(MutableArrayRef<uint8_t> rec) {
257// TODO: Handle errors similar to symbols.
258SmallVector<TiReference, 32> typeRefs;
259discoverTypeIndices(CVType(rec), typeRefs);
260remapRecord(rec, typeRefs);
261}
262
263bool TpiSource::remapTypesInSymbolRecord(MutableArrayRef<uint8_t> rec) {
264// Discover type index references in the record. Skip it if we don't
265// know where they are.
266SmallVector<TiReference, 32> typeRefs;
267if (!discoverTypeIndicesInSymbol(rec, typeRefs))
268return false;
269remapRecord(rec, typeRefs);
270return true;
271}
272
273// A COFF .debug$H section is currently a clang extension. This function checks
274// if a .debug$H section is in a format that we expect / understand, so that we
275// can ignore any sections which are coincidentally also named .debug$H but do
276// not contain a format we recognize.
277static bool canUseDebugH(ArrayRef<uint8_t> debugH) {
278if (debugH.size() < sizeof(object::debug_h_header))
279return false;
280auto *header =
281reinterpret_cast<const object::debug_h_header *>(debugH.data());
282debugH = debugH.drop_front(sizeof(object::debug_h_header));
283return header->Magic == COFF::DEBUG_HASHES_SECTION_MAGIC &&
284header->Version == 0 &&
285header->HashAlgorithm == uint16_t(GlobalTypeHashAlg::BLAKE3) &&
286(debugH.size() % 8 == 0);
287}
288
289static std::optional<ArrayRef<uint8_t>> getDebugH(ObjFile *file) {
290SectionChunk *sec =
291SectionChunk::findByName(file->getDebugChunks(), ".debug$H");
292if (!sec)
293return std::nullopt;
294ArrayRef<uint8_t> contents = sec->getContents();
295if (!canUseDebugH(contents))
296return std::nullopt;
297return contents;
298}
299
300static ArrayRef<GloballyHashedType>
301getHashesFromDebugH(ArrayRef<uint8_t> debugH) {
302assert(canUseDebugH(debugH));
303debugH = debugH.drop_front(sizeof(object::debug_h_header));
304uint32_t count = debugH.size() / sizeof(GloballyHashedType);
305return {reinterpret_cast<const GloballyHashedType *>(debugH.data()), count};
306}
307
308// Merge .debug$T for a generic object file.
309Error TpiSource::mergeDebugT(TypeMerger *m) {
310assert(!ctx.config.debugGHashes &&
311"use remapTpiWithGHashes when ghash is enabled");
312
313CVTypeArray types;
314BinaryStreamReader reader(file->debugTypes, llvm::endianness::little);
315cantFail(reader.readArray(types, reader.getLength()));
316
317// When dealing with PCH.OBJ, some indices were already merged.
318unsigned nbHeadIndices = indexMapStorage.size();
319
320std::optional<PCHMergerInfo> pchInfo;
321if (auto err = mergeTypeAndIdRecords(m->idTable, m->typeTable,
322indexMapStorage, types, pchInfo))
323fatal("codeview::mergeTypeAndIdRecords failed: " +
324toString(std::move(err)));
325if (pchInfo) {
326file->pchSignature = pchInfo->PCHSignature;
327endPrecompIdx = pchInfo->EndPrecompIndex;
328}
329
330// In an object, there is only one mapping for both types and items.
331tpiMap = indexMapStorage;
332ipiMap = indexMapStorage;
333
334if (ctx.config.showSummary) {
335nbTypeRecords = indexMapStorage.size() - nbHeadIndices;
336nbTypeRecordsBytes = reader.getLength();
337// Count how many times we saw each type record in our input. This
338// calculation requires a second pass over the type records to classify each
339// record as a type or index. This is slow, but this code executes when
340// collecting statistics.
341m->tpiCounts.resize(m->getTypeTable().size());
342m->ipiCounts.resize(m->getIDTable().size());
343uint32_t srcIdx = nbHeadIndices;
344for (const CVType &ty : types) {
345TypeIndex dstIdx = tpiMap[srcIdx++];
346// Type merging may fail, so a complex source type may become the simple
347// NotTranslated type, which cannot be used as an array index.
348if (dstIdx.isSimple())
349continue;
350SmallVectorImpl<uint32_t> &counts =
351isIdRecord(ty.kind()) ? m->ipiCounts : m->tpiCounts;
352++counts[dstIdx.toArrayIndex()];
353}
354}
355
356return Error::success();
357}
358
359// Merge types from a type server PDB.
360Error TypeServerSource::mergeDebugT(TypeMerger *m) {
361assert(!ctx.config.debugGHashes &&
362"use remapTpiWithGHashes when ghash is enabled");
363
364pdb::PDBFile &pdbFile = pdbInputFile->session->getPDBFile();
365Expected<pdb::TpiStream &> expectedTpi = pdbFile.getPDBTpiStream();
366if (auto e = expectedTpi.takeError())
367fatal("Type server does not have TPI stream: " + toString(std::move(e)));
368pdb::TpiStream *maybeIpi = nullptr;
369if (pdbFile.hasPDBIpiStream()) {
370Expected<pdb::TpiStream &> expectedIpi = pdbFile.getPDBIpiStream();
371if (auto e = expectedIpi.takeError())
372fatal("Error getting type server IPI stream: " + toString(std::move(e)));
373maybeIpi = &*expectedIpi;
374}
375
376// Merge TPI first, because the IPI stream will reference type indices.
377if (auto err = mergeTypeRecords(m->typeTable, indexMapStorage,
378expectedTpi->typeArray()))
379fatal("codeview::mergeTypeRecords failed: " + toString(std::move(err)));
380tpiMap = indexMapStorage;
381
382// Merge IPI.
383if (maybeIpi) {
384if (auto err = mergeIdRecords(m->idTable, tpiMap, ipiSrc->indexMapStorage,
385maybeIpi->typeArray()))
386fatal("codeview::mergeIdRecords failed: " + toString(std::move(err)));
387ipiMap = ipiSrc->indexMapStorage;
388}
389
390if (ctx.config.showSummary) {
391nbTypeRecords = tpiMap.size() + ipiMap.size();
392nbTypeRecordsBytes =
393expectedTpi->typeArray().getUnderlyingStream().getLength() +
394(maybeIpi ? maybeIpi->typeArray().getUnderlyingStream().getLength()
395: 0);
396
397// Count how many times we saw each type record in our input. If a
398// destination type index is present in the source to destination type index
399// map, that means we saw it once in the input. Add it to our histogram.
400m->tpiCounts.resize(m->getTypeTable().size());
401m->ipiCounts.resize(m->getIDTable().size());
402for (TypeIndex ti : tpiMap)
403if (!ti.isSimple())
404++m->tpiCounts[ti.toArrayIndex()];
405for (TypeIndex ti : ipiMap)
406if (!ti.isSimple())
407++m->ipiCounts[ti.toArrayIndex()];
408}
409
410return Error::success();
411}
412
413Expected<TypeServerSource *> UseTypeServerSource::getTypeServerSource() {
414const codeview::GUID &tsId = typeServerDependency.getGuid();
415StringRef tsPath = typeServerDependency.getName();
416
417TypeServerSource *tsSrc = nullptr;
418auto it = ctx.typeServerSourceMappings.find(tsId);
419if (it != ctx.typeServerSourceMappings.end()) {
420tsSrc = (TypeServerSource *)it->second;
421}
422if (tsSrc == nullptr) {
423// The file failed to load, lookup by name
424PDBInputFile *pdb = PDBInputFile::findFromRecordPath(ctx, tsPath, file);
425if (!pdb)
426return createFileError(tsPath, errorCodeToError(std::error_code(
427ENOENT, std::generic_category())));
428// If an error occurred during loading, throw it now
429if (pdb->loadErrorStr)
430return createFileError(
431tsPath, make_error<StringError>(*pdb->loadErrorStr,
432llvm::inconvertibleErrorCode()));
433
434tsSrc = (TypeServerSource *)pdb->debugTypesObj;
435
436// Just because a file with a matching name was found and it was an actual
437// PDB file doesn't mean it matches. For it to match the InfoStream's GUID
438// must match the GUID specified in the TypeServer2 record.
439if (tsSrc->Guid != tsId) {
440return createFileError(tsPath,
441make_error<pdb::PDBError>(
442pdb::pdb_error_code::signature_out_of_date));
443}
444}
445return tsSrc;
446}
447
448Error UseTypeServerSource::mergeDebugT(TypeMerger *m) {
449Expected<TypeServerSource *> tsSrc = getTypeServerSource();
450if (!tsSrc)
451return tsSrc.takeError();
452
453pdb::PDBFile &pdbSession = (*tsSrc)->pdbInputFile->session->getPDBFile();
454auto expectedInfo = pdbSession.getPDBInfoStream();
455if (!expectedInfo)
456return expectedInfo.takeError();
457
458// Reuse the type index map of the type server.
459tpiMap = (*tsSrc)->tpiMap;
460ipiMap = (*tsSrc)->ipiMap;
461return Error::success();
462}
463
464static bool equalsPath(StringRef path1, StringRef path2) {
465#if defined(_WIN32)
466return path1.equals_insensitive(path2);
467#else
468return path1 == path2;
469#endif
470}
471
472// Find by name an OBJ provided on the command line
473PrecompSource *UsePrecompSource::findObjByName(StringRef fileNameOnly) {
474SmallString<128> currentPath;
475for (auto kv : ctx.precompSourceMappings) {
476StringRef currentFileName = sys::path::filename(kv.second->file->getName(),
477sys::path::Style::windows);
478
479// Compare based solely on the file name (link.exe behavior)
480if (equalsPath(currentFileName, fileNameOnly))
481return (PrecompSource *)kv.second;
482}
483return nullptr;
484}
485
486PrecompSource *UsePrecompSource::findPrecompSource(ObjFile *file,
487PrecompRecord &pr) {
488// Cross-compile warning: given that Clang doesn't generate LF_PRECOMP
489// records, we assume the OBJ comes from a Windows build of cl.exe. Thusly,
490// the paths embedded in the OBJs are in the Windows format.
491SmallString<128> prFileName =
492sys::path::filename(pr.getPrecompFilePath(), sys::path::Style::windows);
493
494auto it = ctx.precompSourceMappings.find(pr.getSignature());
495if (it != ctx.precompSourceMappings.end()) {
496return (PrecompSource *)it->second;
497}
498// Lookup by name
499return findObjByName(prFileName);
500}
501
502Expected<PrecompSource *> UsePrecompSource::findPrecompMap(ObjFile *file,
503PrecompRecord &pr) {
504PrecompSource *precomp = findPrecompSource(file, pr);
505
506if (!precomp)
507return createFileError(
508pr.getPrecompFilePath(),
509make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch));
510
511// Don't rely on the PCH signature to validate the concordance between the PCH
512// and the OBJ that uses it. However we do validate here that the
513// LF_ENDPRECOMP record index lines up with the number of type records
514// LF_PRECOMP is expecting.
515if (precomp->endPrecompIdx != pr.getTypesCount())
516return createFileError(
517toString(file),
518make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch));
519
520return precomp;
521}
522
523/// Merges a precompiled headers TPI map into the current TPI map. The
524/// precompiled headers object will also be loaded and remapped in the
525/// process.
526Error UsePrecompSource::mergeInPrecompHeaderObj() {
527auto e = findPrecompMap(file, precompDependency);
528if (!e)
529return e.takeError();
530
531PrecompSource *precompSrc = *e;
532if (precompSrc->tpiMap.empty())
533return Error::success();
534
535assert(precompDependency.getStartTypeIndex() ==
536TypeIndex::FirstNonSimpleIndex);
537assert(precompDependency.getTypesCount() <= precompSrc->tpiMap.size());
538// Use the previously remapped index map from the precompiled headers.
539indexMapStorage.insert(indexMapStorage.begin(), precompSrc->tpiMap.begin(),
540precompSrc->tpiMap.begin() +
541precompDependency.getTypesCount());
542
543return Error::success();
544}
545
546Error UsePrecompSource::mergeDebugT(TypeMerger *m) {
547// This object was compiled with /Yu, so process the corresponding
548// precompiled headers object (/Yc) first. Some type indices in the current
549// object are referencing data in the precompiled headers object, so we need
550// both to be loaded.
551if (Error e = mergeInPrecompHeaderObj())
552return e;
553
554return TpiSource::mergeDebugT(m);
555}
556
557Error PrecompSource::mergeDebugT(TypeMerger *m) {
558// In some cases, the S_OBJNAME record doesn't contain the PCH signature.
559// The signature comes later with the LF_ENDPRECOMP record, so we first need
560// to merge in all the .PCH.OBJ file type records, before registering below.
561if (Error e = TpiSource::mergeDebugT(m))
562return e;
563
564registerMapping();
565
566return Error::success();
567}
568
569void PrecompSource::registerMapping() {
570if (registered)
571return;
572if (file->pchSignature && *file->pchSignature) {
573auto it = ctx.precompSourceMappings.emplace(*file->pchSignature, this);
574if (!it.second)
575fatal("a PCH object with the same signature has already been provided (" +
576toString(it.first->second->file) + " and " + toString(file) + ")");
577registered = true;
578}
579}
580
581//===----------------------------------------------------------------------===//
582// Parellel GHash type merging implementation.
583//===----------------------------------------------------------------------===//
584
585void TpiSource::loadGHashes() {
586if (std::optional<ArrayRef<uint8_t>> debugH = getDebugH(file)) {
587ghashes = getHashesFromDebugH(*debugH);
588ownedGHashes = false;
589} else {
590CVTypeArray types;
591BinaryStreamReader reader(file->debugTypes, llvm::endianness::little);
592cantFail(reader.readArray(types, reader.getLength()));
593assignGHashesFromVector(GloballyHashedType::hashTypes(types));
594}
595
596fillIsItemIndexFromDebugT();
597}
598
599// Copies ghashes from a vector into an array. These are long lived, so it's
600// worth the time to copy these into an appropriately sized vector to reduce
601// memory usage.
602void TpiSource::assignGHashesFromVector(
603std::vector<GloballyHashedType> &&hashVec) {
604if (hashVec.empty())
605return;
606GloballyHashedType *hashes = new GloballyHashedType[hashVec.size()];
607memcpy(hashes, hashVec.data(), hashVec.size() * sizeof(GloballyHashedType));
608ghashes = ArrayRef(hashes, hashVec.size());
609ownedGHashes = true;
610}
611
612// Faster way to iterate type records. forEachTypeChecked is faster than
613// iterating CVTypeArray. It avoids virtual readBytes calls in inner loops.
614static void forEachTypeChecked(ArrayRef<uint8_t> types,
615function_ref<void(const CVType &)> fn) {
616checkError(
617forEachCodeViewRecord<CVType>(types, [fn](const CVType &ty) -> Error {
618fn(ty);
619return Error::success();
620}));
621}
622
623// Walk over file->debugTypes and fill in the isItemIndex bit vector.
624// TODO: Store this information in .debug$H so that we don't have to recompute
625// it. This is the main bottleneck slowing down parallel ghashing with one
626// thread over single-threaded ghashing.
627void TpiSource::fillIsItemIndexFromDebugT() {
628uint32_t index = 0;
629isItemIndex.resize(ghashes.size());
630forEachTypeChecked(file->debugTypes, [&](const CVType &ty) {
631if (isIdRecord(ty.kind()))
632isItemIndex.set(index);
633++index;
634});
635}
636
637void TpiSource::mergeTypeRecord(TypeIndex curIndex, CVType ty) {
638// Decide if the merged type goes into TPI or IPI.
639bool isItem = isIdRecord(ty.kind());
640MergedInfo &merged = isItem ? mergedIpi : mergedTpi;
641
642// Copy the type into our mutable buffer.
643assert(ty.length() <= codeview::MaxRecordLength);
644size_t offset = merged.recs.size();
645size_t newSize = alignTo(ty.length(), 4);
646merged.recs.resize(offset + newSize);
647auto newRec = MutableArrayRef(&merged.recs[offset], newSize);
648memcpy(newRec.data(), ty.data().data(), newSize);
649
650// Fix up the record prefix and padding bytes if it required resizing.
651if (newSize != ty.length()) {
652reinterpret_cast<RecordPrefix *>(newRec.data())->RecordLen = newSize - 2;
653for (size_t i = ty.length(); i < newSize; ++i)
654newRec[i] = LF_PAD0 + (newSize - i);
655}
656
657// Remap the type indices in the new record.
658remapTypesInTypeRecord(newRec);
659uint32_t pdbHash = check(pdb::hashTypeRecord(CVType(newRec)));
660merged.recSizes.push_back(static_cast<uint16_t>(newSize));
661merged.recHashes.push_back(pdbHash);
662
663// Retain a mapping from PDB function id to PDB function type. This mapping is
664// used during symbol processing to rewrite S_GPROC32_ID symbols to S_GPROC32
665// symbols.
666if (ty.kind() == LF_FUNC_ID || ty.kind() == LF_MFUNC_ID) {
667bool success = ty.length() >= 12;
668TypeIndex funcId = curIndex;
669if (success)
670success &= remapTypeIndex(funcId, TiRefKind::IndexRef);
671TypeIndex funcType =
672*reinterpret_cast<const TypeIndex *>(&newRec.data()[8]);
673if (success) {
674funcIdToType.push_back({funcId, funcType});
675} else {
676StringRef fname = file ? file->getName() : "<unknown PDB>";
677warn("corrupt LF_[M]FUNC_ID record 0x" + utohexstr(curIndex.getIndex()) +
678" in " + fname);
679}
680}
681}
682
683void TpiSource::mergeUniqueTypeRecords(ArrayRef<uint8_t> typeRecords,
684TypeIndex beginIndex) {
685// Re-sort the list of unique types by index.
686if (kind == PDB)
687assert(llvm::is_sorted(uniqueTypes));
688else
689llvm::sort(uniqueTypes);
690
691// Accumulate all the unique types into one buffer in mergedTypes.
692uint32_t ghashIndex = 0;
693auto nextUniqueIndex = uniqueTypes.begin();
694assert(mergedTpi.recs.empty());
695assert(mergedIpi.recs.empty());
696
697// Pre-compute the number of elements in advance to avoid std::vector resizes.
698unsigned nbTpiRecs = 0;
699unsigned nbIpiRecs = 0;
700forEachTypeChecked(typeRecords, [&](const CVType &ty) {
701if (nextUniqueIndex != uniqueTypes.end() &&
702*nextUniqueIndex == ghashIndex) {
703assert(ty.length() <= codeview::MaxRecordLength);
704size_t newSize = alignTo(ty.length(), 4);
705(isIdRecord(ty.kind()) ? nbIpiRecs : nbTpiRecs) += newSize;
706++nextUniqueIndex;
707}
708++ghashIndex;
709});
710mergedTpi.recs.reserve(nbTpiRecs);
711mergedIpi.recs.reserve(nbIpiRecs);
712
713// Do the actual type merge.
714ghashIndex = 0;
715nextUniqueIndex = uniqueTypes.begin();
716forEachTypeChecked(typeRecords, [&](const CVType &ty) {
717if (nextUniqueIndex != uniqueTypes.end() &&
718*nextUniqueIndex == ghashIndex) {
719mergeTypeRecord(beginIndex + ghashIndex, ty);
720++nextUniqueIndex;
721}
722++ghashIndex;
723});
724assert(nextUniqueIndex == uniqueTypes.end() &&
725"failed to merge all desired records");
726assert(uniqueTypes.size() ==
727mergedTpi.recSizes.size() + mergedIpi.recSizes.size() &&
728"missing desired record");
729}
730
731void TpiSource::remapTpiWithGHashes(GHashState *g) {
732assert(ctx.config.debugGHashes && "ghashes must be enabled");
733fillMapFromGHashes(g);
734tpiMap = indexMapStorage;
735ipiMap = indexMapStorage;
736mergeUniqueTypeRecords(file->debugTypes);
737// TODO: Free all unneeded ghash resources now that we have a full index map.
738
739if (ctx.config.showSummary) {
740nbTypeRecords = ghashes.size();
741nbTypeRecordsBytes = file->debugTypes.size();
742}
743}
744
745// PDBs do not actually store global hashes, so when merging a type server
746// PDB we have to synthesize global hashes. To do this, we first synthesize
747// global hashes for the TPI stream, since it is independent, then we
748// synthesize hashes for the IPI stream, using the hashes for the TPI stream
749// as inputs.
750void TypeServerSource::loadGHashes() {
751// Don't hash twice.
752if (!ghashes.empty())
753return;
754pdb::PDBFile &pdbFile = pdbInputFile->session->getPDBFile();
755
756// Hash TPI stream.
757Expected<pdb::TpiStream &> expectedTpi = pdbFile.getPDBTpiStream();
758if (auto e = expectedTpi.takeError())
759fatal("Type server does not have TPI stream: " + toString(std::move(e)));
760assignGHashesFromVector(
761GloballyHashedType::hashTypes(expectedTpi->typeArray()));
762isItemIndex.resize(ghashes.size());
763
764// Hash IPI stream, which depends on TPI ghashes.
765if (!pdbFile.hasPDBIpiStream())
766return;
767Expected<pdb::TpiStream &> expectedIpi = pdbFile.getPDBIpiStream();
768if (auto e = expectedIpi.takeError())
769fatal("error retrieving IPI stream: " + toString(std::move(e)));
770ipiSrc->assignGHashesFromVector(
771GloballyHashedType::hashIds(expectedIpi->typeArray(), ghashes));
772
773// The IPI stream isItemIndex bitvector should be all ones.
774ipiSrc->isItemIndex.resize(ipiSrc->ghashes.size());
775ipiSrc->isItemIndex.set(0, ipiSrc->ghashes.size());
776}
777
778// Flatten discontiguous PDB type arrays to bytes so that we can use
779// forEachTypeChecked instead of CVTypeArray iteration. Copying all types from
780// type servers is faster than iterating all object files compiled with /Z7 with
781// CVTypeArray, which has high overheads due to the virtual interface of
782// BinaryStream::readBytes.
783static ArrayRef<uint8_t> typeArrayToBytes(const CVTypeArray &types) {
784BinaryStreamRef stream = types.getUnderlyingStream();
785ArrayRef<uint8_t> debugTypes;
786checkError(stream.readBytes(0, stream.getLength(), debugTypes));
787return debugTypes;
788}
789
790// Merge types from a type server PDB.
791void TypeServerSource::remapTpiWithGHashes(GHashState *g) {
792assert(ctx.config.debugGHashes && "ghashes must be enabled");
793
794// IPI merging depends on TPI, so do TPI first, then do IPI. No need to
795// propagate errors, those should've been handled during ghash loading.
796pdb::PDBFile &pdbFile = pdbInputFile->session->getPDBFile();
797pdb::TpiStream &tpi = check(pdbFile.getPDBTpiStream());
798fillMapFromGHashes(g);
799tpiMap = indexMapStorage;
800mergeUniqueTypeRecords(typeArrayToBytes(tpi.typeArray()));
801if (pdbFile.hasPDBIpiStream()) {
802pdb::TpiStream &ipi = check(pdbFile.getPDBIpiStream());
803ipiSrc->indexMapStorage.resize(ipiSrc->ghashes.size());
804ipiSrc->fillMapFromGHashes(g);
805ipiMap = ipiSrc->indexMapStorage;
806ipiSrc->tpiMap = tpiMap;
807ipiSrc->ipiMap = ipiMap;
808ipiSrc->mergeUniqueTypeRecords(typeArrayToBytes(ipi.typeArray()));
809
810if (ctx.config.showSummary) {
811nbTypeRecords = ipiSrc->ghashes.size();
812nbTypeRecordsBytes = ipi.typeArray().getUnderlyingStream().getLength();
813}
814}
815
816if (ctx.config.showSummary) {
817nbTypeRecords += ghashes.size();
818nbTypeRecordsBytes += tpi.typeArray().getUnderlyingStream().getLength();
819}
820}
821
822void UseTypeServerSource::remapTpiWithGHashes(GHashState *g) {
823// No remapping to do with /Zi objects. Simply use the index map from the type
824// server. Errors should have been reported earlier. Symbols from this object
825// will be ignored.
826Expected<TypeServerSource *> maybeTsSrc = getTypeServerSource();
827if (!maybeTsSrc) {
828typeMergingError =
829joinErrors(std::move(typeMergingError), maybeTsSrc.takeError());
830return;
831}
832TypeServerSource *tsSrc = *maybeTsSrc;
833tpiMap = tsSrc->tpiMap;
834ipiMap = tsSrc->ipiMap;
835}
836
837void PrecompSource::loadGHashes() {
838if (getDebugH(file)) {
839warn("ignoring .debug$H section; pch with ghash is not implemented");
840}
841
842uint32_t ghashIdx = 0;
843std::vector<GloballyHashedType> hashVec;
844forEachTypeChecked(file->debugTypes, [&](const CVType &ty) {
845// Remember the index of the LF_ENDPRECOMP record so it can be excluded from
846// the PDB. There must be an entry in the list of ghashes so that the type
847// indexes of the following records in the /Yc PCH object line up.
848if (ty.kind() == LF_ENDPRECOMP) {
849EndPrecompRecord endPrecomp;
850cantFail(TypeDeserializer::deserializeAs<EndPrecompRecord>(
851const_cast<CVType &>(ty), endPrecomp));
852file->pchSignature = endPrecomp.getSignature();
853registerMapping();
854endPrecompIdx = ghashIdx;
855}
856
857hashVec.push_back(GloballyHashedType::hashType(ty, hashVec, hashVec));
858isItemIndex.push_back(isIdRecord(ty.kind()));
859++ghashIdx;
860});
861assignGHashesFromVector(std::move(hashVec));
862}
863
864void UsePrecompSource::loadGHashes() {
865auto e = findPrecompMap(file, precompDependency);
866if (!e) {
867warn(toString(e.takeError()));
868return;
869}
870
871PrecompSource *pchSrc = *e;
872
873// To compute ghashes of a /Yu object file, we need to build on the ghashes of
874// the /Yc PCH object. After we are done hashing, discard the ghashes from the
875// PCH source so we don't unnecessarily try to deduplicate them.
876std::vector<GloballyHashedType> hashVec =
877pchSrc->ghashes.take_front(precompDependency.getTypesCount());
878forEachTypeChecked(file->debugTypes, [&](const CVType &ty) {
879hashVec.push_back(GloballyHashedType::hashType(ty, hashVec, hashVec));
880isItemIndex.push_back(isIdRecord(ty.kind()));
881});
882hashVec.erase(hashVec.begin(),
883hashVec.begin() + precompDependency.getTypesCount());
884assignGHashesFromVector(std::move(hashVec));
885}
886
887void UsePrecompSource::remapTpiWithGHashes(GHashState *g) {
888fillMapFromGHashes(g);
889// This object was compiled with /Yu, so process the corresponding
890// precompiled headers object (/Yc) first. Some type indices in the current
891// object are referencing data in the precompiled headers object, so we need
892// both to be loaded.
893if (Error e = mergeInPrecompHeaderObj()) {
894typeMergingError = joinErrors(std::move(typeMergingError), std::move(e));
895return;
896}
897
898tpiMap = indexMapStorage;
899ipiMap = indexMapStorage;
900mergeUniqueTypeRecords(file->debugTypes,
901TypeIndex(precompDependency.getStartTypeIndex() +
902precompDependency.getTypesCount()));
903if (ctx.config.showSummary) {
904nbTypeRecords = ghashes.size();
905nbTypeRecordsBytes = file->debugTypes.size();
906}
907}
908
909namespace {
910/// A concurrent hash table for global type hashing. It is based on this paper:
911/// Concurrent Hash Tables: Fast and General(?)!
912/// https://dl.acm.org/doi/10.1145/3309206
913///
914/// This hash table is meant to be used in two phases:
915/// 1. concurrent insertions
916/// 2. concurrent reads
917/// It does not support lookup, deletion, or rehashing. It uses linear probing.
918///
919/// The paper describes storing a key-value pair in two machine words.
920/// Generally, the values stored in this map are type indices, and we can use
921/// those values to recover the ghash key from a side table. This allows us to
922/// shrink the table entries further at the cost of some loads, and sidesteps
923/// the need for a 128 bit atomic compare-and-swap operation.
924///
925/// During insertion, a priority function is used to decide which insertion
926/// should be preferred. This ensures that the output is deterministic. For
927/// ghashing, lower tpiSrcIdx values (earlier inputs) are preferred.
928///
929class GHashCell;
930struct GHashTable {
931GHashCell *table = nullptr;
932uint32_t tableSize = 0;
933
934GHashTable() = default;
935~GHashTable();
936
937/// Initialize the table with the given size. Because the table cannot be
938/// resized, the initial size of the table must be large enough to contain all
939/// inputs, or insertion may not be able to find an empty cell.
940void init(uint32_t newTableSize);
941
942/// Insert the cell with the given ghash into the table. Return the insertion
943/// position in the table. It is safe for the caller to store the insertion
944/// position because the table cannot be resized.
945uint32_t insert(COFFLinkerContext &ctx, GloballyHashedType ghash,
946GHashCell newCell);
947};
948
949/// A ghash table cell for deduplicating types from TpiSources.
950class GHashCell {
951// Force "data" to be 64-bit aligned; otherwise, some versions of clang
952// will generate calls to libatomic when using some versions of libstdc++
953// on 32-bit targets. (Also, in theory, there could be a target where
954// new[] doesn't always return an 8-byte-aligned allocation.)
955alignas(sizeof(uint64_t)) uint64_t data = 0;
956
957public:
958GHashCell() = default;
959
960// Construct data most to least significant so that sorting works well:
961// - isItem
962// - tpiSrcIdx
963// - ghashIdx
964// Add one to the tpiSrcIdx so that the 0th record from the 0th source has a
965// non-zero representation.
966GHashCell(bool isItem, uint32_t tpiSrcIdx, uint32_t ghashIdx)
967: data((uint64_t(isItem) << 63U) | (uint64_t(tpiSrcIdx + 1) << 32ULL) |
968ghashIdx) {
969assert(tpiSrcIdx == getTpiSrcIdx() && "round trip failure");
970assert(ghashIdx == getGHashIdx() && "round trip failure");
971}
972
973explicit GHashCell(uint64_t data) : data(data) {}
974
975// The empty cell is all zeros.
976bool isEmpty() const { return data == 0ULL; }
977
978/// Extract the tpiSrcIdx.
979uint32_t getTpiSrcIdx() const {
980return ((uint32_t)(data >> 32U) & 0x7FFFFFFF) - 1;
981}
982
983/// Extract the index into the ghash array of the TpiSource.
984uint32_t getGHashIdx() const { return (uint32_t)data; }
985
986bool isItem() const { return data & (1ULL << 63U); }
987
988/// Get the ghash key for this cell.
989GloballyHashedType getGHash(const COFFLinkerContext &ctx) const {
990return ctx.tpiSourceList[getTpiSrcIdx()]->ghashes[getGHashIdx()];
991}
992
993/// The priority function for the cell. The data is stored such that lower
994/// tpiSrcIdx and ghashIdx values are preferred, which means that type record
995/// from earlier sources are more likely to prevail.
996friend inline bool operator<(const GHashCell &l, const GHashCell &r) {
997return l.data < r.data;
998}
999};
1000} // namespace
1001
1002namespace lld::coff {
1003/// This type is just a wrapper around GHashTable with external linkage so it
1004/// can be used from a header.
1005struct GHashState {
1006GHashTable table;
1007};
1008} // namespace lld::coff
1009
1010GHashTable::~GHashTable() { delete[] table; }
1011
1012void GHashTable::init(uint32_t newTableSize) {
1013table = new GHashCell[newTableSize];
1014memset(table, 0, newTableSize * sizeof(GHashCell));
1015tableSize = newTableSize;
1016}
1017
1018uint32_t GHashTable::insert(COFFLinkerContext &ctx, GloballyHashedType ghash,
1019GHashCell newCell) {
1020assert(!newCell.isEmpty() && "cannot insert empty cell value");
1021
1022// FIXME: The low bytes of SHA1 have low entropy for short records, which
1023// type records are. Swap the byte order for better entropy. A better ghash
1024// won't need this.
1025uint32_t startIdx =
1026llvm::byteswap<uint64_t>(*reinterpret_cast<uint64_t *>(&ghash)) %
1027tableSize;
1028
1029// Do a linear probe starting at startIdx.
1030uint32_t idx = startIdx;
1031while (true) {
1032// Run a compare and swap loop. There are four cases:
1033// - cell is empty: CAS into place and return
1034// - cell has matching key, earlier priority: do nothing, return
1035// - cell has matching key, later priority: CAS into place and return
1036// - cell has non-matching key: hash collision, probe next cell
1037auto *cellPtr = reinterpret_cast<std::atomic<GHashCell> *>(&table[idx]);
1038GHashCell oldCell(cellPtr->load());
1039while (oldCell.isEmpty() || oldCell.getGHash(ctx) == ghash) {
1040// Check if there is an existing ghash entry with a higher priority
1041// (earlier ordering). If so, this is a duplicate, we are done.
1042if (!oldCell.isEmpty() && oldCell < newCell)
1043return idx;
1044// Either the cell is empty, or our value is higher priority. Try to
1045// compare and swap. If it succeeds, we are done.
1046if (cellPtr->compare_exchange_weak(oldCell, newCell))
1047return idx;
1048// If the CAS failed, check this cell again.
1049}
1050
1051// Advance the probe. Wrap around to the beginning if we run off the end.
1052++idx;
1053idx = idx == tableSize ? 0 : idx;
1054if (idx == startIdx) {
1055// If this becomes an issue, we could mark failure and rehash from the
1056// beginning with a bigger table. There is no difference between rehashing
1057// internally and starting over.
1058report_fatal_error("ghash table is full");
1059}
1060}
1061llvm_unreachable("left infloop");
1062}
1063
1064TypeMerger::TypeMerger(COFFLinkerContext &c, llvm::BumpPtrAllocator &alloc)
1065: typeTable(alloc), idTable(alloc), ctx(c) {}
1066
1067TypeMerger::~TypeMerger() = default;
1068
1069void TypeMerger::mergeTypesWithGHash() {
1070// Load ghashes. Do type servers and PCH objects first.
1071{
1072llvm::TimeTraceScope timeScope("Load GHASHes");
1073ScopedTimer t1(ctx.loadGHashTimer);
1074parallelForEach(dependencySources,
1075[&](TpiSource *source) { source->loadGHashes(); });
1076parallelForEach(objectSources,
1077[&](TpiSource *source) { source->loadGHashes(); });
1078}
1079
1080llvm::TimeTraceScope timeScope("Merge types (GHASH)");
1081ScopedTimer t2(ctx.mergeGHashTimer);
1082GHashState ghashState;
1083
1084// Estimate the size of hash table needed to deduplicate ghashes. This *must*
1085// be larger than the number of unique types, or hash table insertion may not
1086// be able to find a vacant slot. Summing the input types guarantees this, but
1087// it is a gross overestimate. The table size could be reduced to save memory,
1088// but it would require implementing rehashing, and this table is generally
1089// small compared to total memory usage, at eight bytes per input type record,
1090// and most input type records are larger than eight bytes.
1091size_t tableSize = 0;
1092for (TpiSource *source : ctx.tpiSourceList)
1093tableSize += source->ghashes.size();
1094
1095// Cap the table size so that we can use 32-bit cell indices. Type indices are
1096// also 32-bit, so this is an inherent PDB file format limit anyway.
1097tableSize =
1098std::min(size_t(INT32_MAX) - TypeIndex::FirstNonSimpleIndex, tableSize);
1099ghashState.table.init(static_cast<uint32_t>(tableSize));
1100
1101// Insert ghashes in parallel. During concurrent insertion, we cannot observe
1102// the contents of the hash table cell, but we can remember the insertion
1103// position. Because the table does not rehash, the position will not change
1104// under insertion. After insertion is done, the value of the cell can be read
1105// to retrieve the final PDB type index.
1106parallelFor(0, ctx.tpiSourceList.size(), [&](size_t tpiSrcIdx) {
1107TpiSource *source = ctx.tpiSourceList[tpiSrcIdx];
1108source->indexMapStorage.resize(source->ghashes.size());
1109for (uint32_t i = 0, e = source->ghashes.size(); i < e; i++) {
1110if (source->shouldOmitFromPdb(i)) {
1111source->indexMapStorage[i] = TypeIndex(SimpleTypeKind::NotTranslated);
1112continue;
1113}
1114GloballyHashedType ghash = source->ghashes[i];
1115bool isItem = source->isItemIndex.test(i);
1116uint32_t cellIdx =
1117ghashState.table.insert(ctx, ghash, GHashCell(isItem, tpiSrcIdx, i));
1118
1119// Store the ghash cell index as a type index in indexMapStorage. Later
1120// we will replace it with the PDB type index.
1121source->indexMapStorage[i] = TypeIndex::fromArrayIndex(cellIdx);
1122}
1123});
1124
1125// Collect all non-empty cells and sort them. This will implicitly assign
1126// destination type indices, and partition the entries into type records and
1127// item records. It arranges types in this order:
1128// - type records
1129// - source 0, type 0...
1130// - source 1, type 1...
1131// - item records
1132// - source 0, type 1...
1133// - source 1, type 0...
1134std::vector<GHashCell> entries;
1135for (const GHashCell &cell : ArrayRef(ghashState.table.table, tableSize)) {
1136if (!cell.isEmpty())
1137entries.push_back(cell);
1138}
1139parallelSort(entries, std::less<GHashCell>());
1140log(formatv("ghash table load factor: {0:p} (size {1} / capacity {2})\n",
1141tableSize ? double(entries.size()) / tableSize : 0,
1142entries.size(), tableSize));
1143
1144// Find out how many type and item indices there are.
1145auto mid = llvm::lower_bound(entries, GHashCell(true, 0, 0));
1146assert((mid == entries.end() || mid->isItem()) &&
1147(mid == entries.begin() || !std::prev(mid)->isItem()) &&
1148"midpoint is not midpoint");
1149uint32_t numTypes = std::distance(entries.begin(), mid);
1150uint32_t numItems = std::distance(mid, entries.end());
1151log("Tpi record count: " + Twine(numTypes));
1152log("Ipi record count: " + Twine(numItems));
1153
1154// Make a list of the "unique" type records to merge for each tpi source. Type
1155// merging will skip indices not on this list. Store the destination PDB type
1156// index for these unique types in the tpiMap for each source. The entries for
1157// non-unique types will be filled in prior to type merging.
1158for (uint32_t i = 0, e = entries.size(); i < e; ++i) {
1159auto &cell = entries[i];
1160uint32_t tpiSrcIdx = cell.getTpiSrcIdx();
1161TpiSource *source = ctx.tpiSourceList[tpiSrcIdx];
1162source->uniqueTypes.push_back(cell.getGHashIdx());
1163
1164// Update the ghash table to store the destination PDB type index in the
1165// table.
1166uint32_t pdbTypeIndex = i < numTypes ? i : i - numTypes;
1167uint32_t ghashCellIndex =
1168source->indexMapStorage[cell.getGHashIdx()].toArrayIndex();
1169ghashState.table.table[ghashCellIndex] =
1170GHashCell(cell.isItem(), cell.getTpiSrcIdx(), pdbTypeIndex);
1171}
1172
1173// In parallel, remap all types.
1174for (TpiSource *source : dependencySources)
1175source->remapTpiWithGHashes(&ghashState);
1176parallelForEach(objectSources, [&](TpiSource *source) {
1177source->remapTpiWithGHashes(&ghashState);
1178});
1179
1180// Build a global map of from function ID to function type.
1181for (TpiSource *source : ctx.tpiSourceList) {
1182for (auto idToType : source->funcIdToType)
1183funcIdToType.insert(idToType);
1184source->funcIdToType.clear();
1185}
1186
1187clearGHashes();
1188}
1189
1190void TypeMerger::sortDependencies() {
1191// Order dependencies first, but preserve the existing order.
1192std::vector<TpiSource *> deps;
1193std::vector<TpiSource *> objs;
1194for (TpiSource *s : ctx.tpiSourceList)
1195(s->isDependency() ? deps : objs).push_back(s);
1196uint32_t numDeps = deps.size();
1197uint32_t numObjs = objs.size();
1198ctx.tpiSourceList = std::move(deps);
1199ctx.tpiSourceList.insert(ctx.tpiSourceList.end(), objs.begin(), objs.end());
1200for (uint32_t i = 0, e = ctx.tpiSourceList.size(); i < e; ++i)
1201ctx.tpiSourceList[i]->tpiSrcIdx = i;
1202dependencySources = ArrayRef(ctx.tpiSourceList.data(), numDeps);
1203objectSources = ArrayRef(ctx.tpiSourceList.data() + numDeps, numObjs);
1204}
1205
1206/// Given the index into the ghash table for a particular type, return the type
1207/// index for that type in the output PDB.
1208static TypeIndex loadPdbTypeIndexFromCell(GHashState *g,
1209uint32_t ghashCellIdx) {
1210GHashCell cell = g->table.table[ghashCellIdx];
1211return TypeIndex::fromArrayIndex(cell.getGHashIdx());
1212}
1213
1214/// Free heap allocated ghashes.
1215void TypeMerger::clearGHashes() {
1216for (TpiSource *src : ctx.tpiSourceList) {
1217if (src->ownedGHashes)
1218delete[] src->ghashes.data();
1219src->ghashes = {};
1220src->isItemIndex.clear();
1221src->uniqueTypes.clear();
1222}
1223}
1224
1225// Fill in a TPI or IPI index map using ghashes. For each source type, use its
1226// ghash to lookup its final type index in the PDB, and store that in the map.
1227void TpiSource::fillMapFromGHashes(GHashState *g) {
1228for (size_t i = 0, e = ghashes.size(); i < e; ++i) {
1229TypeIndex fakeCellIndex = indexMapStorage[i];
1230if (fakeCellIndex.isSimple())
1231indexMapStorage[i] = fakeCellIndex;
1232else
1233indexMapStorage[i] =
1234loadPdbTypeIndexFromCell(g, fakeCellIndex.toArrayIndex());
1235}
1236}
1237