summaryrefslogtreecommitdiff
path: root/lld/COFF/Driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/COFF/Driver.cpp')
-rw-r--r--lld/COFF/Driver.cpp118
1 files changed, 82 insertions, 36 deletions
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index f770fff80bcb..7372505bb616 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -21,7 +21,6 @@
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Filesystem.h"
#include "lld/Common/Memory.h"
-#include "lld/Common/Threads.h"
#include "lld/Common/Timer.h"
#include "lld/Common/Version.h"
#include "llvm/ADT/Optional.h"
@@ -39,6 +38,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/Parallel.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/TarWriter.h"
@@ -89,6 +89,8 @@ bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &stdoutOS,
ImportFile::instances.clear();
BitcodeFile::instances.clear();
memset(MergeChunk::instances, 0, sizeof(MergeChunk::instances));
+ TpiSource::clear();
+
return !errorCount();
}
@@ -218,7 +220,7 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
symtab->addFile(make<ObjFile>(mbref));
break;
case file_magic::pdb:
- loadTypeServerSource(mbref);
+ symtab->addFile(make<PDBInputFile>(mbref));
break;
case file_magic::coff_cl_gl_object:
error(filename + ": is not a native COFF file. Recompile without /GL");
@@ -237,9 +239,9 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
}
void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive, bool lazy) {
- auto future =
- std::make_shared<std::future<MBErrPair>>(createFutureForFile(path));
- std::string pathStr = path;
+ auto future = std::make_shared<std::future<MBErrPair>>(
+ createFutureForFile(std::string(path)));
+ std::string pathStr = std::string(path);
enqueueTask([=]() {
auto mbOrErr = future->get();
if (mbOrErr.second) {
@@ -251,7 +253,7 @@ void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive, bool lazy) {
// the option `/nodefaultlib` than a reference to a file in the root
// directory.
std::string nearest;
- if (COFFOptTable().findNearest(pathStr, nearest) > 1)
+ if (optTable.findNearest(pathStr, nearest) > 1)
error(msg);
else
error(msg + "; did you mean '" + nearest + "'");
@@ -343,11 +345,9 @@ void LinkerDriver::parseDirectives(InputFile *file) {
ArgParser parser;
// .drectve is always tokenized using Windows shell rules.
// /EXPORT: option can appear too many times, processing in fastpath.
- opt::InputArgList args;
- std::vector<StringRef> exports;
- std::tie(args, exports) = parser.parseDirectives(s);
+ ParsedDirectives directives = parser.parseDirectives(s);
- for (StringRef e : exports) {
+ for (StringRef e : directives.exports) {
// If a common header file contains dllexported function
// declarations, many object files may end up with having the
// same /EXPORT options. In order to save cost of parsing them,
@@ -366,7 +366,11 @@ void LinkerDriver::parseDirectives(InputFile *file) {
config->exports.push_back(exp);
}
- for (auto *arg : args) {
+ // Handle /include: in bulk.
+ for (StringRef inc : directives.includes)
+ addUndefined(inc);
+
+ for (auto *arg : directives.args) {
switch (arg->getOption().getID()) {
case OPT_aligncomm:
parseAligncomm(arg->getValue());
@@ -452,7 +456,7 @@ Optional<StringRef> LinkerDriver::findFile(StringRef filename) {
}
if (path.endswith_lower(".lib"))
- visitedLibs.insert(sys::path::filename(path));
+ visitedLibs.insert(std::string(sys::path::filename(path)));
return path;
}
@@ -624,6 +628,7 @@ static std::string createResponseFile(const opt::InputArgList &args,
break;
case OPT_implib:
case OPT_pdb:
+ case OPT_pdbstripped:
case OPT_out:
os << arg->getSpelling() << sys::path::filename(arg->getValue()) << "\n";
break;
@@ -640,7 +645,7 @@ static std::string createResponseFile(const opt::InputArgList &args,
for (StringRef path : filePaths)
os << quote(relativeToRoot(path)) << "\n";
- return data.str();
+ return std::string(data.str());
}
enum class DebugKind { Unknown, None, Full, FastLink, GHash, Dwarf, Symtab };
@@ -706,24 +711,25 @@ static unsigned parseDebugTypes(const opt::InputArgList &args) {
return debugTypes;
}
-static std::string getMapFile(const opt::InputArgList &args) {
- auto *arg = args.getLastArg(OPT_lldmap, OPT_lldmap_file);
+static std::string getMapFile(const opt::InputArgList &args,
+ opt::OptSpecifier os, opt::OptSpecifier osFile) {
+ auto *arg = args.getLastArg(os, osFile);
if (!arg)
return "";
- if (arg->getOption().getID() == OPT_lldmap_file)
+ if (arg->getOption().getID() == osFile.getID())
return arg->getValue();
- assert(arg->getOption().getID() == OPT_lldmap);
+ assert(arg->getOption().getID() == os.getID());
StringRef outFile = config->outputFile;
return (outFile.substr(0, outFile.rfind('.')) + ".map").str();
}
static std::string getImplibPath() {
if (!config->implib.empty())
- return config->implib;
+ return std::string(config->implib);
SmallString<128> out = StringRef(config->outputFile);
sys::path::replace_extension(out, ".lib");
- return out.str();
+ return std::string(out.str());
}
// The import name is calculated as follows:
@@ -747,16 +753,16 @@ static std::string getImportName(bool asLib) {
(config->dll || asLib) ? ".dll" : ".exe");
}
- return out.str();
+ return std::string(out.str());
}
static void createImportLibrary(bool asLib) {
std::vector<COFFShortExport> exports;
for (Export &e1 : config->exports) {
COFFShortExport e2;
- e2.Name = e1.name;
- e2.SymbolName = e1.symbolName;
- e2.ExtName = e1.extName;
+ e2.Name = std::string(e1.name);
+ e2.SymbolName = std::string(e1.symbolName);
+ e2.ExtName = std::string(e1.extName);
e2.Ordinal = e1.ordinal;
e2.Noname = e1.noname;
e2.Data = e1.data;
@@ -817,8 +823,8 @@ static void parseModuleDefs(StringRef path) {
mb->getMemBufferRef(), config->machine, config->mingw));
if (config->outputFile.empty())
- config->outputFile = saver.save(m.OutputFile);
- config->importName = 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)
@@ -844,7 +850,8 @@ static void parseModuleDefs(StringRef path) {
// and set as "ExtName = Name". If Name has the form "OtherDll.Func",
// it shouldn't be a normal exported function but a forward to another
// DLL instead. This is supported by both MS and GNU linkers.
- if (e1.ExtName != e1.Name && StringRef(e1.Name).contains('.')) {
+ if (!e1.ExtName.empty() && e1.ExtName != e1.Name &&
+ StringRef(e1.Name).contains('.')) {
e2.name = saver.save(e1.ExtName);
e2.forwardTo = saver.save(e1.Name);
config->exports.push_back(e2);
@@ -903,7 +910,8 @@ static void parseOrderFile(StringRef arg) {
// All symbols that were not present in a given order file are
// considered to have the lowest priority 0 and are placed at
// end of an output section.
- for (std::string s : args::getLines(mb->getMemBufferRef())) {
+ for (StringRef arg : args::getLines(mb->getMemBufferRef())) {
+ std::string s(arg);
if (config->machine == I386 && !isDecorated(s))
s = "_" + s;
@@ -1093,13 +1101,15 @@ Optional<std::string> getReproduceFile(const opt::InputArgList &args) {
if (auto *arg = args.getLastArg(OPT_linkrepro)) {
SmallString<64> path = StringRef(arg->getValue());
sys::path::append(path, "repro.tar");
- return path.str().str();
+ return std::string(path);
}
return None;
}
void LinkerDriver::link(ArrayRef<const char *> argsArr) {
+ ScopedTimer rootTimer(Timer::root());
+
// Needed for LTO.
InitializeAllTargetInfos();
InitializeAllTargets();
@@ -1141,14 +1151,23 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
return;
}
- lld::threadsEnabled = args.hasFlag(OPT_threads, OPT_threads_no, true);
+ // /threads: takes a positive integer and provides the default value for
+ // /opt:lldltojobs=.
+ if (auto *arg = args.getLastArg(OPT_threads)) {
+ StringRef v(arg->getValue());
+ unsigned threads = 0;
+ if (!llvm::to_integer(v, threads, 0) || threads == 0)
+ error(arg->getSpelling() + ": expected a positive integer, but got '" +
+ arg->getValue() + "'");
+ parallel::strategy = hardware_concurrency(threads);
+ config->thinLTOJobs = v.str();
+ }
if (args.hasArg(OPT_show_timing))
config->showTiming = true;
config->showSummary = args.hasArg(OPT_summary);
- ScopedTimer t(Timer::root());
// Handle --version, which is an lld extension. This option is a bit odd
// because it doesn't start with "/", but we deliberately chose "--" to
// avoid conflict with /version and for compatibility with clang-cl.
@@ -1260,11 +1279,23 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
config->pdbAltPath = arg->getValue();
if (args.hasArg(OPT_natvis))
config->natvisFiles = args.getAllArgValues(OPT_natvis);
+ if (args.hasArg(OPT_pdbstream)) {
+ for (const StringRef value : args.getAllArgValues(OPT_pdbstream)) {
+ const std::pair<StringRef, StringRef> nameFile = value.split("=");
+ const StringRef name = nameFile.first;
+ const std::string file = nameFile.second.str();
+ config->namedStreams[name] = file;
+ }
+ }
if (auto *arg = args.getLastArg(OPT_pdb_source_path))
config->pdbSourcePath = arg->getValue();
}
+ // Handle /pdbstripped
+ if (args.hasArg(OPT_pdbstripped))
+ warn("ignoring /pdbstripped flag, it is not yet supported");
+
// Handle /noentry
if (args.hasArg(OPT_noentry)) {
if (args.hasArg(OPT_dll))
@@ -1410,9 +1441,9 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
error("/opt:lldlto: invalid optimization level: " + optLevel);
} else if (s.startswith("lldltojobs=")) {
StringRef jobs = s.substr(11);
- if (jobs.getAsInteger(10, config->thinLTOJobs) ||
- config->thinLTOJobs == 0)
+ if (!get_threadpool_strategy(jobs))
error("/opt:lldltojobs: invalid job count: " + jobs);
+ config->thinLTOJobs = jobs.str();
} else if (s.startswith("lldltopartitions=")) {
StringRef n = s.substr(17);
if (n.getAsInteger(10, config->ltoPartitions) ||
@@ -1543,6 +1574,7 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
!args.hasArg(OPT_profile));
config->integrityCheck =
args.hasFlag(OPT_integritycheck, OPT_integritycheck_no, false);
+ config->cetCompat = args.hasFlag(OPT_cetcompat, OPT_cetcompat_no, false);
config->nxCompat = args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true);
for (auto *arg : args.filtered(OPT_swaprun))
parseSwaprun(arg->getValue());
@@ -1551,13 +1583,24 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
config->debugDwarf = debug == DebugKind::Dwarf;
config->debugGHashes = debug == DebugKind::GHash;
config->debugSymtab = debug == DebugKind::Symtab;
+ config->autoImport =
+ args.hasFlag(OPT_auto_import, OPT_auto_import_no, config->mingw);
+ config->pseudoRelocs = args.hasFlag(
+ OPT_runtime_pseudo_reloc, OPT_runtime_pseudo_reloc_no, config->mingw);
// Don't warn about long section names, such as .debug_info, for mingw or when
// -debug:dwarf is requested.
if (config->mingw || config->debugDwarf)
config->warnLongSectionNames = false;
- config->mapFile = getMapFile(args);
+ config->lldmapFile = getMapFile(args, OPT_lldmap, OPT_lldmap_file);
+ config->mapFile = getMapFile(args, OPT_map, OPT_map_file);
+
+ if (config->lldmapFile != "" && config->lldmapFile == config->mapFile) {
+ warn("/lldmap and /map have the same output file '" + config->mapFile +
+ "'.\n>>> ignoring /lldmap");
+ config->lldmapFile.clear();
+ }
if (config->incremental && args.hasArg(OPT_profile)) {
warn("ignoring '/incremental' due to '/profile' specification");
@@ -1805,9 +1848,11 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
// Needed for MSVC 2017 15.5 CRT.
symtab->addAbsolute(mangle("__enclave_config"), 0);
- if (config->mingw) {
+ if (config->pseudoRelocs) {
symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST__"), 0);
symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST_END__"), 0);
+ }
+ if (config->mingw) {
symtab->addAbsolute(mangle("__CTOR_LIST__"), 0);
symtab->addAbsolute(mangle("__DTOR_LIST__"), 0);
}
@@ -1865,7 +1910,8 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
while (run());
}
- if (config->mingw) {
+ if (config->autoImport) {
+ // MinGW specific.
// Load any further object files that might be needed for doing automatic
// imports.
//
@@ -1997,7 +2043,7 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
writeResult();
// Stop early so we can print the results.
- Timer::root().stop();
+ rootTimer.stop();
if (config->showTiming)
Timer::root().print();
}