llvm-project/lld/lib/Driver/Driver.cpp
Rui Ueyama 2c64aef35f Remove YAML/Native round-trip passes.
The round-trip passes were introduced in r193300. The intention of
the change was to make sure that LLD is capable of reading end
writing such file formats.

But that turned out to be yet another over-designed stuff that had
been slowing down everyday development.

The passes ran after the core linker and before the writer. If you
had an additional piece of information that needs to be passed from
front-end to the writer, you had to invent a way to save the data to
YAML/Native. These passes forced us to do that even if that data
was not needed to be represented neither in an object file nor in
an executable/DSO. It doesn't make sense. We don't need these passes.

http://reviews.llvm.org/D7480

llvm-svn: 230069
2015-02-20 22:10:28 +00:00

132 lines
4.4 KiB
C++

//===- lib/Driver/Driver.cpp - Linker Driver Emulator ---------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lld/Core/ArchiveLibraryFile.h"
#include "lld/Core/File.h"
#include "lld/Core/Instrumentation.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/Parallel.h"
#include "lld/Core/PassManager.h"
#include "lld/Core/Reader.h"
#include "lld/Core/Resolver.h"
#include "lld/Core/Writer.h"
#include "lld/Driver/Driver.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/Arg.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
#include <mutex>
namespace lld {
FileVector makeErrorFile(StringRef path, std::error_code ec) {
std::vector<std::unique_ptr<File>> result;
result.push_back(llvm::make_unique<ErrorFile>(path, ec));
return result;
}
FileVector parseMemberFiles(FileVector &files) {
std::vector<std::unique_ptr<File>> members;
for (std::unique_ptr<File> &file : files) {
if (auto *archive = dyn_cast<ArchiveLibraryFile>(file.get())) {
if (std::error_code ec = archive->parseAllMembers(members))
return makeErrorFile(file->path(), ec);
} else {
members.push_back(std::move(file));
}
}
return members;
}
FileVector loadFile(LinkingContext &ctx, StringRef path, bool wholeArchive) {
ErrorOr<std::unique_ptr<MemoryBuffer>> mb
= MemoryBuffer::getFileOrSTDIN(path);
if (std::error_code ec = mb.getError())
return makeErrorFile(path, ec);
std::vector<std::unique_ptr<File>> files;
if (std::error_code ec = ctx.registry().loadFile(std::move(mb.get()), files))
return makeErrorFile(path, ec);
if (wholeArchive)
return parseMemberFiles(files);
return files;
}
/// This is where the link is actually performed.
bool Driver::link(LinkingContext &context, raw_ostream &diagnostics) {
// Honor -mllvm
if (!context.llvmOptions().empty()) {
unsigned numArgs = context.llvmOptions().size();
const char **args = new const char *[numArgs + 2];
args[0] = "lld (LLVM option parsing)";
for (unsigned i = 0; i != numArgs; ++i)
args[i + 1] = context.llvmOptions()[i];
args[numArgs + 1] = 0;
llvm::cl::ParseCommandLineOptions(numArgs + 1, args);
}
if (context.getNodes().empty())
return false;
// File::parse may add items to the node list which may invalidate
// existing iterators. Avoid using iterator to access elements.
std::vector<std::unique_ptr<Node>> &nodes = context.getNodes();
for (size_t i = 0; i < nodes.size(); ++i)
if (FileNode *node = dyn_cast<FileNode>(nodes[i].get()))
context.getTaskGroup().spawn([node] { node->getFile()->parse(); });
std::vector<std::unique_ptr<File>> internalFiles;
context.createInternalFiles(internalFiles);
for (auto i = internalFiles.rbegin(), e = internalFiles.rend(); i != e; ++i) {
auto &members = context.getNodes();
members.insert(members.begin(), llvm::make_unique<FileNode>(std::move(*i)));
}
// Give target a chance to add files.
std::vector<std::unique_ptr<File>> implicitFiles;
context.createImplicitFiles(implicitFiles);
for (auto i = implicitFiles.rbegin(), e = implicitFiles.rend(); i != e; ++i) {
auto &members = context.getNodes();
members.insert(members.begin(), llvm::make_unique<FileNode>(std::move(*i)));
}
// Give target a chance to sort the input files.
// Mach-O uses this chance to move all object files before library files.
context.maybeSortInputFiles();
// Do core linking.
ScopedTask resolveTask(getDefaultDomain(), "Resolve");
Resolver resolver(context);
if (!resolver.resolve())
return false;
std::unique_ptr<MutableFile> merged = resolver.resultFile();
resolveTask.end();
// Run passes on linked atoms.
ScopedTask passTask(getDefaultDomain(), "Passes");
PassManager pm;
context.addPasses(pm);
pm.runOnFile(merged);
passTask.end();
// Give linked atoms to Writer to generate output file.
ScopedTask writeTask(getDefaultDomain(), "Write");
if (std::error_code ec = context.writeFile(*merged)) {
diagnostics << "Failed to write file '" << context.outputPath()
<< "': " << ec.message() << "\n";
return false;
}
return true;
}
} // namespace