Skip to content

Commit

Permalink
[LLD] Remove global state in lld/COFF
Browse files Browse the repository at this point in the history
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
  • Loading branch information
amykhuang committed Sep 16, 2021
1 parent c96d457 commit b4fa71e
Show file tree
Hide file tree
Showing 37 changed files with 692 additions and 607 deletions.
1 change: 1 addition & 0 deletions lld/COFF/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
53 changes: 53 additions & 0 deletions lld/COFF/COFFLinkerContext.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//===- 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),
symbolMergingTimer("Symbol Merging", addObjectsTimer),
typeMergingTimer("Type Merging", addObjectsTimer),
tpiStreamLayoutTimer("TPI Stream Layout", totalPdbLinkTimer),
publicsLayoutTimer("Publics Stream Layout", totalPdbLinkTimer),
diskCommitTimer("Commit to Disk", totalPdbLinkTimer),
loadGHashTimer("Global Type Hashing", addObjectsTimer),
mergeGHashTimer("GHash Type Merging", addObjectsTimer) {}

COFFLinkerContext::~COFFLinkerContext() { clearGHashes(); }

void COFFLinkerContext::clearGHashes() {
for (TpiSource *src : tpiSourceList) {
if (src->ownedGHashes)
delete[] src->ghashes.data();
src->ghashes = {};
src->isItemIndex.clear();
src->uniqueTypes.clear();
}
}

} // namespace coff
} // namespace lld
88 changes: 88 additions & 0 deletions lld/COFF/COFFLinkerContext.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//===- 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();

void addTpiSource(TpiSource *tpi) { tpiSourceList.push_back(tpi); }

/// Free heap allocated ghashes.
void clearGHashes();

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 symbolMergingTimer;
Timer typeMergingTimer;
Timer tpiStreamLayoutTimer;
Timer publicsLayoutTimer;
Timer diskCommitTimer;
Timer loadGHashTimer;
Timer mergeGHashTimer;
};

} // namespace coff
} // namespace lld

#endif
12 changes: 7 additions & 5 deletions lld/COFF/CallGraphSort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//

#include "CallGraphSort.h"
#include "COFFLinkerContext.h"
#include "InputFiles.h"
#include "SymbolTable.h"
#include "Symbols.h"
Expand Down Expand Up @@ -48,7 +49,7 @@ struct Cluster {

class CallGraphSort {
public:
CallGraphSort();
CallGraphSort(const COFFLinkerContext &ctx);

DenseMap<const SectionChunk *, int> run();

Expand All @@ -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;

Expand All @@ -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);
Expand Down Expand Up @@ -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();
}
4 changes: 3 additions & 1 deletion lld/COFF/CallGraphSort.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
13 changes: 6 additions & 7 deletions lld/COFF/Chunks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 1 addition & 3 deletions lld/COFF/Chunks.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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();

Expand All @@ -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:
Expand Down
7 changes: 4 additions & 3 deletions lld/COFF/DLL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
//===----------------------------------------------------------------------===//

#include "DLL.h"
#include "COFFLinkerContext.h"
#include "Chunks.h"
#include "SymbolTable.h"
#include "llvm/Object/COFF.h"
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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));
Expand Down
2 changes: 1 addition & 1 deletion lld/COFF/DLL.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down
Loading

0 comments on commit b4fa71e

Please sign in to comment.