[lld] 6f7483b - Reland "[LLD] Remove global state in lld/COFF" after fixing asan and msan test failures

Geoffrey Martin-Noble via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 17 18:00:41 PDT 2021


No worries. Thanks for the fix :-)

On Fri, Sep 17, 2021 at 5:42 PM Amy Huang <akhuang at google.com> wrote:

> Whoops, I'll fix that.
>
> On Fri, Sep 17, 2021 at 5:40 PM Geoffrey Martin-Noble <gcmn at google.com>
> wrote:
>
>> I'm seeing diagnostic failures that appear to be coming from this commit
>>
>> llvm-project/lld/Common/Timer.cpp:29:38: error: field 'name' will be
>> initialized after field 'total' [-Werror,-Wreorder-ctor]
>> Timer::Timer(llvm::StringRef name) : name(std::string(name)), total(0) {}
>>
>> Could you take a look?
>>
>> On Fri, Sep 17, 2021 at 5:19 PM Amy Huang via llvm-commits <
>> llvm-commits at lists.llvm.org> wrote:
>>
>>>
>>> Author: Amy Huang
>>> Date: 2021-09-17T17:18:42-07:00
>>> New Revision: 6f7483b1ece4747f2aafe4baa05fc07e7dc9ed9d
>>>
>>> URL:
>>> https://github.com/llvm/llvm-project/commit/6f7483b1ece4747f2aafe4baa05fc07e7dc9ed9d
>>> DIFF:
>>> https://github.com/llvm/llvm-project/commit/6f7483b1ece4747f2aafe4baa05fc07e7dc9ed9d.diff
>>>
>>> LOG: Reland "[LLD] Remove global state in lld/COFF" after fixing asan
>>> and msan test failures
>>>
>>> Original commit description:
>>>
>>>   [LLD] Remove global state in lld/COFF
>>>
>>>   This patch removes globals from the lldCOFF library, by moving globals
>>>   into a context class (COFFLinkingContext) and passing it around
>>> wherever
>>>   it's needed.
>>>
>>>   See https://lists.llvm.org/pipermail/llvm-dev/2021-June/151184.html
>>> for
>>>   context about removing globals from LLD.
>>>
>>>   I also haven't moved the `driver` or `config` variables yet.
>>>
>>>   Differential Revision: https://reviews.llvm.org/D109634
>>>
>>> This reverts commit a2fd05ada9030eab2258fff25e77a05adccae128.
>>>
>>> Original commits were b4fa71eed34d967195514fe9b0a5211fca2bc5bc
>>> and e03c7e367adb8f228332e3c2ef8f45484597b719.
>>>
>>> Added:
>>>     lld/COFF/COFFLinkerContext.cpp
>>>     lld/COFF/COFFLinkerContext.h
>>>     lld/test/COFF/timers.ll
>>>
>>> Modified:
>>>     lld/COFF/CMakeLists.txt
>>>     lld/COFF/CallGraphSort.cpp
>>>     lld/COFF/CallGraphSort.h
>>>     lld/COFF/Chunks.cpp
>>>     lld/COFF/Chunks.h
>>>     lld/COFF/DLL.cpp
>>>     lld/COFF/DLL.h
>>>     lld/COFF/DebugTypes.cpp
>>>     lld/COFF/DebugTypes.h
>>>     lld/COFF/Driver.cpp
>>>     lld/COFF/Driver.h
>>>     lld/COFF/ICF.cpp
>>>     lld/COFF/ICF.h
>>>     lld/COFF/InputFiles.cpp
>>>     lld/COFF/InputFiles.h
>>>     lld/COFF/LLDMapFile.cpp
>>>     lld/COFF/LLDMapFile.h
>>>     lld/COFF/LTO.cpp
>>>     lld/COFF/LTO.h
>>>     lld/COFF/MapFile.cpp
>>>     lld/COFF/MapFile.h
>>>     lld/COFF/MarkLive.cpp
>>>     lld/COFF/MarkLive.h
>>>     lld/COFF/MinGW.cpp
>>>     lld/COFF/MinGW.h
>>>     lld/COFF/PDB.cpp
>>>     lld/COFF/PDB.h
>>>     lld/COFF/SymbolTable.cpp
>>>     lld/COFF/SymbolTable.h
>>>     lld/COFF/TypeMerger.h
>>>     lld/COFF/Writer.cpp
>>>     lld/COFF/Writer.h
>>>     lld/Common/Timer.cpp
>>>     lld/include/lld/Common/Timer.h
>>>     llvm/utils/gn/secondary/lld/COFF/BUILD.gn
>>>
>>> Removed:
>>>
>>>
>>>
>>>
>>> ################################################################################
>>> diff  --git a/lld/COFF/CMakeLists.txt b/lld/COFF/CMakeLists.txt
>>> index bbcd337b210f3..b32b9cfcff04e 100644
>>> --- a/lld/COFF/CMakeLists.txt
>>> +++ b/lld/COFF/CMakeLists.txt
>>> @@ -5,6 +5,7 @@ add_public_tablegen_target(COFFOptionsTableGen)
>>>  add_lld_library(lldCOFF
>>>    CallGraphSort.cpp
>>>    Chunks.cpp
>>> +  COFFLinkerContext.cpp
>>>    DebugTypes.cpp
>>>    DLL.cpp
>>>    Driver.cpp
>>>
>>> diff  --git a/lld/COFF/COFFLinkerContext.cpp
>>> b/lld/COFF/COFFLinkerContext.cpp
>>> new file mode 100644
>>> index 0000000000000..a280cacb932e2
>>> --- /dev/null
>>> +++ b/lld/COFF/COFFLinkerContext.cpp
>>> @@ -0,0 +1,40 @@
>>> +//===- COFFContext.cpp
>>> ----------------------------------------------------===//
>>> +// Part of the LLVM Project, under the Apache License v2.0 with LLVM
>>> Exceptions.
>>> +// See https://llvm.org/LICENSE.txt for license information.
>>> +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +//
>>> +// Description
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +#include "COFFLinkerContext.h"
>>> +#include "lld/Common/Memory.h"
>>> +#include "llvm/DebugInfo/CodeView/TypeHashing.h"
>>> +
>>> +namespace lld {
>>> +namespace coff {
>>> +
>>> +COFFLinkerContext::COFFLinkerContext()
>>> +    : symtab(*this), rootTimer("Total Linking Time"),
>>> +      inputFileTimer("Input File Reading", rootTimer),
>>> +      ltoTimer("LTO", rootTimer), gcTimer("GC", rootTimer),
>>> +      icfTimer("ICF", rootTimer), codeLayoutTimer("Code Layout",
>>> rootTimer),
>>> +      outputCommitTimer("Commit Output File", rootTimer),
>>> +      totalMapTimer("MAP Emission (Cumulative)", rootTimer),
>>> +      symbolGatherTimer("Gather Symbols", totalMapTimer),
>>> +      symbolStringsTimer("Build Symbol Strings", totalMapTimer),
>>> +      writeTimer("Write to File", totalMapTimer),
>>> +      totalPdbLinkTimer("PDB Emission (Cumulative)", rootTimer),
>>> +      addObjectsTimer("Add Objects", totalPdbLinkTimer),
>>> +      typeMergingTimer("Type Merging", addObjectsTimer),
>>> +      loadGHashTimer("Global Type Hashing", addObjectsTimer),
>>> +      mergeGHashTimer("GHash Type Merging", addObjectsTimer),
>>> +      symbolMergingTimer("Symbol Merging", addObjectsTimer),
>>> +      publicsLayoutTimer("Publics Stream Layout", totalPdbLinkTimer),
>>> +      tpiStreamLayoutTimer("TPI Stream Layout", totalPdbLinkTimer),
>>> +      diskCommitTimer("Commit to Disk", totalPdbLinkTimer) {}
>>> +
>>> +} // namespace coff
>>> +} // namespace lld
>>>
>>> diff  --git a/lld/COFF/COFFLinkerContext.h b/lld/COFF/COFFLinkerContext.h
>>> new file mode 100644
>>> index 0000000000000..e5223da86ef83
>>> --- /dev/null
>>> +++ b/lld/COFF/COFFLinkerContext.h
>>> @@ -0,0 +1,85 @@
>>> +//===- COFFLinkerContext.h --------------------------------------*- C++
>>> -*-===//
>>> +//
>>> +// Part of the LLVM Project, under the Apache License v2.0 with LLVM
>>> Exceptions.
>>> +// See https://llvm.org/LICENSE.txt for license information.
>>> +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +#ifndef LLD_COFF_COFFLinkerContext_H
>>> +#define LLD_COFF_COFFLinkerContext_H
>>> +
>>> +#include "Chunks.h"
>>> +#include "Config.h"
>>> +#include "DebugTypes.h"
>>> +#include "InputFiles.h"
>>> +#include "SymbolTable.h"
>>> +#include "Writer.h"
>>> +#include "lld/Common/Timer.h"
>>> +
>>> +namespace lld {
>>> +namespace coff {
>>> +
>>> +class COFFLinkerContext {
>>> +public:
>>> +  COFFLinkerContext();
>>> +  COFFLinkerContext(const COFFLinkerContext &) = delete;
>>> +  COFFLinkerContext &operator=(const COFFLinkerContext &) = delete;
>>> +  ~COFFLinkerContext() = default;
>>> +
>>> +  void addTpiSource(TpiSource *tpi) { tpiSourceList.push_back(tpi); }
>>> +
>>> +  SymbolTable symtab;
>>> +
>>> +  std::vector<ObjFile *> objFileInstances;
>>> +  std::map<std::string, PDBInputFile *> pdbInputFileInstances;
>>> +  std::vector<ImportFile *> importFileInstances;
>>> +  std::vector<BitcodeFile *> bitcodeFileInstances;
>>> +
>>> +  MergeChunk *mergeChunkInstances[Log2MaxSectionAlignment + 1] = {};
>>> +
>>> +  /// All sources of type information in the program.
>>> +  std::vector<TpiSource *> tpiSourceList;
>>> +
>>> +  std::map<llvm::codeview::GUID, TpiSource *> typeServerSourceMappings;
>>> +  std::map<uint32_t, TpiSource *> precompSourceMappings;
>>> +
>>> +  /// List of all output sections. After output sections are finalized,
>>> this
>>> +  /// can be indexed by getOutputSection.
>>> +  std::vector<OutputSection *> outputSections;
>>> +
>>> +  OutputSection *getOutputSection(const Chunk *c) const {
>>> +    return c->osidx == 0 ? nullptr : outputSections[c->osidx - 1];
>>> +  }
>>> +
>>> +  // All timers used in the COFF linker.
>>> +  Timer rootTimer;
>>> +  Timer inputFileTimer;
>>> +  Timer ltoTimer;
>>> +  Timer gcTimer;
>>> +  Timer icfTimer;
>>> +
>>> +  // Writer timers.
>>> +  Timer codeLayoutTimer;
>>> +  Timer outputCommitTimer;
>>> +  Timer totalMapTimer;
>>> +  Timer symbolGatherTimer;
>>> +  Timer symbolStringsTimer;
>>> +  Timer writeTimer;
>>> +
>>> +  // PDB timers.
>>> +  Timer totalPdbLinkTimer;
>>> +  Timer addObjectsTimer;
>>> +  Timer typeMergingTimer;
>>> +  Timer loadGHashTimer;
>>> +  Timer mergeGHashTimer;
>>> +  Timer symbolMergingTimer;
>>> +  Timer publicsLayoutTimer;
>>> +  Timer tpiStreamLayoutTimer;
>>> +  Timer diskCommitTimer;
>>> +};
>>> +
>>> +} // namespace coff
>>> +} // namespace lld
>>> +
>>> +#endif
>>>
>>> diff  --git a/lld/COFF/CallGraphSort.cpp b/lld/COFF/CallGraphSort.cpp
>>> index d3e5312ce7fdd..709e69b24914b 100644
>>> --- a/lld/COFF/CallGraphSort.cpp
>>> +++ b/lld/COFF/CallGraphSort.cpp
>>> @@ -12,6 +12,7 @@
>>>
>>>  //===----------------------------------------------------------------------===//
>>>
>>>  #include "CallGraphSort.h"
>>> +#include "COFFLinkerContext.h"
>>>  #include "InputFiles.h"
>>>  #include "SymbolTable.h"
>>>  #include "Symbols.h"
>>> @@ -48,7 +49,7 @@ struct Cluster {
>>>
>>>  class CallGraphSort {
>>>  public:
>>> -  CallGraphSort();
>>> +  CallGraphSort(const COFFLinkerContext &ctx);
>>>
>>>    DenseMap<const SectionChunk *, int> run();
>>>
>>> @@ -70,7 +71,7 @@ using SectionPair = std::pair<const SectionChunk *,
>>> const SectionChunk *>;
>>>  // Take the edge list in Config->CallGraphProfile, resolve symbol names
>>> to
>>>  // Symbols, and generate a graph between InputSections with the provided
>>>  // weights.
>>> -CallGraphSort::CallGraphSort() {
>>> +CallGraphSort::CallGraphSort(const COFFLinkerContext &ctx) {
>>>    MapVector<SectionPair, uint64_t> &profile = config->callGraphProfile;
>>>    DenseMap<const SectionChunk *, int> secToCluster;
>>>
>>> @@ -95,7 +96,7 @@ CallGraphSort::CallGraphSort() {
>>>      // output.  This messes with the cluster size and density
>>> calculations.  We
>>>      // would also end up moving input sections in other output sections
>>> without
>>>      // moving them closer to what calls them.
>>> -    if (fromSec->getOutputSection() != toSec->getOutputSection())
>>> +    if (ctx.getOutputSection(fromSec) != ctx.getOutputSection(toSec))
>>>        continue;
>>>
>>>      int from = getOrCreateNode(fromSec);
>>> @@ -240,6 +241,7 @@ DenseMap<const SectionChunk *, int>
>>> CallGraphSort::run() {
>>>  // This first builds a call graph based on the profile data then merges
>>> sections
>>>  // according to the C³ heuristic. All clusters are then sorted by a
>>> density
>>>  // metric to further improve locality.
>>> -DenseMap<const SectionChunk *, int>
>>> coff::computeCallGraphProfileOrder() {
>>> -  return CallGraphSort().run();
>>> +DenseMap<const SectionChunk *, int>
>>> +coff::computeCallGraphProfileOrder(const COFFLinkerContext &ctx) {
>>> +  return CallGraphSort(ctx).run();
>>>  }
>>>
>>> diff  --git a/lld/COFF/CallGraphSort.h b/lld/COFF/CallGraphSort.h
>>> index e4f372137448c..99f35d6b62762 100644
>>> --- a/lld/COFF/CallGraphSort.h
>>> +++ b/lld/COFF/CallGraphSort.h
>>> @@ -14,8 +14,10 @@
>>>  namespace lld {
>>>  namespace coff {
>>>  class SectionChunk;
>>> +class COFFLinkerContext;
>>>
>>> -llvm::DenseMap<const SectionChunk *, int>
>>> computeCallGraphProfileOrder();
>>> +llvm::DenseMap<const SectionChunk *, int>
>>> +computeCallGraphProfileOrder(const COFFLinkerContext &ctx);
>>>  } // namespace coff
>>>  } // namespace lld
>>>
>>>
>>> diff  --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
>>> index 36d5f371326fe..9f6dbd1725096 100644
>>> --- a/lld/COFF/Chunks.cpp
>>> +++ b/lld/COFF/Chunks.cpp
>>> @@ -7,10 +7,11 @@
>>>
>>>  //===----------------------------------------------------------------------===//
>>>
>>>  #include "Chunks.h"
>>> +#include "COFFLinkerContext.h"
>>>  #include "InputFiles.h"
>>> +#include "SymbolTable.h"
>>>  #include "Symbols.h"
>>>  #include "Writer.h"
>>> -#include "SymbolTable.h"
>>>  #include "lld/Common/ErrorHandler.h"
>>>  #include "llvm/ADT/Twine.h"
>>>  #include "llvm/BinaryFormat/COFF.h"
>>> @@ -385,7 +386,7 @@ void SectionChunk::applyRelocation(uint8_t *off,
>>>    // section is needed to compute SECREL and SECTION relocations used
>>> in debug
>>>    // info.
>>>    Chunk *c = sym ? sym->getChunk() : nullptr;
>>> -  OutputSection *os = c ? c->getOutputSection() : nullptr;
>>> +  OutputSection *os = c ? file->ctx.getOutputSection(c) : nullptr;
>>>
>>>    // Skip the relocation if it refers to a discarded section, and
>>> diagnose it
>>>    // as an error if appropriate. If a symbol was discarded early, it
>>> may be
>>> @@ -938,18 +939,16 @@ uint8_t Baserel::getDefaultType() {
>>>    }
>>>  }
>>>
>>> -MergeChunk *MergeChunk::instances[Log2MaxSectionAlignment + 1] = {};
>>> -
>>>  MergeChunk::MergeChunk(uint32_t alignment)
>>>      : builder(StringTableBuilder::RAW, alignment) {
>>>    setAlignment(alignment);
>>>  }
>>>
>>> -void MergeChunk::addSection(SectionChunk *c) {
>>> +void MergeChunk::addSection(COFFLinkerContext &ctx, SectionChunk *c) {
>>>    assert(isPowerOf2_32(c->getAlignment()));
>>>    uint8_t p2Align = llvm::Log2_32(c->getAlignment());
>>> -  assert(p2Align < array_lengthof(instances));
>>> -  auto *&mc = instances[p2Align];
>>> +  assert(p2Align < array_lengthof(ctx.mergeChunkInstances));
>>> +  auto *&mc = ctx.mergeChunkInstances[p2Align];
>>>    if (!mc)
>>>      mc = make<MergeChunk>(c->getAlignment());
>>>    mc->sections.push_back(c);
>>>
>>> diff  --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h
>>> index bdd3faa179a8a..daaa043ffaceb 100644
>>> --- a/lld/COFF/Chunks.h
>>> +++ b/lld/COFF/Chunks.h
>>> @@ -101,7 +101,6 @@ class Chunk {
>>>    // chunk has a back pointer to an output section.
>>>    void setOutputSectionIdx(uint16_t o) { osidx = o; }
>>>    uint16_t getOutputSectionIdx() const { return osidx; }
>>> -  OutputSection *getOutputSection() const;
>>>
>>>    // Windows-specific.
>>>    // Collect all locations that contain absolute addresses for base
>>> relocations.
>>> @@ -415,7 +414,7 @@ inline StringRef Chunk::getDebugName() const {
>>>  class MergeChunk : public NonSectionChunk {
>>>  public:
>>>    MergeChunk(uint32_t alignment);
>>> -  static void addSection(SectionChunk *c);
>>> +  static void addSection(COFFLinkerContext &ctx, SectionChunk *c);
>>>    void finalizeContents();
>>>    void assignSubsectionRVAs();
>>>
>>> @@ -424,7 +423,6 @@ class MergeChunk : public NonSectionChunk {
>>>    size_t getSize() const override;
>>>    void writeTo(uint8_t *buf) const override;
>>>
>>> -  static MergeChunk *instances[Log2MaxSectionAlignment + 1];
>>>    std::vector<SectionChunk *> sections;
>>>
>>>  private:
>>>
>>> diff  --git a/lld/COFF/DLL.cpp b/lld/COFF/DLL.cpp
>>> index b9e12ef4b34dd..6fec9df5617db 100644
>>> --- a/lld/COFF/DLL.cpp
>>> +++ b/lld/COFF/DLL.cpp
>>> @@ -18,6 +18,7 @@
>>>
>>>  //===----------------------------------------------------------------------===//
>>>
>>>  #include "DLL.h"
>>> +#include "COFFLinkerContext.h"
>>>  #include "Chunks.h"
>>>  #include "SymbolTable.h"
>>>  #include "llvm/Object/COFF.h"
>>> @@ -631,7 +632,7 @@ uint64_t DelayLoadContents::getDirSize() {
>>>    return dirs.size() * sizeof(delay_import_directory_table_entry);
>>>  }
>>>
>>> -void DelayLoadContents::create(Defined *h) {
>>> +void DelayLoadContents::create(COFFLinkerContext &ctx, Defined *h) {
>>>    helper = h;
>>>    std::vector<std::vector<DefinedImportData *>> v = binImports(imports);
>>>
>>> @@ -660,13 +661,13 @@ void DelayLoadContents::create(Defined *h) {
>>>          // call targets for Control Flow Guard.
>>>          StringRef symName = saver.save("__imp_load_" + extName);
>>>          s->loadThunkSym =
>>> -            cast<DefinedSynthetic>(symtab->addSynthetic(symName, t));
>>> +            cast<DefinedSynthetic>(ctx.symtab.addSynthetic(symName, t));
>>>        }
>>>      }
>>>      thunks.push_back(tm);
>>>      StringRef tmName =
>>>          saver.save("__tailMerge_" + syms[0]->getDLLName().lower());
>>> -    symtab->addSynthetic(tmName, tm);
>>> +    ctx.symtab.addSynthetic(tmName, tm);
>>>      // Terminate with null values.
>>>      addresses.push_back(make<NullChunk>(8));
>>>      names.push_back(make<NullChunk>(8));
>>>
>>> diff  --git a/lld/COFF/DLL.h b/lld/COFF/DLL.h
>>> index ce0ee01c4a3df..0d594e675bd23 100644
>>> --- a/lld/COFF/DLL.h
>>> +++ b/lld/COFF/DLL.h
>>> @@ -40,7 +40,7 @@ class DelayLoadContents {
>>>  public:
>>>    void add(DefinedImportData *sym) { imports.push_back(sym); }
>>>    bool empty() { return imports.empty(); }
>>> -  void create(Defined *helper);
>>> +  void create(COFFLinkerContext &ctx, Defined *helper);
>>>    std::vector<Chunk *> getChunks();
>>>    std::vector<Chunk *> getDataChunks();
>>>    ArrayRef<Chunk *> getCodeChunks() { return thunks; }
>>>
>>> diff  --git a/lld/COFF/DebugTypes.cpp b/lld/COFF/DebugTypes.cpp
>>> index 97be5bc79ac34..115b66c34332d 100644
>>> --- a/lld/COFF/DebugTypes.cpp
>>> +++ b/lld/COFF/DebugTypes.cpp
>>> @@ -7,6 +7,7 @@
>>>
>>>  //===----------------------------------------------------------------------===//
>>>
>>>  #include "DebugTypes.h"
>>> +#include "COFFLinkerContext.h"
>>>  #include "Chunks.h"
>>>  #include "Driver.h"
>>>  #include "InputFiles.h"
>>> @@ -14,7 +15,6 @@
>>>  #include "TypeMerger.h"
>>>  #include "lld/Common/ErrorHandler.h"
>>>  #include "lld/Common/Memory.h"
>>> -#include "lld/Common/Timer.h"
>>>  #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
>>>  #include "llvm/DebugInfo/CodeView/TypeRecord.h"
>>>  #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
>>> @@ -46,8 +46,8 @@ class TypeServerIpiSource;
>>>  // before any dependent OBJ.
>>>  class TypeServerSource : public TpiSource {
>>>  public:
>>> -  explicit TypeServerSource(PDBInputFile *f)
>>> -      : TpiSource(PDB, nullptr), pdbInputFile(f) {
>>> +  explicit TypeServerSource(COFFLinkerContext &ctx, PDBInputFile *f)
>>> +      : TpiSource(ctx, PDB, nullptr), pdbInputFile(f) {
>>>      if (f->loadErr && *f->loadErr)
>>>        return;
>>>      pdb::PDBFile &file = f->session->getPDBFile();
>>> @@ -55,7 +55,7 @@ class TypeServerSource : public TpiSource {
>>>      if (!expectedInfo)
>>>        return;
>>>      Guid = expectedInfo->getGuid();
>>> -    auto it = mappings.emplace(Guid, this);
>>> +    auto it = ctx.typeServerSourceMappings.emplace(Guid, this);
>>>      assert(it.second);
>>>      (void)it;
>>>    }
>>> @@ -74,8 +74,6 @@ class TypeServerSource : public TpiSource {
>>>
>>>    // The PDB signature GUID.
>>>    codeview::GUID Guid;
>>> -
>>> -  static std::map<codeview::GUID, TypeServerSource *> mappings;
>>>  };
>>>
>>>  // Companion to TypeServerSource. Stores the index map for the IPI
>>> stream in the
>>> @@ -83,7 +81,8 @@ class TypeServerSource : public TpiSource {
>>>  // invariant of one type index space per source.
>>>  class TypeServerIpiSource : public TpiSource {
>>>  public:
>>> -  explicit TypeServerIpiSource() : TpiSource(PDBIpi, nullptr) {}
>>> +  explicit TypeServerIpiSource(COFFLinkerContext &ctx)
>>> +      : TpiSource(ctx, PDBIpi, nullptr) {}
>>>
>>>    friend class TypeServerSource;
>>>
>>> @@ -101,8 +100,8 @@ class UseTypeServerSource : public TpiSource {
>>>    Expected<TypeServerSource *> getTypeServerSource();
>>>
>>>  public:
>>> -  UseTypeServerSource(ObjFile *f, TypeServer2Record ts)
>>> -      : TpiSource(UsingPDB, f), typeServerDependency(ts) {}
>>> +  UseTypeServerSource(COFFLinkerContext &ctx, ObjFile *f,
>>> TypeServer2Record ts)
>>> +      : TpiSource(ctx, UsingPDB, f), typeServerDependency(ts) {}
>>>
>>>    Error mergeDebugT(TypeMerger *m) override;
>>>
>>> @@ -121,11 +120,11 @@ class UseTypeServerSource : public TpiSource {
>>>  // such files, clang does not.
>>>  class PrecompSource : public TpiSource {
>>>  public:
>>> -  PrecompSource(ObjFile *f) : TpiSource(PCH, f) {
>>> +  PrecompSource(COFFLinkerContext &ctx, ObjFile *f) : TpiSource(ctx,
>>> PCH, f) {
>>>      if (!f->pchSignature || !*f->pchSignature)
>>>        fatal(toString(f) +
>>>              " claims to be a PCH object, but does not have a valid
>>> signature");
>>> -    auto it = mappings.emplace(*f->pchSignature, this);
>>> +    auto it = ctx.precompSourceMappings.emplace(*f->pchSignature, this);
>>>      if (!it.second)
>>>        fatal("a PCH object with the same signature has already been
>>> provided (" +
>>>              toString(it.first->second->file) + " and " + toString(file)
>>> + ")");
>>> @@ -134,16 +133,14 @@ class PrecompSource : public TpiSource {
>>>    void loadGHashes() override;
>>>
>>>    bool isDependency() const override { return true; }
>>> -
>>> -  static std::map<uint32_t, PrecompSource *> mappings;
>>>  };
>>>
>>>  // This class represents the debug type stream of an OBJ file that
>>> depends on a
>>>  // Microsoft precompiled headers OBJ (see PrecompSource).
>>>  class UsePrecompSource : public TpiSource {
>>>  public:
>>> -  UsePrecompSource(ObjFile *f, PrecompRecord precomp)
>>> -      : TpiSource(UsingPCH, f), precompDependency(precomp) {}
>>> +  UsePrecompSource(COFFLinkerContext &ctx, ObjFile *f, PrecompRecord
>>> precomp)
>>> +      : TpiSource(ctx, UsingPCH, f), precompDependency(precomp) {}
>>>
>>>    Error mergeDebugT(TypeMerger *m) override;
>>>
>>> @@ -153,6 +150,10 @@ class UsePrecompSource : public TpiSource {
>>>  private:
>>>    Error mergeInPrecompHeaderObj();
>>>
>>> +  PrecompSource *findObjByName(StringRef fileNameOnly);
>>> +  PrecompSource *findPrecompSource(ObjFile *file, PrecompRecord &pr);
>>> +  Expected<PrecompSource *> findPrecompMap(ObjFile *file, PrecompRecord
>>> &pr);
>>> +
>>>  public:
>>>    // Information about the Precomp OBJ dependency, that needs to be
>>> loaded in
>>>    // before merging this OBJ.
>>> @@ -160,13 +161,9 @@ class UsePrecompSource : public TpiSource {
>>>  };
>>>  } // namespace
>>>
>>> -std::vector<TpiSource *> TpiSource::instances;
>>> -ArrayRef<TpiSource *> TpiSource::dependencySources;
>>> -ArrayRef<TpiSource *> TpiSource::objectSources;
>>> -
>>> -TpiSource::TpiSource(TpiKind k, ObjFile *f)
>>> -    : kind(k), tpiSrcIdx(instances.size()), file(f) {
>>> -  instances.push_back(this);
>>> +TpiSource::TpiSource(COFFLinkerContext &ctx, TpiKind k, ObjFile *f)
>>> +    : ctx(ctx), kind(k), tpiSrcIdx(ctx.tpiSourceList.size()), file(f) {
>>> +  ctx.addTpiSource(this);
>>>  }
>>>
>>>  // Vtable key method.
>>> @@ -175,52 +172,35 @@ TpiSource::~TpiSource() {
>>>    consumeError(std::move(typeMergingError));
>>>  }
>>>
>>> -void TpiSource::sortDependencies() {
>>> -  // Order dependencies first, but preserve the existing order.
>>> -  std::vector<TpiSource *> deps;
>>> -  std::vector<TpiSource *> objs;
>>> -  for (TpiSource *s : instances)
>>> -    (s->isDependency() ? deps : objs).push_back(s);
>>> -  uint32_t numDeps = deps.size();
>>> -  uint32_t numObjs = objs.size();
>>> -  instances = std::move(deps);
>>> -  instances.insert(instances.end(), objs.begin(), objs.end());
>>> -  for (uint32_t i = 0, e = instances.size(); i < e; ++i)
>>> -    instances[i]->tpiSrcIdx = i;
>>> -  dependencySources = makeArrayRef(instances.data(), numDeps);
>>> -  objectSources = makeArrayRef(instances.data() + numDeps, numObjs);
>>> -}
>>> -
>>> -TpiSource *lld::coff::makeTpiSource(ObjFile *file) {
>>> -  return make<TpiSource>(TpiSource::Regular, file);
>>> +TpiSource *lld::coff::makeTpiSource(COFFLinkerContext &ctx, ObjFile
>>> *file) {
>>> +  return make<TpiSource>(ctx, TpiSource::Regular, file);
>>>  }
>>>
>>> -TpiSource *lld::coff::makeTypeServerSource(PDBInputFile *pdbInputFile) {
>>> +TpiSource *lld::coff::makeTypeServerSource(COFFLinkerContext &ctx,
>>> +                                           PDBInputFile *pdbInputFile) {
>>>    // Type server sources come in pairs: the TPI stream, and the IPI
>>> stream.
>>> -  auto *tpiSource = make<TypeServerSource>(pdbInputFile);
>>> +  auto *tpiSource = make<TypeServerSource>(ctx, pdbInputFile);
>>>    if (pdbInputFile->session->getPDBFile().hasPDBIpiStream())
>>> -    tpiSource->ipiSrc = make<TypeServerIpiSource>();
>>> +    tpiSource->ipiSrc = make<TypeServerIpiSource>(ctx);
>>>    return tpiSource;
>>>  }
>>>
>>> -TpiSource *lld::coff::makeUseTypeServerSource(ObjFile *file,
>>> +TpiSource *lld::coff::makeUseTypeServerSource(COFFLinkerContext &ctx,
>>> +                                              ObjFile *file,
>>>                                                TypeServer2Record ts) {
>>> -  return make<UseTypeServerSource>(file, ts);
>>> +  return make<UseTypeServerSource>(ctx, file, ts);
>>>  }
>>>
>>> -TpiSource *lld::coff::makePrecompSource(ObjFile *file) {
>>> -  return make<PrecompSource>(file);
>>> +TpiSource *lld::coff::makePrecompSource(COFFLinkerContext &ctx, ObjFile
>>> *file) {
>>> +  return make<PrecompSource>(ctx, file);
>>>  }
>>>
>>> -TpiSource *lld::coff::makeUsePrecompSource(ObjFile *file,
>>> +TpiSource *lld::coff::makeUsePrecompSource(COFFLinkerContext &ctx,
>>> +                                           ObjFile *file,
>>>                                             PrecompRecord precomp) {
>>> -  return make<UsePrecompSource>(file, precomp);
>>> +  return make<UsePrecompSource>(ctx, file, precomp);
>>>  }
>>>
>>> -std::map<codeview::GUID, TypeServerSource *> TypeServerSource::mappings;
>>> -
>>> -std::map<uint32_t, PrecompSource *> PrecompSource::mappings;
>>> -
>>>  bool TpiSource::remapTypeIndex(TypeIndex &ti, TiRefKind refKind) const {
>>>    if (ti.isSimple())
>>>      return true;
>>> @@ -419,12 +399,12 @@ Expected<TypeServerSource *>
>>> UseTypeServerSource::getTypeServerSource() {
>>>    StringRef tsPath = typeServerDependency.getName();
>>>
>>>    TypeServerSource *tsSrc;
>>> -  auto it = TypeServerSource::mappings.find(tsId);
>>> -  if (it != TypeServerSource::mappings.end()) {
>>> -    tsSrc = it->second;
>>> +  auto it = ctx.typeServerSourceMappings.find(tsId);
>>> +  if (it != ctx.typeServerSourceMappings.end()) {
>>> +    tsSrc = (TypeServerSource *)it->second;
>>>    } else {
>>>      // The file failed to load, lookup by name
>>> -    PDBInputFile *pdb = PDBInputFile::findFromRecordPath(tsPath, file);
>>> +    PDBInputFile *pdb = PDBInputFile::findFromRecordPath(ctx, tsPath,
>>> file);
>>>      if (!pdb)
>>>        return createFileError(tsPath, errorCodeToError(std::error_code(
>>>                                           ENOENT,
>>> std::generic_category())));
>>> @@ -471,36 +451,37 @@ static bool equalsPath(StringRef path1, StringRef
>>> path2) {
>>>  }
>>>
>>>  // Find by name an OBJ provided on the command line
>>> -static PrecompSource *findObjByName(StringRef fileNameOnly) {
>>> +PrecompSource *UsePrecompSource::findObjByName(StringRef fileNameOnly) {
>>>    SmallString<128> currentPath;
>>> -  for (auto kv : PrecompSource::mappings) {
>>> +  for (auto kv : ctx.precompSourceMappings) {
>>>      StringRef currentFileName =
>>> sys::path::filename(kv.second->file->getName(),
>>>
>>>  sys::path::Style::windows);
>>>
>>>      // Compare based solely on the file name (link.exe behavior)
>>>      if (equalsPath(currentFileName, fileNameOnly))
>>> -      return kv.second;
>>> +      return (PrecompSource *)kv.second;
>>>    }
>>>    return nullptr;
>>>  }
>>>
>>> -static PrecompSource *findPrecompSource(ObjFile *file, PrecompRecord
>>> &pr) {
>>> +PrecompSource *UsePrecompSource::findPrecompSource(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.
>>>    SmallString<128> prFileName =
>>>        sys::path::filename(pr.getPrecompFilePath(),
>>> sys::path::Style::windows);
>>>
>>> -  auto it = PrecompSource::mappings.find(pr.getSignature());
>>> -  if (it != PrecompSource::mappings.end()) {
>>> -    return it->second;
>>> +  auto it = ctx.precompSourceMappings.find(pr.getSignature());
>>> +  if (it != ctx.precompSourceMappings.end()) {
>>> +    return (PrecompSource *)it->second;
>>>    }
>>>    // Lookup by name
>>>    return findObjByName(prFileName);
>>>  }
>>>
>>> -static Expected<PrecompSource *> findPrecompMap(ObjFile *file,
>>> -                                                PrecompRecord &pr) {
>>> +Expected<PrecompSource *> UsePrecompSource::findPrecompMap(ObjFile
>>> *file,
>>> +
>>>  PrecompRecord &pr) {
>>>    PrecompSource *precomp = findPrecompSource(file, pr);
>>>
>>>    if (!precomp)
>>> @@ -555,22 +536,6 @@ Error UsePrecompSource::mergeDebugT(TypeMerger *m) {
>>>    return TpiSource::mergeDebugT(m);
>>>  }
>>>
>>> -uint32_t TpiSource::countTypeServerPDBs() {
>>> -  return TypeServerSource::mappings.size();
>>> -}
>>> -
>>> -uint32_t TpiSource::countPrecompObjs() {
>>> -  return PrecompSource::mappings.size();
>>> -}
>>> -
>>> -void TpiSource::clear() {
>>> -  // Clean up any owned ghash allocations.
>>> -  clearGHashes();
>>> -  TpiSource::instances.clear();
>>> -  TypeServerSource::mappings.clear();
>>> -  PrecompSource::mappings.clear();
>>> -}
>>> -
>>>
>>>  //===----------------------------------------------------------------------===//
>>>  // Parellel GHash type merging implementation.
>>>
>>>  //===----------------------------------------------------------------------===//
>>> @@ -926,7 +891,8 @@ struct GHashTable {
>>>    /// Insert the cell with the given ghash into the table. Return the
>>> insertion
>>>    /// position in the table. It is safe for the caller to store the
>>> insertion
>>>    /// position because the table cannot be resized.
>>> -  uint32_t insert(GloballyHashedType ghash, GHashCell newCell);
>>> +  uint32_t insert(COFFLinkerContext &ctx, GloballyHashedType ghash,
>>> +                  GHashCell newCell);
>>>  };
>>>
>>>  /// A ghash table cell for deduplicating types from TpiSources.
>>> @@ -965,8 +931,8 @@ class GHashCell {
>>>    bool isItem() const { return data & (1ULL << 63U); }
>>>
>>>    /// Get the ghash key for this cell.
>>> -  GloballyHashedType getGHash() const {
>>> -    return TpiSource::instances[getTpiSrcIdx()]->ghashes[getGHashIdx()];
>>> +  GloballyHashedType getGHash(const COFFLinkerContext &ctx) const {
>>> +    return ctx.tpiSourceList[getTpiSrcIdx()]->ghashes[getGHashIdx()];
>>>    }
>>>
>>>    /// The priority function for the cell. The data is stored such that
>>> lower
>>> @@ -996,7 +962,8 @@ void GHashTable::init(uint32_t newTableSize) {
>>>    tableSize = newTableSize;
>>>  }
>>>
>>> -uint32_t GHashTable::insert(GloballyHashedType ghash, GHashCell
>>> newCell) {
>>> +uint32_t GHashTable::insert(COFFLinkerContext &ctx, GloballyHashedType
>>> ghash,
>>> +                            GHashCell newCell) {
>>>    assert(!newCell.isEmpty() && "cannot insert empty cell value");
>>>
>>>    // FIXME: The low bytes of SHA1 have low entropy for short records,
>>> which
>>> @@ -1015,7 +982,7 @@ uint32_t GHashTable::insert(GloballyHashedType
>>> ghash, GHashCell newCell) {
>>>      // - cell has non-matching key: hash collision, probe next cell
>>>      auto *cellPtr = reinterpret_cast<std::atomic<GHashCell>
>>> *>(&table[idx]);
>>>      GHashCell oldCell(cellPtr->load());
>>> -    while (oldCell.isEmpty() || oldCell.getGHash() == ghash) {
>>> +    while (oldCell.isEmpty() || oldCell.getGHash(ctx) == ghash) {
>>>        // Check if there is an existing ghash entry with a higher
>>> priority
>>>        // (earlier ordering). If so, this is a duplicate, we are done.
>>>        if (!oldCell.isEmpty() && oldCell < newCell)
>>> @@ -1040,22 +1007,22 @@ uint32_t GHashTable::insert(GloballyHashedType
>>> ghash, GHashCell newCell) {
>>>    llvm_unreachable("left infloop");
>>>  }
>>>
>>> -TypeMerger::TypeMerger(llvm::BumpPtrAllocator &alloc)
>>> -    : typeTable(alloc), idTable(alloc) {}
>>> +TypeMerger::TypeMerger(COFFLinkerContext &c, llvm::BumpPtrAllocator
>>> &alloc)
>>> +    : typeTable(alloc), idTable(alloc), ctx(c) {}
>>>
>>>  TypeMerger::~TypeMerger() = default;
>>>
>>>  void TypeMerger::mergeTypesWithGHash() {
>>>    // Load ghashes. Do type servers and PCH objects first.
>>>    {
>>> -    ScopedTimer t1(loadGHashTimer);
>>> -    parallelForEach(TpiSource::dependencySources,
>>> +    ScopedTimer t1(ctx.loadGHashTimer);
>>> +    parallelForEach(dependencySources,
>>>                      [&](TpiSource *source) { source->loadGHashes(); });
>>> -    parallelForEach(TpiSource::objectSources,
>>> +    parallelForEach(objectSources,
>>>                      [&](TpiSource *source) { source->loadGHashes(); });
>>>    }
>>>
>>> -  ScopedTimer t2(mergeGHashTimer);
>>> +  ScopedTimer t2(ctx.mergeGHashTimer);
>>>    GHashState ghashState;
>>>
>>>    // Estimate the size of hash table needed to deduplicate ghashes.
>>> This *must*
>>> @@ -1066,7 +1033,7 @@ void TypeMerger::mergeTypesWithGHash() {
>>>    // small compared to total memory usage, at eight bytes per input
>>> type record,
>>>    // and most input type records are larger than eight bytes.
>>>    size_t tableSize = 0;
>>> -  for (TpiSource *source : TpiSource::instances)
>>> +  for (TpiSource *source : ctx.tpiSourceList)
>>>      tableSize += source->ghashes.size();
>>>
>>>    // Cap the table size so that we can use 32-bit cell indices. Type
>>> indices are
>>> @@ -1080,8 +1047,8 @@ void TypeMerger::mergeTypesWithGHash() {
>>>    // position. Because the table does not rehash, the position will not
>>> change
>>>    // under insertion. After insertion is done, the value of the cell
>>> can be read
>>>    // to retrieve the final PDB type index.
>>> -  parallelForEachN(0, TpiSource::instances.size(), [&](size_t
>>> tpiSrcIdx) {
>>> -    TpiSource *source = TpiSource::instances[tpiSrcIdx];
>>> +  parallelForEachN(0, ctx.tpiSourceList.size(), [&](size_t tpiSrcIdx) {
>>> +    TpiSource *source = ctx.tpiSourceList[tpiSrcIdx];
>>>      source->indexMapStorage.resize(source->ghashes.size());
>>>      for (uint32_t i = 0, e = source->ghashes.size(); i < e; i++) {
>>>        if (source->shouldOmitFromPdb(i)) {
>>> @@ -1091,7 +1058,7 @@ void TypeMerger::mergeTypesWithGHash() {
>>>        GloballyHashedType ghash = source->ghashes[i];
>>>        bool isItem = source->isItemIndex.test(i);
>>>        uint32_t cellIdx =
>>> -          ghashState.table.insert(ghash, GHashCell(isItem, tpiSrcIdx,
>>> i));
>>> +          ghashState.table.insert(ctx, ghash, GHashCell(isItem,
>>> tpiSrcIdx, i));
>>>
>>>        // Store the ghash cell index as a type index in indexMapStorage.
>>> Later
>>>        // we will replace it with the PDB type index.
>>> @@ -1137,7 +1104,7 @@ void TypeMerger::mergeTypesWithGHash() {
>>>    for (uint32_t i = 0, e = entries.size(); i < e; ++i) {
>>>      auto &cell = entries[i];
>>>      uint32_t tpiSrcIdx = cell.getTpiSrcIdx();
>>> -    TpiSource *source = TpiSource::instances[tpiSrcIdx];
>>> +    TpiSource *source = ctx.tpiSourceList[tpiSrcIdx];
>>>      source->uniqueTypes.push_back(cell.getGHashIdx());
>>>
>>>      // Update the ghash table to store the destination PDB type index
>>> in the
>>> @@ -1150,21 +1117,37 @@ void TypeMerger::mergeTypesWithGHash() {
>>>    }
>>>
>>>    // In parallel, remap all types.
>>> -  for_each(TpiSource::dependencySources, [&](TpiSource *source) {
>>> +  for_each(dependencySources, [&](TpiSource *source) {
>>>      source->remapTpiWithGHashes(&ghashState);
>>>    });
>>> -  parallelForEach(TpiSource::objectSources, [&](TpiSource *source) {
>>> +  parallelForEach(objectSources, [&](TpiSource *source) {
>>>      source->remapTpiWithGHashes(&ghashState);
>>>    });
>>>
>>>    // Build a global map of from function ID to function type.
>>> -  for (TpiSource *source : TpiSource::instances) {
>>> +  for (TpiSource *source : ctx.tpiSourceList) {
>>>      for (auto idToType : source->funcIdToType)
>>>        funcIdToType.insert(idToType);
>>>      source->funcIdToType.clear();
>>>    }
>>>
>>> -  TpiSource::clearGHashes();
>>> +  clearGHashes();
>>> +}
>>> +
>>> +void TypeMerger::sortDependencies() {
>>> +  // Order dependencies first, but preserve the existing order.
>>> +  std::vector<TpiSource *> deps;
>>> +  std::vector<TpiSource *> objs;
>>> +  for (TpiSource *s : ctx.tpiSourceList)
>>> +    (s->isDependency() ? deps : objs).push_back(s);
>>> +  uint32_t numDeps = deps.size();
>>> +  uint32_t numObjs = objs.size();
>>> +  ctx.tpiSourceList = std::move(deps);
>>> +  ctx.tpiSourceList.insert(ctx.tpiSourceList.end(), objs.begin(),
>>> objs.end());
>>> +  for (uint32_t i = 0, e = ctx.tpiSourceList.size(); i < e; ++i)
>>> +    ctx.tpiSourceList[i]->tpiSrcIdx = i;
>>> +  dependencySources = makeArrayRef(ctx.tpiSourceList.data(), numDeps);
>>> +  objectSources = makeArrayRef(ctx.tpiSourceList.data() + numDeps,
>>> numObjs);
>>>  }
>>>
>>>  /// Given the index into the ghash table for a particular type, return
>>> the type
>>> @@ -1175,6 +1158,17 @@ static TypeIndex
>>> loadPdbTypeIndexFromCell(GHashState *g,
>>>    return TypeIndex::fromArrayIndex(cell.getGHashIdx());
>>>  }
>>>
>>> +/// Free heap allocated ghashes.
>>> +void TypeMerger::clearGHashes() {
>>> +  for (TpiSource *src : ctx.tpiSourceList) {
>>> +    if (src->ownedGHashes)
>>> +      delete[] src->ghashes.data();
>>> +    src->ghashes = {};
>>> +    src->isItemIndex.clear();
>>> +    src->uniqueTypes.clear();
>>> +  }
>>> +}
>>> +
>>>  // Fill in a TPI or IPI index map using ghashes. For each source type,
>>> use its
>>>  // ghash to lookup its final type index in the PDB, and store that in
>>> the map.
>>>  void TpiSource::fillMapFromGHashes(GHashState *g) {
>>> @@ -1187,13 +1181,3 @@ void TpiSource::fillMapFromGHashes(GHashState *g)
>>> {
>>>            loadPdbTypeIndexFromCell(g, fakeCellIndex.toArrayIndex());
>>>    }
>>>  }
>>> -
>>> -void TpiSource::clearGHashes() {
>>> -  for (TpiSource *src : TpiSource::instances) {
>>> -    if (src->ownedGHashes)
>>> -      delete[] src->ghashes.data();
>>> -    src->ghashes = {};
>>> -    src->isItemIndex.clear();
>>> -    src->uniqueTypes.clear();
>>> -  }
>>> -}
>>>
>>> diff  --git a/lld/COFF/DebugTypes.h b/lld/COFF/DebugTypes.h
>>> index faad30b141e92..b02b5b884cf7e 100644
>>> --- a/lld/COFF/DebugTypes.h
>>> +++ b/lld/COFF/DebugTypes.h
>>> @@ -37,12 +37,13 @@ class ObjFile;
>>>  class PDBInputFile;
>>>  class TypeMerger;
>>>  struct GHashState;
>>> +class COFFLinkerContext;
>>>
>>>  class TpiSource {
>>>  public:
>>>    enum TpiKind : uint8_t { Regular, PCH, UsingPCH, PDB, PDBIpi,
>>> UsingPDB };
>>>
>>> -  TpiSource(TpiKind k, ObjFile *f);
>>> +  TpiSource(COFFLinkerContext &ctx, TpiKind k, ObjFile *f);
>>>    virtual ~TpiSource();
>>>
>>>    /// Produce a mapping from the type and item indices used in the
>>> object
>>> @@ -93,6 +94,8 @@ class TpiSource {
>>>    // Walk over file->debugTypes and fill in the isItemIndex bit vector.
>>>    void fillIsItemIndexFromDebugT();
>>>
>>> +  COFFLinkerContext &ctx;
>>> +
>>>  public:
>>>    bool remapTypesInSymbolRecord(MutableArrayRef<uint8_t> rec);
>>>
>>> @@ -109,29 +112,6 @@ class TpiSource {
>>>      return ghashIdx == endPrecompGHashIdx;
>>>    }
>>>
>>> -  /// All sources of type information in the program.
>>> -  static std::vector<TpiSource *> instances;
>>> -
>>> -  /// Dependency type sources, such as type servers or PCH object
>>> files. These
>>> -  /// must be processed before objects that rely on them. Set by
>>> -  /// TpiSources::sortDependencies.
>>> -  static ArrayRef<TpiSource *> dependencySources;
>>> -
>>> -  /// Object file sources. These must be processed after
>>> dependencySources.
>>> -  static ArrayRef<TpiSource *> objectSources;
>>> -
>>> -  /// Sorts the dependencies and reassigns TpiSource indices.
>>> -  static void sortDependencies();
>>> -
>>> -  static uint32_t countTypeServerPDBs();
>>> -  static uint32_t countPrecompObjs();
>>> -
>>> -  /// Free heap allocated ghashes.
>>> -  static void clearGHashes();
>>> -
>>> -  /// Clear global data structures for TpiSources.
>>> -  static void clear();
>>> -
>>>    const TpiKind kind;
>>>    bool ownedGHashes = true;
>>>    uint32_t tpiSrcIdx = 0;
>>> @@ -186,12 +166,13 @@ class TpiSource {
>>>    uint64_t nbTypeRecordsBytes = 0;
>>>  };
>>>
>>> -TpiSource *makeTpiSource(ObjFile *file);
>>> -TpiSource *makeTypeServerSource(PDBInputFile *pdbInputFile);
>>> -TpiSource *makeUseTypeServerSource(ObjFile *file,
>>> +TpiSource *makeTpiSource(COFFLinkerContext &ctx, ObjFile *f);
>>> +TpiSource *makeTypeServerSource(COFFLinkerContext &ctx,
>>> +                                PDBInputFile *pdbInputFile);
>>> +TpiSource *makeUseTypeServerSource(COFFLinkerContext &ctx, ObjFile
>>> *file,
>>>                                     llvm::codeview::TypeServer2Record
>>> ts);
>>> -TpiSource *makePrecompSource(ObjFile *file);
>>> -TpiSource *makeUsePrecompSource(ObjFile *file,
>>> +TpiSource *makePrecompSource(COFFLinkerContext &ctx, ObjFile *file);
>>> +TpiSource *makeUsePrecompSource(COFFLinkerContext &ctx, ObjFile *file,
>>>                                  llvm::codeview::PrecompRecord ts);
>>>
>>>  } // namespace coff
>>>
>>> diff  --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
>>> index fd9ae7f47bf87..9ebd1c336c594 100644
>>> --- a/lld/COFF/Driver.cpp
>>> +++ b/lld/COFF/Driver.cpp
>>> @@ -7,6 +7,7 @@
>>>
>>>  //===----------------------------------------------------------------------===//
>>>
>>>  #include "Driver.h"
>>> +#include "COFFLinkerContext.h"
>>>  #include "Config.h"
>>>  #include "DebugTypes.h"
>>>  #include "ICF.h"
>>> @@ -59,8 +60,6 @@ using namespace llvm::sys;
>>>  namespace lld {
>>>  namespace coff {
>>>
>>> -static Timer inputFileTimer("Input File Reading", Timer::root());
>>> -
>>>  Configuration *config;
>>>  LinkerDriver *driver;
>>>
>>> @@ -70,14 +69,7 @@ bool link(ArrayRef<const char *> args, bool
>>> canExitEarly, raw_ostream &stdoutOS,
>>>    lld::stderrOS = &stderrOS;
>>>
>>>    errorHandler().cleanupCallback = []() {
>>> -    TpiSource::clear();
>>>      freeArena();
>>> -    ObjFile::instances.clear();
>>> -    PDBInputFile::instances.clear();
>>> -    ImportFile::instances.clear();
>>> -    BitcodeFile::instances.clear();
>>> -    memset(MergeChunk::instances, 0, sizeof(MergeChunk::instances));
>>> -    OutputSection::clear();
>>>    };
>>>
>>>    errorHandler().logName = args::getFilenameWithoutExe(args[0]);
>>> @@ -87,9 +79,9 @@ bool link(ArrayRef<const char *> args, bool
>>> canExitEarly, raw_ostream &stdoutOS,
>>>    errorHandler().exitEarly = canExitEarly;
>>>    stderrOS.enable_colors(stderrOS.has_colors());
>>>
>>> +  COFFLinkerContext ctx;
>>>    config = make<Configuration>();
>>> -  symtab = make<SymbolTable>();
>>> -  driver = make<LinkerDriver>();
>>> +  driver = make<LinkerDriver>(ctx);
>>>
>>>    driver->linkerMain(args);
>>>
>>> @@ -174,8 +166,8 @@ static StringRef mangle(StringRef sym) {
>>>    return sym;
>>>  }
>>>
>>> -static bool findUnderscoreMangle(StringRef sym) {
>>> -  Symbol *s = symtab->findMangle(mangle(sym));
>>> +bool LinkerDriver::findUnderscoreMangle(StringRef sym) {
>>> +  Symbol *s = ctx.symtab.findMangle(mangle(sym));
>>>    return s && !isa<Undefined>(s);
>>>  }
>>>
>>> @@ -213,30 +205,30 @@ void
>>> LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
>>>          addArchiveBuffer(m, "<whole-archive>", filename, memberIndex++);
>>>        return;
>>>      }
>>> -    symtab->addFile(make<ArchiveFile>(mbref));
>>> +    ctx.symtab.addFile(make<ArchiveFile>(ctx, mbref));
>>>      break;
>>>    case file_magic::bitcode:
>>>      if (lazy)
>>> -      symtab->addFile(make<LazyObjFile>(mbref));
>>> +      ctx.symtab.addFile(make<LazyObjFile>(ctx, mbref));
>>>      else
>>> -      symtab->addFile(make<BitcodeFile>(mbref, "", 0));
>>> +      ctx.symtab.addFile(make<BitcodeFile>(ctx, mbref, "", 0));
>>>      break;
>>>    case file_magic::coff_object:
>>>    case file_magic::coff_import_library:
>>>      if (lazy)
>>> -      symtab->addFile(make<LazyObjFile>(mbref));
>>> +      ctx.symtab.addFile(make<LazyObjFile>(ctx, mbref));
>>>      else
>>> -      symtab->addFile(make<ObjFile>(mbref));
>>> +      ctx.symtab.addFile(make<ObjFile>(ctx, mbref));
>>>      break;
>>>    case file_magic::pdb:
>>> -    symtab->addFile(make<PDBInputFile>(mbref));
>>> +    ctx.symtab.addFile(make<PDBInputFile>(ctx, mbref));
>>>      break;
>>>    case file_magic::coff_cl_gl_object:
>>>      error(filename + ": is not a native COFF file. Recompile without
>>> /GL");
>>>      break;
>>>    case file_magic::pecoff_executable:
>>>      if (config->mingw) {
>>> -      symtab->addFile(make<DLLFile>(mbref));
>>> +      ctx.symtab.addFile(make<DLLFile>(ctx, mbref));
>>>        break;
>>>      }
>>>      if (filename.endswith_insensitive(".dll")) {
>>> @@ -280,24 +272,24 @@ void
>>> LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName,
>>>                                      uint64_t offsetInArchive) {
>>>    file_magic magic = identify_magic(mb.getBuffer());
>>>    if (magic == file_magic::coff_import_library) {
>>> -    InputFile *imp = make<ImportFile>(mb);
>>> +    InputFile *imp = make<ImportFile>(ctx, mb);
>>>      imp->parentName = parentName;
>>> -    symtab->addFile(imp);
>>> +    ctx.symtab.addFile(imp);
>>>      return;
>>>    }
>>>
>>>    InputFile *obj;
>>>    if (magic == file_magic::coff_object) {
>>> -    obj = make<ObjFile>(mb);
>>> +    obj = make<ObjFile>(ctx, mb);
>>>    } else if (magic == file_magic::bitcode) {
>>> -    obj = make<BitcodeFile>(mb, parentName, offsetInArchive);
>>> +    obj = make<BitcodeFile>(ctx, mb, parentName, offsetInArchive);
>>>    } else {
>>>      error("unknown file type: " + mb.getBufferIdentifier());
>>>      return;
>>>    }
>>>
>>>    obj->parentName = parentName;
>>> -  symtab->addFile(obj);
>>> +  ctx.symtab.addFile(obj);
>>>    log("Loaded " + toString(obj) + " for " + symName);
>>>  }
>>>
>>> @@ -547,7 +539,7 @@ void LinkerDriver::addLibSearchPaths() {
>>>  }
>>>
>>>  Symbol *LinkerDriver::addUndefined(StringRef name) {
>>> -  Symbol *b = symtab->addUndefined(name);
>>> +  Symbol *b = ctx.symtab.addUndefined(name);
>>>    if (!b->isGCRoot) {
>>>      b->isGCRoot = true;
>>>      config->gcroot.push_back(b);
>>> @@ -562,14 +554,14 @@ StringRef LinkerDriver::mangleMaybe(Symbol *s) {
>>>      return "";
>>>
>>>    // Otherwise, see if a similar, mangled symbol exists in the symbol
>>> table.
>>> -  Symbol *mangled = symtab->findMangle(unmangled->getName());
>>> +  Symbol *mangled = ctx.symtab.findMangle(unmangled->getName());
>>>    if (!mangled)
>>>      return "";
>>>
>>>    // If we find a similar mangled symbol, make this an alias to it and
>>> return
>>>    // its name.
>>>    log(unmangled->getName() + " aliased to " + mangled->getName());
>>> -  unmangled->weakAlias = symtab->addUndefined(mangled->getName());
>>> +  unmangled->weakAlias = ctx.symtab.addUndefined(mangled->getName());
>>>    return mangled->getName();
>>>  }
>>>
>>> @@ -939,7 +931,7 @@ void LinkerDriver::enqueueTask(std::function<void()>
>>> task) {
>>>  }
>>>
>>>  bool LinkerDriver::run() {
>>> -  ScopedTimer t(inputFileTimer);
>>> +  ScopedTimer t(ctx.inputFileTimer);
>>>
>>>    bool didWork = !taskQueue.empty();
>>>    while (!taskQueue.empty()) {
>>> @@ -952,7 +944,7 @@ bool LinkerDriver::run() {
>>>  // Parse an /order file. If an option is given, the linker places
>>>  // COMDAT sections in the same order as their names appear in the
>>>  // given file.
>>> -static void parseOrderFile(StringRef arg) {
>>> +static void parseOrderFile(COFFLinkerContext &ctx, StringRef arg) {
>>>    // For some reason, the MSVC linker requires a filename to be
>>>    // preceded by "@".
>>>    if (!arg.startswith("@")) {
>>> @@ -962,7 +954,7 @@ static void parseOrderFile(StringRef arg) {
>>>
>>>    // Get a list of all comdat sections for error checking.
>>>    DenseSet<StringRef> set;
>>> -  for (Chunk *c : symtab->getChunks())
>>> +  for (Chunk *c : ctx.symtab.getChunks())
>>>      if (auto *sec = dyn_cast<SectionChunk>(c))
>>>        if (sec->sym)
>>>          set.insert(sec->sym->getName());
>>> @@ -996,7 +988,7 @@ static void parseOrderFile(StringRef arg) {
>>>    driver->takeBuffer(std::move(mb));
>>>  }
>>>
>>> -static void parseCallGraphFile(StringRef path) {
>>> +static void parseCallGraphFile(COFFLinkerContext &ctx, StringRef path) {
>>>    std::unique_ptr<MemoryBuffer> mb =
>>>        CHECK(MemoryBuffer::getFile(path, /*IsText=*/false,
>>>                                    /*RequiresNullTerminator=*/false,
>>> @@ -1005,7 +997,7 @@ static void parseCallGraphFile(StringRef path) {
>>>
>>>    // Build a map from symbol name to section.
>>>    DenseMap<StringRef, Symbol *> map;
>>> -  for (ObjFile *file : ObjFile::instances)
>>> +  for (ObjFile *file : ctx.objFileInstances)
>>>      for (Symbol *sym : file->getSymbols())
>>>        if (sym)
>>>          map[sym->getName()] = sym;
>>> @@ -1042,8 +1034,8 @@ static void parseCallGraphFile(StringRef path) {
>>>    driver->takeBuffer(std::move(mb));
>>>  }
>>>
>>> -static void readCallGraphsFromObjectFiles() {
>>> -  for (ObjFile *obj : ObjFile::instances) {
>>> +static void readCallGraphsFromObjectFiles(COFFLinkerContext &ctx) {
>>> +  for (ObjFile *obj : ctx.objFileInstances) {
>>>      if (obj->callgraphSec) {
>>>        ArrayRef<uint8_t> contents;
>>>        cantFail(
>>> @@ -1077,7 +1069,7 @@ static void markAddrsig(Symbol *s) {
>>>        c->keepUnique = true;
>>>  }
>>>
>>> -static void findKeepUniqueSections() {
>>> +static void findKeepUniqueSections(COFFLinkerContext &ctx) {
>>>    // Exported symbols could be address-significant in other executables
>>> or DSOs,
>>>    // so we conservatively mark them as address-significant.
>>>    for (Export &r : config->exports)
>>> @@ -1085,7 +1077,7 @@ static void findKeepUniqueSections() {
>>>
>>>    // Visit the address-significance table in each object file and mark
>>> each
>>>    // referenced symbol as address-significant.
>>> -  for (ObjFile *obj : ObjFile::instances) {
>>> +  for (ObjFile *obj : ctx.objFileInstances) {
>>>      ArrayRef<Symbol *> syms = obj->getSymbols();
>>>      if (obj->addrsigSec) {
>>>        ArrayRef<uint8_t> contents;
>>> @@ -1169,7 +1161,7 @@ static void parsePDBAltPath(StringRef altPath) {
>>>  void LinkerDriver::convertResources() {
>>>    std::vector<ObjFile *> resourceObjFiles;
>>>
>>> -  for (ObjFile *f : ObjFile::instances) {
>>> +  for (ObjFile *f : ctx.objFileInstances) {
>>>      if (f->isResourceObjFile())
>>>        resourceObjFiles.push_back(f);
>>>    }
>>> @@ -1191,8 +1183,9 @@ void LinkerDriver::convertResources() {
>>>        f->includeResourceChunks();
>>>      return;
>>>    }
>>> -  ObjFile *f = make<ObjFile>(convertResToCOFF(resources,
>>> resourceObjFiles));
>>> -  symtab->addFile(f);
>>> +  ObjFile *f =
>>> +      make<ObjFile>(ctx, convertResToCOFF(resources, resourceObjFiles));
>>> +  ctx.symtab.addFile(f);
>>>    f->includeResourceChunks();
>>>  }
>>>
>>> @@ -1219,9 +1212,9 @@ void LinkerDriver::maybeExportMinGWSymbols(const
>>> opt::InputArgList &args) {
>>>      if (Optional<StringRef> path = doFindFile(arg->getValue()))
>>>        exporter.addWholeArchive(*path);
>>>
>>> -  symtab->forEachSymbol([&](Symbol *s) {
>>> +  ctx.symtab.forEachSymbol([&](Symbol *s) {
>>>      auto *def = dyn_cast<Defined>(s);
>>> -    if (!exporter.shouldExport(def))
>>> +    if (!exporter.shouldExport(ctx, def))
>>>        return;
>>>
>>>      if (!def->isGCRoot) {
>>> @@ -1266,7 +1259,7 @@ Optional<std::string> getReproduceFile(const
>>> opt::InputArgList &args) {
>>>  }
>>>
>>>  void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
>>> -  ScopedTimer rootTimer(Timer::root());
>>> +  ScopedTimer rootTimer(ctx.rootTimer);
>>>
>>>    // Needed for LTO.
>>>    InitializeAllTargetInfos();
>>> @@ -2018,32 +2011,32 @@ void LinkerDriver::linkerMain(ArrayRef<const
>>> char *> argsArr) {
>>>    if (config->imageBase == uint64_t(-1))
>>>      config->imageBase = getDefaultImageBase();
>>>
>>> -  symtab->addSynthetic(mangle("__ImageBase"), nullptr);
>>> +  ctx.symtab.addSynthetic(mangle("__ImageBase"), nullptr);
>>>    if (config->machine == I386) {
>>> -    symtab->addAbsolute("___safe_se_handler_table", 0);
>>> -    symtab->addAbsolute("___safe_se_handler_count", 0);
>>> +    ctx.symtab.addAbsolute("___safe_se_handler_table", 0);
>>> +    ctx.symtab.addAbsolute("___safe_se_handler_count", 0);
>>>    }
>>>
>>> -  symtab->addAbsolute(mangle("__guard_fids_count"), 0);
>>> -  symtab->addAbsolute(mangle("__guard_fids_table"), 0);
>>> -  symtab->addAbsolute(mangle("__guard_flags"), 0);
>>> -  symtab->addAbsolute(mangle("__guard_iat_count"), 0);
>>> -  symtab->addAbsolute(mangle("__guard_iat_table"), 0);
>>> -  symtab->addAbsolute(mangle("__guard_longjmp_count"), 0);
>>> -  symtab->addAbsolute(mangle("__guard_longjmp_table"), 0);
>>> +  ctx.symtab.addAbsolute(mangle("__guard_fids_count"), 0);
>>> +  ctx.symtab.addAbsolute(mangle("__guard_fids_table"), 0);
>>> +  ctx.symtab.addAbsolute(mangle("__guard_flags"), 0);
>>> +  ctx.symtab.addAbsolute(mangle("__guard_iat_count"), 0);
>>> +  ctx.symtab.addAbsolute(mangle("__guard_iat_table"), 0);
>>> +  ctx.symtab.addAbsolute(mangle("__guard_longjmp_count"), 0);
>>> +  ctx.symtab.addAbsolute(mangle("__guard_longjmp_table"), 0);
>>>    // Needed for MSVC 2017 15.5 CRT.
>>> -  symtab->addAbsolute(mangle("__enclave_config"), 0);
>>> +  ctx.symtab.addAbsolute(mangle("__enclave_config"), 0);
>>>    // Needed for MSVC 2019 16.8 CRT.
>>> -  symtab->addAbsolute(mangle("__guard_eh_cont_count"), 0);
>>> -  symtab->addAbsolute(mangle("__guard_eh_cont_table"), 0);
>>> +  ctx.symtab.addAbsolute(mangle("__guard_eh_cont_count"), 0);
>>> +  ctx.symtab.addAbsolute(mangle("__guard_eh_cont_table"), 0);
>>>
>>>    if (config->pseudoRelocs) {
>>> -    symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST__"), 0);
>>> -    symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST_END__"), 0);
>>> +    ctx.symtab.addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST__"), 0);
>>> +    ctx.symtab.addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST_END__"),
>>> 0);
>>>    }
>>>    if (config->mingw) {
>>> -    symtab->addAbsolute(mangle("__CTOR_LIST__"), 0);
>>> -    symtab->addAbsolute(mangle("__DTOR_LIST__"), 0);
>>> +    ctx.symtab.addAbsolute(mangle("__CTOR_LIST__"), 0);
>>> +    ctx.symtab.addAbsolute(mangle("__DTOR_LIST__"), 0);
>>>    }
>>>
>>>    // This code may add new undefined symbols to the link, which may
>>> enqueue more
>>> @@ -2069,12 +2062,12 @@ void LinkerDriver::linkerMain(ArrayRef<const
>>> char *> argsArr) {
>>>      for (auto pair : config->alternateNames) {
>>>        StringRef from = pair.first;
>>>        StringRef to = pair.second;
>>> -      Symbol *sym = symtab->find(from);
>>> +      Symbol *sym = ctx.symtab.find(from);
>>>        if (!sym)
>>>          continue;
>>>        if (auto *u = dyn_cast<Undefined>(sym))
>>>          if (!u->weakAlias)
>>> -          u->weakAlias = symtab->addUndefined(to);
>>> +          u->weakAlias = ctx.symtab.addUndefined(to);
>>>      }
>>>
>>>      // If any inputs are bitcode files, the LTO code generator may
>>> create
>>> @@ -2082,25 +2075,25 @@ void LinkerDriver::linkerMain(ArrayRef<const
>>> char *> argsArr) {
>>>      // file's symbol table. If any of those library functions are
>>> defined in a
>>>      // bitcode file in an archive member, we need to arrange to use LTO
>>> to
>>>      // compile those archive members by adding them to the link
>>> beforehand.
>>> -    if (!BitcodeFile::instances.empty())
>>> +    if (!ctx.bitcodeFileInstances.empty())
>>>        for (auto *s : lto::LTO::getRuntimeLibcallSymbols())
>>> -        symtab->addLibcall(s);
>>> +        ctx.symtab.addLibcall(s);
>>>
>>>      // Windows specific -- if __load_config_used can be resolved,
>>> resolve it.
>>> -    if (symtab->findUnderscore("_load_config_used"))
>>> +    if (ctx.symtab.findUnderscore("_load_config_used"))
>>>        addUndefined(mangle("_load_config_used"));
>>>    } while (run());
>>>
>>>    if (args.hasArg(OPT_include_optional)) {
>>>      // Handle /includeoptional
>>>      for (auto *arg : args.filtered(OPT_include_optional))
>>> -      if (dyn_cast_or_null<LazyArchive>(symtab->find(arg->getValue())))
>>> +      if
>>> (dyn_cast_or_null<LazyArchive>(ctx.symtab.find(arg->getValue())))
>>>          addUndefined(arg->getValue());
>>>      while (run());
>>>    }
>>>
>>>    // Create wrapped symbols for -wrap option.
>>> -  std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args);
>>> +  std::vector<WrappedSymbol> wrapped = addWrappedSymbols(ctx, args);
>>>    // Load more object files that might be needed for wrapped symbols.
>>>    if (!wrapped.empty())
>>>      while (run());
>>> @@ -2126,7 +2119,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char
>>> *> argsArr) {
>>>      // If it ends up pulling in more object files from static libraries,
>>>      // (and maybe doing more stdcall fixups along the way), this would
>>> need
>>>      // to loop these two calls.
>>> -    symtab->loadMinGWSymbols();
>>> +    ctx.symtab.loadMinGWSymbols();
>>>      run();
>>>    }
>>>
>>> @@ -2134,8 +2127,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char
>>> *> argsArr) {
>>>    // If we are going to do codegen for link-time optimization, check for
>>>    // unresolvable symbols first, so we don't spend time generating code
>>> that
>>>    // will fail to link anyway.
>>> -  if (!BitcodeFile::instances.empty() && !config->forceUnresolved)
>>> -    symtab->reportUnresolvable();
>>> +  if (!ctx.bitcodeFileInstances.empty() && !config->forceUnresolved)
>>> +    ctx.symtab.reportUnresolvable();
>>>    if (errorCount())
>>>      return;
>>>
>>> @@ -2149,7 +2142,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char
>>> *> argsArr) {
>>>    // Do LTO by compiling bitcode input files to a set of native COFF
>>> files then
>>>    // link those files (unless -thinlto-index-only was given, in which
>>> case we
>>>    // resolve symbols and write indices, but don't generate native code
>>> or link).
>>> -  symtab->addCombinedLTOObjects();
>>> +  ctx.symtab.addCombinedLTOObjects();
>>>
>>>    // If -thinlto-index-only is given, we should create only "index
>>>    // files" and not object files. Index file creation is already done
>>> @@ -2163,10 +2156,10 @@ void LinkerDriver::linkerMain(ArrayRef<const
>>> char *> argsArr) {
>>>
>>>    // Apply symbol renames for -wrap.
>>>    if (!wrapped.empty())
>>> -    wrapSymbols(wrapped);
>>> +    wrapSymbols(ctx, wrapped);
>>>
>>>    // Resolve remaining undefined symbols and warn about imported locals.
>>> -  symtab->resolveRemainingUndefines();
>>> +  ctx.symtab.resolveRemainingUndefines();
>>>    if (errorCount())
>>>      return;
>>>
>>> @@ -2177,12 +2170,12 @@ void LinkerDriver::linkerMain(ArrayRef<const
>>> char *> argsArr) {
>>>      // order provided on the command line, while lld will pull in needed
>>>      // files from static libraries only after the last object file on
>>> the
>>>      // command line.
>>> -    for (auto i = ObjFile::instances.begin(), e =
>>> ObjFile::instances.end();
>>> +    for (auto i = ctx.objFileInstances.begin(), e =
>>> ctx.objFileInstances.end();
>>>           i != e; i++) {
>>>        ObjFile *file = *i;
>>>        if (isCrtend(file->getName())) {
>>> -        ObjFile::instances.erase(i);
>>> -        ObjFile::instances.push_back(file);
>>> +        ctx.objFileInstances.erase(i);
>>> +        ctx.objFileInstances.push_back(file);
>>>          break;
>>>        }
>>>      }
>>> @@ -2207,7 +2200,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char
>>> *> argsArr) {
>>>      StringRef name = pair.first;
>>>      uint32_t alignment = pair.second;
>>>
>>> -    Symbol *sym = symtab->find(name);
>>> +    Symbol *sym = ctx.symtab.find(name);
>>>      if (!sym) {
>>>        warn("/aligncomm symbol " + name + " not found");
>>>        continue;
>>> @@ -2239,16 +2232,16 @@ void LinkerDriver::linkerMain(ArrayRef<const
>>> char *> argsArr) {
>>>    if (auto *arg = args.getLastArg(OPT_order)) {
>>>      if (args.hasArg(OPT_call_graph_ordering_file))
>>>        error("/order and /call-graph-order-file may not be used
>>> together");
>>> -    parseOrderFile(arg->getValue());
>>> +    parseOrderFile(ctx, arg->getValue());
>>>      config->callGraphProfileSort = false;
>>>    }
>>>
>>>    // Handle /call-graph-ordering-file and /call-graph-profile-sort
>>> (default on).
>>>    if (config->callGraphProfileSort) {
>>>      if (auto *arg = args.getLastArg(OPT_call_graph_ordering_file)) {
>>> -      parseCallGraphFile(arg->getValue());
>>> +      parseCallGraphFile(ctx, arg->getValue());
>>>      }
>>> -    readCallGraphsFromObjectFiles();
>>> +    readCallGraphsFromObjectFiles(ctx);
>>>    }
>>>
>>>    // Handle /print-symbol-order.
>>> @@ -2265,7 +2258,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char
>>> *> argsArr) {
>>>        // functions. This doesn't bring in more object files, but only
>>> marks
>>>        // functions that already have been included to be retained.
>>>        for (const char *n : {"__gxx_personality_v0",
>>> "__gcc_personality_v0"}) {
>>> -        Defined *d =
>>> dyn_cast_or_null<Defined>(symtab->findUnderscore(n));
>>> +        Defined *d =
>>> dyn_cast_or_null<Defined>(ctx.symtab.findUnderscore(n));
>>>          if (d && !d->isGCRoot) {
>>>            d->isGCRoot = true;
>>>            config->gcroot.push_back(d);
>>> @@ -2273,7 +2266,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char
>>> *> argsArr) {
>>>        }
>>>      }
>>>
>>> -    markLive(symtab->getChunks());
>>> +    markLive(ctx);
>>>    }
>>>
>>>    // Needs to happen after the last call to addFile().
>>> @@ -2281,17 +2274,17 @@ void LinkerDriver::linkerMain(ArrayRef<const
>>> char *> argsArr) {
>>>
>>>    // Identify identical COMDAT sections to merge them.
>>>    if (config->doICF != ICFLevel::None) {
>>> -    findKeepUniqueSections();
>>> -    doICF(symtab->getChunks(), config->doICF);
>>> +    findKeepUniqueSections(ctx);
>>> +    doICF(ctx, config->doICF);
>>>    }
>>>
>>>    // Write the result.
>>> -  writeResult();
>>> +  writeResult(ctx);
>>>
>>>    // Stop early so we can print the results.
>>>    rootTimer.stop();
>>>    if (config->showTiming)
>>> -    Timer::root().print();
>>> +    ctx.rootTimer.print();
>>>  }
>>>
>>>  } // namespace coff
>>>
>>> diff  --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h
>>> index 5729bed69528b..7c2fbe3c7d64c 100644
>>> --- a/lld/COFF/Driver.h
>>> +++ b/lld/COFF/Driver.h
>>> @@ -9,6 +9,7 @@
>>>  #ifndef LLD_COFF_DRIVER_H
>>>  #define LLD_COFF_DRIVER_H
>>>
>>> +#include "COFFLinkerContext.h"
>>>  #include "Config.h"
>>>  #include "SymbolTable.h"
>>>  #include "lld/Common/LLVM.h"
>>> @@ -78,6 +79,8 @@ class ArgParser {
>>>
>>>  class LinkerDriver {
>>>  public:
>>> +  LinkerDriver(COFFLinkerContext &c) : ctx(c) {}
>>> +
>>>    void linkerMain(llvm::ArrayRef<const char *> args);
>>>
>>>    // Used by the resolver to parse .drectve section contents.
>>> @@ -103,6 +106,8 @@ class LinkerDriver {
>>>    StringRef doFindLib(StringRef filename);
>>>    StringRef doFindLibMinGW(StringRef filename);
>>>
>>> +  bool findUnderscoreMangle(StringRef sym);
>>> +
>>>    // Parses LIB environment which contains a list of search paths.
>>>    void addLibSearchPaths();
>>>
>>> @@ -148,6 +153,8 @@ class LinkerDriver {
>>>    std::vector<MemoryBufferRef> resources;
>>>
>>>    llvm::StringSet<> directivesExports;
>>> +
>>> +  COFFLinkerContext &ctx;
>>>  };
>>>
>>>  // Functions below this line are defined in DriverUtils.cpp.
>>>
>>> diff  --git a/lld/COFF/ICF.cpp b/lld/COFF/ICF.cpp
>>> index 7326469672968..8323626623948 100644
>>> --- a/lld/COFF/ICF.cpp
>>> +++ b/lld/COFF/ICF.cpp
>>> @@ -18,6 +18,7 @@
>>>
>>>  //===----------------------------------------------------------------------===//
>>>
>>>  #include "ICF.h"
>>> +#include "COFFLinkerContext.h"
>>>  #include "Chunks.h"
>>>  #include "Symbols.h"
>>>  #include "lld/Common/ErrorHandler.h"
>>> @@ -36,12 +37,10 @@ using namespace llvm;
>>>  namespace lld {
>>>  namespace coff {
>>>
>>> -static Timer icfTimer("ICF", Timer::root());
>>> -
>>>  class ICF {
>>>  public:
>>> -  ICF(ICFLevel icfLevel) : icfLevel(icfLevel){};
>>> -  void run(ArrayRef<Chunk *> v);
>>> +  ICF(COFFLinkerContext &c, ICFLevel icfLevel) : icfLevel(icfLevel),
>>> ctx(c){};
>>> +  void run();
>>>
>>>  private:
>>>    void segregate(size_t begin, size_t end, bool constant);
>>> @@ -64,6 +63,8 @@ class ICF {
>>>    int cnt = 0;
>>>    std::atomic<bool> repeat = {false};
>>>    ICFLevel icfLevel = ICFLevel::All;
>>> +
>>> +  COFFLinkerContext &ctx;
>>>  };
>>>
>>>  // Returns true if section S is subject of ICF.
>>> @@ -246,12 +247,12 @@ void ICF::forEachClass(std::function<void(size_t,
>>> size_t)> fn) {
>>>  // Merge identical COMDAT sections.
>>>  // Two sections are considered the same if their section headers,
>>>  // contents and relocations are all the same.
>>> -void ICF::run(ArrayRef<Chunk *> vec) {
>>> -  ScopedTimer t(icfTimer);
>>> +void ICF::run() {
>>> +  ScopedTimer t(ctx.icfTimer);
>>>
>>>    // Collect only mergeable sections and group by hash value.
>>>    uint32_t nextId = 1;
>>> -  for (Chunk *c : vec) {
>>> +  for (Chunk *c : ctx.symtab.getChunks()) {
>>>      if (auto *sc = dyn_cast<SectionChunk>(c)) {
>>>        if (isEligible(sc))
>>>          chunks.push_back(sc);
>>> @@ -262,7 +263,7 @@ void ICF::run(ArrayRef<Chunk *> vec) {
>>>
>>>    // Make sure that ICF doesn't merge sections that are being handled
>>> by string
>>>    // tail merging.
>>> -  for (MergeChunk *mc : MergeChunk::instances)
>>> +  for (MergeChunk *mc : ctx.mergeChunkInstances)
>>>      if (mc)
>>>        for (SectionChunk *sc : mc->sections)
>>>          sc->eqClass[0] = nextId++;
>>> @@ -317,8 +318,8 @@ void ICF::run(ArrayRef<Chunk *> vec) {
>>>  }
>>>
>>>  // Entry point to ICF.
>>> -void doICF(ArrayRef<Chunk *> chunks, ICFLevel icfLevel) {
>>> -  ICF(icfLevel).run(chunks);
>>> +void doICF(COFFLinkerContext &ctx, ICFLevel icfLevel) {
>>> +  ICF(ctx, icfLevel).run();
>>>  }
>>>
>>>  } // namespace coff
>>>
>>> diff  --git a/lld/COFF/ICF.h b/lld/COFF/ICF.h
>>> index f8cc8071f9eb7..10e6792a5418f 100644
>>> --- a/lld/COFF/ICF.h
>>> +++ b/lld/COFF/ICF.h
>>> @@ -17,8 +17,9 @@ namespace lld {
>>>  namespace coff {
>>>
>>>  class Chunk;
>>> +class COFFLinkerContext;
>>>
>>> -void doICF(ArrayRef<Chunk *> chunks, ICFLevel);
>>> +void doICF(COFFLinkerContext &ctx, ICFLevel);
>>>
>>>  } // namespace coff
>>>  } // namespace lld
>>>
>>> diff  --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
>>> index f32353ca4f94a..4b38e3d1a99bc 100644
>>> --- a/lld/COFF/InputFiles.cpp
>>> +++ b/lld/COFF/InputFiles.cpp
>>> @@ -7,6 +7,7 @@
>>>
>>>  //===----------------------------------------------------------------------===//
>>>
>>>  #include "InputFiles.h"
>>> +#include "COFFLinkerContext.h"
>>>  #include "Chunks.h"
>>>  #include "Config.h"
>>>  #include "DebugTypes.h"
>>> @@ -69,11 +70,6 @@ std::string lld::toString(const coff::InputFile
>>> *file) {
>>>        .str();
>>>  }
>>>
>>> -std::vector<ObjFile *> ObjFile::instances;
>>> -std::map<std::string, PDBInputFile *> PDBInputFile::instances;
>>> -std::vector<ImportFile *> ImportFile::instances;
>>> -std::vector<BitcodeFile *> BitcodeFile::instances;
>>> -
>>>  /// Checks that Source is compatible with being a weak alias to Target.
>>>  /// If Source is Undefined and has no weak alias set, makes it a weak
>>>  /// alias to Target.
>>> @@ -98,7 +94,8 @@ static bool ignoredSymbolName(StringRef name) {
>>>    return name == "@feat.00" || name == "@comp.id";
>>>  }
>>>
>>> -ArchiveFile::ArchiveFile(MemoryBufferRef m) : InputFile(ArchiveKind, m)
>>> {}
>>> +ArchiveFile::ArchiveFile(COFFLinkerContext &ctx, MemoryBufferRef m)
>>> +    : InputFile(ctx, ArchiveKind, m) {}
>>>
>>>  void ArchiveFile::parse() {
>>>    // Parse a MemoryBufferRef as an archive file.
>>> @@ -106,7 +103,7 @@ void ArchiveFile::parse() {
>>>
>>>    // Read the symbol table to construct Lazy objects.
>>>    for (const Archive::Symbol &sym : file->symbols())
>>> -    symtab->addLazyArchive(this, sym);
>>> +    ctx.symtab.addLazyArchive(this, sym);
>>>  }
>>>
>>>  // Returns a buffer pointing to a member file containing a given symbol.
>>> @@ -144,11 +141,11 @@ void LazyObjFile::fetch() {
>>>
>>>    InputFile *file;
>>>    if (isBitcode(mb))
>>> -    file = make<BitcodeFile>(mb, "", 0, std::move(symbols));
>>> +    file = make<BitcodeFile>(ctx, mb, "", 0, std::move(symbols));
>>>    else
>>> -    file = make<ObjFile>(mb, std::move(symbols));
>>> +    file = make<ObjFile>(ctx, mb, std::move(symbols));
>>>    mb = {};
>>> -  symtab->addFile(file);
>>> +  ctx.symtab.addFile(file);
>>>  }
>>>
>>>  void LazyObjFile::parse() {
>>> @@ -158,7 +155,7 @@ void LazyObjFile::parse() {
>>>          CHECK(lto::InputFile::create(this->mb), this);
>>>      for (const lto::InputFile::Symbol &sym : obj->symbols()) {
>>>        if (!sym.isUndefined())
>>> -        symtab->addLazyObject(this, sym.getName());
>>> +        ctx.symtab.addLazyObject(this, sym.getName());
>>>      }
>>>      return;
>>>    }
>>> @@ -175,7 +172,7 @@ void LazyObjFile::parse() {
>>>      StringRef name = check(coffObj->getSymbolName(coffSym));
>>>      if (coffSym.isAbsolute() && ignoredSymbolName(name))
>>>        continue;
>>> -    symtab->addLazyObject(this, name);
>>> +    ctx.symtab.addLazyObject(this, name);
>>>      i += coffSym.getNumberOfAuxSymbols();
>>>    }
>>>  }
>>> @@ -293,7 +290,7 @@ SectionChunk *ObjFile::readSection(uint32_t
>>> sectionNumber,
>>>      // COFF sections that look like string literal sections (i.e. no
>>>      // relocations, in .rdata, leader symbol name matches the MSVC name
>>> mangling
>>>      // for string literals) are subject to string tail merging.
>>> -    MergeChunk::addSection(c);
>>> +    MergeChunk::addSection(ctx, c);
>>>    else if (name == ".rsrc" || name.startswith(".rsrc$"))
>>>      resourceChunks.push_back(c);
>>>    else
>>> @@ -387,8 +384,8 @@ Symbol *ObjFile::createRegular(COFFSymbolRef sym) {
>>>    if (sym.isExternal()) {
>>>      StringRef name = check(coffObj->getSymbolName(sym));
>>>      if (sc)
>>> -      return symtab->addRegular(this, name, sym.getGeneric(), sc,
>>> -                                sym.getValue());
>>> +      return ctx.symtab.addRegular(this, name, sym.getGeneric(), sc,
>>> +                                   sym.getValue());
>>>      // For MinGW symbols named .weak.* that point to a discarded
>>> section,
>>>      // don't create an Undefined symbol. If nothing ever refers to the
>>> symbol,
>>>      // everything should be fine. If something actually refers to the
>>> symbol
>>> @@ -396,7 +393,7 @@ Symbol *ObjFile::createRegular(COFFSymbolRef sym) {
>>>      // references at the end.
>>>      if (config->mingw && name.startswith(".weak."))
>>>        return nullptr;
>>> -    return symtab->addUndefined(name, this, false);
>>> +    return ctx.symtab.addUndefined(name, this, false);
>>>    }
>>>    if (sc)
>>>      return make<DefinedRegular>(this, /*Name*/ "", /*IsCOMDAT*/ false,
>>> @@ -464,7 +461,7 @@ void ObjFile::initializeSymbols() {
>>>    for (auto &kv : weakAliases) {
>>>      Symbol *sym = kv.first;
>>>      uint32_t idx = kv.second;
>>> -    checkAndSetWeakAlias(symtab, this, sym, symbols[idx]);
>>> +    checkAndSetWeakAlias(&ctx.symtab, this, sym, symbols[idx]);
>>>    }
>>>
>>>    // Free the memory used by sparseChunks now that symbol loading is
>>> finished.
>>> @@ -473,7 +470,7 @@ void ObjFile::initializeSymbols() {
>>>
>>>  Symbol *ObjFile::createUndefined(COFFSymbolRef sym) {
>>>    StringRef name = check(coffObj->getSymbolName(sym));
>>> -  return symtab->addUndefined(name, this, sym.isWeakExternal());
>>> +  return ctx.symtab.addUndefined(name, this, sym.isWeakExternal());
>>>  }
>>>
>>>  static const coff_aux_section_definition *findSectionDef(COFFObjectFile
>>> *obj,
>>> @@ -543,13 +540,13 @@ void ObjFile::handleComdatSelection(
>>>           Twine((int)leaderSelection) + " in " +
>>> toString(leader->getFile()) +
>>>           " and " + Twine((int)selection) + " in " + toString(this))
>>>              .str());
>>> -    symtab->reportDuplicate(leader, this);
>>> +    ctx.symtab.reportDuplicate(leader, this);
>>>      return;
>>>    }
>>>
>>>    switch (selection) {
>>>    case IMAGE_COMDAT_SELECT_NODUPLICATES:
>>> -    symtab->reportDuplicate(leader, this);
>>> +    ctx.symtab.reportDuplicate(leader, this);
>>>      break;
>>>
>>>    case IMAGE_COMDAT_SELECT_ANY:
>>> @@ -559,14 +556,14 @@ void ObjFile::handleComdatSelection(
>>>    case IMAGE_COMDAT_SELECT_SAME_SIZE:
>>>      if (leaderChunk->getSize() != getSection(sym)->SizeOfRawData) {
>>>        if (!config->mingw) {
>>> -        symtab->reportDuplicate(leader, this);
>>> +        ctx.symtab.reportDuplicate(leader, this);
>>>        } else {
>>>          const coff_aux_section_definition *leaderDef = nullptr;
>>>          if (leaderChunk->file)
>>>            leaderDef = findSectionDef(leaderChunk->file->getCOFFObj(),
>>>                                       leaderChunk->getSectionNumber());
>>>          if (!leaderDef || leaderDef->Length != def->Length)
>>> -          symtab->reportDuplicate(leader, this);
>>> +          ctx.symtab.reportDuplicate(leader, this);
>>>        }
>>>      }
>>>      break;
>>> @@ -577,7 +574,7 @@ void ObjFile::handleComdatSelection(
>>>      // if the two comdat sections have e.g.
>>> diff erent alignment.
>>>      // Match that.
>>>      if (leaderChunk->getContents() != newChunk.getContents())
>>> -      symtab->reportDuplicate(leader, this, &newChunk, sym.getValue());
>>> +      ctx.symtab.reportDuplicate(leader, this, &newChunk,
>>> sym.getValue());
>>>      break;
>>>    }
>>>
>>> @@ -620,8 +617,8 @@ Optional<Symbol *> ObjFile::createDefined(
>>>    if (sym.isCommon()) {
>>>      auto *c = make<CommonChunk>(sym);
>>>      chunks.push_back(c);
>>> -    return symtab->addCommon(this, getName(), sym.getValue(),
>>> sym.getGeneric(),
>>> -                             c);
>>> +    return ctx.symtab.addCommon(this, getName(), sym.getValue(),
>>> +                                sym.getGeneric(), c);
>>>    }
>>>
>>>    if (sym.isAbsolute()) {
>>> @@ -634,7 +631,7 @@ Optional<Symbol *> ObjFile::createDefined(
>>>        return nullptr;
>>>
>>>      if (sym.isExternal())
>>> -      return symtab->addAbsolute(name, sym);
>>> +      return ctx.symtab.addAbsolute(name, sym);
>>>      return make<DefinedAbsolute>(name, sym);
>>>    }
>>>
>>> @@ -667,7 +664,7 @@ Optional<Symbol *> ObjFile::createDefined(
>>>
>>>      if (sym.isExternal()) {
>>>        std::tie(leader, prevailing) =
>>> -          symtab->addComdat(this, getName(), sym.getGeneric());
>>> +          ctx.symtab.addComdat(this, getName(), sym.getGeneric());
>>>      } else {
>>>        leader = make<DefinedRegular>(this, /*Name*/ "", /*IsCOMDAT*/
>>> false,
>>>                                      /*IsExternal*/ false,
>>> sym.getGeneric());
>>> @@ -789,12 +786,11 @@ void ObjFile::initializeDependencies() {
>>>    else
>>>      data = getDebugSection(".debug$T");
>>>
>>> -  // 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);
>>> +      debugTypesObj = makeTpiSource(ctx, this);
>>>      return;
>>>    }
>>>
>>> @@ -812,7 +808,7 @@ void ObjFile::initializeDependencies() {
>>>
>>>    // This object file is a PCH file that others will depend on.
>>>    if (isPCH) {
>>> -    debugTypesObj = makePrecompSource(this);
>>> +    debugTypesObj = makePrecompSource(ctx, this);
>>>      return;
>>>    }
>>>
>>> @@ -820,8 +816,8 @@ void ObjFile::initializeDependencies() {
>>>    if (firstType->kind() == LF_TYPESERVER2) {
>>>      TypeServer2Record ts = cantFail(
>>>
>>>  TypeDeserializer::deserializeAs<TypeServer2Record>(firstType->data()));
>>> -    debugTypesObj = makeUseTypeServerSource(this, ts);
>>> -    PDBInputFile::enqueue(ts.getName(), this);
>>> +    debugTypesObj = makeUseTypeServerSource(ctx, this, ts);
>>> +    enqueuePdbFile(ts.getName(), this);
>>>      return;
>>>    }
>>>
>>> @@ -830,14 +826,14 @@ void ObjFile::initializeDependencies() {
>>>    if (firstType->kind() == LF_PRECOMP) {
>>>      PrecompRecord precomp = cantFail(
>>>
>>>  TypeDeserializer::deserializeAs<PrecompRecord>(firstType->data()));
>>> -    debugTypesObj = makeUsePrecompSource(this, precomp);
>>> +    debugTypesObj = makeUsePrecompSource(ctx, this, precomp);
>>>      // Drop the LF_PRECOMP record from the input stream.
>>>      debugTypes = debugTypes.drop_front(firstType->RecordData.size());
>>>      return;
>>>    }
>>>
>>>    // This is a plain old object file.
>>> -  debugTypesObj = makeTpiSource(this);
>>> +  debugTypesObj = makeTpiSource(ctx, this);
>>>  }
>>>
>>>  // Make a PDB path assuming the PDB is in the same folder as the OBJ
>>> @@ -855,7 +851,7 @@ static std::string getPdbBaseName(ObjFile *file,
>>> StringRef tSPath) {
>>>
>>>  // The casing of the PDB path stamped in the OBJ can
>>> diff er from the actual path
>>>  // on disk. With this, we ensure to always use lowercase as a key for
>>> the
>>> -// PDBInputFile::instances map, at least on Windows.
>>> +// pdbInputFileInstances map, at least on Windows.
>>>  static std::string normalizePdbPath(StringRef path) {
>>>  #if defined(_WIN32)
>>>    return path.lower();
>>> @@ -879,33 +875,25 @@ static Optional<std::string> findPdbPath(StringRef
>>> pdbPath,
>>>    return None;
>>>  }
>>>
>>> -PDBInputFile::PDBInputFile(MemoryBufferRef m) : InputFile(PDBKind, m) {}
>>> +PDBInputFile::PDBInputFile(COFFLinkerContext &ctx, MemoryBufferRef m)
>>> +    : InputFile(ctx, PDBKind, m) {}
>>>
>>>  PDBInputFile::~PDBInputFile() = default;
>>>
>>> -PDBInputFile *PDBInputFile::findFromRecordPath(StringRef path,
>>> +PDBInputFile *PDBInputFile::findFromRecordPath(const COFFLinkerContext
>>> &ctx,
>>> +                                               StringRef path,
>>>                                                 ObjFile *fromFile) {
>>>    auto p = findPdbPath(path.str(), fromFile);
>>>    if (!p)
>>>      return nullptr;
>>> -  auto it = PDBInputFile::instances.find(*p);
>>> -  if (it != PDBInputFile::instances.end())
>>> +  auto it = ctx.pdbInputFileInstances.find(*p);
>>> +  if (it != ctx.pdbInputFileInstances.end())
>>>      return it->second;
>>>    return nullptr;
>>>  }
>>>
>>> -void PDBInputFile::enqueue(StringRef path, ObjFile *fromFile) {
>>> -  auto p = findPdbPath(path.str(), fromFile);
>>> -  if (!p)
>>> -    return;
>>> -  auto it = PDBInputFile::instances.emplace(*p, nullptr);
>>> -  if (!it.second)
>>> -    return; // already scheduled for load
>>> -  driver->enqueuePDB(*p);
>>> -}
>>> -
>>>  void PDBInputFile::parse() {
>>> -  PDBInputFile::instances[mb.getBufferIdentifier().str()] = this;
>>> +  ctx.pdbInputFileInstances[mb.getBufferIdentifier().str()] = this;
>>>
>>>    std::unique_ptr<pdb::IPDBSession> thisSession;
>>>    loadErr.emplace(pdb::NativeSession::createFromPdb(
>>> @@ -923,7 +911,7 @@ void PDBInputFile::parse() {
>>>      loadErr.emplace(expectedInfo.takeError());
>>>      return;
>>>    }
>>> -  debugTypesObj = makeTypeServerSource(this);
>>> +  debugTypesObj = makeTypeServerSource(ctx, this);
>>>  }
>>>
>>>  // Used only for DWARF debug info, which is not common (except in MinGW
>>> @@ -957,6 +945,16 @@ Optional<DILineInfo>
>>> ObjFile::getDILineInfo(uint32_t offset,
>>>    return dwarf->getDILineInfo(offset, sectionIndex);
>>>  }
>>>
>>> +void ObjFile::enqueuePdbFile(StringRef path, ObjFile *fromFile) {
>>> +  auto p = findPdbPath(path.str(), fromFile);
>>> +  if (!p)
>>> +    return;
>>> +  auto it = ctx.pdbInputFileInstances.emplace(*p, nullptr);
>>> +  if (!it.second)
>>> +    return; // already scheduled for load
>>> +  driver->enqueuePDB(*p);
>>> +}
>>> +
>>>  void ImportFile::parse() {
>>>    const char *buf = mb.getBufferStart();
>>>    const auto *hdr = reinterpret_cast<const coff_import_header *>(buf);
>>> @@ -990,31 +988,31 @@ void ImportFile::parse() {
>>>    this->hdr = hdr;
>>>    externalName = extName;
>>>
>>> -  impSym = symtab->addImportData(impName, this);
>>> +  impSym = ctx.symtab.addImportData(impName, this);
>>>    // If this was a duplicate, we logged an error but may continue;
>>>    // in this case, impSym is nullptr.
>>>    if (!impSym)
>>>      return;
>>>
>>>    if (hdr->getType() == llvm::COFF::IMPORT_CONST)
>>> -    static_cast<void>(symtab->addImportData(name, this));
>>> +    static_cast<void>(ctx.symtab.addImportData(name, this));
>>>
>>>    // If type is function, we need to create a thunk which jump to an
>>>    // address pointed by the __imp_ symbol. (This allows you to call
>>>    // DLL functions just like regular non-DLL functions.)
>>>    if (hdr->getType() == llvm::COFF::IMPORT_CODE)
>>> -    thunkSym = symtab->addImportThunk(
>>> +    thunkSym = ctx.symtab.addImportThunk(
>>>          name, cast_or_null<DefinedImportData>(impSym), hdr->Machine);
>>>  }
>>>
>>> -BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
>>> -                         uint64_t offsetInArchive)
>>> -    : BitcodeFile(mb, archiveName, offsetInArchive, {}) {}
>>> +BitcodeFile::BitcodeFile(COFFLinkerContext &ctx, MemoryBufferRef mb,
>>> +                         StringRef archiveName, uint64_t
>>> offsetInArchive)
>>> +    : BitcodeFile(ctx, mb, archiveName, offsetInArchive, {}) {}
>>>
>>> -BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
>>> -                         uint64_t offsetInArchive,
>>> +BitcodeFile::BitcodeFile(COFFLinkerContext &ctx, MemoryBufferRef mb,
>>> +                         StringRef archiveName, uint64_t
>>> offsetInArchive,
>>>                           std::vector<Symbol *> &&symbols)
>>> -    : InputFile(BitcodeKind, mb), symbols(std::move(symbols)) {
>>> +    : InputFile(ctx, BitcodeKind, mb), symbols(std::move(symbols)) {
>>>    std::string path = mb.getBufferIdentifier().str();
>>>    if (config->thinLTOIndexOnly)
>>>      path = replaceThinLTOSuffix(mb.getBufferIdentifier());
>>> @@ -1069,7 +1067,7 @@ void BitcodeFile::parse() {
>>>    for (size_t i = 0; i != obj->getComdatTable().size(); ++i)
>>>      // FIXME: Check nodeduplicate
>>>      comdat[i] =
>>> -        symtab->addComdat(this,
>>> saver.save(obj->getComdatTable()[i].first));
>>> +        ctx.symtab.addComdat(this,
>>> saver.save(obj->getComdatTable()[i].first));
>>>    for (const lto::InputFile::Symbol &objSym : obj->symbols()) {
>>>      StringRef symName = saver.save(objSym.getName());
>>>      int comdatIndex = objSym.getComdatIndex();
>>> @@ -1080,27 +1078,27 @@ void BitcodeFile::parse() {
>>>      else
>>>        fakeSC = &ltoDataSectionChunk.chunk;
>>>      if (objSym.isUndefined()) {
>>> -      sym = symtab->addUndefined(symName, this, false);
>>> +      sym = ctx.symtab.addUndefined(symName, this, false);
>>>      } else if (objSym.isCommon()) {
>>> -      sym = symtab->addCommon(this, symName, objSym.getCommonSize());
>>> +      sym = ctx.symtab.addCommon(this, symName, objSym.getCommonSize());
>>>      } else if (objSym.isWeak() && objSym.isIndirect()) {
>>>        // Weak external.
>>> -      sym = symtab->addUndefined(symName, this, true);
>>> +      sym = ctx.symtab.addUndefined(symName, this, true);
>>>        std::string fallback =
>>> std::string(objSym.getCOFFWeakExternalFallback());
>>> -      Symbol *alias = symtab->addUndefined(saver.save(fallback));
>>> -      checkAndSetWeakAlias(symtab, this, sym, alias);
>>> +      Symbol *alias = ctx.symtab.addUndefined(saver.save(fallback));
>>> +      checkAndSetWeakAlias(&ctx.symtab, this, sym, alias);
>>>      } else if (comdatIndex != -1) {
>>>        if (symName == obj->getComdatTable()[comdatIndex].first) {
>>>          sym = comdat[comdatIndex].first;
>>>          if (cast<DefinedRegular>(sym)->data == nullptr)
>>>            cast<DefinedRegular>(sym)->data = &fakeSC->repl;
>>>        } else if (comdat[comdatIndex].second) {
>>> -        sym = symtab->addRegular(this, symName, nullptr, fakeSC);
>>> +        sym = ctx.symtab.addRegular(this, symName, nullptr, fakeSC);
>>>        } else {
>>> -        sym = symtab->addUndefined(symName, this, false);
>>> +        sym = ctx.symtab.addUndefined(symName, this, false);
>>>        }
>>>      } else {
>>> -      sym = symtab->addRegular(this, symName, nullptr, fakeSC);
>>> +      sym = ctx.symtab.addRegular(this, symName, nullptr, fakeSC);
>>>      }
>>>      symbols.push_back(sym);
>>>      if (objSym.isUsed())
>>> @@ -1185,9 +1183,9 @@ void DLLFile::parse() {
>>>      }
>>>
>>>      StringRef impName = saver.save("__imp_" + symbolName);
>>> -    symtab->addLazyDLLSymbol(this, s, impName);
>>> +    ctx.symtab.addLazyDLLSymbol(this, s, impName);
>>>      if (code)
>>> -      symtab->addLazyDLLSymbol(this, s, symbolName);
>>> +      ctx.symtab.addLazyDLLSymbol(this, s, symbolName);
>>>    }
>>>  }
>>>
>>> @@ -1219,6 +1217,6 @@ void DLLFile::makeImport(DLLFile::Symbol *s) {
>>>    p += s->symbolName.size() + 1;
>>>    memcpy(p, s->dllName.data(), s->dllName.size());
>>>    MemoryBufferRef mbref = MemoryBufferRef(StringRef(buf, size),
>>> s->dllName);
>>> -  ImportFile *impFile = make<ImportFile>(mbref);
>>> -  symtab->addFile(impFile);
>>> +  ImportFile *impFile = make<ImportFile>(ctx, mbref);
>>> +  ctx.symtab.addFile(impFile);
>>>  }
>>>
>>> diff  --git a/lld/COFF/InputFiles.h b/lld/COFF/InputFiles.h
>>> index 47b5c588c5af7..801c668d3ae45 100644
>>> --- a/lld/COFF/InputFiles.h
>>> +++ b/lld/COFF/InputFiles.h
>>> @@ -38,6 +38,7 @@ namespace lld {
>>>  class DWARFCache;
>>>
>>>  namespace coff {
>>> +class COFFLinkerContext;
>>>
>>>  std::vector<MemoryBufferRef> getArchiveMembers(llvm::object::Archive
>>> *file);
>>>
>>> @@ -91,8 +92,11 @@ class InputFile {
>>>    // Returns .drectve section contents if exist.
>>>    StringRef getDirectives() { return directives; }
>>>
>>> +  COFFLinkerContext &ctx;
>>> +
>>>  protected:
>>> -  InputFile(Kind k, MemoryBufferRef m) : mb(m), fileKind(k) {}
>>> +  InputFile(COFFLinkerContext &c, Kind k, MemoryBufferRef m)
>>> +      : mb(m), ctx(c), fileKind(k) {}
>>>
>>>    StringRef directives;
>>>
>>> @@ -103,7 +107,7 @@ class InputFile {
>>>  // .lib or .a file.
>>>  class ArchiveFile : public InputFile {
>>>  public:
>>> -  explicit ArchiveFile(MemoryBufferRef m);
>>> +  explicit ArchiveFile(COFFLinkerContext &ctx, MemoryBufferRef m);
>>>    static bool classof(const InputFile *f) { return f->kind() ==
>>> ArchiveKind; }
>>>    void parse() override;
>>>
>>> @@ -120,7 +124,8 @@ class ArchiveFile : public InputFile {
>>>  // .obj or .o file between -start-lib and -end-lib.
>>>  class LazyObjFile : public InputFile {
>>>  public:
>>> -  explicit LazyObjFile(MemoryBufferRef m) : InputFile(LazyObjectKind,
>>> m) {}
>>> +  explicit LazyObjFile(COFFLinkerContext &ctx, MemoryBufferRef m)
>>> +      : InputFile(ctx, LazyObjectKind, m) {}
>>>    static bool classof(const InputFile *f) {
>>>      return f->kind() == LazyObjectKind;
>>>    }
>>> @@ -136,9 +141,11 @@ class LazyObjFile : public InputFile {
>>>  // .obj or .o file. This may be a member of an archive file.
>>>  class ObjFile : public InputFile {
>>>  public:
>>> -  explicit ObjFile(MemoryBufferRef m) : InputFile(ObjectKind, m) {}
>>> -  explicit ObjFile(MemoryBufferRef m, std::vector<Symbol *> &&symbols)
>>> -      : InputFile(ObjectKind, m), symbols(std::move(symbols)) {}
>>> +  explicit ObjFile(COFFLinkerContext &ctx, MemoryBufferRef m)
>>> +      : InputFile(ctx, ObjectKind, m) {}
>>> +  explicit ObjFile(COFFLinkerContext &ctx, MemoryBufferRef m,
>>> +                   std::vector<Symbol *> &&symbols)
>>> +      : InputFile(ctx, ObjectKind, m), symbols(std::move(symbols)) {}
>>>    static bool classof(const InputFile *f) { return f->kind() ==
>>> ObjectKind; }
>>>    void parse() override;
>>>    MachineTypes getMachineType() override;
>>> @@ -175,8 +182,6 @@ class ObjFile : public InputFile {
>>>
>>>    bool isResourceObjFile() const { return !resourceChunks.empty(); }
>>>
>>> -  static std::vector<ObjFile *> instances;
>>> -
>>>    // Flags in the absolute @feat.00 symbol if it is present. These
>>> usually
>>>    // indicate if an object was compiled with certain security features
>>> enabled
>>>    // like stack guard, safeseh, /guard:cf, or other things.
>>> @@ -228,6 +233,8 @@ class ObjFile : public InputFile {
>>>      return getSection(sym.getSectionNumber());
>>>    }
>>>
>>> +  void enqueuePdbFile(StringRef path, ObjFile *fromFile);
>>> +
>>>    void initializeChunks();
>>>    void initializeSymbols();
>>>    void initializeFlags();
>>> @@ -318,16 +325,13 @@ class ObjFile : public InputFile {
>>>  // stream.
>>>  class PDBInputFile : public InputFile {
>>>  public:
>>> -  explicit PDBInputFile(MemoryBufferRef m);
>>> +  explicit PDBInputFile(COFFLinkerContext &ctx, MemoryBufferRef m);
>>>    ~PDBInputFile();
>>>    static bool classof(const InputFile *f) { return f->kind() ==
>>> PDBKind; }
>>>    void parse() override;
>>>
>>> -  static void enqueue(StringRef path, ObjFile *fromFile);
>>> -
>>> -  static PDBInputFile *findFromRecordPath(StringRef path, ObjFile
>>> *fromFile);
>>> -
>>> -  static std::map<std::string, PDBInputFile *> instances;
>>> +  static PDBInputFile *findFromRecordPath(const COFFLinkerContext &ctx,
>>> +                                          StringRef path, ObjFile
>>> *fromFile);
>>>
>>>    // Record possible errors while opening the PDB file
>>>    llvm::Optional<Error> loadErr;
>>> @@ -344,12 +348,11 @@ class PDBInputFile : public InputFile {
>>>  // for details about the format.
>>>  class ImportFile : public InputFile {
>>>  public:
>>> -  explicit ImportFile(MemoryBufferRef m) : InputFile(ImportKind, m) {}
>>> +  explicit ImportFile(COFFLinkerContext &ctx, MemoryBufferRef m)
>>> +      : InputFile(ctx, ImportKind, m) {}
>>>
>>>    static bool classof(const InputFile *f) { return f->kind() ==
>>> ImportKind; }
>>>
>>> -  static std::vector<ImportFile *> instances;
>>> -
>>>    Symbol *impSym = nullptr;
>>>    Symbol *thunkSym = nullptr;
>>>    std::string dllName;
>>> @@ -377,16 +380,15 @@ class ImportFile : public InputFile {
>>>  // Used for LTO.
>>>  class BitcodeFile : public InputFile {
>>>  public:
>>> -  BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
>>> +  BitcodeFile(COFFLinkerContext &ctx, MemoryBufferRef mb, StringRef
>>> archiveName,
>>>                uint64_t offsetInArchive);
>>> -  explicit BitcodeFile(MemoryBufferRef m, StringRef archiveName,
>>> -                       uint64_t offsetInArchive,
>>> +  explicit BitcodeFile(COFFLinkerContext &ctx, MemoryBufferRef m,
>>> +                       StringRef archiveName, uint64_t offsetInArchive,
>>>                         std::vector<Symbol *> &&symbols);
>>>    ~BitcodeFile();
>>>    static bool classof(const InputFile *f) { return f->kind() ==
>>> BitcodeKind; }
>>>    ArrayRef<Symbol *> getSymbols() { return symbols; }
>>>    MachineTypes getMachineType() override;
>>> -  static std::vector<BitcodeFile *> instances;
>>>    std::unique_ptr<llvm::lto::InputFile> obj;
>>>
>>>  private:
>>> @@ -398,7 +400,8 @@ class BitcodeFile : public InputFile {
>>>  // .dll file. MinGW only.
>>>  class DLLFile : public InputFile {
>>>  public:
>>> -  explicit DLLFile(MemoryBufferRef m) : InputFile(DLLKind, m) {}
>>> +  explicit DLLFile(COFFLinkerContext &ctx, MemoryBufferRef m)
>>> +      : InputFile(ctx, DLLKind, m) {}
>>>    static bool classof(const InputFile *f) { return f->kind() ==
>>> DLLKind; }
>>>    void parse() override;
>>>    MachineTypes getMachineType() override;
>>>
>>> diff  --git a/lld/COFF/LLDMapFile.cpp b/lld/COFF/LLDMapFile.cpp
>>> index 79df33a3535fd..639b186dbb6f9 100644
>>> --- a/lld/COFF/LLDMapFile.cpp
>>> +++ b/lld/COFF/LLDMapFile.cpp
>>> @@ -19,6 +19,7 @@
>>>
>>>  //===----------------------------------------------------------------------===//
>>>
>>>  #include "LLDMapFile.h"
>>> +#include "COFFLinkerContext.h"
>>>  #include "SymbolTable.h"
>>>  #include "Symbols.h"
>>>  #include "Writer.h"
>>> @@ -44,9 +45,9 @@ static void writeHeader(raw_ostream &os, uint64_t
>>> addr, uint64_t size,
>>>  }
>>>
>>>  // Returns a list of all symbols that we want to print out.
>>> -static std::vector<DefinedRegular *> getSymbols() {
>>> +static std::vector<DefinedRegular *> getSymbols(const COFFLinkerContext
>>> &ctx) {
>>>    std::vector<DefinedRegular *> v;
>>> -  for (ObjFile *file : ObjFile::instances)
>>> +  for (ObjFile *file : ctx.objFileInstances)
>>>      for (Symbol *b : file->getSymbols())
>>>        if (auto *sym = dyn_cast_or_null<DefinedRegular>(b))
>>>          if (sym && !sym->getCOFFSymbol().isSectionDefinition())
>>> @@ -86,7 +87,7 @@ getSymbolStrings(ArrayRef<DefinedRegular *> syms) {
>>>    return ret;
>>>  }
>>>
>>> -void lld::coff::writeLLDMapFile(ArrayRef<OutputSection *>
>>> outputSections) {
>>> +void lld::coff::writeLLDMapFile(const COFFLinkerContext &ctx) {
>>>    if (config->lldmapFile.empty())
>>>      return;
>>>
>>> @@ -96,7 +97,7 @@ void lld::coff::writeLLDMapFile(ArrayRef<OutputSection
>>> *> outputSections) {
>>>      fatal("cannot open " + config->lldmapFile + ": " + ec.message());
>>>
>>>    // Collect symbol info that we want to print out.
>>> -  std::vector<DefinedRegular *> syms = getSymbols();
>>> +  std::vector<DefinedRegular *> syms = getSymbols(ctx);
>>>    SymbolMapTy sectionSyms = getSectionSyms(syms);
>>>    DenseMap<DefinedRegular *, std::string> symStr =
>>> getSymbolStrings(syms);
>>>
>>> @@ -104,7 +105,7 @@ void
>>> lld::coff::writeLLDMapFile(ArrayRef<OutputSection *> outputSections) {
>>>    os << "Address  Size     Align Out     In      Symbol\n";
>>>
>>>    // Print out file contents.
>>> -  for (OutputSection *sec : outputSections) {
>>> +  for (OutputSection *sec : ctx.outputSections) {
>>>      writeHeader(os, sec->getRVA(), sec->getVirtualSize(),
>>> /*align=*/pageSize);
>>>      os << sec->name << '\n';
>>>
>>>
>>> diff  --git a/lld/COFF/LLDMapFile.h b/lld/COFF/LLDMapFile.h
>>> index b731293a8625d..72e999a61900a 100644
>>> --- a/lld/COFF/LLDMapFile.h
>>> +++ b/lld/COFF/LLDMapFile.h
>>> @@ -9,12 +9,10 @@
>>>  #ifndef LLD_COFF_LLDMAPFILE_H
>>>  #define LLD_COFF_LLDMAPFILE_H
>>>
>>> -#include "llvm/ADT/ArrayRef.h"
>>> -
>>>  namespace lld {
>>>  namespace coff {
>>> -class OutputSection;
>>> -void writeLLDMapFile(llvm::ArrayRef<OutputSection *> outputSections);
>>> +class COFFLinkerContext;
>>> +void writeLLDMapFile(const COFFLinkerContext &ctx);
>>>  }
>>>  }
>>>
>>>
>>> diff  --git a/lld/COFF/LTO.cpp b/lld/COFF/LTO.cpp
>>> index 6e38f53f21362..ce9c4fd0d51b2 100644
>>> --- a/lld/COFF/LTO.cpp
>>> +++ b/lld/COFF/LTO.cpp
>>> @@ -156,7 +156,7 @@ void BitcodeCompiler::add(BitcodeFile &f) {
>>>
>>>  // Merge all the bitcode files we have seen, codegen the
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210917/39ec3da3/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 3992 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210917/39ec3da3/attachment.bin>


More information about the llvm-commits mailing list