llvm-project/lld/lib/Driver/Driver.cpp
Rui Ueyama bc6b52e68e Move RoundTrip tests behind LLVM_RUN_ROUNDTRIP_TEST env flag.
If the environment variable is defined and not empty, RoundTrip tests
are run. The reason to move the tests behind the flag is because they
are too slow to enable by default.

LLD linking time on llvm-tblgen improved from 2m7s to 2.3s. About 60x
faster now in this case.

Differential Revision: http://llvm-reviews.chandlerc.com/D3126

llvm-svn: 204296
2014-03-20 02:49:33 +00:00

145 lines
4.2 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/Driver/Driver.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/Instrumentation.h"
#include "lld/Core/PassManager.h"
#include "lld/Core/Parallel.h"
#include "lld/Core/Resolver.h"
#include "lld/ReaderWriter/Reader.h"
#include "lld/ReaderWriter/Writer.h"
#include "lld/Passes/RoundTripNativePass.h"
#include "lld/Passes/RoundTripYAMLPass.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 {
/// 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);
}
InputGraph &inputGraph = context.inputGraph();
if (!inputGraph.size())
return false;
bool fail = false;
// Read inputs
ScopedTask readTask(getDefaultDomain(), "Read Args");
TaskGroup tg;
std::mutex diagnosticsMutex;
for (auto &ie : inputGraph.inputElements()) {
// Skip Hidden elements.
if (ie->isHidden())
continue;
tg.spawn([&] {
// Writes to the same output stream is not guaranteed to be thread-safe.
// We buffer the diagnostics output to a separate string-backed output
// stream, acquire the lock, and then print it out.
std::string buf;
llvm::raw_string_ostream stream(buf);
if (error_code ec = ie->parse(context, stream)) {
FileNode *fileNode = dyn_cast<FileNode>(ie.get());
stream << fileNode->errStr(ec) << "\n";
fail = true;
}
stream.flush();
if (!buf.empty()) {
std::lock_guard<std::mutex> lock(diagnosticsMutex);
diagnostics << buf;
}
});
}
tg.sync();
readTask.end();
if (fail)
return false;
std::unique_ptr<SimpleFileNode> fileNode(
new SimpleFileNode("Internal Files"));
InputGraph::FileVectorT internalFiles;
context.createInternalFiles(internalFiles);
if (internalFiles.size())
fileNode->addFiles(std::move(internalFiles));
// Give target a chance to add files.
InputGraph::FileVectorT implicitFiles;
context.createImplicitFiles(implicitFiles);
if (implicitFiles.size())
fileNode->addFiles(std::move(implicitFiles));
context.inputGraph().insertOneElementAt(std::move(fileNode),
InputGraph::Position::BEGIN);
context.inputGraph().assignOrdinals();
context.inputGraph().doPostProcess();
// 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);
#ifndef NDEBUG
llvm::Optional<std::string> env = llvm::sys::Process::GetEnv("LLD_RUN_ROUNDTRIP_TEST");
if (env.hasValue() && !env.getValue().empty()) {
pm.add(std::unique_ptr<Pass>(new RoundTripYAMLPass(context)));
pm.add(std::unique_ptr<Pass>(new RoundTripNativePass(context)));
}
#endif
pm.runOnFile(merged);
passTask.end();
// Give linked atoms to Writer to generate output file.
ScopedTask writeTask(getDefaultDomain(), "Write");
if (error_code ec = context.writeFile(*merged)) {
diagnostics << "Failed to write file '" << context.outputPath()
<< "': " << ec.message() << "\n";
return false;
}
return true;
}
} // namespace