Index: include/lld/Core/File.h =================================================================== --- include/lld/Core/File.h +++ include/lld/Core/File.h @@ -20,6 +20,7 @@ #include "llvm/Support/ErrorHandling.h" #include #include +#include #include namespace lld { @@ -161,11 +162,7 @@ /// (because YAML reader does not read blobs but structured data). void setLastError(std::error_code err) { _lastError = err; } - std::error_code parse() { - if (!_lastError.hasValue()) - _lastError = doParse(); - return _lastError.getValue(); - } + std::error_code parse(); // Usually each file owns a std::unique_ptr. // However, there's one special case. If a file is an archive file, @@ -239,7 +236,6 @@ static atom_collection_empty _noUndefinedAtoms; static atom_collection_empty _noSharedLibraryAtoms; static atom_collection_empty _noAbsoluteAtoms; - llvm::Optional _lastError; mutable llvm::BumpPtrAllocator _allocator; private: @@ -247,6 +243,8 @@ Kind _kind; mutable uint64_t _ordinal; std::shared_ptr _sharedMemoryBuffer; + llvm::Optional _lastError; + std::mutex _parseMutex; }; /// \brief A mutable File. Index: include/lld/Core/LinkingContext.h =================================================================== --- include/lld/Core/LinkingContext.h +++ include/lld/Core/LinkingContext.h @@ -13,6 +13,7 @@ #include "lld/Core/Error.h" #include "lld/Core/LLVM.h" #include "lld/Core/Node.h" +#include "lld/Core/Parallel.h" #include "lld/Core/Reference.h" #include "lld/Core/range.h" #include "lld/ReaderWriter/Reader.h" @@ -323,6 +324,8 @@ // Derived classes may use that chance to rearrange the input files. virtual void maybeSortInputFiles() {} + TaskGroup &getTaskGroup() { return _taskGroup; } + /// @} protected: LinkingContext(); // Must be subclassed @@ -370,6 +373,7 @@ private: /// Validate the subclass bits. Only called by validate. virtual bool validateImpl(raw_ostream &diagnostics) = 0; + TaskGroup _taskGroup; }; } // end namespace lld Index: include/lld/Core/Resolver.h =================================================================== --- include/lld/Core/Resolver.h +++ include/lld/Core/Resolver.h @@ -62,7 +62,7 @@ void maybeAddSectionGroupOrGnuLinkOnce(const DefinedAtom &atom); /// \brief The main function that iterates over the files to resolve - void resolveUndefines(); + bool resolveUndefines(); void updateReferences(); void deadStripOptimize(); bool checkUndefines(); Index: lib/Core/File.cpp =================================================================== --- lib/Core/File.cpp +++ lib/Core/File.cpp @@ -9,6 +9,7 @@ #include "lld/Core/File.h" #include "lld/Core/LLVM.h" +#include namespace lld { @@ -19,4 +20,11 @@ File::atom_collection_empty File::_noSharedLibraryAtoms; File::atom_collection_empty File::_noAbsoluteAtoms; +std::error_code File::parse() { + std::lock_guard lock(_parseMutex); + if (!_lastError.hasValue()) + _lastError = doParse(); + return _lastError.getValue(); +} + } // namespace lld Index: lib/Core/Resolver.cpp =================================================================== --- lib/Core/Resolver.cpp +++ lib/Core/Resolver.cpp @@ -236,7 +236,7 @@ for (int i = begin; i < end; ++i) if (FileNode *node = dyn_cast(inputs[i].get())) if (_newUndefinesAdded[node->getFile()]) - return true; + return true; return false; } @@ -263,7 +263,7 @@ // 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 @@ 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 @@ } bool Resolver::resolve() { - resolveUndefines(); + if (!resolveUndefines()) + return false; updateReferences(); deadStripOptimize(); if (checkUndefines()) Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -77,42 +77,9 @@ 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 &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(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 lock(diagnosticsMutex); - diagnostics << buf; - } - }); - } - tg.sync(); - readTask.end(); - - if (fail) - return false; + for (std::unique_ptr &ie : context.getNodes()) + if (FileNode *node = dyn_cast(ie.get())) + context.getTaskGroup().spawn([node] { node->getFile()->parse(); }); std::vector> internalFiles; context.createInternalFiles(internalFiles); Index: lib/ReaderWriter/ELF/ELFFile.h =================================================================== --- lib/ReaderWriter/ELF/ELFFile.h +++ lib/ReaderWriter/ELF/ELFFile.h @@ -116,7 +116,9 @@ 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 mb, bool atomizeStrings = false) : File(mb->getBufferIdentifier(), kindObject), _mb(std::move(mb)), Index: lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp =================================================================== --- lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp +++ lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp @@ -87,6 +87,13 @@ ""); } +static int getGroupStartPos(std::vector> &nodes) { + for (int i = 0, e = nodes.size(); i < e; ++i) + if (GroupEnd *group = dyn_cast(nodes[i].get())) + return i - group->getSize(); + llvm::report_fatal_error("internal error"); +} + void PECOFFLinkingContext::addLibraryFile(std::unique_ptr file) { GroupEnd *currentGroupEnd; int pos = -1; @@ -111,7 +118,7 @@ // Create a file for the entry point function. std::unique_ptr entry(new FileNode( llvm::make_unique(*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(new FileNode( @@ -339,6 +346,8 @@ void pecoff::ResolvableSymbols::readAllSymbols() { std::lock_guard lock(_mutex); for (File *file : _queue) { + if (file->parse()) + return; if (auto *archive = dyn_cast(file)) { for (const std::string &sym : archive->getDefinedSymbols()) _defined.insert(sym);