[lld] f860fe3 - [LLD] Remove global state in lldCommon
Alexandre Ganea via llvm-commits
llvm-commits at lists.llvm.org
Sun Jan 16 05:58:05 PST 2022
Author: Alexandre Ganea
Date: 2022-01-16T08:57:57-05:00
New Revision: f860fe362282ed69b9d4503a20e5d20b9a041189
URL: https://github.com/llvm/llvm-project/commit/f860fe362282ed69b9d4503a20e5d20b9a041189
DIFF: https://github.com/llvm/llvm-project/commit/f860fe362282ed69b9d4503a20e5d20b9a041189.diff
LOG: [LLD] Remove global state in lldCommon
Move all variables at file-scope or function-static-scope into a hosting structure (lld::CommonLinkerContext) that lives at lldMain()-scope. Drivers will inherit from this structure and add their own global state, in the same way as for the existing COFFLinkerContext.
See discussion in https://lists.llvm.org/pipermail/llvm-dev/2021-June/151184.html
Differential Revision: https://reviews.llvm.org/D108850
Added:
lld/Common/CommonLinkerContext.cpp
lld/include/lld/Common/CommonLinkerContext.h
Modified:
lld/COFF/COFFLinkerContext.h
lld/COFF/Chunks.cpp
lld/COFF/DLL.cpp
lld/COFF/Driver.cpp
lld/COFF/DriverUtils.cpp
lld/COFF/InputFiles.cpp
lld/COFF/LTO.cpp
lld/COFF/MinGW.cpp
lld/COFF/PDB.cpp
lld/COFF/SymbolTable.cpp
lld/COFF/Writer.cpp
lld/Common/CMakeLists.txt
lld/Common/ErrorHandler.cpp
lld/Common/Memory.cpp
lld/Common/TargetOptionsCommandFlags.cpp
lld/ELF/AArch64ErrataFix.cpp
lld/ELF/ARMErrataFix.cpp
lld/ELF/Arch/PPC64.cpp
lld/ELF/Driver.cpp
lld/ELF/DriverUtils.cpp
lld/ELF/InputFiles.cpp
lld/ELF/InputSection.cpp
lld/ELF/LinkerScript.cpp
lld/ELF/MarkLive.cpp
lld/ELF/ScriptParser.cpp
lld/ELF/SyntheticSections.cpp
lld/ELF/Thunks.cpp
lld/ELF/Writer.cpp
lld/MachO/ConcatOutputSection.cpp
lld/MachO/Driver.cpp
lld/MachO/DriverUtils.cpp
lld/MachO/InputFiles.cpp
lld/MachO/LTO.cpp
lld/MachO/SyntheticSections.cpp
lld/MachO/Writer.cpp
lld/MinGW/Driver.cpp
lld/include/lld/Common/Driver.h
lld/include/lld/Common/ErrorHandler.h
lld/include/lld/Common/Memory.h
lld/include/lld/Core/LinkingContext.h
lld/tools/lld/lld.cpp
lld/wasm/Driver.cpp
lld/wasm/InputFiles.cpp
lld/wasm/SymbolTable.cpp
lld/wasm/Writer.cpp
Removed:
################################################################################
diff --git a/lld/COFF/COFFLinkerContext.h b/lld/COFF/COFFLinkerContext.h
index e5223da86ef83..a3a6f94a94137 100644
--- a/lld/COFF/COFFLinkerContext.h
+++ b/lld/COFF/COFFLinkerContext.h
@@ -15,12 +15,13 @@
#include "InputFiles.h"
#include "SymbolTable.h"
#include "Writer.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/Timer.h"
namespace lld {
namespace coff {
-class COFFLinkerContext {
+class COFFLinkerContext : public CommonLinkerContext {
public:
COFFLinkerContext();
COFFLinkerContext(const COFFLinkerContext &) = delete;
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 54cb8c99071de..6cabb22d98cf2 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -12,7 +12,6 @@
#include "SymbolTable.h"
#include "Symbols.h"
#include "Writer.h"
-#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Object/COFF.h"
@@ -430,7 +429,7 @@ void SectionChunk::sortRelocations() {
return;
warn("some relocations in " + file->getName() + " are not sorted");
MutableArrayRef<coff_relocation> newRelocs(
- bAlloc.Allocate<coff_relocation>(relocsSize), relocsSize);
+ bAlloc().Allocate<coff_relocation>(relocsSize), relocsSize);
memcpy(newRelocs.data(), relocsData, relocsSize * sizeof(coff_relocation));
llvm::sort(newRelocs, cmpByVa);
setRelocs(newRelocs);
diff --git a/lld/COFF/DLL.cpp b/lld/COFF/DLL.cpp
index 6fec9df5617db..bfa2a6910e2b7 100644
--- a/lld/COFF/DLL.cpp
+++ b/lld/COFF/DLL.cpp
@@ -659,14 +659,14 @@ void DelayLoadContents::create(COFFLinkerContext &ctx, Defined *h) {
// Add a syntentic symbol for this load thunk, using the "__imp_load"
// prefix, in case this thunk needs to be added to the list of valid
// call targets for Control Flow Guard.
- StringRef symName = saver.save("__imp_load_" + extName);
+ StringRef symName = saver().save("__imp_load_" + extName);
s->loadThunkSym =
cast<DefinedSynthetic>(ctx.symtab.addSynthetic(symName, t));
}
}
thunks.push_back(tm);
StringRef tmName =
- saver.save("__tailMerge_" + syms[0]->getDLLName().lower());
+ saver().save("__tailMerge_" + syms[0]->getDLLName().lower());
ctx.symtab.addSynthetic(tmName, tm);
// Terminate with null values.
addresses.push_back(make<NullChunk>(8));
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index f8da63c5edbfb..0d833af98efb6 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -19,9 +19,7 @@
#include "Writer.h"
#include "lld/Common/Args.h"
#include "lld/Common/Driver.h"
-#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Filesystem.h"
-#include "lld/Common/Memory.h"
#include "lld/Common/Timer.h"
#include "lld/Common/Version.h"
#include "llvm/ADT/Optional.h"
@@ -63,36 +61,23 @@ namespace coff {
std::unique_ptr<Configuration> config;
std::unique_ptr<LinkerDriver> driver;
-bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &stdoutOS,
- raw_ostream &stderrOS) {
- lld::stdoutOS = &stdoutOS;
- lld::stderrOS = &stderrOS;
+bool link(ArrayRef<const char *> args, raw_ostream &stdoutOS,
+ raw_ostream &stderrOS, bool exitEarly, bool disableOutput) {
+ // This driver-specific context will be freed later by lldMain().
+ // It is created on the heap to avoid destructors if 'exitEarly' is set.
+ auto *ctx = new COFFLinkerContext;
- errorHandler().cleanupCallback = []() {
- freeArena();
- };
-
- errorHandler().logName = args::getFilenameWithoutExe(args[0]);
- errorHandler().errorLimitExceededMsg =
- "too many errors emitted, stopping now"
- " (use /errorlimit:0 to see all errors)";
- errorHandler().exitEarly = canExitEarly;
- stderrOS.enable_colors(stderrOS.has_colors());
+ ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
+ ctx->e.logName = args::getFilenameWithoutExe(args[0]);
+ ctx->e.errorLimitExceededMsg = "too many errors emitted, stopping now"
+ " (use /errorlimit:0 to see all errors)";
- COFFLinkerContext ctx;
config = std::make_unique<Configuration>();
- driver = std::make_unique<LinkerDriver>(ctx);
+ driver = std::make_unique<LinkerDriver>(*ctx);
driver->linkerMain(args);
- // Call exit() if we can to avoid calling destructors.
- if (canExitEarly)
- exitLld(errorCount() ? 1 : 0);
-
- bool ret = errorCount() == 0;
- if (!canExitEarly)
- errorHandler().reset();
- return ret;
+ return errorCount() == 0;
}
// Parse options of the form "old;new".
@@ -162,7 +147,7 @@ static std::future<MBErrPair> createFutureForFile(std::string path) {
static StringRef mangle(StringRef sym) {
assert(config->machine != IMAGE_FILE_MACHINE_UNKNOWN);
if (config->machine == I386)
- return saver.save("_" + sym);
+ return saver().save("_" + sym);
return sym;
}
@@ -358,9 +343,9 @@ void LinkerDriver::parseDirectives(InputFile *file) {
Export exp = parseExport(e);
if (config->machine == I386 && config->mingw) {
if (!isDecorated(exp.name))
- exp.name = saver.save("_" + exp.name);
+ exp.name = saver().save("_" + exp.name);
if (!exp.extName.empty() && !isDecorated(exp.extName))
- exp.extName = saver.save("_" + exp.extName);
+ exp.extName = saver().save("_" + exp.extName);
}
exp.directives = true;
config->exports.push_back(exp);
@@ -442,11 +427,11 @@ StringRef LinkerDriver::doFindFile(StringRef filename) {
SmallString<128> path = dir;
sys::path::append(path, filename);
if (sys::fs::exists(path.str()))
- return saver.save(path.str());
+ return saver().save(path.str());
if (!hasExt) {
path.append(".obj");
if (sys::fs::exists(path.str()))
- return saver.save(path.str());
+ return saver().save(path.str());
}
}
return filename;
@@ -483,7 +468,7 @@ StringRef LinkerDriver::doFindLibMinGW(StringRef filename) {
SmallString<128> s = filename;
sys::path::replace_extension(s, ".a");
- StringRef libName = saver.save("lib" + s.str());
+ StringRef libName = saver().save("lib" + s.str());
return doFindFile(libName);
}
@@ -492,7 +477,7 @@ StringRef LinkerDriver::doFindLib(StringRef filename) {
// Add ".lib" to Filename if that has no file extension.
bool hasExt = filename.contains('.');
if (!hasExt)
- filename = saver.save(filename + ".lib");
+ filename = saver().save(filename + ".lib");
StringRef ret = doFindFile(filename);
// For MinGW, if the find above didn't turn up anything, try
// looking for a MinGW formatted library name.
@@ -525,7 +510,7 @@ void LinkerDriver::addLibSearchPaths() {
Optional<std::string> envOpt = Process::GetEnv("LIB");
if (!envOpt.hasValue())
return;
- StringRef env = saver.save(*envOpt);
+ StringRef env = saver().save(*envOpt);
while (!env.empty()) {
StringRef path;
std::tie(path, env) = env.split(';');
@@ -872,8 +857,8 @@ static void parseModuleDefs(StringRef path) {
driver->takeBuffer(std::move(mb));
if (config->outputFile.empty())
- config->outputFile = std::string(saver.save(m.OutputFile));
- config->importName = std::string(saver.save(m.ImportName));
+ config->outputFile = std::string(saver().save(m.OutputFile));
+ config->importName = std::string(saver().save(m.ImportName));
if (m.ImageBase)
config->imageBase = m.ImageBase;
if (m.StackReserve)
@@ -901,13 +886,13 @@ static void parseModuleDefs(StringRef path) {
// DLL instead. This is supported by both MS and GNU linkers.
if (!e1.ExtName.empty() && e1.ExtName != e1.Name &&
StringRef(e1.Name).contains('.')) {
- e2.name = saver.save(e1.ExtName);
- e2.forwardTo = saver.save(e1.Name);
+ e2.name = saver().save(e1.ExtName);
+ e2.forwardTo = saver().save(e1.Name);
config->exports.push_back(e2);
continue;
}
- e2.name = saver.save(e1.Name);
- e2.extName = saver.save(e1.ExtName);
+ e2.name = saver().save(e1.Name);
+ e2.extName = saver().save(e1.ExtName);
e2.ordinal = e1.Ordinal;
e2.noname = e1.Noname;
e2.data = e1.Data;
@@ -1904,9 +1889,9 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
Export e = parseExport(arg->getValue());
if (config->machine == I386) {
if (!isDecorated(e.name))
- e.name = saver.save("_" + e.name);
+ e.name = saver().save("_" + e.name);
if (!e.extName.empty() && !isDecorated(e.extName))
- e.extName = saver.save("_" + e.extName);
+ e.extName = saver().save("_" + e.extName);
}
config->exports.push_back(e);
}
diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp
index 0921c8e27f5ae..ac0f1f972c798 100644
--- a/lld/COFF/DriverUtils.cpp
+++ b/lld/COFF/DriverUtils.cpp
@@ -48,17 +48,17 @@ const uint16_t RT_MANIFEST = 24;
class Executor {
public:
- explicit Executor(StringRef s) : prog(saver.save(s)) {}
- void add(StringRef s) { args.push_back(saver.save(s)); }
- void add(std::string &s) { args.push_back(saver.save(s)); }
- void add(Twine s) { args.push_back(saver.save(s)); }
- void add(const char *s) { args.push_back(saver.save(s)); }
+ explicit Executor(StringRef s) : prog(saver().save(s)) {}
+ void add(StringRef s) { args.push_back(saver().save(s)); }
+ void add(std::string &s) { args.push_back(saver().save(s)); }
+ void add(Twine s) { args.push_back(saver().save(s)); }
+ void add(const char *s) { args.push_back(saver().save(s)); }
void run() {
ErrorOr<std::string> exeOrErr = sys::findProgramByName(prog);
if (auto ec = exeOrErr.getError())
fatal("unable to find " + prog + " in PATH: " + ec.message());
- StringRef exe = saver.save(*exeOrErr);
+ StringRef exe = saver().save(*exeOrErr);
args.insert(args.begin(), exe);
if (sys::ExecuteAndWait(args[0], args) != 0)
@@ -636,14 +636,14 @@ static StringRef killAt(StringRef sym, bool prefix) {
sym = sym.substr(0, sym.find('@', 1));
if (!sym.startswith("@")) {
if (prefix && !sym.startswith("_"))
- return saver.save("_" + sym);
+ return saver().save("_" + sym);
return sym;
}
// For fastcall, remove the leading @ and replace it with an
// underscore, if prefixes are used.
sym = sym.substr(1);
if (prefix)
- sym = saver.save("_" + sym);
+ sym = saver().save("_" + sym);
return sym;
}
@@ -854,7 +854,7 @@ opt::InputArgList ArgParser::parse(ArrayRef<const char *> argv) {
argv.data() + argv.size());
if (!args.hasArg(OPT_lldignoreenv))
addLINK(expandedArgv);
- cl::ExpandResponseFiles(saver, getQuotingStyle(args), expandedArgv);
+ cl::ExpandResponseFiles(saver(), getQuotingStyle(args), expandedArgv);
args = optTable.ParseArgs(makeArrayRef(expandedArgv).drop_front(),
missingIndex, missingCount);
@@ -901,7 +901,7 @@ ParsedDirectives ArgParser::parseDirectives(StringRef s) {
// Handle /EXPORT and /INCLUDE in a fast path. These directives can appear for
// potentially every symbol in the object, so they must be handled quickly.
SmallVector<StringRef, 16> tokens;
- cl::TokenizeWindowsCommandLineNoCopy(s, saver, tokens);
+ cl::TokenizeWindowsCommandLineNoCopy(s, saver(), tokens);
for (StringRef tok : tokens) {
if (tok.startswith_insensitive("/export:") ||
tok.startswith_insensitive("-export:"))
@@ -914,7 +914,7 @@ ParsedDirectives ArgParser::parseDirectives(StringRef s) {
// already copied quoted arguments for us, so those do not need to be
// copied again.
bool HasNul = tok.end() != s.end() && tok.data()[tok.size()] == '\0';
- rest.push_back(HasNul ? tok.data() : saver.save(tok).data());
+ rest.push_back(HasNul ? tok.data() : saver().save(tok).data());
}
}
@@ -948,7 +948,7 @@ void ArgParser::addLINK(SmallVector<const char *, 256> &argv) {
std::vector<const char *> ArgParser::tokenize(StringRef s) {
SmallVector<const char *, 16> tokens;
- cl::TokenizeWindowsCommandLine(s, saver, tokens);
+ cl::TokenizeWindowsCommandLine(s, saver(), tokens);
return std::vector<const char *>(tokens.begin(), tokens.end());
}
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index 1d79d97acad26..0f3f5e0ffe7c5 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -15,8 +15,6 @@
#include "SymbolTable.h"
#include "Symbols.h"
#include "lld/Common/DWARF.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
#include "llvm-c/lto.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
@@ -905,7 +903,7 @@ ObjFile::getVariableLocation(StringRef var) {
Optional<std::pair<std::string, unsigned>> ret = dwarf->getVariableLoc(var);
if (!ret)
return None;
- return std::make_pair(saver.save(ret->first), ret->second);
+ return std::make_pair(saver().save(ret->first), ret->second);
}
// Used only for DWARF debug info, which is not common (except in MinGW
@@ -940,8 +938,8 @@ void ImportFile::parse() {
fatal("broken import library");
// Read names and create an __imp_ symbol.
- StringRef name = saver.save(StringRef(buf + sizeof(*hdr)));
- StringRef impName = saver.save("__imp_" + name);
+ StringRef name = saver().save(StringRef(buf + sizeof(*hdr)));
+ StringRef impName = saver().save("__imp_" + name);
const char *nameStart = buf + sizeof(coff_import_header) + name.size() + 1;
dllName = std::string(StringRef(nameStart));
StringRef extName;
@@ -995,11 +993,12 @@ BitcodeFile::BitcodeFile(COFFLinkerContext &ctx, MemoryBufferRef mb,
// into consideration at LTO time (which very likely causes undefined
// symbols later in the link stage). So we append file offset to make
// filename unique.
- MemoryBufferRef mbref(
- mb.getBuffer(),
- saver.save(archiveName.empty() ? path
- : archiveName + sys::path::filename(path) +
- utostr(offsetInArchive)));
+ MemoryBufferRef mbref(mb.getBuffer(),
+ saver().save(archiveName.empty()
+ ? path
+ : archiveName +
+ sys::path::filename(path) +
+ utostr(offsetInArchive)));
obj = check(lto::InputFile::create(mbref));
}
@@ -1035,6 +1034,7 @@ FakeSectionChunk ltoDataSectionChunk(<oDataSection.section);
} // namespace
void BitcodeFile::parse() {
+ llvm::StringSaver &saver = lld::saver();
std::vector<std::pair<Symbol *, bool>> comdat(obj->getComdatTable().size());
for (size_t i = 0; i != obj->getComdatTable().size(); ++i)
// FIXME: Check nodeduplicate
@@ -1156,11 +1156,11 @@ void DLLFile::parse() {
s->nameType = ImportNameType::IMPORT_NAME;
if (coffObj->getMachine() == I386) {
- s->symbolName = symbolName = saver.save("_" + symbolName);
+ s->symbolName = symbolName = saver().save("_" + symbolName);
s->nameType = ImportNameType::IMPORT_NAME_NOPREFIX;
}
- StringRef impName = saver.save("__imp_" + symbolName);
+ StringRef impName = saver().save("__imp_" + symbolName);
ctx.symtab.addLazyDLLSymbol(this, s, impName);
if (code)
ctx.symtab.addLazyDLLSymbol(this, s, symbolName);
@@ -1179,7 +1179,7 @@ void DLLFile::makeImport(DLLFile::Symbol *s) {
size_t impSize = s->dllName.size() + s->symbolName.size() + 2; // +2 for NULs
size_t size = sizeof(coff_import_header) + impSize;
- char *buf = bAlloc.Allocate<char>(size);
+ char *buf = bAlloc().Allocate<char>(size);
memset(buf, 0, size);
char *p = buf;
auto *imp = reinterpret_cast<coff_import_header *>(p);
diff --git a/lld/COFF/LTO.cpp b/lld/COFF/LTO.cpp
index f117b62192c84..2dbe7b146402e 100644
--- a/lld/COFF/LTO.cpp
+++ b/lld/COFF/LTO.cpp
@@ -11,7 +11,7 @@
#include "InputFiles.h"
#include "Symbols.h"
#include "lld/Common/Args.h"
-#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/Strings.h"
#include "lld/Common/TargetOptionsCommandFlags.h"
#include "llvm/ADT/STLExtras.h"
@@ -209,8 +209,8 @@ std::vector<InputFile *> BitcodeCompiler::compile(COFFLinkerContext &ctx) {
// - foo.exe.lto.1.obj
// - ...
StringRef ltoObjName =
- saver.save(Twine(config->outputFile) + ".lto" +
- (i == 0 ? Twine("") : Twine('.') + Twine(i)) + ".obj");
+ saver().save(Twine(config->outputFile) + ".lto" +
+ (i == 0 ? Twine("") : Twine('.') + Twine(i)) + ".obj");
// Get the native object contents either from the cache or from memory. Do
// not use the cached MemoryBuffer directly, or the PDB will not be
diff --git a/lld/COFF/MinGW.cpp b/lld/COFF/MinGW.cpp
index 148ebe5eea66d..7a3a3853572f3 100644
--- a/lld/COFF/MinGW.cpp
+++ b/lld/COFF/MinGW.cpp
@@ -11,7 +11,6 @@
#include "Driver.h"
#include "InputFiles.h"
#include "SymbolTable.h"
-#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/Object/COFF.h"
@@ -184,8 +183,8 @@ void lld::coff::writeDefFile(StringRef name) {
static StringRef mangle(Twine sym) {
assert(config->machine != IMAGE_FILE_MACHINE_UNKNOWN);
if (config->machine == I386)
- return saver.save("_" + sym);
- return saver.save(sym);
+ return saver().save("_" + sym);
+ return saver().save(sym);
}
// Handles -wrap option.
@@ -249,7 +248,7 @@ void lld::coff::wrapSymbols(COFFLinkerContext &ctx,
// referenced it or not, though.)
if (imp) {
DefinedLocalImport *wrapimp = make<DefinedLocalImport>(
- saver.save("__imp_" + w.wrap->getName()), d);
+ saver().save("__imp_" + w.wrap->getName()), d);
ctx.symtab.localImportChunks.push_back(wrapimp->getChunk());
map[imp] = wrapimp;
}
diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp
index a4cef1d0df3b2..dea84eca5b121 100644
--- a/lld/COFF/PDB.cpp
+++ b/lld/COFF/PDB.cpp
@@ -16,7 +16,6 @@
#include "Symbols.h"
#include "TypeMerger.h"
#include "Writer.h"
-#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Timer.h"
#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
@@ -75,7 +74,7 @@ class PDBLinker {
public:
PDBLinker(COFFLinkerContext &ctx)
- : builder(bAlloc), tMerger(ctx, bAlloc), ctx(ctx) {
+ : builder(bAlloc()), tMerger(ctx, bAlloc()), ctx(ctx) {
// This isn't strictly necessary, but link.exe usually puts an empty string
// as the first "valid" string in the string table, so we do the same in
// order to maintain as much byte-for-byte compatibility as possible.
@@ -501,7 +500,7 @@ static void addGlobalSymbol(pdb::GSIStreamBuilder &builder, uint16_t modIndex,
case SymbolKind::S_LPROCREF: {
// sym is a temporary object, so we have to copy and reallocate the record
// to stabilize it.
- uint8_t *mem = bAlloc.Allocate<uint8_t>(sym.length());
+ uint8_t *mem = bAlloc().Allocate<uint8_t>(sym.length());
memcpy(mem, sym.data().data(), sym.length());
builder.addGlobalSymbol(CVSymbol(makeArrayRef(mem, sym.length())));
break;
@@ -1003,7 +1002,7 @@ static void warnUnusable(InputFile *f, Error e) {
// Allocate memory for a .debug$S / .debug$F section and relocate it.
static ArrayRef<uint8_t> relocateDebugChunk(SectionChunk &debugChunk) {
- uint8_t *buffer = bAlloc.Allocate<uint8_t>(debugChunk.getSize());
+ uint8_t *buffer = bAlloc().Allocate<uint8_t>(debugChunk.getSize());
assert(debugChunk.getOutputSectionIdx() == 0 &&
"debug sections should not be in output sections");
debugChunk.writeTo(buffer);
@@ -1417,6 +1416,7 @@ static void addCommonLinkerModuleSymbols(StringRef path,
ebs.Fields.push_back(path);
ebs.Fields.push_back("cmd");
ebs.Fields.push_back(argStr);
+ llvm::BumpPtrAllocator &bAlloc = lld::bAlloc();
mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
ons, bAlloc, CodeViewContainer::Pdb));
mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
@@ -1448,7 +1448,7 @@ static void addLinkerModuleCoffGroup(PartialSection *sec,
cgs.Characteristics |= llvm::COFF::IMAGE_SCN_MEM_WRITE;
mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
- cgs, bAlloc, CodeViewContainer::Pdb));
+ cgs, bAlloc(), CodeViewContainer::Pdb));
}
static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &mod,
@@ -1461,7 +1461,7 @@ static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &mod,
sym.Rva = os.getRVA();
sym.SectionNumber = os.sectionIndex;
mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
- sym, bAlloc, CodeViewContainer::Pdb));
+ sym, bAlloc(), CodeViewContainer::Pdb));
// Skip COFF groups in MinGW because it adds a significant footprint to the
// PDB, due to each function being in its own section
@@ -1536,6 +1536,7 @@ void PDBLinker::addImportFilesToPDB() {
ts.Segment = thunkOS->sectionIndex;
ts.Offset = thunkChunk->getRVA() - thunkOS->getRVA();
+ llvm::BumpPtrAllocator &bAlloc = lld::bAlloc();
mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol(
ons, bAlloc, CodeViewContainer::Pdb));
mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol(
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 9ceac7af7f914..db2db9c9272eb 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -134,7 +134,7 @@ getFileLineDwarf(const SectionChunk *c, uint32_t addr) {
const DILineInfo &lineInfo = *optionalLineInfo;
if (lineInfo.FileName == DILineInfo::BadString)
return None;
- return std::make_pair(saver.save(lineInfo.FileName), lineInfo.Line);
+ return std::make_pair(saver().save(lineInfo.FileName), lineInfo.Line);
}
static Optional<std::pair<StringRef, uint32_t>>
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 4a41c541ee7f9..12db942f1db55 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -485,7 +485,7 @@ static bool createThunks(OutputSection *os, int margin) {
MutableArrayRef<coff_relocation> newRelocs;
if (originalRelocs.data() == curRelocs.data()) {
newRelocs = makeMutableArrayRef(
- bAlloc.Allocate<coff_relocation>(originalRelocs.size()),
+ bAlloc().Allocate<coff_relocation>(originalRelocs.size()),
originalRelocs.size());
} else {
newRelocs = makeMutableArrayRef(
diff --git a/lld/Common/CMakeLists.txt b/lld/Common/CMakeLists.txt
index 9fdc67be79012..1ae7da1f5f7f0 100644
--- a/lld/Common/CMakeLists.txt
+++ b/lld/Common/CMakeLists.txt
@@ -28,6 +28,7 @@ set_source_files_properties("${version_inc}"
add_lld_library(lldCommon
Args.cpp
+ CommonLinkerContext.cpp
DWARF.cpp
ErrorHandler.cpp
Filesystem.cpp
diff --git a/lld/Common/CommonLinkerContext.cpp b/lld/Common/CommonLinkerContext.cpp
new file mode 100644
index 0000000000000..75a58e84e03a8
--- /dev/null
+++ b/lld/Common/CommonLinkerContext.cpp
@@ -0,0 +1,41 @@
+//===- CommonLinkerContext.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
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Memory.h"
+
+using namespace llvm;
+using namespace lld;
+
+// Reference to the current LLD instance.
+static CommonLinkerContext *lctx;
+
+CommonLinkerContext::CommonLinkerContext() { lctx = this; }
+
+CommonLinkerContext::~CommonLinkerContext() {
+ assert(lctx);
+ // Explicitly call the destructors since we created the objects with placement
+ // new in SpecificAlloc::create().
+ for (auto &it : instances)
+ it.second->~SpecificAllocBase();
+ lctx = nullptr;
+}
+
+CommonLinkerContext &lld::commonContext() {
+ assert(lctx);
+ return *lctx;
+}
+
+bool lld::hasContext() { return lctx != nullptr; }
+
+void CommonLinkerContext::destroy() {
+ if (lctx == nullptr)
+ return;
+ delete lctx;
+}
diff --git a/lld/Common/ErrorHandler.cpp b/lld/Common/ErrorHandler.cpp
index 399b6cac75470..15b3bd058ee9b 100644
--- a/lld/Common/ErrorHandler.cpp
+++ b/lld/Common/ErrorHandler.cpp
@@ -10,6 +10,7 @@
#include "llvm/Support/Parallel.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
@@ -18,51 +19,69 @@
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
-#include <mutex>
#include <regex>
using namespace llvm;
using namespace lld;
-// The functions defined in this file can be called from multiple threads,
-// but lld::outs() or lld::errs() are not thread-safe. We protect them using a
-// mutex.
-static std::mutex mu;
-
-// We want to separate multi-line messages with a newline. `sep` is "\n"
-// if the last messages was multi-line. Otherwise "".
-static StringRef sep;
-
static StringRef getSeparator(const Twine &msg) {
if (StringRef(msg.str()).contains('\n'))
return "\n";
return "";
}
-raw_ostream *lld::stdoutOS;
-raw_ostream *lld::stderrOS;
+ErrorHandler::~ErrorHandler() {
+ if (cleanupCallback)
+ cleanupCallback();
+}
+
+void ErrorHandler::initialize(llvm::raw_ostream &stdoutOS,
+ llvm::raw_ostream &stderrOS, bool exitEarly,
+ bool disableOutput) {
+ this->stdoutOS = &stdoutOS;
+ this->stderrOS = &stderrOS;
+ stderrOS.enable_colors(stderrOS.has_colors());
+ this->exitEarly = exitEarly;
+ this->disableOutput = disableOutput;
+}
-ErrorHandler &lld::errorHandler() {
- static ErrorHandler handler;
- return handler;
+void ErrorHandler::flushStreams() {
+ std::lock_guard<std::mutex> lock(mu);
+ outs().flush();
+ errs().flush();
}
+ErrorHandler &lld::errorHandler() { return context().e; }
+
raw_ostream &lld::outs() {
- if (errorHandler().disableOutput)
+ ErrorHandler &e = errorHandler();
+ return e.outs();
+}
+
+raw_ostream &lld::errs() {
+ ErrorHandler &e = errorHandler();
+ return e.errs();
+}
+
+raw_ostream &ErrorHandler::outs() {
+ if (disableOutput)
return llvm::nulls();
return stdoutOS ? *stdoutOS : llvm::outs();
}
-raw_ostream &lld::errs() {
- if (errorHandler().disableOutput)
+raw_ostream &ErrorHandler::errs() {
+ if (disableOutput)
return llvm::nulls();
return stderrOS ? *stderrOS : llvm::errs();
}
void lld::exitLld(int val) {
- // Delete any temporary file, while keeping the memory mapping open.
- if (errorHandler().outputBuffer)
- errorHandler().outputBuffer->discard();
+ if (hasContext()) {
+ ErrorHandler &e = errorHandler();
+ // Delete any temporary file, while keeping the memory mapping open.
+ if (e.outputBuffer)
+ e.outputBuffer->discard();
+ }
// Re-throw a possible signal or exception once/if it was catched by
// safeLldMain().
@@ -75,11 +94,9 @@ void lld::exitLld(int val) {
if (!CrashRecoveryContext::GetCurrent())
llvm_shutdown();
- {
- std::lock_guard<std::mutex> lock(mu);
- lld::outs().flush();
- lld::errs().flush();
- }
+ if (hasContext())
+ lld::errorHandler().flushStreams();
+
// When running inside safeLldMain(), restore the control flow back to the
// CrashRecoveryContext. Otherwise simply use _exit(), meanning no cleanup,
// since we want to avoid further crashes on shutdown.
diff --git a/lld/Common/Memory.cpp b/lld/Common/Memory.cpp
index c53e1d3e6cfc7..7c90ff1d799c8 100644
--- a/lld/Common/Memory.cpp
+++ b/lld/Common/Memory.cpp
@@ -7,16 +7,19 @@
//===----------------------------------------------------------------------===//
#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
using namespace llvm;
using namespace lld;
-BumpPtrAllocator lld::bAlloc;
-StringSaver lld::saver{bAlloc};
-std::vector<SpecificAllocBase *> lld::SpecificAllocBase::instances;
-
-void lld::freeArena() {
- for (SpecificAllocBase *alloc : SpecificAllocBase::instances)
- alloc->reset();
- bAlloc.Reset();
+SpecificAllocBase *
+lld::SpecificAllocBase::getOrCreate(void *tag, size_t size, size_t align,
+ SpecificAllocBase *(&creator)(void *)) {
+ auto &instances = context().instances;
+ auto &instance = instances[tag];
+ if (instance == nullptr) {
+ void *storage = context().bAlloc.Allocate(size, align);
+ instance = creator(storage);
+ }
+ return instance;
}
diff --git a/lld/Common/TargetOptionsCommandFlags.cpp b/lld/Common/TargetOptionsCommandFlags.cpp
index d39477ed89adc..b7749c4a20325 100644
--- a/lld/Common/TargetOptionsCommandFlags.cpp
+++ b/lld/Common/TargetOptionsCommandFlags.cpp
@@ -7,12 +7,9 @@
//===----------------------------------------------------------------------===//
#include "lld/Common/TargetOptionsCommandFlags.h"
-
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/Target/TargetOptions.h"
-static llvm::codegen::RegisterCodeGenFlags CGF;
-
llvm::TargetOptions lld::initTargetOptionsFromCodeGenFlags() {
return llvm::codegen::InitTargetOptionsFromCodeGenFlags(llvm::Triple());
}
diff --git a/lld/ELF/AArch64ErrataFix.cpp b/lld/ELF/AArch64ErrataFix.cpp
index a1e276ea9c77e..d45edf9bd8ff4 100644
--- a/lld/ELF/AArch64ErrataFix.cpp
+++ b/lld/ELF/AArch64ErrataFix.cpp
@@ -33,7 +33,7 @@
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/Strings.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/raw_ostream.h"
@@ -398,9 +398,9 @@ Patch843419Section::Patch843419Section(InputSection *p, uint64_t off)
patchee(p), patcheeOffset(off) {
this->parent = p->getParent();
patchSym = addSyntheticLocal(
- saver.save("__CortexA53843419_" + utohexstr(getLDSTAddr())), STT_FUNC, 0,
- getSize(), *this);
- addSyntheticLocal(saver.save("$x"), STT_NOTYPE, 0, 0, *this);
+ saver().save("__CortexA53843419_" + utohexstr(getLDSTAddr())), STT_FUNC,
+ 0, getSize(), *this);
+ addSyntheticLocal(saver().save("$x"), STT_NOTYPE, 0, 0, *this);
}
uint64_t Patch843419Section::getLDSTAddr() const {
diff --git a/lld/ELF/ARMErrataFix.cpp b/lld/ELF/ARMErrataFix.cpp
index cfaa3109afe88..25b47b90cef81 100644
--- a/lld/ELF/ARMErrataFix.cpp
+++ b/lld/ELF/ARMErrataFix.cpp
@@ -22,7 +22,7 @@
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/Strings.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/raw_ostream.h"
@@ -142,9 +142,9 @@ Patch657417Section::Patch657417Section(InputSection *p, uint64_t off,
patchee(p), patcheeOffset(off), instr(instr), isARM(isARM) {
parent = p->getParent();
patchSym = addSyntheticLocal(
- saver.save("__CortexA8657417_" + utohexstr(getBranchAddr())), STT_FUNC,
+ saver().save("__CortexA8657417_" + utohexstr(getBranchAddr())), STT_FUNC,
isARM ? 0 : 1, getSize(), *this);
- addSyntheticLocal(saver.save(isARM ? "$a" : "$t"), STT_NOTYPE, 0, 0, *this);
+ addSyntheticLocal(saver().save(isARM ? "$a" : "$t"), STT_NOTYPE, 0, 0, *this);
}
uint64_t Patch657417Section::getBranchAddr() const {
diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp
index 69a9118ca30ea..d9e4fc97ea0be 100644
--- a/lld/ELF/Arch/PPC64.cpp
+++ b/lld/ELF/Arch/PPC64.cpp
@@ -11,8 +11,7 @@
#include "SyntheticSections.h"
#include "Target.h"
#include "Thunks.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "llvm/Support/Endian.h"
using namespace llvm;
@@ -197,7 +196,7 @@ static bool addOptional(StringRef name, uint64_t value,
Symbol *sym = symtab->find(name);
if (!sym || sym->isDefined())
return false;
- sym->resolve(Defined{/*file=*/nullptr, saver.save(name), STB_GLOBAL,
+ sym->resolve(Defined{/*file=*/nullptr, saver().save(name), STB_GLOBAL,
STV_HIDDEN, STT_FUNC, value,
/*size=*/0, /*section=*/nullptr});
defined.push_back(cast<Defined>(sym));
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 5e7b74e2e4c55..13ee90dd4f267 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -77,14 +77,13 @@ std::unique_ptr<LinkerDriver> elf::driver;
static void setConfigs(opt::InputArgList &args);
static void readConfigs(opt::InputArgList &args);
-bool elf::link(ArrayRef<const char *> args, bool canExitEarly,
- raw_ostream &stdoutOS, raw_ostream &stderrOS) {
- lld::stdoutOS = &stdoutOS;
- lld::stderrOS = &stderrOS;
-
- errorHandler().cleanupCallback = []() {
- freeArena();
+bool elf::link(ArrayRef<const char *> args, raw_ostream &stdoutOS,
+ raw_ostream &stderrOS, bool exitEarly, bool disableOutput) {
+ // This driver-specific context will be freed later by lldMain().
+ auto *ctx = new CommonLinkerContext;
+ ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
+ ctx->e.cleanupCallback = []() {
inputSections.clear();
outputSections.clear();
memoryBuffers.clear();
@@ -106,13 +105,9 @@ bool elf::link(ArrayRef<const char *> args, bool canExitEarly,
SharedFile::vernauxNum = 0;
};
-
- errorHandler().logName = args::getFilenameWithoutExe(args[0]);
- errorHandler().errorLimitExceededMsg =
- "too many errors emitted, stopping now (use "
- "-error-limit=0 to see all errors)";
- errorHandler().exitEarly = canExitEarly;
- stderrOS.enable_colors(stderrOS.has_colors());
+ ctx->e.logName = args::getFilenameWithoutExe(args[0]);
+ ctx->e.errorLimitExceededMsg = "too many errors emitted, stopping now (use "
+ "-error-limit=0 to see all errors)";
config = std::make_unique<Configuration>();
driver = std::make_unique<LinkerDriver>();
@@ -126,15 +121,7 @@ bool elf::link(ArrayRef<const char *> args, bool canExitEarly,
driver->linkerMain(args);
- // Exit immediately if we don't need to return to the caller.
- // This saves time because the overhead of calling destructors
- // for all globally-allocated objects is not negligible.
- int hasError = errorCount() ? 1 : 0;
- if (canExitEarly)
- exitLld(hasError);
- else
- errorHandler().reset();
- return !hasError;
+ return errorCount() == 0;
}
// Parses a linker -m option.
@@ -1259,7 +1246,7 @@ static void readConfigs(opt::InputArgList &args) {
// Parse LTO options.
if (auto *arg = args.getLastArg(OPT_plugin_opt_mcpu_eq))
- parseClangOption(saver.save("-mcpu=" + StringRef(arg->getValue())),
+ parseClangOption(saver().save("-mcpu=" + StringRef(arg->getValue())),
arg->getSpelling());
for (opt::Arg *arg : args.filtered(OPT_plugin_opt_eq_minus))
@@ -2072,9 +2059,9 @@ static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {
if (!sym)
continue;
- Symbol *real = addUnusedUndefined(saver.save("__real_" + name));
+ Symbol *real = addUnusedUndefined(saver().save("__real_" + name));
Symbol *wrap =
- addUnusedUndefined(saver.save("__wrap_" + name), sym->binding);
+ addUnusedUndefined(saver().save("__wrap_" + name), sym->binding);
v.push_back({sym, real, wrap});
// We want to tell LTO not to inline symbols to be overwritten
diff --git a/lld/ELF/DriverUtils.cpp b/lld/ELF/DriverUtils.cpp
index 54d2d0ae6fb9f..ac29b47abcc96 100644
--- a/lld/ELF/DriverUtils.cpp
+++ b/lld/ELF/DriverUtils.cpp
@@ -13,8 +13,7 @@
//===----------------------------------------------------------------------===//
#include "Driver.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/Reproduce.h"
#include "lld/Common/Version.h"
#include "llvm/ADT/Optional.h"
@@ -102,7 +101,7 @@ static void concatLTOPluginOptions(SmallVectorImpl<const char *> &args) {
for (size_t i = 0, e = args.size(); i != e; ++i) {
StringRef s = args[i];
if ((s == "-plugin-opt" || s == "--plugin-opt") && i + 1 != e) {
- v.push_back(saver.save(s + "=" + args[i + 1]).data());
+ v.push_back(saver().save(s + "=" + args[i + 1]).data());
++i;
} else {
v.push_back(args[i]);
@@ -125,7 +124,7 @@ opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> argv) {
// Expand response files (arguments in the form of @<filename>)
// and then parse the argument again.
- cl::ExpandResponseFiles(saver, getQuotingStyle(args), vec);
+ cl::ExpandResponseFiles(saver(), getQuotingStyle(args), vec);
concatLTOPluginOptions(vec);
args = this->ParseArgs(vec, missingIndex, missingCount);
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 04fa48f63c030..5cd32453e318d 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -13,9 +13,8 @@
#include "SymbolTable.h"
#include "Symbols.h"
#include "SyntheticSections.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/DWARF.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/Analysis.h"
#include "llvm/IR/LLVMContext.h"
@@ -111,7 +110,7 @@ Optional<MemoryBufferRef> elf::readFile(StringRef path) {
// The --chroot option changes our virtual root directory.
// This is useful when you are dealing with files created by --reproduce.
if (!config->chroot.empty() && path.startswith("/"))
- path = saver.save(config->chroot + path);
+ path = saver().save(config->chroot + path);
log(path);
config->dependencyFiles.insert(llvm::CachedHashString(path));
@@ -1526,8 +1525,8 @@ template <class ELFT> void SharedFile::parse() {
}
StringRef verName = stringTable.data() + verneeds[idx];
versionedNameBuffer.clear();
- name =
- saver.save((name + "@" + verName).toStringRef(versionedNameBuffer));
+ name = saver().save(
+ (name + "@" + verName).toStringRef(versionedNameBuffer));
}
Symbol *s = symtab.addSymbol(
Undefined{this, name, sym.getBinding(), sym.st_other, sym.getType()});
@@ -1569,7 +1568,7 @@ template <class ELFT> void SharedFile::parse() {
reinterpret_cast<const Elf_Verdef *>(verdefs[idx])->getAux()->vda_name;
versionedNameBuffer.clear();
name = (name + "@" + verName).toStringRef(versionedNameBuffer);
- symtab.addSymbol(SharedSymbol{*this, saver.save(name), sym.getBinding(),
+ symtab.addSymbol(SharedSymbol{*this, saver().save(name), sym.getBinding(),
sym.st_other, sym.getType(), sym.st_value,
sym.st_size, alignment, idx});
}
@@ -1652,11 +1651,10 @@ BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
// into consideration at LTO time (which very likely causes undefined
// symbols later in the link stage). So we append file offset to make
// filename unique.
- StringRef name =
- archiveName.empty()
- ? saver.save(path)
- : saver.save(archiveName + "(" + path::filename(path) + " at " +
- utostr(offsetInArchive) + ")");
+ StringRef name = archiveName.empty()
+ ? saver().save(path)
+ : saver().save(archiveName + "(" + path::filename(path) +
+ " at " + utostr(offsetInArchive) + ")");
MemoryBufferRef mbref(mb.getBuffer(), name);
obj = CHECK(lto::InputFile::create(mbref), this);
@@ -1692,7 +1690,7 @@ createBitcodeSymbol(Symbol *&sym, const std::vector<bool> &keptComdats,
if (sym) {
name = sym->getName();
} else {
- name = saver.save(objSym.getName());
+ name = saver().save(objSym.getName());
sym = symtab->insert(name);
}
@@ -1742,8 +1740,8 @@ void BitcodeFile::parseLazy() {
symbols.resize(obj->symbols().size());
for (auto it : llvm::enumerate(obj->symbols()))
if (!it.value().isUndefined())
- symbols[it.index()] =
- symtab.addSymbol(LazyObject{*this, saver.save(it.value().getName())});
+ symbols[it.index()] = symtab.addSymbol(
+ LazyObject{*this, saver().save(it.value().getName())});
}
void BinaryFile::parse() {
@@ -1761,6 +1759,8 @@ void BinaryFile::parse() {
if (!isAlnum(s[i]))
s[i] = '_';
+ llvm::StringSaver &saver = lld::saver();
+
symtab->addSymbol(Defined{nullptr, saver.save(s + "_start"), STB_GLOBAL,
STV_DEFAULT, STT_OBJECT, 0, 0, section});
symtab->addSymbol(Defined{nullptr, saver.save(s + "_end"), STB_GLOBAL,
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index feeb29057772d..8a47cf4d07064 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -18,8 +18,7 @@
#include "SyntheticSections.h"
#include "Target.h"
#include "Thunks.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
@@ -143,7 +142,7 @@ void InputSectionBase::uncompress() const {
{
static std::mutex mu;
std::lock_guard<std::mutex> lock(mu);
- uncompressedBuf = bAlloc.Allocate<char>(size);
+ uncompressedBuf = bAlloc().Allocate<char>(size);
}
if (Error e = zlib::uncompress(toStringRef(rawData), uncompressedBuf, size))
@@ -236,7 +235,7 @@ template <typename ELFT> void InputSectionBase::parseCompressedHeader() {
// Restore the original section name.
// (e.g. ".zdebug_info" -> ".debug_info")
- name = saver.save("." + name.substr(2));
+ name = saver().save("." + name.substr(2));
return;
}
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index fa41f4d5c50e3..a5f11ae0b1818 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -19,7 +19,7 @@
#include "SyntheticSections.h"
#include "Target.h"
#include "Writer.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/Strings.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
@@ -64,8 +64,8 @@ static StringRef getOutputSectionName(const InputSectionBase *s) {
if (InputSectionBase *rel = isec->getRelocatedSection()) {
OutputSection *out = rel->getOutputSection();
if (s->type == SHT_RELA)
- return saver.save(".rela" + out->name);
- return saver.save(".rel" + out->name);
+ return saver().save(".rela" + out->name);
+ return saver().save(".rel" + out->name);
}
}
diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp
index 4d3d79d4ee80b..597c0684b8b2b 100644
--- a/lld/ELF/MarkLive.cpp
+++ b/lld/ELF/MarkLive.cpp
@@ -27,7 +27,7 @@
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/Strings.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/ELF.h"
@@ -308,8 +308,8 @@ template <class ELFT> void MarkLive<ELFT>::run() {
// As a workaround for glibc libc.a before 2.34
// (https://sourceware.org/PR27492), retain __libc_atexit and similar
// sections regardless of zStartStopGC.
- cNamedSections[saver.save("__start_" + sec->name)].push_back(sec);
- cNamedSections[saver.save("__stop_" + sec->name)].push_back(sec);
+ cNamedSections[saver().save("__start_" + sec->name)].push_back(sec);
+ cNamedSections[saver().save("__stop_" + sec->name)].push_back(sec);
}
}
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index f26b6c41adf20..7331d1156f278 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -20,7 +20,7 @@
#include "ScriptLexer.h"
#include "Symbols.h"
#include "Target.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
@@ -290,7 +290,7 @@ void ScriptParser::addFile(StringRef s) {
SmallString<128> pathData;
StringRef path = (config->sysroot + s).toStringRef(pathData);
if (sys::fs::exists(path))
- driver->addFile(saver.save(path), /*withLOption=*/false);
+ driver->addFile(saver().save(path), /*withLOption=*/false);
else
setError("cannot find " + s + " inside " + config->sysroot);
return;
@@ -304,7 +304,7 @@ void ScriptParser::addFile(StringRef s) {
if (config->sysroot.empty())
driver->addFile(s.substr(1), /*withLOption=*/false);
else
- driver->addFile(saver.save(config->sysroot + "/" + s.substr(1)),
+ driver->addFile(saver().save(config->sysroot + "/" + s.substr(1)),
/*withLOption=*/false);
} else if (s.startswith("-l")) {
// Case 3: search in the list of library paths.
@@ -327,7 +327,7 @@ void ScriptParser::addFile(StringRef s) {
} else {
// Finally, search in the list of library paths.
if (Optional<std::string> path = findFromSearchPaths(s))
- driver->addFile(saver.save(*path), /*withLOption=*/true);
+ driver->addFile(saver().save(*path), /*withLOption=*/true);
else
setError("unable to find " + s);
}
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index aef6434dca799..6ac1fc3e39705 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -22,9 +22,8 @@
#include "Symbols.h"
#include "Target.h"
#include "Writer.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/DWARF.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
#include "lld/Common/Strings.h"
#include "lld/Common/Version.h"
#include "llvm/ADT/SetOperations.h"
@@ -73,7 +72,7 @@ static ArrayRef<uint8_t> getVersion() {
// This is only for testing.
StringRef s = getenv("LLD_VERSION");
if (s.empty())
- s = saver.save(Twine("Linker: ") + getLLDVersion());
+ s = saver().save(Twine("Linker: ") + getLLDVersion());
// +1 to include the terminating '\0'.
return {(const uint8_t *)s.data(), s.size() + 1};
@@ -255,7 +254,7 @@ MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() {
InputSection *elf::createInterpSection() {
// StringSaver guarantees that the returned string ends with '\0'.
- StringRef s = saver.save(config->dynamicLinker);
+ StringRef s = saver().save(config->dynamicLinker);
ArrayRef<uint8_t> contents = {(const uint8_t *)s.data(), s.size() + 1};
return make<InputSection>(nullptr, SHF_ALLOC, SHT_PROGBITS, 1, contents,
diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index 38de4db191f45..ae740810acb57 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -27,8 +27,7 @@
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Endian.h"
@@ -434,7 +433,7 @@ void AArch64ABSLongThunk::writeTo(uint8_t *buf) {
}
void AArch64ABSLongThunk::addSymbols(ThunkSection &isec) {
- addSymbol(saver.save("__AArch64AbsLongThunk_" + destination.getName()),
+ addSymbol(saver().save("__AArch64AbsLongThunk_" + destination.getName()),
STT_FUNC, 0, isec);
addSymbol("$x", STT_NOTYPE, 0, isec);
addSymbol("$d", STT_NOTYPE, 8, isec);
@@ -460,8 +459,8 @@ void AArch64ADRPThunk::writeTo(uint8_t *buf) {
}
void AArch64ADRPThunk::addSymbols(ThunkSection &isec) {
- addSymbol(saver.save("__AArch64ADRPThunk_" + destination.getName()), STT_FUNC,
- 0, isec);
+ addSymbol(saver().save("__AArch64ADRPThunk_" + destination.getName()),
+ STT_FUNC, 0, isec);
addSymbol("$x", STT_NOTYPE, 0, isec);
}
@@ -560,7 +559,7 @@ void ARMV7ABSLongThunk::writeLong(uint8_t *buf) {
}
void ARMV7ABSLongThunk::addSymbols(ThunkSection &isec) {
- addSymbol(saver.save("__ARMv7ABSLongThunk_" + destination.getName()),
+ addSymbol(saver().save("__ARMv7ABSLongThunk_" + destination.getName()),
STT_FUNC, 0, isec);
addSymbol("$a", STT_NOTYPE, 0, isec);
}
@@ -578,7 +577,7 @@ void ThumbV7ABSLongThunk::writeLong(uint8_t *buf) {
}
void ThumbV7ABSLongThunk::addSymbols(ThunkSection &isec) {
- addSymbol(saver.save("__Thumbv7ABSLongThunk_" + destination.getName()),
+ addSymbol(saver().save("__Thumbv7ABSLongThunk_" + destination.getName()),
STT_FUNC, 1, isec);
addSymbol("$t", STT_NOTYPE, 0, isec);
}
@@ -599,8 +598,8 @@ void ARMV7PILongThunk::writeLong(uint8_t *buf) {
}
void ARMV7PILongThunk::addSymbols(ThunkSection &isec) {
- addSymbol(saver.save("__ARMV7PILongThunk_" + destination.getName()), STT_FUNC,
- 0, isec);
+ addSymbol(saver().save("__ARMV7PILongThunk_" + destination.getName()),
+ STT_FUNC, 0, isec);
addSymbol("$a", STT_NOTYPE, 0, isec);
}
@@ -620,7 +619,7 @@ void ThumbV7PILongThunk::writeLong(uint8_t *buf) {
}
void ThumbV7PILongThunk::addSymbols(ThunkSection &isec) {
- addSymbol(saver.save("__ThumbV7PILongThunk_" + destination.getName()),
+ addSymbol(saver().save("__ThumbV7PILongThunk_" + destination.getName()),
STT_FUNC, 1, isec);
addSymbol("$t", STT_NOTYPE, 0, isec);
}
@@ -635,7 +634,7 @@ void ARMV5ABSLongThunk::writeLong(uint8_t *buf) {
}
void ARMV5ABSLongThunk::addSymbols(ThunkSection &isec) {
- addSymbol(saver.save("__ARMv5ABSLongThunk_" + destination.getName()),
+ addSymbol(saver().save("__ARMv5ABSLongThunk_" + destination.getName()),
STT_FUNC, 0, isec);
addSymbol("$a", STT_NOTYPE, 0, isec);
addSymbol("$d", STT_NOTYPE, 4, isec);
@@ -661,8 +660,8 @@ void ARMV5PILongThunk::writeLong(uint8_t *buf) {
}
void ARMV5PILongThunk::addSymbols(ThunkSection &isec) {
- addSymbol(saver.save("__ARMV5PILongThunk_" + destination.getName()), STT_FUNC,
- 0, isec);
+ addSymbol(saver().save("__ARMV5PILongThunk_" + destination.getName()),
+ STT_FUNC, 0, isec);
addSymbol("$a", STT_NOTYPE, 0, isec);
addSymbol("$d", STT_NOTYPE, 12, isec);
}
@@ -691,7 +690,7 @@ void ThumbV6MABSLongThunk::writeLong(uint8_t *buf) {
}
void ThumbV6MABSLongThunk::addSymbols(ThunkSection &isec) {
- addSymbol(saver.save("__Thumbv6MABSLongThunk_" + destination.getName()),
+ addSymbol(saver().save("__Thumbv6MABSLongThunk_" + destination.getName()),
STT_FUNC, 1, isec);
addSymbol("$t", STT_NOTYPE, 0, isec);
addSymbol("$d", STT_NOTYPE, 8, isec);
@@ -717,7 +716,7 @@ void ThumbV6MPILongThunk::writeLong(uint8_t *buf) {
}
void ThumbV6MPILongThunk::addSymbols(ThunkSection &isec) {
- addSymbol(saver.save("__Thumbv6MPILongThunk_" + destination.getName()),
+ addSymbol(saver().save("__Thumbv6MPILongThunk_" + destination.getName()),
STT_FUNC, 1, isec);
addSymbol("$t", STT_NOTYPE, 0, isec);
addSymbol("$d", STT_NOTYPE, 12, isec);
@@ -735,7 +734,7 @@ void MipsThunk::writeTo(uint8_t *buf) {
}
void MipsThunk::addSymbols(ThunkSection &isec) {
- addSymbol(saver.save("__LA25Thunk_" + destination.getName()), STT_FUNC, 0,
+ addSymbol(saver().save("__LA25Thunk_" + destination.getName()), STT_FUNC, 0,
isec);
}
@@ -758,8 +757,9 @@ void MicroMipsThunk::writeTo(uint8_t *buf) {
}
void MicroMipsThunk::addSymbols(ThunkSection &isec) {
- Defined *d = addSymbol(
- saver.save("__microLA25Thunk_" + destination.getName()), STT_FUNC, 0, isec);
+ Defined *d =
+ addSymbol(saver().save("__microLA25Thunk_" + destination.getName()),
+ STT_FUNC, 0, isec);
d->stOther |= STO_MIPS_MICROMIPS;
}
@@ -782,8 +782,9 @@ void MicroMipsR6Thunk::writeTo(uint8_t *buf) {
}
void MicroMipsR6Thunk::addSymbols(ThunkSection &isec) {
- Defined *d = addSymbol(
- saver.save("__microLA25Thunk_" + destination.getName()), STT_FUNC, 0, isec);
+ Defined *d =
+ addSymbol(saver().save("__microLA25Thunk_" + destination.getName()),
+ STT_FUNC, 0, isec);
d->stOther |= STO_MIPS_MICROMIPS;
}
@@ -843,7 +844,7 @@ void PPC32PltCallStub::addSymbols(ThunkSection &isec) {
else
os << ".plt_pic32.";
os << destination.getName();
- addSymbol(saver.save(os.str()), STT_FUNC, 0, isec);
+ addSymbol(saver().save(os.str()), STT_FUNC, 0, isec);
}
bool PPC32PltCallStub::isCompatibleWith(const InputSection &isec,
@@ -852,7 +853,7 @@ bool PPC32PltCallStub::isCompatibleWith(const InputSection &isec,
}
void PPC32LongThunk::addSymbols(ThunkSection &isec) {
- addSymbol(saver.save("__LongThunk_" + destination.getName()), STT_FUNC, 0,
+ addSymbol(saver().save("__LongThunk_" + destination.getName()), STT_FUNC, 0,
isec);
}
@@ -896,8 +897,8 @@ void PPC64PltCallStub::writeTo(uint8_t *buf) {
}
void PPC64PltCallStub::addSymbols(ThunkSection &isec) {
- Defined *s = addSymbol(saver.save("__plt_" + destination.getName()), STT_FUNC,
- 0, isec);
+ Defined *s = addSymbol(saver().save("__plt_" + destination.getName()),
+ STT_FUNC, 0, isec);
s->needsTocRestore = true;
s->file = destination.file;
}
@@ -947,7 +948,7 @@ void PPC64R2SaveStub::writeTo(uint8_t *buf) {
}
void PPC64R2SaveStub::addSymbols(ThunkSection &isec) {
- Defined *s = addSymbol(saver.save("__toc_save_" + destination.getName()),
+ Defined *s = addSymbol(saver().save("__toc_save_" + destination.getName()),
STT_FUNC, 0, isec);
s->needsTocRestore = true;
}
@@ -983,7 +984,7 @@ void PPC64R12SetupStub::writeTo(uint8_t *buf) {
}
void PPC64R12SetupStub::addSymbols(ThunkSection &isec) {
- addSymbol(saver.save("__gep_setup_" + destination.getName()), STT_FUNC, 0,
+ addSymbol(saver().save("__gep_setup_" + destination.getName()), STT_FUNC, 0,
isec);
}
@@ -1019,7 +1020,7 @@ void PPC64PCRelPLTStub::writeTo(uint8_t *buf) {
}
void PPC64PCRelPLTStub::addSymbols(ThunkSection &isec) {
- addSymbol(saver.save("__plt_pcrel_" + destination.getName()), STT_FUNC, 0,
+ addSymbol(saver().save("__plt_pcrel_" + destination.getName()), STT_FUNC, 0,
isec);
}
@@ -1035,7 +1036,7 @@ void PPC64LongBranchThunk::writeTo(uint8_t *buf) {
}
void PPC64LongBranchThunk::addSymbols(ThunkSection &isec) {
- addSymbol(saver.save("__long_branch_" + destination.getName()), STT_FUNC, 0,
+ addSymbol(saver().save("__long_branch_" + destination.getName()), STT_FUNC, 0,
isec);
}
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 742ea81fcb575..e5b211c329f21 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -20,8 +20,8 @@
#include "SyntheticSections.h"
#include "Target.h"
#include "lld/Common/Arrays.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/Filesystem.h"
-#include "lld/Common/Memory.h"
#include "lld/Common/Strings.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
@@ -2216,9 +2216,9 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *sec) {
StringRef s = sec->name;
if (!isValidCIdentifier(s))
return;
- addOptionalRegular(saver.save("__start_" + s), sec, 0,
+ addOptionalRegular(saver().save("__start_" + s), sec, 0,
config->zStartStopVisibility);
- addOptionalRegular(saver.save("__stop_" + s), sec, -1,
+ addOptionalRegular(saver().save("__stop_" + s), sec, -1,
config->zStartStopVisibility);
}
diff --git a/lld/MachO/ConcatOutputSection.cpp b/lld/MachO/ConcatOutputSection.cpp
index f63c2e6eb321c..4fae93469b5ff 100644
--- a/lld/MachO/ConcatOutputSection.cpp
+++ b/lld/MachO/ConcatOutputSection.cpp
@@ -13,8 +13,7 @@
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/TimeProfiler.h"
@@ -322,8 +321,8 @@ void ConcatOutputSection::finalize() {
// get written are happy.
thunkInfo.isec->live = true;
- StringRef thunkName = saver.save(funcSym->getName() + ".thunk." +
- std::to_string(thunkInfo.sequence++));
+ StringRef thunkName = saver().save(funcSym->getName() + ".thunk." +
+ std::to_string(thunkInfo.sequence++));
r.referent = thunkInfo.sym = symtab->addDefined(
thunkName, /*file=*/nullptr, thunkInfo.isec, /*value=*/0,
/*size=*/thunkSize, /*isWeakDef=*/false, /*isPrivateExtern=*/true,
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index f4b294888b070..0962683782320 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -128,7 +128,7 @@ static Optional<StringRef> findFramework(StringRef name) {
// only append suffix if realpath() succeeds
Twine suffixed = location + suffix;
if (fs::exists(suffixed))
- return resolvedFrameworks[key] = saver.save(suffixed.str());
+ return resolvedFrameworks[key] = saver().save(suffixed.str());
}
// Suffix lookup failed, fall through to the no-suffix case.
}
@@ -165,7 +165,7 @@ getSearchPaths(unsigned optionCode, InputArgList &args,
path::append(buffer, path);
// Do not warn about paths that are computed via the syslib roots
if (fs::is_directory(buffer)) {
- paths.push_back(saver.save(buffer.str()));
+ paths.push_back(saver().save(buffer.str()));
found = true;
}
}
@@ -183,7 +183,7 @@ getSearchPaths(unsigned optionCode, InputArgList &args,
SmallString<261> buffer(root);
path::append(buffer, path);
if (fs::is_directory(buffer))
- paths.push_back(saver.save(buffer.str()));
+ paths.push_back(saver().save(buffer.str()));
}
}
return paths;
@@ -1102,14 +1102,13 @@ static void referenceStubBinder() {
symtab->addUndefined("dyld_stub_binder", /*file=*/nullptr, /*isWeak=*/false);
}
-bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
- raw_ostream &stdoutOS, raw_ostream &stderrOS) {
- lld::stdoutOS = &stdoutOS;
- lld::stderrOS = &stderrOS;
-
- errorHandler().cleanupCallback = []() {
- freeArena();
+bool macho::link(ArrayRef<const char *> argsArr, raw_ostream &stdoutOS,
+ raw_ostream &stderrOS, bool exitEarly, bool disableOutput) {
+ // This driver-specific context will be freed later by lldMain().
+ auto *ctx = new CommonLinkerContext;
+ ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
+ ctx->e.cleanupCallback = []() {
resolvedFrameworks.clear();
resolvedLibraries.clear();
cachedReads.clear();
@@ -1130,17 +1129,15 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
InputFile::resetIdCount();
};
- errorHandler().logName = args::getFilenameWithoutExe(argsArr[0]);
- stderrOS.enable_colors(stderrOS.has_colors());
+ ctx->e.logName = args::getFilenameWithoutExe(argsArr[0]);
MachOOptTable parser;
InputArgList args = parser.parse(argsArr.slice(1));
- errorHandler().errorLimitExceededMsg =
- "too many errors emitted, stopping now "
- "(use --error-limit=0 to see all errors)";
- errorHandler().errorLimit = args::getInteger(args, OPT_error_limit_eq, 20);
- errorHandler().verbose = args.hasArg(OPT_verbose);
+ ctx->e.errorLimitExceededMsg = "too many errors emitted, stopping now "
+ "(use --error-limit=0 to see all errors)";
+ ctx->e.errorLimit = args::getInteger(args, OPT_error_limit_eq, 20);
+ ctx->e.verbose = args.hasArg(OPT_verbose);
if (args.hasArg(OPT_help_hidden)) {
parser.printHelp(argsArr[0], /*showHidden=*/true);
@@ -1184,7 +1181,7 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
// these are meaningful for our text based stripping
if (config->osoPrefix.equals(".") || config->osoPrefix.endswith(sep))
expanded += sep;
- config->osoPrefix = saver.save(expanded.str());
+ config->osoPrefix = saver().save(expanded.str());
}
}
@@ -1470,7 +1467,7 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
// Parse LTO options.
if (const Arg *arg = args.getLastArg(OPT_mcpu))
- parseClangOption(saver.save("-mcpu=" + StringRef(arg->getValue())),
+ parseClangOption(saver().save("-mcpu=" + StringRef(arg->getValue())),
arg->getSpelling());
for (const Arg *arg : args.filtered(OPT_mllvm))
@@ -1561,11 +1558,5 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
timeTraceProfilerCleanup();
}
-
- if (canExitEarly)
- exitLld(errorCount() ? 1 : 0);
-
- bool ret = errorCount() == 0;
- errorHandler().reset();
- return ret;
+ return errorCount() == 0;
}
diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp
index 3c5440544614c..83940b54486ff 100644
--- a/lld/MachO/DriverUtils.cpp
+++ b/lld/MachO/DriverUtils.cpp
@@ -13,8 +13,7 @@
#include "Target.h"
#include "lld/Common/Args.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/Reproduce.h"
#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/DenseMap.h"
@@ -82,7 +81,7 @@ InputArgList MachOOptTable::parse(ArrayRef<const char *> argv) {
// Expand response files (arguments in the form of @<filename>)
// and then parse the argument again.
- cl::ExpandResponseFiles(saver, cl::TokenizeGNUCommandLine, vec);
+ cl::ExpandResponseFiles(saver(), cl::TokenizeGNUCommandLine, vec);
InputArgList args = ParseArgs(vec, missingIndex, missingCount);
// Handle -fatal_warnings early since it converts missing argument warnings
@@ -191,12 +190,12 @@ Optional<StringRef> macho::resolveDylibPath(StringRef dylibPath) {
bool tbdExists = fs::exists(tbdPath);
searchedDylib(tbdPath, tbdExists);
if (tbdExists)
- return saver.save(tbdPath.str());
+ return saver().save(tbdPath.str());
bool dylibExists = fs::exists(dylibPath);
searchedDylib(dylibPath, dylibExists);
if (dylibExists)
- return saver.save(dylibPath);
+ return saver().save(dylibPath);
return {};
}
@@ -261,7 +260,7 @@ macho::findPathCombination(const Twine &name,
bool exists = fs::exists(location);
searchedDylib(location, exists);
if (exists)
- return saver.save(location.str());
+ return saver().save(location.str());
}
}
return {};
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index cebf22b993b7f..09f3813798cd9 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -56,9 +56,8 @@
#include "SyntheticSections.h"
#include "Target.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/DWARF.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
#include "lld/Common/Reproduce.h"
#include "llvm/ADT/iterator.h"
#include "llvm/BinaryFormat/MachO.h"
@@ -210,6 +209,8 @@ Optional<MemoryBufferRef> macho::readFile(StringRef path) {
return cachedReads[key] = mbref;
}
+ llvm::BumpPtrAllocator &bAlloc = lld::bAlloc();
+
// Object files and archive files may be fat files, which contain multiple
// real files for
diff erent CPU ISAs. Here, we search for a file that matches
// with the current link target and returns it as a MemoryBufferRef.
@@ -241,7 +242,7 @@ Optional<MemoryBufferRef> macho::readFile(StringRef path) {
}
InputFile::InputFile(Kind kind, const InterfaceFile &interface)
- : id(idCount++), fileKind(kind), name(saver.save(interface.getPath())) {}
+ : id(idCount++), fileKind(kind), name(saver().save(interface.getPath())) {}
// Some sections comprise of fixed-size records, so instead of splitting them at
// symbol boundaries, we split them based on size. Records are distinct from
@@ -1177,7 +1178,7 @@ DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella,
// Find all the $ld$* symbols to process first.
parseTrie(buf + c->export_off, c->export_size,
[&](const Twine &name, uint64_t flags) {
- StringRef savedName = saver.save(name);
+ StringRef savedName = saver().save(name);
if (handleLDSymbol(savedName))
return;
entries.push_back({savedName, flags});
@@ -1251,7 +1252,7 @@ DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella,
umbrella = this;
this->umbrella = umbrella;
- installName = saver.save(interface.getInstallName());
+ installName = saver().save(interface.getInstallName());
compatibilityVersion = interface.getCompatibilityVersion().rawValue();
currentVersion = interface.getCurrentVersion().rawValue();
@@ -1270,7 +1271,7 @@ DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella,
exportingFile = isImplicitlyLinked(installName) ? this : umbrella;
auto addSymbol = [&](const Twine &name) -> void {
- StringRef savedName = saver.save(name);
+ StringRef savedName = saver().save(name);
if (exportingFile->hiddenSymbols.contains(CachedHashStringRef(savedName)))
return;
@@ -1389,7 +1390,7 @@ void DylibFile::handleLDPreviousSymbol(StringRef name, StringRef originalName) {
config->platformInfo.minimum >= end)
return;
- this->installName = saver.save(installName);
+ this->installName = saver().save(installName);
if (!compatVersion.empty()) {
VersionTuple cVersion;
@@ -1411,7 +1412,7 @@ void DylibFile::handleLDInstallNameSymbol(StringRef name,
if (!condition.consume_front("os") || version.tryParse(condition))
warn("failed to parse os version, symbol '" + originalName + "' ignored");
else if (version == config->platformInfo.minimum)
- this->installName = saver.save(installName);
+ this->installName = saver().save(installName);
}
void DylibFile::handleLDHideSymbol(StringRef name, StringRef originalName) {
@@ -1516,7 +1517,7 @@ void ArchiveFile::fetch(const object::Archive::Symbol &sym) {
static macho::Symbol *createBitcodeSymbol(const lto::InputFile::Symbol &objSym,
BitcodeFile &file) {
- StringRef name = saver.save(objSym.getName());
+ StringRef name = saver().save(objSym.getName());
if (objSym.isUndefined())
return symtab->addUndefined(name, &file, /*isWeakRef=*/objSym.isWeak());
@@ -1558,11 +1559,12 @@ BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
// So, we append the archive name to disambiguate two members with the same
// name from multiple
diff erent archives, and offset within the archive to
// disambiguate two members of the same name from a single archive.
- MemoryBufferRef mbref(
- mb.getBuffer(),
- saver.save(archiveName.empty() ? path
- : archiveName + sys::path::filename(path) +
- utostr(offsetInArchive)));
+ MemoryBufferRef mbref(mb.getBuffer(),
+ saver().save(archiveName.empty()
+ ? path
+ : archiveName +
+ sys::path::filename(path) +
+ utostr(offsetInArchive)));
obj = check(lto::InputFile::create(mbref));
diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp
index c71ea33d28965..fd49a09229d11 100644
--- a/lld/MachO/LTO.cpp
+++ b/lld/MachO/LTO.cpp
@@ -14,7 +14,7 @@
#include "Target.h"
#include "lld/Common/Args.h"
-#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/Strings.h"
#include "lld/Common/TargetOptionsCommandFlags.h"
#include "llvm/LTO/Config.h"
@@ -148,7 +148,7 @@ std::vector<ObjFile *> BitcodeCompiler::compile() {
modTime = getModTime(filePath);
}
ret.push_back(make<ObjFile>(
- MemoryBufferRef(buf[i], saver.save(filePath.str())), modTime, ""));
+ MemoryBufferRef(buf[i], saver().save(filePath.str())), modTime, ""));
}
for (std::unique_ptr<MemoryBuffer> &file : files)
if (file)
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
index 23e908646d000..bc20379bee130 100644
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -16,8 +16,7 @@
#include "SymbolTable.h"
#include "Symbols.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/EndianStream.h"
@@ -834,7 +833,7 @@ void SymtabSection::emitBeginSourceStab(DWARFUnit *compileUnit) {
if (!dir.endswith(sep))
dir += sep;
stab.strx = stringTableSection.addString(
- saver.save(dir + compileUnit->getUnitDIE().getShortName()));
+ saver().save(dir + compileUnit->getUnitDIE().getShortName()));
stabs.emplace_back(std::move(stab));
}
@@ -856,7 +855,7 @@ void SymtabSection::emitObjectFileStab(ObjFile *file) {
if (!file->archiveName.empty())
path.append({"(", file->getName(), ")"});
- StringRef adjustedPath = saver.save(path.str());
+ StringRef adjustedPath = saver().save(path.str());
adjustedPath.consume_front(config->osoPrefix);
stab.strx = stringTableSection.addString(adjustedPath);
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 4c7d1c2eeb32b..c76dc691346e6 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -22,8 +22,7 @@
#include "UnwindInfoSection.h"
#include "lld/Common/Arrays.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/LEB128.h"
@@ -611,7 +610,7 @@ static bool needsBinding(const Symbol *sym) {
}
static void prepareSymbolRelocation(Symbol *sym, const InputSection *isec,
- const Reloc &r) {
+ const lld::macho::Reloc &r) {
assert(sym->isLive());
const RelocAttrs &relocAttrs = target->getRelocAttrs(r.type);
@@ -644,7 +643,7 @@ void Writer::scanRelocations() {
continue;
for (auto it = isec->relocs.begin(); it != isec->relocs.end(); ++it) {
- Reloc &r = *it;
+ lld::macho::Reloc &r = *it;
if (target->hasAttr(r.type, RelocAttrBits::SUBTRAHEND)) {
// Skip over the following UNSIGNED relocation -- it's just there as the
// minuend, and doesn't have the usual UNSIGNED semantics. We don't want
@@ -858,8 +857,8 @@ static size_t getSymbolPriority(const SymbolPriorityEntry &entry,
if (f->archiveName.empty())
filename = path::filename(f->getName());
else
- filename = saver.save(path::filename(f->archiveName) + "(" +
- path::filename(f->getName()) + ")");
+ filename = saver().save(path::filename(f->archiveName) + "(" +
+ path::filename(f->getName()) + ")");
return std::max(entry.objectFiles.lookup(filename), entry.anyObjectFile);
}
@@ -1216,7 +1215,7 @@ void macho::createSyntheticSections() {
// This section contains space for just a single word, and will be used by
// dyld to cache an address to the image loader it uses.
- uint8_t *arr = bAlloc.Allocate<uint8_t>(target->wordSize);
+ uint8_t *arr = bAlloc().Allocate<uint8_t>(target->wordSize);
memset(arr, 0, target->wordSize);
in.imageLoaderCache = make<ConcatInputSection>(
segment_names::data, section_names::data, /*file=*/nullptr,
diff --git a/lld/MinGW/Driver.cpp b/lld/MinGW/Driver.cpp
index 7c6b865a2e398..f0ac5eeb67835 100644
--- a/lld/MinGW/Driver.cpp
+++ b/lld/MinGW/Driver.cpp
@@ -100,7 +100,7 @@ opt::InputArgList MinGWOptTable::parse(ArrayRef<const char *> argv) {
unsigned missingCount;
SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size());
- cl::ExpandResponseFiles(saver, getQuotingStyle(), vec);
+ cl::ExpandResponseFiles(saver(), getQuotingStyle(), vec);
opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount);
if (missingCount)
@@ -154,12 +154,10 @@ searchLibrary(StringRef name, ArrayRef<StringRef> searchPaths, bool bStatic) {
// Convert Unix-ish command line arguments to Windows-ish ones and
// then call coff::link.
-bool mingw::link(ArrayRef<const char *> argsArr, bool canExitEarly,
- raw_ostream &stdoutOS, raw_ostream &stderrOS) {
- lld::stdoutOS = &stdoutOS;
- lld::stderrOS = &stderrOS;
-
- stderrOS.enable_colors(stderrOS.has_colors());
+bool mingw::link(ArrayRef<const char *> argsArr, raw_ostream &stdoutOS,
+ raw_ostream &stderrOS, bool exitEarly, bool disableOutput) {
+ auto *ctx = new CommonLinkerContext;
+ ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
MinGWOptTable parser;
opt::InputArgList args = parser.parse(argsArr.slice(1));
@@ -445,5 +443,9 @@ bool mingw::link(ArrayRef<const char *> argsArr, bool canExitEarly,
// Pass the actual binary name, to make error messages be printed with
// the right prefix.
vec[0] = argsArr[0];
- return coff::link(vec, canExitEarly, stdoutOS, stderrOS);
+
+ // The context will be re-created in the COFF driver.
+ lld::CommonLinkerContext::destroy();
+
+ return coff::link(vec, stdoutOS, stderrOS, exitEarly, disableOutput);
}
diff --git a/lld/include/lld/Common/CommonLinkerContext.h b/lld/include/lld/Common/CommonLinkerContext.h
new file mode 100644
index 0000000000000..ba1074a7869d1
--- /dev/null
+++ b/lld/include/lld/Common/CommonLinkerContext.h
@@ -0,0 +1,63 @@
+//===- CommonLinkerContext.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
+//
+//===----------------------------------------------------------------------===//
+//
+// Entry point for all global state in lldCommon. The objective is for LLD to be
+// used "as a library" in a thread-safe manner.
+//
+// Instead of program-wide globals or function-local statics, we prefer
+// aggregating all "global" states into a heap-based structure
+// (CommonLinkerContext). This also achieves deterministic initialization &
+// shutdown for all "global" states.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_COMMON_COMMONLINKINGCONTEXT_H
+#define LLD_COMMON_COMMONLINKINGCONTEXT_H
+
+#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Memory.h"
+#include "llvm/CodeGen/CommandFlags.h"
+#include "llvm/Support/StringSaver.h"
+
+namespace llvm {
+class raw_ostream;
+} // namespace llvm
+
+namespace lld {
+struct SpecificAllocBase;
+class CommonLinkerContext {
+public:
+ CommonLinkerContext();
+ virtual ~CommonLinkerContext();
+
+ static void destroy();
+
+ llvm::BumpPtrAllocator bAlloc;
+ llvm::StringSaver saver{bAlloc};
+ llvm::DenseMap<void *, SpecificAllocBase *> instances;
+
+ ErrorHandler e;
+
+private:
+ llvm::codegen::RegisterCodeGenFlags cgf;
+};
+
+// Retrieve the global state. Only one state can exist per application.
+CommonLinkerContext &commonContext();
+
+template <typename T = CommonLinkerContext> T &context() {
+ return static_cast<T &>(commonContext());
+}
+
+bool hasContext();
+
+inline llvm::StringSaver &saver() { return context().saver; }
+inline llvm::BumpPtrAllocator &bAlloc() { return context().bAlloc; }
+} // namespace lld
+
+#endif
diff --git a/lld/include/lld/Common/Driver.h b/lld/include/lld/Common/Driver.h
index 0e505a16463e7..91cb91b9f8082 100644
--- a/lld/include/lld/Common/Driver.h
+++ b/lld/include/lld/Common/Driver.h
@@ -9,6 +9,7 @@
#ifndef LLD_COMMON_DRIVER_H
#define LLD_COMMON_DRIVER_H
+#include "lld/Common/CommonLinkerContext.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/raw_ostream.h"
@@ -28,28 +29,28 @@ SafeReturn safeLldMain(int argc, const char **argv, llvm::raw_ostream &stdoutOS,
llvm::raw_ostream &stderrOS);
namespace coff {
-bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
- llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
+bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
+ llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
}
namespace mingw {
-bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
- llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
+bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
+ llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
}
namespace elf {
-bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
- llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
+bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
+ llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
}
namespace macho {
-bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
- llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
+bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
+ llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
}
namespace wasm {
-bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
- llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
+bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
+ llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
}
}
diff --git a/lld/include/lld/Common/ErrorHandler.h b/lld/include/lld/Common/ErrorHandler.h
index d95a2537c1f2c..ce077290d60b3 100644
--- a/lld/include/lld/Common/ErrorHandler.h
+++ b/lld/include/lld/Common/ErrorHandler.h
@@ -73,6 +73,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileOutputBuffer.h"
+#include <mutex>
namespace llvm {
class DiagnosticInfo;
@@ -81,11 +82,6 @@ class raw_ostream;
namespace lld {
-// We wrap stdout and stderr so that you can pass alternative stdout/stderr as
-// arguments to lld::*::link() functions.
-extern llvm::raw_ostream *stdoutOS;
-extern llvm::raw_ostream *stderrOS;
-
llvm::raw_ostream &outs();
llvm::raw_ostream &errs();
@@ -93,6 +89,11 @@ enum class ErrorTag { LibNotFound, SymbolNotFound };
class ErrorHandler {
public:
+ ~ErrorHandler();
+
+ void initialize(llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS,
+ bool exitEarly, bool disableOutput);
+
uint64_t errorCount = 0;
uint64_t errorLimit = 20;
StringRef errorLimitExceededMsg = "too many errors emitted, stopping now";
@@ -112,11 +113,9 @@ class ErrorHandler {
void message(const Twine &msg, llvm::raw_ostream &s);
void warn(const Twine &msg);
- void reset() {
- if (cleanupCallback)
- cleanupCallback();
- *this = ErrorHandler();
- }
+ raw_ostream &outs();
+ raw_ostream &errs();
+ void flushStreams();
std::unique_ptr<llvm::FileOutputBuffer> outputBuffer;
@@ -126,6 +125,19 @@ class ErrorHandler {
std::string getLocation(const Twine &msg);
void reportDiagnostic(StringRef location, Colors c, StringRef diagKind,
const Twine &msg);
+
+ // We want to separate multi-line messages with a newline. `sep` is "\n"
+ // if the last messages was multi-line. Otherwise "".
+ llvm::StringRef sep;
+
+ // We wrap stdout and stderr so that you can pass alternative stdout/stderr as
+ // arguments to lld::*::link() functions. Since lld::outs() or lld::errs() can
+ // be indirectly called from multiple threads, we protect them using a mutex.
+ // In the future, we plan on supporting several concurent linker contexts,
+ // which explains why the mutex is not a global but part of this context.
+ std::mutex mu;
+ llvm::raw_ostream *stdoutOS{};
+ llvm::raw_ostream *stderrOS{};
};
/// Returns the default error handler.
diff --git a/lld/include/lld/Common/Memory.h b/lld/include/lld/Common/Memory.h
index f516a327cfb2b..0b2f474c30135 100644
--- a/lld/include/lld/Common/Memory.h
+++ b/lld/include/lld/Common/Memory.h
@@ -22,42 +22,41 @@
#define LLD_COMMON_MEMORY_H
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/StringSaver.h"
-#include <vector>
namespace lld {
-
-// Use this arena if your object doesn't have a destructor.
-extern llvm::BumpPtrAllocator bAlloc;
-extern llvm::StringSaver saver;
-
-void freeArena();
-
-// These two classes are hack to keep track of all
-// SpecificBumpPtrAllocator instances.
+// A base class only used by the CommonLinkerContext to keep track of the
+// SpecificAlloc<> instances.
struct SpecificAllocBase {
- SpecificAllocBase() { instances.push_back(this); }
virtual ~SpecificAllocBase() = default;
- virtual void reset() = 0;
- static std::vector<SpecificAllocBase *> instances;
+ static SpecificAllocBase *getOrCreate(void *tag, size_t size, size_t align,
+ SpecificAllocBase *(&creator)(void *));
};
+// An arena of specific types T, created on-demand.
template <class T> struct SpecificAlloc : public SpecificAllocBase {
- void reset() override { alloc.DestroyAll(); }
+ static SpecificAllocBase *create(void *storage) {
+ return new (storage) SpecificAlloc<T>();
+ }
llvm::SpecificBumpPtrAllocator<T> alloc;
+ static int tag;
};
-// Use a static local for these singletons so they are only registered if an
-// object of this instance is ever constructed. Otherwise we will create and
-// register ELF allocators for COFF and the reverse.
+// The address of this static member is only used as a key in
+// CommonLinkerContext::instances. Its value does not matter.
+template <class T> int SpecificAlloc<T>::tag = 0;
+
+// Creates the arena on-demand on the first call; or returns it, if it was
+// already created.
template <typename T>
inline llvm::SpecificBumpPtrAllocator<T> &getSpecificAllocSingleton() {
- static SpecificAlloc<T> instance;
- return instance.alloc;
+ SpecificAllocBase *instance = SpecificAllocBase::getOrCreate(
+ &SpecificAlloc<T>::tag, sizeof(SpecificAlloc<T>),
+ alignof(SpecificAlloc<T>), SpecificAlloc<T>::create);
+ return ((SpecificAlloc<T> *)instance)->alloc;
}
-// Use this arena if your object has a destructor.
-// Your destructor will be invoked from freeArena().
+// Creates new instances of T off a (almost) contiguous arena/object pool. The
+// instances are destroyed whenever lldMain() goes out of scope.
template <typename T, typename... U> T *make(U &&... args) {
return new (getSpecificAllocSingleton<T>().Allocate())
T(std::forward<U>(args)...);
diff --git a/lld/include/lld/Core/LinkingContext.h b/lld/include/lld/Core/LinkingContext.h
index e090ff9902318..091369e143190 100644
--- a/lld/include/lld/Core/LinkingContext.h
+++ b/lld/include/lld/Core/LinkingContext.h
@@ -9,6 +9,7 @@
#ifndef LLD_CORE_LINKING_CONTEXT_H
#define LLD_CORE_LINKING_CONTEXT_H
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Core/Node.h"
#include "lld/Core/Reader.h"
#include "llvm/ADT/ArrayRef.h"
@@ -34,7 +35,7 @@ class SharedLibraryFile;
/// The base class LinkingContext contains the options needed by core linking.
/// Subclasses of LinkingContext have additional options needed by specific
/// Writers.
-class LinkingContext {
+class LinkingContext : public CommonLinkerContext {
public:
virtual ~LinkingContext();
diff --git a/lld/tools/lld/lld.cpp b/lld/tools/lld/lld.cpp
index cad97f2153c28..7cf55e91d30e1 100644
--- a/lld/tools/lld/lld.cpp
+++ b/lld/tools/lld/lld.cpp
@@ -87,6 +87,8 @@ static bool isPETarget(std::vector<const char *> &v) {
// Expand response files (arguments in the form of @<filename>)
// to allow detecting the -m argument from arguments in them.
SmallVector<const char *, 256> expandedArgs(v.data(), v.data() + v.size());
+ BumpPtrAllocator a;
+ StringSaver saver(a);
cl::ExpandResponseFiles(saver, getDefaultQuotingStyle(), expandedArgs);
for (auto it = expandedArgs.begin(); it + 1 != expandedArgs.end(); ++it) {
if (StringRef(*it) != "-m")
@@ -134,27 +136,43 @@ static Flavor parseFlavor(std::vector<const char *> &v) {
return parseProgname(arg0);
}
+static bool inTestOutputDisabled = false;
+
/// Universal linker main(). This linker emulates the gnu, darwin, or
/// windows linker based on the argv[0] or -flavor option.
static int lldMain(int argc, const char **argv, llvm::raw_ostream &stdoutOS,
llvm::raw_ostream &stderrOS, bool exitEarly = true) {
std::vector<const char *> args(argv, argv + argc);
- switch (parseFlavor(args)) {
- case Gnu:
- if (isPETarget(args))
- return !mingw::link(args, exitEarly, stdoutOS, stderrOS);
- return !elf::link(args, exitEarly, stdoutOS, stderrOS);
- case WinLink:
- return !coff::link(args, exitEarly, stdoutOS, stderrOS);
- case Darwin:
- return !macho::link(args, exitEarly, stdoutOS, stderrOS);
- case Wasm:
- return !lld::wasm::link(args, exitEarly, stdoutOS, stderrOS);
- default:
+ auto link = [&args]() {
+ Flavor f = parseFlavor(args);
+ if (f == Gnu && isPETarget(args))
+ return mingw::link;
+ if (f == Gnu)
+ return elf::link;
+ if (f == WinLink)
+ return coff::link;
+ if (f == Darwin)
+ return macho::link;
+ if (f == Wasm)
+ return lld::wasm::link;
die("lld is a generic driver.\n"
"Invoke ld.lld (Unix), ld64.lld (macOS), lld-link (Windows), wasm-ld"
" (WebAssembly) instead");
- }
+ }();
+ // Run the driver. If an error occurs, false will be returned.
+ int r = !link(args, stdoutOS, stderrOS, exitEarly, inTestOutputDisabled);
+
+ // Exit immediately if we don't need to return to the caller.
+ // This saves time because the overhead of calling destructors
+ // for all globally-allocated objects is not negligible.
+ if (exitEarly)
+ exitLld(r);
+
+ // Delete the global context and clear the global context pointer, so that it
+ // cannot be accessed anymore.
+ CommonLinkerContext::destroy();
+
+ return r;
}
// Similar to lldMain except that exceptions are caught.
@@ -176,7 +194,7 @@ SafeReturn lld::safeLldMain(int argc, const char **argv,
// Cleanup memory and reset everything back in pristine condition. This path
// is only taken when LLD is in test, or when it is used as a library.
llvm::CrashRecoveryContext crc;
- if (!crc.RunSafely([&]() { errorHandler().reset(); })) {
+ if (!crc.RunSafely([&]() { CommonLinkerContext::destroy(); })) {
// The memory is corrupted beyond any possible recovery.
return {r, /*canRunAgain=*/false};
}
@@ -207,8 +225,7 @@ int main(int argc, const char **argv) {
for (unsigned i = inTestVerbosity(); i > 0; --i) {
// Disable stdout/stderr for all iterations but the last one.
- if (i != 1)
- errorHandler().disableOutput = true;
+ inTestOutputDisabled = (i != 1);
// Execute one iteration.
auto r = safeLldMain(argc, argv, llvm::outs(), llvm::errs());
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 59abfaadf3989..8554cb66d56c4 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -81,18 +81,15 @@ class LinkerDriver {
};
} // anonymous namespace
-bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &stdoutOS,
- raw_ostream &stderrOS) {
- lld::stdoutOS = &stdoutOS;
- lld::stderrOS = &stderrOS;
+bool link(ArrayRef<const char *> args, raw_ostream &stdoutOS,
+ raw_ostream &stderrOS, bool exitEarly, bool disableOutput) {
+ // This driver-specific context will be freed later by lldMain().
+ auto *ctx = new CommonLinkerContext;
- errorHandler().cleanupCallback = []() { freeArena(); };
-
- errorHandler().logName = args::getFilenameWithoutExe(args[0]);
- errorHandler().errorLimitExceededMsg =
- "too many errors emitted, stopping now (use "
- "-error-limit=0 to see all errors)";
- stderrOS.enable_colors(stderrOS.has_colors());
+ ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
+ ctx->e.logName = args::getFilenameWithoutExe(args[0]);
+ ctx->e.errorLimitExceededMsg = "too many errors emitted, stopping now (use "
+ "-error-limit=0 to see all errors)";
config = make<Configuration>();
symtab = make<SymbolTable>();
@@ -100,13 +97,7 @@ bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &stdoutOS,
initLLVM();
LinkerDriver().linkerMain(args);
- // Exit immediately if we don't need to return to the caller.
- // This saves time because the overhead of calling destructors
- // for all globally-allocated objects is not negligible.
- if (canExitEarly)
- exitLld(errorCount() ? 1 : 0);
-
- return !errorCount();
+ return errorCount() == 0;
}
// Create prefix string literals used in Options.td
@@ -189,7 +180,7 @@ opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> argv) {
// Expand response files (arguments in the form of @<filename>)
// and then parse the argument again.
- cl::ExpandResponseFiles(saver, getQuotingStyle(args), vec);
+ cl::ExpandResponseFiles(saver(), getQuotingStyle(args), vec);
args = this->ParseArgs(vec, missingIndex, missingCount);
handleColorDiagnostics(args);
@@ -760,8 +751,8 @@ static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {
if (!sym)
continue;
- Symbol *real = addUndefined(saver.save("__real_" + name));
- Symbol *wrap = addUndefined(saver.save("__wrap_" + name));
+ Symbol *real = addUndefined(saver().save("__real_" + name));
+ Symbol *wrap = addUndefined(saver().save("__wrap_" + name));
v.push_back({sym, real, wrap});
// We want to tell LTO not to inline symbols to be overwritten
diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp
index e3a7f56ab884a..3e3b31ab1ee5e 100644
--- a/lld/wasm/InputFiles.cpp
+++ b/lld/wasm/InputFiles.cpp
@@ -12,8 +12,7 @@
#include "InputElement.h"
#include "OutputSegment.h"
#include "SymbolTable.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/Reproduce.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/Wasm.h"
@@ -721,7 +720,7 @@ static uint8_t mapVisibility(GlobalValue::VisibilityTypes gvVisibility) {
static Symbol *createBitcodeSymbol(const std::vector<bool> &keptComdats,
const lto::InputFile::Symbol &objSym,
BitcodeFile &f) {
- StringRef name = saver.save(objSym.getName());
+ StringRef name = saver().save(objSym.getName());
uint32_t flags = objSym.isWeak() ? WASM_SYMBOL_BINDING_WEAK : 0;
flags |= mapVisibility(objSym.getVisibility());
@@ -756,9 +755,9 @@ BitcodeFile::BitcodeFile(MemoryBufferRef m, StringRef archiveName,
// symbols later in the link stage). So we append file offset to make
// filename unique.
StringRef name = archiveName.empty()
- ? saver.save(path)
- : saver.save(archiveName + "(" + path::filename(path) +
- " at " + utostr(offsetInArchive) + ")");
+ ? saver().save(path)
+ : saver().save(archiveName + "(" + path::filename(path) +
+ " at " + utostr(offsetInArchive) + ")");
MemoryBufferRef mbref(mb.getBuffer(), name);
obj = check(lto::InputFile::create(mbref));
diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp
index 63e66c145747e..ef1402248eec8 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -11,8 +11,7 @@
#include "InputChunks.h"
#include "InputElement.h"
#include "WriterUtils.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "llvm/ADT/SetVector.h"
#define DEBUG_TYPE "lld"
@@ -843,7 +842,7 @@ InputFunction *SymbolTable::replaceWithUnreachable(Symbol *sym,
void SymbolTable::replaceWithUndefined(Symbol *sym) {
// Add a synthetic dummy for weak undefined functions. These dummies will
// be GC'd if not used as the target of any "call" instructions.
- StringRef debugName = saver.save("undefined_weak:" + toString(*sym));
+ StringRef debugName = saver().save("undefined_weak:" + toString(*sym));
replaceWithUnreachable(sym, *sym->getSignature(), debugName);
// Hide our dummy to prevent export.
sym->setHidden(true);
@@ -941,7 +940,8 @@ void SymbolTable::handleSymbolVariants() {
if (symbol != defined) {
auto *f = cast<FunctionSymbol>(symbol);
reportFunctionSignatureMismatch(symName, f, defined, false);
- StringRef debugName = saver.save("signature_mismatch:" + toString(*f));
+ StringRef debugName =
+ saver().save("signature_mismatch:" + toString(*f));
replaceWithUnreachable(f, *f->signature, debugName);
}
}
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index f1ebe54ca60da..70a8af058d792 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -17,8 +17,7 @@
#include "SymbolTable.h"
#include "SyntheticSections.h"
#include "WriterUtils.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/Strings.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallSet.h"
@@ -190,7 +189,7 @@ void Writer::createRelocSections() {
else if (sec->type == WASM_SEC_CODE)
name = "reloc.CODE";
else if (sec->type == WASM_SEC_CUSTOM)
- name = saver.save("reloc." + sec->name);
+ name = saver().save("reloc." + sec->name);
else
llvm_unreachable(
"relocations only supported for code, data, or custom sections");
@@ -389,8 +388,8 @@ static void addStartStopSymbols(const OutputSegment *seg) {
LLVM_DEBUG(dbgs() << "addStartStopSymbols: " << name << "\n");
uint64_t start = seg->startVA;
uint64_t stop = start + seg->size;
- symtab->addOptionalDataSymbol(saver.save("__start_" + name), start);
- symtab->addOptionalDataSymbol(saver.save("__stop_" + name), stop);
+ symtab->addOptionalDataSymbol(saver().save("__start_" + name), start);
+ symtab->addOptionalDataSymbol(saver().save("__stop_" + name), stop);
}
void Writer::addSections() {
@@ -958,7 +957,7 @@ static void createFunction(DefinedFunction *func, StringRef bodyContent) {
writeUleb128(os, bodyContent.size(), "function size");
os << bodyContent;
}
- ArrayRef<uint8_t> body = arrayRefFromStringRef(saver.save(functionBody));
+ ArrayRef<uint8_t> body = arrayRefFromStringRef(saver().save(functionBody));
cast<SyntheticFunction>(func->function)->setBody(body);
}
More information about the llvm-commits
mailing list