Index: clang-tools-extra/clang-doc/tool/ClangDocMain.cpp =================================================================== --- clang-tools-extra/clang-doc/tool/ClangDocMain.cpp +++ clang-tools-extra/clang-doc/tool/ClangDocMain.cpp @@ -38,6 +38,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/ThreadPool.h" #include "llvm/Support/raw_ostream.h" #include @@ -67,6 +68,12 @@ llvm::cl::desc("CSS stylesheets to extend the default styles."), llvm::cl::cat(ClangDocCategory)); +static llvm::cl::opt ThreadCount( + "thread-count", + llvm::cl::desc("Threads to use for collecting and reducing infos."), + llvm::cl::init(llvm::hardware_concurrency()), + llvm::cl::cat(ClangDocCategory)); + enum OutputFormatTy { md, yaml, @@ -153,30 +160,6 @@ return Path; } -// Iterate through tool results and build string map of info vectors from the -// encoded bitstreams. -bool bitcodeResultsToInfos( - tooling::ToolResults &Results, - llvm::StringMap>> &Output) { - bool Err = false; - Results.forEachResult([&](StringRef Key, StringRef Value) { - llvm::BitstreamCursor Stream(Value); - doc::ClangDocBitcodeReader Reader(Stream); - auto Infos = Reader.readBitcode(); - if (!Infos) { - llvm::errs() << toString(Infos.takeError()) << "\n"; - Err = true; - return; - } - for (auto &I : Infos.get()) { - auto R = - Output.try_emplace(Key, std::vector>()); - R.first->second.emplace_back(std::move(I)); - } - }); - return Err; -} - int main(int argc, const char **argv) { llvm::sys::PrintStackTraceOnErrorSignal(argv[0]); std::error_code OK; @@ -237,37 +220,67 @@ // In ToolResults, the Key is the hashed USR and the value is the // bitcode-encoded representation of the Info object. llvm::outs() << "Collecting infos...\n"; - llvm::StringMap>> USRToInfos; - if (bitcodeResultsToInfos(*Exec->get()->getToolResults(), USRToInfos)) - return 1; + llvm::StringMap> USRToBitcode; + Exec->get()->getToolResults()->forEachResult( + [&](StringRef Key, StringRef Value) { + auto R = USRToBitcode.try_emplace(Key, std::vector()); + R.first->second.emplace_back(Value); + }); // First reducing phase (reduce all decls into one info per decl). - llvm::outs() << "Reducing " << USRToInfos.size() << " infos...\n"; - for (auto &Group : USRToInfos) { - auto Reduced = doc::mergeInfos(Group.getValue()); - if (!Reduced) { - llvm::errs() << llvm::toString(Reduced.takeError()); - continue; - } + llvm::outs() << "Reducing " << USRToBitcode.size() << " infos...\n"; + bool Error = false; + llvm::ThreadPool Pool(ThreadCount); + for (auto &Group : USRToBitcode) { + Pool.async([&]() { + std::vector> Infos; - doc::Info *I = Reduced.get().get(); - auto InfoPath = getInfoOutputFile(OutDirectory, I->Path, I->extractName(), - "." + Format); - if (!InfoPath) { - llvm::errs() << toString(InfoPath.takeError()) << "\n"; - return 1; - } - std::error_code FileErr; - llvm::raw_fd_ostream InfoOS(InfoPath.get(), FileErr, llvm::sys::fs::F_None); - if (FileErr != OK) { - llvm::errs() << "Error opening info file: " << FileErr.message() << "\n"; - continue; - } + for (auto &Bitcode : Group.getValue()) { + llvm::BitstreamCursor Stream(Bitcode); + doc::ClangDocBitcodeReader Reader(Stream); + auto ReadInfos = Reader.readBitcode(); + if (!ReadInfos) { + llvm::errs() << toString(ReadInfos.takeError()) << "\n"; + Error = true; + return; + } + std::move(ReadInfos->begin(), ReadInfos->end(), + std::back_inserter(Infos)); + } + + auto Reduced = doc::mergeInfos(Infos); + if (!Reduced) { + llvm::errs() << llvm::toString(Reduced.takeError()); + return; + } + + doc::Info *I = Reduced.get().get(); + auto InfoPath = getInfoOutputFile(OutDirectory, I->Path, I->extractName(), + "." + Format); + if (!InfoPath) { + llvm::errs() << toString(InfoPath.takeError()) << "\n"; + Error = true; + return; + } + std::error_code FileErr; + llvm::raw_fd_ostream InfoOS(InfoPath.get(), FileErr, + llvm::sys::fs::F_None); + if (FileErr != OK) { + llvm::errs() << "Error opening info file: " << FileErr.message() + << "\n"; + return; + } - if (auto Err = G->get()->generateDocForInfo(I, InfoOS, CDCtx)) - llvm::errs() << toString(std::move(Err)) << "\n"; + if (auto Err = G->get()->generateDocForInfo(I, InfoOS, CDCtx)) + llvm::errs() << toString(std::move(Err)) << "\n"; + }); } + Pool.wait(); + + if (Error) + return 1; + if (!G->get()->createResources(CDCtx)) return 1;