Index: include/lld/ReaderWriter/ELFTargetInfo.h =================================================================== --- include/lld/ReaderWriter/ELFTargetInfo.h +++ include/lld/ReaderWriter/ELFTargetInfo.h @@ -21,6 +21,7 @@ #include "llvm/Support/ELF.h" #include +#include namespace lld { class DefinedAtom; @@ -128,6 +129,7 @@ bool _useShlibUndefines; std::vector _inputSearchPaths; llvm::BumpPtrAllocator _extraStrings; + mutable std::mutex _readerMutex; mutable std::unique_ptr _elfReader; mutable std::unique_ptr _yamlReader; mutable std::unique_ptr _writer; Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -8,10 +8,12 @@ //===----------------------------------------------------------------------===// #include "lld/Driver/Driver.h" + #include "lld/Core/LLVM.h" #include "lld/Core/InputFiles.h" -#include "lld/Core/Resolver.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" @@ -39,20 +41,43 @@ } // Read inputs - InputFiles inputs; + std::vector>> files( + targetInfo.inputFiles().size()); + size_t index = 0; + std::atomic fail(false); + TaskGroup tg; for (const auto &input : targetInfo.inputFiles()) { - std::vector> files; if (targetInfo.logInputFiles()) llvm::outs() << input.getPath() << "\n"; - - error_code ec = targetInfo.readFile(input.getPath(), files); - if (ec) { - diagnostics << "Failed to read file: " << input.getPath() << ": " - << ec.message() << "\n"; - return true; - } - inputs.appendFiles(files); + + tg.spawn([&, index] { + auto buffer = input.getBuffer(); + if (error_code ec = buffer) { + diagnostics << "Failed to read file: " << input.getPath() + << ": " << ec.message() << "\n"; + fail = true; + return; + } + + std::unique_ptr buff(MemoryBuffer::getMemBuffer( + buffer->getBuffer(), buffer->getBufferIdentifier())); + if (error_code ec = targetInfo.parseFile(buff, files[index])) { + diagnostics << "Failed to read file: " << input.getPath() + << ": " << ec.message() << "\n"; + fail = true; + return; + } + }); + ++index; } + tg.sync(); + + if (fail) + return true; + + InputFiles inputs; + for (auto &f : files) + inputs.appendFiles(f); // Give target a chance to add files. targetInfo.addImplicitFiles(inputs); Index: lib/ReaderWriter/ELF/ELFTargetInfo.cpp =================================================================== --- lib/ReaderWriter/ELF/ELFTargetInfo.cpp +++ lib/ReaderWriter/ELF/ELFTargetInfo.cpp @@ -94,21 +94,27 @@ error_code ELFTargetInfo::parseFile(std::unique_ptr &mb, std::vector> &result) const { + std::unique_lock lock(_readerMutex); if (!_elfReader) _elfReader = createReaderELF(*this); + lock.unlock(); error_code ec = _elfReader->parseFile(mb, result); if (ec) { // Not an ELF file, check file extension to see if it might be yaml StringRef path = mb->getBufferIdentifier(); - if ( path.endswith(".objtxt") ) { + if (path.endswith(".objtxt")) { + lock.lock(); if (!_yamlReader) _yamlReader = createReaderYAML(*this); + lock.unlock(); ec = _yamlReader->parseFile(mb, result); } if (ec) { // Not a yaml file, assume it is a linkerscript + lock.lock(); if (!_linkerScriptReader) _linkerScriptReader.reset(new ReaderLinkerScript(*this)); + lock.unlock(); ec = _linkerScriptReader->parseFile(mb, result); } } Index: lib/ReaderWriter/ELF/File.h =================================================================== --- lib/ReaderWriter/ELF/File.h +++ lib/ReaderWriter/ELF/File.h @@ -114,6 +114,8 @@ typedef std::unordered_map MergedSectionMapT; typedef typename MergedSectionMapT::iterator MergedSectionMapIterT; + typedef llvm::DenseMap> + SectionSymbolsT; public: ELFFile(const ELFTargetInfo &ti, StringRef name) @@ -140,7 +142,8 @@ binaryFile.take(); - std::map > sectionSymbols; + /// \brief Map from sections to a list of symbols that section contains. + SectionSymbolsT sectionSymbols; // Sections that have merge string property std::vector mergeStringSections; @@ -308,8 +311,21 @@ } } + // Iterate over sections by object file position. The pointers point into + // the memory mapped file, so it's valid to sort based on them. + std::vector secSyms; + secSyms.reserve(sectionSymbols.size()); for (auto &i : sectionSymbols) { - auto &symbols = i.second; + secSyms.push_back(&i); + } + std::sort(secSyms.begin(), secSyms.end(), + [](const typename SectionSymbolsT::value_type *a, + const typename SectionSymbolsT::value_type *b) { + return a->first < b->first; + }); + + for (auto &i : secSyms) { + auto &symbols = i->second; // Sort symbols by position. std::stable_sort(symbols.begin(), symbols.end(), [](const Elf_Sym * A, const Elf_Sym * B) { @@ -317,15 +333,15 @@ }); StringRef sectionContents; - if ((EC = _objFile->getSectionContents(i.first, sectionContents))) + if ((EC = _objFile->getSectionContents(i->first, sectionContents))) return; StringRef sectionName; - if ((EC = _objFile->getSectionName(i.first, sectionName))) + if ((EC = _objFile->getSectionName(i->first, sectionName))) return; // If the section has no symbols, create a custom atom for it. - if (i.first->sh_type == llvm::ELF::SHT_PROGBITS && symbols.empty() && + if (i->first->sh_type == llvm::ELF::SHT_PROGBITS && symbols.empty() && !sectionContents.empty()) { Elf_Sym *sym = new (_readerStorage) Elf_Sym; sym->st_name = 0; @@ -337,7 +353,7 @@ ArrayRef content((const uint8_t *)sectionContents.data(), sectionContents.size()); auto newAtom = new (_readerStorage) - ELFDefinedAtom(*this, sectionName, sectionName, sym, i.first, + ELFDefinedAtom(*this, sectionName, sectionName, sym, i->first, content, 0, 0, _references); newAtom->setOrdinal(++ordinal); _definedAtoms._atoms.push_back(newAtom); @@ -350,10 +366,10 @@ ELFReference *anonPrecededBy = nullptr; ELFReference *anonFollowedBy = nullptr; - // i.first is the section the symbol lives in + // i->first is the section the symbol lives in for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) { StringRef symbolName; - if ((EC = _objFile->getSymbolName(i.first, *si, symbolName))) + if ((EC = _objFile->getSymbolName(i->first, *si, symbolName))) return; const Elf_Shdr *section = _objFile->getSection(*si); @@ -378,7 +394,7 @@ uint64_t contentSize; if (si + 1 == se) { // if this is the last symbol, take up the remaining data. - contentSize = isCommon ? 0 : i.first->sh_size - (*si)->st_value; + contentSize = isCommon ? 0 : i->first->sh_size - (*si)->st_value; } else { contentSize = isCommon ? 0 : (*(si + 1))->st_value - (*si)->st_value; } @@ -412,7 +428,7 @@ *sym = **si; sym->setBinding(llvm::ELF::STB_GLOBAL); anonAtom = createDefinedAtomAndAssignRelocations( - "", sectionName, sym, i.first, + "", sectionName, sym, i->first, ArrayRef( (uint8_t *)sectionContents.data() + (*si)->st_value, contentSize)); @@ -457,7 +473,7 @@ } auto newAtom = createDefinedAtomAndAssignRelocations( - symbolName, sectionName, *si, i.first, symbolData); + symbolName, sectionName, *si, i->first, symbolData); newAtom->setOrdinal(++ordinal); @@ -584,7 +600,7 @@ (rai.r_offset < symbol->st_value + content.size()))) continue; bool isMips64EL = _objFile->isMips64EL(); - Kind kind = (Kind) rai.getType(isMips64EL); + Reference::Kind kind = (Reference::Kind) rai.getType(isMips64EL); uint32_t symbolIndex = rai.getSymbol(isMips64EL); auto *ERef = new (_readerStorage) ELFReference(&rai, rai.r_offset - symbol->st_value, nullptr, @@ -598,7 +614,7 @@ if ((ri.r_offset >= symbol->st_value) && (ri.r_offset < symbol->st_value + content.size())) { bool isMips64EL = _objFile->isMips64EL(); - Kind kind = (Kind) ri.getType(isMips64EL); + Reference::Kind kind = (Reference::Kind) ri.getType(isMips64EL); uint32_t symbolIndex = ri.getSymbol(isMips64EL); auto *ERef = new (_readerStorage) ELFReference(&ri, ri.r_offset - symbol->st_value, nullptr,