aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Ganea <alexandre.ganea@legionlabs.com>2022-01-16 11:03:06 -0500
committerAlexandre Ganea <alexandre.ganea@legionlabs.com>2022-01-16 11:03:06 -0500
commite6b153947dfae5d666c4bac56b10ee82ddb173c4 (patch)
tree3401901ddd583e31e5c601b71a8d5a31f62ff3a3
parent30a4020a7db866990199f523a60ad474d7ec3efa (diff)
downloadllvm-e6b153947dfae5d666c4bac56b10ee82ddb173c4.zip
llvm-e6b153947dfae5d666c4bac56b10ee82ddb173c4.tar.gz
llvm-e6b153947dfae5d666c4bac56b10ee82ddb173c4.tar.bz2
Revert [LLD] Remove global state in lldCommon
It seems to be causing issues on https://lab.llvm.org/buildbot/#/builders/123/builds/8383
-rw-r--r--lld/COFF/COFFLinkerContext.h3
-rw-r--r--lld/COFF/Chunks.cpp3
-rw-r--r--lld/COFF/DLL.cpp4
-rw-r--r--lld/COFF/Driver.cpp69
-rw-r--r--lld/COFF/DriverUtils.cpp24
-rw-r--r--lld/COFF/InputFiles.cpp26
-rw-r--r--lld/COFF/LTO.cpp6
-rw-r--r--lld/COFF/MinGW.cpp7
-rw-r--r--lld/COFF/PDB.cpp13
-rw-r--r--lld/COFF/SymbolTable.cpp2
-rw-r--r--lld/COFF/Writer.cpp2
-rw-r--r--lld/Common/CMakeLists.txt1
-rw-r--r--lld/Common/CommonLinkerContext.cpp44
-rw-r--r--lld/Common/ErrorHandler.cpp69
-rw-r--r--lld/Common/Memory.cpp19
-rw-r--r--lld/Common/TargetOptionsCommandFlags.cpp3
-rw-r--r--lld/ELF/AArch64ErrataFix.cpp8
-rw-r--r--lld/ELF/ARMErrataFix.cpp6
-rw-r--r--lld/ELF/Arch/PPC64.cpp5
-rw-r--r--lld/ELF/Driver.cpp39
-rw-r--r--lld/ELF/DriverUtils.cpp7
-rw-r--r--lld/ELF/InputFiles.cpp28
-rw-r--r--lld/ELF/InputSection.cpp7
-rw-r--r--lld/ELF/LinkerScript.cpp6
-rw-r--r--lld/ELF/MarkLive.cpp6
-rw-r--r--lld/ELF/ScriptParser.cpp8
-rw-r--r--lld/ELF/SyntheticSections.cpp7
-rw-r--r--lld/ELF/Thunks.cpp57
-rw-r--r--lld/ELF/Writer.cpp6
-rw-r--r--lld/MachO/ConcatOutputSection.cpp7
-rw-r--r--lld/MachO/Driver.cpp43
-rw-r--r--lld/MachO/DriverUtils.cpp11
-rw-r--r--lld/MachO/InputFiles.cpp30
-rw-r--r--lld/MachO/LTO.cpp4
-rw-r--r--lld/MachO/SyntheticSections.cpp7
-rw-r--r--lld/MachO/Writer.cpp13
-rw-r--r--lld/MinGW/Driver.cpp18
-rw-r--r--lld/include/lld/Common/CommonLinkerContext.h65
-rw-r--r--lld/include/lld/Common/Driver.h21
-rw-r--r--lld/include/lld/Common/ErrorHandler.h32
-rw-r--r--lld/include/lld/Common/Memory.h43
-rw-r--r--lld/include/lld/Core/LinkingContext.h3
-rw-r--r--lld/tools/lld/lld.cpp49
-rw-r--r--lld/wasm/Driver.cpp33
-rw-r--r--lld/wasm/InputFiles.cpp11
-rw-r--r--lld/wasm/SymbolTable.cpp8
-rw-r--r--lld/wasm/Writer.cpp11
47 files changed, 394 insertions, 500 deletions
diff --git a/lld/COFF/COFFLinkerContext.h b/lld/COFF/COFFLinkerContext.h
index a3a6f94..e5223da 100644
--- a/lld/COFF/COFFLinkerContext.h
+++ b/lld/COFF/COFFLinkerContext.h
@@ -15,13 +15,12 @@
#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 : public CommonLinkerContext {
+class COFFLinkerContext {
public:
COFFLinkerContext();
COFFLinkerContext(const COFFLinkerContext &) = delete;
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 6cabb22..54cb8c9 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -12,6 +12,7 @@
#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"
@@ -429,7 +430,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 bfa2a69..6fec9df 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 0d833af..f8da63c 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -19,7 +19,9 @@
#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"
@@ -61,23 +63,36 @@ namespace coff {
std::unique_ptr<Configuration> config;
std::unique_ptr<LinkerDriver> driver;
-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;
+bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &stdoutOS,
+ raw_ostream &stderrOS) {
+ lld::stdoutOS = &stdoutOS;
+ lld::stderrOS = &stderrOS;
- 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)";
+ 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());
+ COFFLinkerContext ctx;
config = std::make_unique<Configuration>();
- driver = std::make_unique<LinkerDriver>(*ctx);
+ driver = std::make_unique<LinkerDriver>(ctx);
driver->linkerMain(args);
- return errorCount() == 0;
+ // 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;
}
// Parse options of the form "old;new".
@@ -147,7 +162,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;
}
@@ -343,9 +358,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);
@@ -427,11 +442,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;
@@ -468,7 +483,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);
}
@@ -477,7 +492,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.
@@ -510,7 +525,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(';');
@@ -857,8 +872,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)
@@ -886,13 +901,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;
@@ -1889,9 +1904,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 ac0f1f9..0921c8e 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 0f3f5e0..1d79d97 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -15,6 +15,8 @@
#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"
@@ -903,7 +905,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
@@ -938,8 +940,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;
@@ -993,12 +995,11 @@ 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));
}
@@ -1034,7 +1035,6 @@ FakeSectionChunk ltoDataSectionChunk(&ltoDataSection.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 2dbe7b1..f117b62 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/CommonLinkerContext.h"
+#include "lld/Common/ErrorHandler.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 7a3a385..148ebe5 100644
--- a/lld/COFF/MinGW.cpp
+++ b/lld/COFF/MinGW.cpp
@@ -11,6 +11,7 @@
#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"
@@ -183,8 +184,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.
@@ -248,7 +249,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 dea84ec..a4cef1d 100644
--- a/lld/COFF/PDB.cpp
+++ b/lld/COFF/PDB.cpp
@@ -16,6 +16,7 @@
#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"
@@ -74,7 +75,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.
@@ -500,7 +501,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;
@@ -1002,7 +1003,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);
@@ -1416,7 +1417,6 @@ 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,7 +1536,6 @@ 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 db2db9c..9ceac7a 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 12db942..4a41c54 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 1ae7da1..9fdc67b 100644
--- a/lld/Common/CMakeLists.txt
+++ b/lld/Common/CMakeLists.txt
@@ -28,7 +28,6 @@ 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
deleted file mode 100644
index e4f6e36..0000000
--- a/lld/Common/CommonLinkerContext.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-//===- 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. This is a temporary situation, until
-// we pass this context everywhere by reference, or we make it a thread_local,
-// as in https://reviews.llvm.org/D108850?id=370678 where each thread can be
-// associated with a LLD instance. Only then will LLD be free of global state.
-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 15b3bd0..399b6ca 100644
--- a/lld/Common/ErrorHandler.cpp
+++ b/lld/Common/ErrorHandler.cpp
@@ -10,7 +10,6 @@
#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"
@@ -19,69 +18,51 @@
#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 "";
}
-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;
-}
+raw_ostream *lld::stdoutOS;
+raw_ostream *lld::stderrOS;
-void ErrorHandler::flushStreams() {
- std::lock_guard<std::mutex> lock(mu);
- outs().flush();
- errs().flush();
+ErrorHandler &lld::errorHandler() {
+ static ErrorHandler handler;
+ return handler;
}
-ErrorHandler &lld::errorHandler() { return context().e; }
-
raw_ostream &lld::outs() {
- ErrorHandler &e = errorHandler();
- return e.outs();
-}
-
-raw_ostream &lld::errs() {
- ErrorHandler &e = errorHandler();
- return e.errs();
-}
-
-raw_ostream &ErrorHandler::outs() {
- if (disableOutput)
+ if (errorHandler().disableOutput)
return llvm::nulls();
return stdoutOS ? *stdoutOS : llvm::outs();
}
-raw_ostream &ErrorHandler::errs() {
- if (disableOutput)
+raw_ostream &lld::errs() {
+ if (errorHandler().disableOutput)
return llvm::nulls();
return stderrOS ? *stderrOS : llvm::errs();
}
void lld::exitLld(int val) {
- if (hasContext()) {
- ErrorHandler &e = errorHandler();
- // Delete any temporary file, while keeping the memory mapping open.
- if (e.outputBuffer)
- e.outputBuffer->discard();
- }
+ // Delete any temporary file, while keeping the memory mapping open.
+ if (errorHandler().outputBuffer)
+ errorHandler().outputBuffer->discard();
// Re-throw a possible signal or exception once/if it was catched by
// safeLldMain().
@@ -94,9 +75,11 @@ void lld::exitLld(int val) {
if (!CrashRecoveryContext::GetCurrent())
llvm_shutdown();
- if (hasContext())
- lld::errorHandler().flushStreams();
-
+ {
+ std::lock_guard<std::mutex> lock(mu);
+ lld::outs().flush();
+ lld::errs().flush();
+ }
// 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 7c90ff1..c53e1d3 100644
--- a/lld/Common/Memory.cpp
+++ b/lld/Common/Memory.cpp
@@ -7,19 +7,16 @@
//===----------------------------------------------------------------------===//
#include "lld/Common/Memory.h"
-#include "lld/Common/CommonLinkerContext.h"
using namespace llvm;
using namespace lld;
-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;
+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();
}
diff --git a/lld/Common/TargetOptionsCommandFlags.cpp b/lld/Common/TargetOptionsCommandFlags.cpp
index b7749c4..d39477e 100644
--- a/lld/Common/TargetOptionsCommandFlags.cpp
+++ b/lld/Common/TargetOptionsCommandFlags.cpp
@@ -7,9 +7,12 @@
//===----------------------------------------------------------------------===//
#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 d45edf9..a1e276e 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/CommonLinkerContext.h"
+#include "lld/Common/Memory.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 25b47b9..cfaa310 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/CommonLinkerContext.h"
+#include "lld/Common/Memory.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 d9e4fc9..69a9118 100644
--- a/lld/ELF/Arch/PPC64.cpp
+++ b/lld/ELF/Arch/PPC64.cpp
@@ -11,7 +11,8 @@
#include "SyntheticSections.h"
#include "Target.h"
#include "Thunks.h"
-#include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Memory.h"
#include "llvm/Support/Endian.h"
using namespace llvm;
@@ -196,7 +197,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 13ee90d..5e7b74e 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -77,13 +77,14 @@ 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, raw_ostream &stdoutOS,
- raw_ostream &stderrOS, bool exitEarly, bool disableOutput) {
- // This driver-specific context will be freed later by lldMain().
- auto *ctx = new CommonLinkerContext;
+bool elf::link(ArrayRef<const char *> args, bool canExitEarly,
+ raw_ostream &stdoutOS, raw_ostream &stderrOS) {
+ lld::stdoutOS = &stdoutOS;
+ lld::stderrOS = &stderrOS;
+
+ errorHandler().cleanupCallback = []() {
+ freeArena();
- ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
- ctx->e.cleanupCallback = []() {
inputSections.clear();
outputSections.clear();
memoryBuffers.clear();
@@ -105,9 +106,13 @@ bool elf::link(ArrayRef<const char *> args, raw_ostream &stdoutOS,
SharedFile::vernauxNum = 0;
};
- ctx->e.logName = args::getFilenameWithoutExe(args[0]);
- ctx->e.errorLimitExceededMsg = "too many errors emitted, stopping now (use "
- "-error-limit=0 to see all errors)";
+
+ 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());
config = std::make_unique<Configuration>();
driver = std::make_unique<LinkerDriver>();
@@ -121,7 +126,15 @@ bool elf::link(ArrayRef<const char *> args, raw_ostream &stdoutOS,
driver->linkerMain(args);
- return errorCount() == 0;
+ // 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;
}
// Parses a linker -m option.
@@ -1246,7 +1259,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))
@@ -2059,9 +2072,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 ac29b47..54d2d0a 100644
--- a/lld/ELF/DriverUtils.cpp
+++ b/lld/ELF/DriverUtils.cpp
@@ -13,7 +13,8 @@
//===----------------------------------------------------------------------===//
#include "Driver.h"
-#include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Memory.h"
#include "lld/Common/Reproduce.h"
#include "lld/Common/Version.h"
#include "llvm/ADT/Optional.h"
@@ -101,7 +102,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]);
@@ -124,7 +125,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 5cd32453..04fa48f 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -13,8 +13,9 @@
#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"
@@ -110,7 +111,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));
@@ -1525,8 +1526,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()});
@@ -1568,7 +1569,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});
}
@@ -1651,10 +1652,11 @@ 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);
@@ -1690,7 +1692,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);
}
@@ -1740,8 +1742,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() {
@@ -1759,8 +1761,6 @@ 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 8a47cf4..feeb290 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -18,7 +18,8 @@
#include "SyntheticSections.h"
#include "Target.h"
#include "Thunks.h"
-#include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Memory.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
@@ -142,7 +143,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))
@@ -235,7 +236,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 a5f11ae..fa41f4d 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/CommonLinkerContext.h"
+#include "lld/Common/Memory.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 597c068..4d3d79d 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/CommonLinkerContext.h"
+#include "lld/Common/Memory.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 7331d11..f26b6c4 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/CommonLinkerContext.h"
+#include "lld/Common/Memory.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 6ac1fc3..aef6434 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -22,8 +22,9 @@
#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"
@@ -72,7 +73,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};
@@ -254,7 +255,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 ae74081..38de4db1 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -27,7 +27,8 @@
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
-#include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Memory.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Endian.h"
@@ -433,7 +434,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);
@@ -459,8 +460,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);
}
@@ -559,7 +560,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);
}
@@ -577,7 +578,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);
}
@@ -598,8 +599,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);
}
@@ -619,7 +620,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);
}
@@ -634,7 +635,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);
@@ -660,8 +661,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);
}
@@ -690,7 +691,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);
@@ -716,7 +717,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);
@@ -734,7 +735,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);
}
@@ -757,9 +758,8 @@ 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,9 +782,8 @@ 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;
}
@@ -844,7 +843,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,
@@ -853,7 +852,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);
}
@@ -897,8 +896,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;
}
@@ -948,7 +947,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;
}
@@ -984,7 +983,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);
}
@@ -1020,7 +1019,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);
}
@@ -1036,7 +1035,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 e5b211c..742ea81 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 4fae934..f63c2e6 100644
--- a/lld/MachO/ConcatOutputSection.cpp
+++ b/lld/MachO/ConcatOutputSection.cpp
@@ -13,7 +13,8 @@
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
-#include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Memory.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/TimeProfiler.h"
@@ -321,8 +322,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 0962683..f4b2948 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,13 +1102,14 @@ static void referenceStubBinder() {
symtab->addUndefined("dyld_stub_binder", /*file=*/nullptr, /*isWeak=*/false);
}
-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;
+bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
+ raw_ostream &stdoutOS, raw_ostream &stderrOS) {
+ lld::stdoutOS = &stdoutOS;
+ lld::stderrOS = &stderrOS;
+
+ errorHandler().cleanupCallback = []() {
+ freeArena();
- ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
- ctx->e.cleanupCallback = []() {
resolvedFrameworks.clear();
resolvedLibraries.clear();
cachedReads.clear();
@@ -1129,15 +1130,17 @@ bool macho::link(ArrayRef<const char *> argsArr, raw_ostream &stdoutOS,
InputFile::resetIdCount();
};
- ctx->e.logName = args::getFilenameWithoutExe(argsArr[0]);
+ errorHandler().logName = args::getFilenameWithoutExe(argsArr[0]);
+ stderrOS.enable_colors(stderrOS.has_colors());
MachOOptTable parser;
InputArgList args = parser.parse(argsArr.slice(1));
- 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);
+ 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);
if (args.hasArg(OPT_help_hidden)) {
parser.printHelp(argsArr[0], /*showHidden=*/true);
@@ -1181,7 +1184,7 @@ bool macho::link(ArrayRef<const char *> argsArr, raw_ostream &stdoutOS,
// 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());
}
}
@@ -1467,7 +1470,7 @@ bool macho::link(ArrayRef<const char *> argsArr, raw_ostream &stdoutOS,
// 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))
@@ -1558,5 +1561,11 @@ bool macho::link(ArrayRef<const char *> argsArr, raw_ostream &stdoutOS,
timeTraceProfilerCleanup();
}
- return errorCount() == 0;
+
+ if (canExitEarly)
+ exitLld(errorCount() ? 1 : 0);
+
+ bool ret = errorCount() == 0;
+ errorHandler().reset();
+ return ret;
}
diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp
index 83940b5..3c54405 100644
--- a/lld/MachO/DriverUtils.cpp
+++ b/lld/MachO/DriverUtils.cpp
@@ -13,7 +13,8 @@
#include "Target.h"
#include "lld/Common/Args.h"
-#include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Memory.h"
#include "lld/Common/Reproduce.h"
#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/DenseMap.h"
@@ -81,7 +82,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
@@ -190,12 +191,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 {};
}
@@ -260,7 +261,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 09f3813..cebf22b 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -56,8 +56,9 @@
#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"
@@ -209,8 +210,6 @@ 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 different CPU ISAs. Here, we search for a file that matches
// with the current link target and returns it as a MemoryBufferRef.
@@ -242,7 +241,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
@@ -1178,7 +1177,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});
@@ -1252,7 +1251,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();
@@ -1271,7 +1270,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;
@@ -1390,7 +1389,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;
@@ -1412,7 +1411,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) {
@@ -1517,7 +1516,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());
@@ -1559,12 +1558,11 @@ BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
// So, we append the archive name to disambiguate two members with the same
// name from multiple different 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 fd49a09..c71ea33 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/CommonLinkerContext.h"
+#include "lld/Common/ErrorHandler.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 bc20379..23e9086 100644
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -16,7 +16,8 @@
#include "SymbolTable.h"
#include "Symbols.h"
-#include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Memory.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/EndianStream.h"
@@ -833,7 +834,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));
}
@@ -855,7 +856,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 c76dc69..4c7d1c2 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -22,7 +22,8 @@
#include "UnwindInfoSection.h"
#include "lld/Common/Arrays.h"
-#include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Memory.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/LEB128.h"
@@ -610,7 +611,7 @@ static bool needsBinding(const Symbol *sym) {
}
static void prepareSymbolRelocation(Symbol *sym, const InputSection *isec,
- const lld::macho::Reloc &r) {
+ const Reloc &r) {
assert(sym->isLive());
const RelocAttrs &relocAttrs = target->getRelocAttrs(r.type);
@@ -643,7 +644,7 @@ void Writer::scanRelocations() {
continue;
for (auto it = isec->relocs.begin(); it != isec->relocs.end(); ++it) {
- lld::macho::Reloc &r = *it;
+ 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
@@ -857,8 +858,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);
}
@@ -1215,7 +1216,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 f0ac5ee..7c6b865 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,10 +154,12 @@ 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, raw_ostream &stdoutOS,
- raw_ostream &stderrOS, bool exitEarly, bool disableOutput) {
- auto *ctx = new CommonLinkerContext;
- ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
+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());
MinGWOptTable parser;
opt::InputArgList args = parser.parse(argsArr.slice(1));
@@ -443,9 +445,5 @@ bool mingw::link(ArrayRef<const char *> argsArr, raw_ostream &stdoutOS,
// Pass the actual binary name, to make error messages be printed with
// the right prefix.
vec[0] = argsArr[0];
-
- // The context will be re-created in the COFF driver.
- lld::CommonLinkerContext::destroy();
-
- return coff::link(vec, stdoutOS, stderrOS, exitEarly, disableOutput);
+ return coff::link(vec, canExitEarly, stdoutOS, stderrOS);
}
diff --git a/lld/include/lld/Common/CommonLinkerContext.h b/lld/include/lld/Common/CommonLinkerContext.h
deleted file mode 100644
index 3954d38d..0000000
--- a/lld/include/lld/Common/CommonLinkerContext.h
+++ /dev/null
@@ -1,65 +0,0 @@
-//===- 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. Currently only one state can exist per process,
-// but in the future we plan on supporting an arbitrary number of LLD instances
-// in a single process.
-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 91cb91b..0e505a1 100644
--- a/lld/include/lld/Common/Driver.h
+++ b/lld/include/lld/Common/Driver.h
@@ -9,7 +9,6 @@
#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"
@@ -29,28 +28,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, llvm::raw_ostream &stdoutOS,
- llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
+bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
+ llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
}
namespace mingw {
-bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
- llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
+bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
+ llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
}
namespace elf {
-bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
- llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
+bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
+ llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
}
namespace macho {
-bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
- llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
+bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
+ llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
}
namespace wasm {
-bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
- llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
+bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
+ llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
}
}
diff --git a/lld/include/lld/Common/ErrorHandler.h b/lld/include/lld/Common/ErrorHandler.h
index ce07729..d95a253 100644
--- a/lld/include/lld/Common/ErrorHandler.h
+++ b/lld/include/lld/Common/ErrorHandler.h
@@ -73,7 +73,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileOutputBuffer.h"
-#include <mutex>
namespace llvm {
class DiagnosticInfo;
@@ -82,6 +81,11 @@ 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();
@@ -89,11 +93,6 @@ 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";
@@ -113,9 +112,11 @@ public:
void message(const Twine &msg, llvm::raw_ostream &s);
void warn(const Twine &msg);
- raw_ostream &outs();
- raw_ostream &errs();
- void flushStreams();
+ void reset() {
+ if (cleanupCallback)
+ cleanupCallback();
+ *this = ErrorHandler();
+ }
std::unique_ptr<llvm::FileOutputBuffer> outputBuffer;
@@ -125,19 +126,6 @@ private:
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 0b2f474..f516a32 100644
--- a/lld/include/lld/Common/Memory.h
+++ b/lld/include/lld/Common/Memory.h
@@ -22,41 +22,42 @@
#define LLD_COMMON_MEMORY_H
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/StringSaver.h"
+#include <vector>
namespace lld {
-// A base class only used by the CommonLinkerContext to keep track of the
-// SpecificAlloc<> instances.
+
+// 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.
struct SpecificAllocBase {
+ SpecificAllocBase() { instances.push_back(this); }
virtual ~SpecificAllocBase() = default;
- static SpecificAllocBase *getOrCreate(void *tag, size_t size, size_t align,
- SpecificAllocBase *(&creator)(void *));
+ virtual void reset() = 0;
+ static std::vector<SpecificAllocBase *> instances;
};
-// An arena of specific types T, created on-demand.
template <class T> struct SpecificAlloc : public SpecificAllocBase {
- static SpecificAllocBase *create(void *storage) {
- return new (storage) SpecificAlloc<T>();
- }
+ void reset() override { alloc.DestroyAll(); }
llvm::SpecificBumpPtrAllocator<T> alloc;
- static int tag;
};
-// 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.
+// 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.
template <typename T>
inline llvm::SpecificBumpPtrAllocator<T> &getSpecificAllocSingleton() {
- SpecificAllocBase *instance = SpecificAllocBase::getOrCreate(
- &SpecificAlloc<T>::tag, sizeof(SpecificAlloc<T>),
- alignof(SpecificAlloc<T>), SpecificAlloc<T>::create);
- return ((SpecificAlloc<T> *)instance)->alloc;
+ static SpecificAlloc<T> instance;
+ return instance.alloc;
}
-// Creates new instances of T off a (almost) contiguous arena/object pool. The
-// instances are destroyed whenever lldMain() goes out of scope.
+// Use this arena if your object has a destructor.
+// Your destructor will be invoked from freeArena().
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 091369e..e090ff9 100644
--- a/lld/include/lld/Core/LinkingContext.h
+++ b/lld/include/lld/Core/LinkingContext.h
@@ -9,7 +9,6 @@
#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"
@@ -35,7 +34,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 : public CommonLinkerContext {
+class LinkingContext {
public:
virtual ~LinkingContext();
diff --git a/lld/tools/lld/lld.cpp b/lld/tools/lld/lld.cpp
index 7cf55e9..cad97f2 100644
--- a/lld/tools/lld/lld.cpp
+++ b/lld/tools/lld/lld.cpp
@@ -87,8 +87,6 @@ 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")
@@ -136,43 +134,27 @@ 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);
- 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;
+ 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:
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.
@@ -194,7 +176,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([&]() { CommonLinkerContext::destroy(); })) {
+ if (!crc.RunSafely([&]() { errorHandler().reset(); })) {
// The memory is corrupted beyond any possible recovery.
return {r, /*canRunAgain=*/false};
}
@@ -225,7 +207,8 @@ int main(int argc, const char **argv) {
for (unsigned i = inTestVerbosity(); i > 0; --i) {
// Disable stdout/stderr for all iterations but the last one.
- inTestOutputDisabled = (i != 1);
+ if (i != 1)
+ errorHandler().disableOutput = true;
// 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 8554cb6..59abfaad 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -81,15 +81,18 @@ private:
};
} // anonymous namespace
-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;
+bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &stdoutOS,
+ raw_ostream &stderrOS) {
+ lld::stdoutOS = &stdoutOS;
+ lld::stderrOS = &stderrOS;
- 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)";
+ 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());
config = make<Configuration>();
symtab = make<SymbolTable>();
@@ -97,7 +100,13 @@ bool link(ArrayRef<const char *> args, raw_ostream &stdoutOS,
initLLVM();
LinkerDriver().linkerMain(args);
- return errorCount() == 0;
+ // 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();
}
// Create prefix string literals used in Options.td
@@ -180,7 +189,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);
@@ -751,8 +760,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 3e3b31a..e3a7f56 100644
--- a/lld/wasm/InputFiles.cpp
+++ b/lld/wasm/InputFiles.cpp
@@ -12,7 +12,8 @@
#include "InputElement.h"
#include "OutputSegment.h"
#include "SymbolTable.h"
-#include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Memory.h"
#include "lld/Common/Reproduce.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/Wasm.h"
@@ -720,7 +721,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());
@@ -755,9 +756,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 ef14022..63e66c1 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -11,7 +11,8 @@
#include "InputChunks.h"
#include "InputElement.h"
#include "WriterUtils.h"
-#include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Memory.h"
#include "llvm/ADT/SetVector.h"
#define DEBUG_TYPE "lld"
@@ -842,7 +843,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);
@@ -940,8 +941,7 @@ 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 70a8af0..f1ebe54 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -17,7 +17,8 @@
#include "SymbolTable.h"
#include "SyntheticSections.h"
#include "WriterUtils.h"
-#include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/ErrorHandler.h"
+#include "lld/Common/Memory.h"
#include "lld/Common/Strings.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallSet.h"
@@ -189,7 +190,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");
@@ -388,8 +389,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() {
@@ -957,7 +958,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);
}