summaryrefslogtreecommitdiffstats
path: root/lld/lib
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2015-01-16 15:54:13 +0000
committerRui Ueyama <ruiu@google.com>2015-01-16 15:54:13 +0000
commitd4730ea555f1ac7a84a12199a2e9627dc9e4e31c (patch)
tree5a39727b21f5f77c72da370a861fbe9d16473484 /lld/lib
parent694cb5d9b7724a0c6dba3adbf7c855e847a6f0de (diff)
downloadbcm5719-llvm-d4730ea555f1ac7a84a12199a2e9627dc9e4e31c.tar.gz
bcm5719-llvm-d4730ea555f1ac7a84a12199a2e9627dc9e4e31c.zip
Run the resolver in parallel with the reader.
This patch makes File::parse() multi-thread safe. If one thread is running File::parse(), other threads will block if they try to call the same method. File::parse() is idempotent, so you can safely call multiple times. With this change, we don't have to wait for all worker threads to finish in Driver::link(). Previously, Driver::link() calls TaskGroup::sync() to wait for all threads running File::parse(). This was not ideal because we couldn't start the resolver until we parse all files. This patch increase parallelism by making Driver::link() to not wait for worker threads. The resolver calls parse() to make sure that the file being read has been parsed, and then uses the file. In this approach, the resolver can run with the parser threads in parallel. http://reviews.llvm.org/D6994 llvm-svn: 226281
Diffstat (limited to 'lld/lib')
-rw-r--r--lld/lib/Core/File.cpp8
-rw-r--r--lld/lib/Core/Resolver.cpp14
-rw-r--r--lld/lib/Driver/Driver.cpp39
-rw-r--r--lld/lib/ReaderWriter/ELF/ELFFile.h4
-rw-r--r--lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp11
5 files changed, 34 insertions, 42 deletions
diff --git a/lld/lib/Core/File.cpp b/lld/lib/Core/File.cpp
index 624fca9386d..dbac86b368a 100644
--- a/lld/lib/Core/File.cpp
+++ b/lld/lib/Core/File.cpp
@@ -9,6 +9,7 @@
#include "lld/Core/File.h"
#include "lld/Core/LLVM.h"
+#include <mutex>
namespace lld {
@@ -19,4 +20,11 @@ File::atom_collection_empty<UndefinedAtom> File::_noUndefinedAtoms;
File::atom_collection_empty<SharedLibraryAtom> File::_noSharedLibraryAtoms;
File::atom_collection_empty<AbsoluteAtom> File::_noAbsoluteAtoms;
+std::error_code File::parse() {
+ std::lock_guard<std::mutex> lock(_parseMutex);
+ if (!_lastError.hasValue())
+ _lastError = doParse();
+ return _lastError.getValue();
+}
+
} // namespace lld
diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp
index ae2c71f06ad..da7fd53c120 100644
--- a/lld/lib/Core/Resolver.cpp
+++ b/lld/lib/Core/Resolver.cpp
@@ -236,7 +236,7 @@ bool Resolver::undefinesAdded(int begin, int end) {
for (int i = begin; i < end; ++i)
if (FileNode *node = dyn_cast<FileNode>(inputs[i].get()))
if (_newUndefinesAdded[node->getFile()])
- return true;
+ return true;
return false;
}
@@ -263,7 +263,7 @@ File *Resolver::getFile(int &index, int &groupLevel) {
// Keep adding atoms until _context.getNextFile() returns an error. This
// function is where undefined atoms are resolved.
-void Resolver::resolveUndefines() {
+bool Resolver::resolveUndefines() {
ScopedTask task(getDefaultDomain(), "resolveUndefines");
int index = 0;
int groupLevel = 0;
@@ -271,7 +271,12 @@ void Resolver::resolveUndefines() {
bool undefAdded = false;
File *file = getFile(index, groupLevel);
if (!file)
- return;
+ return true;
+ if (std::error_code ec = file->parse()) {
+ llvm::errs() << "Cannot open " + file->path()
+ << ": " << ec.message() << "\n";
+ return false;
+ }
switch (file->kind()) {
case File::kindObject:
if (groupLevel > 0)
@@ -441,7 +446,8 @@ void Resolver::removeCoalescedAwayAtoms() {
}
bool Resolver::resolve() {
- resolveUndefines();
+ if (!resolveUndefines())
+ return false;
updateReferences();
deadStripOptimize();
if (checkUndefines())
diff --git a/lld/lib/Driver/Driver.cpp b/lld/lib/Driver/Driver.cpp
index 85c2bd9d402..dc4b49132d0 100644
--- a/lld/lib/Driver/Driver.cpp
+++ b/lld/lib/Driver/Driver.cpp
@@ -77,42 +77,9 @@ bool Driver::link(LinkingContext &context, raw_ostream &diagnostics) {
if (context.getNodes().empty())
return false;
- bool fail = false;
-
- // Read inputs
- ScopedTask readTask(getDefaultDomain(), "Read Args");
- TaskGroup tg;
- std::mutex diagnosticsMutex;
- for (std::unique_ptr<Node> &ie : context.getNodes()) {
- 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 (FileNode *node = dyn_cast<FileNode>(ie.get())) {
- if (File *file = node->getFile()) {
- if (std::error_code ec = file->parse()) {
- stream << "Cannot open " + file->path()
- << ": " << ec.message() << "\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;
+ for (std::unique_ptr<Node> &ie : context.getNodes())
+ if (FileNode *node = dyn_cast<FileNode>(ie.get()))
+ context.getTaskGroup().spawn([node] { node->getFile()->parse(); });
std::vector<std::unique_ptr<File>> internalFiles;
context.createInternalFiles(internalFiles);
diff --git a/lld/lib/ReaderWriter/ELF/ELFFile.h b/lld/lib/ReaderWriter/ELF/ELFFile.h
index baab0d3a5ba..388e5b89089 100644
--- a/lld/lib/ReaderWriter/ELF/ELFFile.h
+++ b/lld/lib/ReaderWriter/ELF/ELFFile.h
@@ -116,7 +116,9 @@ template <class ELFT> class ELFFile : public File {
public:
ELFFile(StringRef name)
- : File(name, kindObject), _ordinal(0), _doStringsMerge(false) {}
+ : File(name, kindObject), _ordinal(0), _doStringsMerge(false) {
+ setLastError(std::error_code());
+ }
ELFFile(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings = false)
: File(mb->getBufferIdentifier(), kindObject), _mb(std::move(mb)),
diff --git a/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp b/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
index 97ef52a5eaf..e7e07f1a51d 100644
--- a/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
@@ -87,6 +87,13 @@ std::unique_ptr<File> PECOFFLinkingContext::createUndefinedSymbolFile() const {
"<command line option /include>");
}
+static int getGroupStartPos(std::vector<std::unique_ptr<Node>> &nodes) {
+ for (int i = 0, e = nodes.size(); i < e; ++i)
+ if (GroupEnd *group = dyn_cast<GroupEnd>(nodes[i].get()))
+ return i - group->getSize();
+ llvm::report_fatal_error("internal error");
+}
+
void PECOFFLinkingContext::addLibraryFile(std::unique_ptr<FileNode> file) {
GroupEnd *currentGroupEnd;
int pos = -1;
@@ -111,7 +118,7 @@ bool PECOFFLinkingContext::createImplicitFiles(
// Create a file for the entry point function.
std::unique_ptr<FileNode> entry(new FileNode(
llvm::make_unique<pecoff::EntryPointFile>(*this, syms)));
- members.insert(members.begin(), std::move(entry));
+ members.insert(members.begin() + getGroupStartPos(members), std::move(entry));
// Create a file for __ImageBase.
std::unique_ptr<FileNode> fileNode(new FileNode(
@@ -339,6 +346,8 @@ void pecoff::ResolvableSymbols::add(File *file) {
void pecoff::ResolvableSymbols::readAllSymbols() {
std::lock_guard<std::mutex> lock(_mutex);
for (File *file : _queue) {
+ if (file->parse())
+ return;
if (auto *archive = dyn_cast<ArchiveLibraryFile>(file)) {
for (const std::string &sym : archive->getDefinedSymbols())
_defined.insert(sym);
OpenPOWER on IntegriCloud