https://github.com/PeterChou1 updated 
https://github.com/llvm/llvm-project/pull/94717

>From eeb334620df72c395a5ad27f44a864a6a0c194a5 Mon Sep 17 00:00:00 2001
From: PeterChou1 <peter.c...@mail.utoronto.ca>
Date: Thu, 6 Jun 2024 23:18:12 -0400
Subject: [PATCH 1/2] [clang][clang-doc] add asset path

---
 .../clang-doc/tool/ClangDocMain.cpp           | 73 ++++++++++++++-----
 1 file changed, 55 insertions(+), 18 deletions(-)

diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp 
b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
index 21b581fa6df2e..df53c46b4a76e 100644
--- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
+++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -81,6 +81,12 @@ static llvm::cl::list<std::string> UserStylesheets(
     llvm::cl::desc("CSS stylesheets to extend the default styles."),
     llvm::cl::cat(ClangDocCategory));
 
+static llvm::cl::opt<std::string>
+    UserAssetPath("asset",
+                  llvm::cl::desc("User supplied asset path for html output to "
+                                 "override the default css and js files"),
+                  llvm::cl::cat(ClangDocCategory));
+
 static llvm::cl::opt<std::string> SourceRoot("source-root", llvm::cl::desc(R"(
 Directory where processed files are stored.
 Links to definition locations will only be
@@ -131,12 +137,54 @@ std::string GetExecutablePath(const char *Argv0, void 
*MainAddr) {
   return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
 }
 
+void GetAssetFiles(clang::doc::ClangDocContext CDCtx) {
+  std::error_code Code;
+  for (auto DirIt = llvm::sys::fs::directory_iterator(
+                std::string(UserAssetPath), Code),
+            dir_end = llvm::sys::fs::directory_iterator();
+       !Code && DirIt != dir_end; DirIt.increment(Code)) {
+    llvm::SmallString<128> filePath = llvm::SmallString<128>(DirIt->path());
+    if (llvm::sys::fs::is_regular_file(filePath)) {
+      if (filePath.ends_with(".css")) {
+        CDCtx.UserStylesheets.push_back(std::string(filePath));
+      } else if (filePath.ends_with(".js")) {
+        CDCtx.FilesToCopy.push_back(std::string(filePath));
+      }
+    }
+  }
+}
+
+void GetDefaultAssetFiles(const char *Argv0,
+                          clang::doc::ClangDocContext CDCtx) {
+  void *MainAddr = (void *)(intptr_t)GetExecutablePath;
+  std::string ClangDocPath = GetExecutablePath(Argv0, MainAddr);
+  llvm::SmallString<128> NativeClangDocPath;
+  llvm::sys::path::native(ClangDocPath, NativeClangDocPath);
+
+  llvm::SmallString<128> AssetsPath;
+  AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath);
+  llvm::sys::path::append(AssetsPath, "..", "share", "clang");
+  llvm::SmallString<128> DefaultStylesheet;
+  llvm::sys::path::native(AssetsPath, DefaultStylesheet);
+  llvm::sys::path::append(DefaultStylesheet,
+                          "clang-doc-default-stylesheet.css");
+  llvm::SmallString<128> IndexJS;
+  llvm::sys::path::native(AssetsPath, IndexJS);
+  llvm::sys::path::append(IndexJS, "index.js");
+  CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(),
+                               std::string(DefaultStylesheet));
+  CDCtx.FilesToCopy.emplace_back(IndexJS.str());
+
+  llvm::outs() << "No default asset path found using default asset path: "
+               << AssetsPath << "\n";
+}
+
 int main(int argc, const char **argv) {
   llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
   std::error_code OK;
 
   const char *Overview =
-    R"(Generates documentation from source code and comments.
+      R"(Generates documentation from source code and comments.
 
 Example usage for files without flags (default):
 
@@ -182,23 +230,12 @@ Example usage for a project using a compile commands 
database:
       {"index.js", "index_json.js"}};
 
   if (Format == "html") {
-    void *MainAddr = (void *)(intptr_t)GetExecutablePath;
-    std::string ClangDocPath = GetExecutablePath(argv[0], MainAddr);
-    llvm::SmallString<128> NativeClangDocPath;
-    llvm::sys::path::native(ClangDocPath, NativeClangDocPath);
-    llvm::SmallString<128> AssetsPath;
-    AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath);
-    llvm::sys::path::append(AssetsPath, "..", "share", "clang");
-    llvm::SmallString<128> DefaultStylesheet;
-    llvm::sys::path::native(AssetsPath, DefaultStylesheet);
-    llvm::sys::path::append(DefaultStylesheet,
-                            "clang-doc-default-stylesheet.css");
-    llvm::SmallString<128> IndexJS;
-    llvm::sys::path::native(AssetsPath, IndexJS);
-    llvm::sys::path::append(IndexJS, "index.js");
-    CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(),
-                                 std::string(DefaultStylesheet));
-    CDCtx.FilesToCopy.emplace_back(IndexJS.str());
+    if (!UserAssetPath.empty() &&
+        llvm::sys::fs::is_directory(std::string(UserAssetPath))) {
+      GetAssetFiles(CDCtx);
+    } else {
+      GetDefaultAssetFiles(argv[0], CDCtx);
+    }
   }
 
   // Mapping phase

>From d535cb7b7c92a22931b276a8c9fe97a2f04c2258 Mon Sep 17 00:00:00 2001
From: PeterChou1 <peter.c...@mail.utoronto.ca>
Date: Fri, 7 Jun 2024 01:40:29 -0400
Subject: [PATCH 2/2] [clang][clang-doc] fixes bug caused by not passing by
 reference

---
 .../clang-doc/tool/ClangDocMain.cpp           | 455 +++++++++---------
 1 file changed, 228 insertions(+), 227 deletions(-)

diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp 
b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
index df53c46b4a76e..ab6f6198aae32 100644
--- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
+++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -54,38 +54,38 @@ static llvm::cl::extrahelp 
CommonHelp(CommonOptionsParser::HelpMessage);
 static llvm::cl::OptionCategory ClangDocCategory("clang-doc options");
 
 static llvm::cl::opt<std::string>
-    ProjectName("project-name", llvm::cl::desc("Name of project."),
-                llvm::cl::cat(ClangDocCategory));
+        ProjectName("project-name", llvm::cl::desc("Name of project."),
+                    llvm::cl::cat(ClangDocCategory));
 
 static llvm::cl::opt<bool> IgnoreMappingFailures(
-    "ignore-map-errors",
-    llvm::cl::desc("Continue if files are not mapped correctly."),
-    llvm::cl::init(true), llvm::cl::cat(ClangDocCategory));
+        "ignore-map-errors",
+        llvm::cl::desc("Continue if files are not mapped correctly."),
+        llvm::cl::init(true), llvm::cl::cat(ClangDocCategory));
 
 static llvm::cl::opt<std::string>
-    OutDirectory("output",
-                 llvm::cl::desc("Directory for outputting generated files."),
-                 llvm::cl::init("docs"), llvm::cl::cat(ClangDocCategory));
+        OutDirectory("output",
+                     llvm::cl::desc("Directory for outputting generated 
files."),
+                     llvm::cl::init("docs"), llvm::cl::cat(ClangDocCategory));
 
 static llvm::cl::opt<bool>
-    PublicOnly("public", llvm::cl::desc("Document only public declarations."),
-               llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
+        PublicOnly("public", llvm::cl::desc("Document only public 
declarations."),
+                   llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
 
 static llvm::cl::opt<bool> DoxygenOnly(
-    "doxygen",
-    llvm::cl::desc("Use only doxygen-style comments to generate docs."),
-    llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
+        "doxygen",
+        llvm::cl::desc("Use only doxygen-style comments to generate docs."),
+        llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
 
 static llvm::cl::list<std::string> UserStylesheets(
-    "stylesheets", llvm::cl::CommaSeparated,
-    llvm::cl::desc("CSS stylesheets to extend the default styles."),
-    llvm::cl::cat(ClangDocCategory));
+        "stylesheets", llvm::cl::CommaSeparated,
+        llvm::cl::desc("CSS stylesheets to extend the default styles."),
+        llvm::cl::cat(ClangDocCategory));
 
 static llvm::cl::opt<std::string>
-    UserAssetPath("asset",
-                  llvm::cl::desc("User supplied asset path for html output to "
-                                 "override the default css and js files"),
-                  llvm::cl::cat(ClangDocCategory));
+        UserAssetPath("asset",
+                      llvm::cl::desc("User supplied asset path for html output 
to "
+                                     "override the default css and js files"),
+                      llvm::cl::cat(ClangDocCategory));
 
 static llvm::cl::opt<std::string> SourceRoot("source-root", llvm::cl::desc(R"(
 Directory where processed files are stored.
@@ -94,38 +94,38 @@ generated if the file is in this dir.)"),
                                              llvm::cl::cat(ClangDocCategory));
 
 static llvm::cl::opt<std::string>
-    RepositoryUrl("repository", llvm::cl::desc(R"(
+        RepositoryUrl("repository", llvm::cl::desc(R"(
 URL of repository that hosts code.
 Used for links to definition locations.)"),
-                  llvm::cl::cat(ClangDocCategory));
+                      llvm::cl::cat(ClangDocCategory));
 
 enum OutputFormatTy {
-  md,
-  yaml,
-  html,
+    md,
+    yaml,
+    html,
 };
 
 static llvm::cl::opt<OutputFormatTy>
-    FormatEnum("format", llvm::cl::desc("Format for outputted docs."),
-               llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml",
-                                           "Documentation in YAML format."),
-                                clEnumValN(OutputFormatTy::md, "md",
-                                           "Documentation in MD format."),
-                                clEnumValN(OutputFormatTy::html, "html",
-                                           "Documentation in HTML format.")),
-               llvm::cl::init(OutputFormatTy::yaml),
-               llvm::cl::cat(ClangDocCategory));
+        FormatEnum("format", llvm::cl::desc("Format for outputted docs."),
+                   llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml",
+                                               "Documentation in YAML 
format."),
+                                    clEnumValN(OutputFormatTy::md, "md",
+                                               "Documentation in MD format."),
+                                    clEnumValN(OutputFormatTy::html, "html",
+                                               "Documentation in HTML 
format.")),
+                   llvm::cl::init(OutputFormatTy::yaml),
+                   llvm::cl::cat(ClangDocCategory));
 
 std::string getFormatString() {
-  switch (FormatEnum) {
-  case OutputFormatTy::yaml:
-    return "yaml";
-  case OutputFormatTy::md:
-    return "md";
-  case OutputFormatTy::html:
-    return "html";
-  }
-  llvm_unreachable("Unknown OutputFormatTy");
+    switch (FormatEnum) {
+        case OutputFormatTy::yaml:
+            return "yaml";
+        case OutputFormatTy::md:
+            return "md";
+        case OutputFormatTy::html:
+            return "html";
+    }
+    llvm_unreachable("Unknown OutputFormatTy");
 }
 
 // This function isn't referenced outside its translation unit, but it
@@ -134,57 +134,58 @@ std::string getFormatString() {
 // address of main, and some platforms can't implement GetMainExecutable
 // without being given the address of a function in the main executable).
 std::string GetExecutablePath(const char *Argv0, void *MainAddr) {
-  return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
+    return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
 }
 
-void GetAssetFiles(clang::doc::ClangDocContext CDCtx) {
-  std::error_code Code;
-  for (auto DirIt = llvm::sys::fs::directory_iterator(
-                std::string(UserAssetPath), Code),
-            dir_end = llvm::sys::fs::directory_iterator();
-       !Code && DirIt != dir_end; DirIt.increment(Code)) {
-    llvm::SmallString<128> filePath = llvm::SmallString<128>(DirIt->path());
-    if (llvm::sys::fs::is_regular_file(filePath)) {
-      if (filePath.ends_with(".css")) {
-        CDCtx.UserStylesheets.push_back(std::string(filePath));
-      } else if (filePath.ends_with(".js")) {
-        CDCtx.FilesToCopy.push_back(std::string(filePath));
-      }
+void GetAssetFiles(clang::doc::ClangDocContext &CDCtx) {
+    std::error_code Code;
+    for (auto DirIt = llvm::sys::fs::directory_iterator(
+            std::string(UserAssetPath), Code),
+                 dir_end = llvm::sys::fs::directory_iterator();
+         !Code && DirIt != dir_end; DirIt.increment(Code)) {
+        llvm::SmallString<128> filePath = 
llvm::SmallString<128>(DirIt->path());
+        if (llvm::sys::fs::is_regular_file(filePath)) {
+            if (filePath.ends_with(".css")) {
+                CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(),
+                                             std::string(filePath));
+            } else if (filePath.ends_with(".js")) {
+                CDCtx.FilesToCopy.emplace_back(filePath.str());
+            }
+        }
     }
-  }
 }
 
 void GetDefaultAssetFiles(const char *Argv0,
-                          clang::doc::ClangDocContext CDCtx) {
-  void *MainAddr = (void *)(intptr_t)GetExecutablePath;
-  std::string ClangDocPath = GetExecutablePath(Argv0, MainAddr);
-  llvm::SmallString<128> NativeClangDocPath;
-  llvm::sys::path::native(ClangDocPath, NativeClangDocPath);
-
-  llvm::SmallString<128> AssetsPath;
-  AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath);
-  llvm::sys::path::append(AssetsPath, "..", "share", "clang");
-  llvm::SmallString<128> DefaultStylesheet;
-  llvm::sys::path::native(AssetsPath, DefaultStylesheet);
-  llvm::sys::path::append(DefaultStylesheet,
-                          "clang-doc-default-stylesheet.css");
-  llvm::SmallString<128> IndexJS;
-  llvm::sys::path::native(AssetsPath, IndexJS);
-  llvm::sys::path::append(IndexJS, "index.js");
-  CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(),
-                               std::string(DefaultStylesheet));
-  CDCtx.FilesToCopy.emplace_back(IndexJS.str());
-
-  llvm::outs() << "No default asset path found using default asset path: "
-               << AssetsPath << "\n";
+                          clang::doc::ClangDocContext &CDCtx) {
+    void *MainAddr = (void *)(intptr_t)GetExecutablePath;
+    std::string ClangDocPath = GetExecutablePath(Argv0, MainAddr);
+    llvm::SmallString<128> NativeClangDocPath;
+    llvm::sys::path::native(ClangDocPath, NativeClangDocPath);
+
+    llvm::SmallString<128> AssetsPath;
+    AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath);
+    llvm::sys::path::append(AssetsPath, "..", "share", "clang");
+    llvm::SmallString<128> DefaultStylesheet;
+    llvm::sys::path::native(AssetsPath, DefaultStylesheet);
+    llvm::sys::path::append(DefaultStylesheet,
+                            "clang-doc-default-stylesheet.css");
+    llvm::SmallString<128> IndexJS;
+    llvm::sys::path::native(AssetsPath, IndexJS);
+    llvm::sys::path::append(IndexJS, "index.js");
+    CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(),
+                                 std::string(DefaultStylesheet));
+    CDCtx.FilesToCopy.emplace_back(IndexJS.str());
+
+    llvm::outs() << "No default asset path found using default asset path: "
+                 << AssetsPath << "\n";
 }
 
 int main(int argc, const char **argv) {
-  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
-  std::error_code OK;
+    llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+    std::error_code OK;
 
-  const char *Overview =
-      R"(Generates documentation from source code and comments.
+    const char *Overview =
+            R"(Generates documentation from source code and comments.
 
 Example usage for files without flags (default):
 
@@ -195,150 +196,150 @@ Example usage for a project using a compile commands 
database:
   $ clang-doc --executor=all-TUs compile_commands.json
 )";
 
-  auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
-      argc, argv, ClangDocCategory, Overview);
-
-  if (!Executor) {
-    llvm::errs() << toString(Executor.takeError()) << "\n";
-    return 1;
-  }
-
-  // Fail early if an invalid format was provided.
-  std::string Format = getFormatString();
-  llvm::outs() << "Emiting docs in " << Format << " format.\n";
-  auto G = doc::findGeneratorByName(Format);
-  if (!G) {
-    llvm::errs() << toString(G.takeError()) << "\n";
-    return 1;
-  }
-
-  ArgumentsAdjuster ArgAdjuster;
-  if (!DoxygenOnly)
-    ArgAdjuster = combineAdjusters(
-        getInsertArgumentAdjuster("-fparse-all-comments",
-                                  tooling::ArgumentInsertPosition::END),
-        ArgAdjuster);
-
-  clang::doc::ClangDocContext CDCtx = {
-      Executor->get()->getExecutionContext(),
-      ProjectName,
-      PublicOnly,
-      OutDirectory,
-      SourceRoot,
-      RepositoryUrl,
-      {UserStylesheets.begin(), UserStylesheets.end()},
-      {"index.js", "index_json.js"}};
-
-  if (Format == "html") {
-    if (!UserAssetPath.empty() &&
-        llvm::sys::fs::is_directory(std::string(UserAssetPath))) {
-      GetAssetFiles(CDCtx);
-    } else {
-      GetDefaultAssetFiles(argv[0], CDCtx);
+    auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
+            argc, argv, ClangDocCategory, Overview);
+
+    if (!Executor) {
+        llvm::errs() << toString(Executor.takeError()) << "\n";
+        return 1;
+    }
+
+    // Fail early if an invalid format was provided.
+    std::string Format = getFormatString();
+    llvm::outs() << "Emiting docs in " << Format << " format.\n";
+    auto G = doc::findGeneratorByName(Format);
+    if (!G) {
+        llvm::errs() << toString(G.takeError()) << "\n";
+        return 1;
     }
-  }
-
-  // Mapping phase
-  llvm::outs() << "Mapping decls...\n";
-  auto Err =
-      Executor->get()->execute(doc::newMapperActionFactory(CDCtx), 
ArgAdjuster);
-  if (Err) {
-    if (IgnoreMappingFailures)
-      llvm::errs() << "Error mapping decls in files. Clang-doc will ignore "
-                      "these files and continue:\n"
-                   << toString(std::move(Err)) << "\n";
-    else {
-      llvm::errs() << toString(std::move(Err)) << "\n";
-      return 1;
+
+    ArgumentsAdjuster ArgAdjuster;
+    if (!DoxygenOnly)
+        ArgAdjuster = combineAdjusters(
+                getInsertArgumentAdjuster("-fparse-all-comments",
+                                          
tooling::ArgumentInsertPosition::END),
+                ArgAdjuster);
+
+    clang::doc::ClangDocContext CDCtx = {
+            Executor->get()->getExecutionContext(),
+            ProjectName,
+            PublicOnly,
+            OutDirectory,
+            SourceRoot,
+            RepositoryUrl,
+            {UserStylesheets.begin(), UserStylesheets.end()},
+            {"index.js", "index_json.js"}};
+
+    if (Format == "html") {
+        if (!UserAssetPath.empty() &&
+            llvm::sys::fs::is_directory(std::string(UserAssetPath))) {
+            GetAssetFiles(CDCtx);
+        } else {
+            GetDefaultAssetFiles(argv[0], CDCtx);
+        }
     }
-  }
-
-  // Collect values into output by key.
-  // 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<std::vector<StringRef>> USRToBitcode;
-  Executor->get()->getToolResults()->forEachResult(
-      [&](StringRef Key, StringRef Value) {
-        auto R = USRToBitcode.try_emplace(Key, std::vector<StringRef>());
-        R.first->second.emplace_back(Value);
-      });
-
-  // Collects all Infos according to their unique USR value. This map is added
-  // to from the thread pool below and is protected by the USRToInfoMutex.
-  llvm::sys::Mutex USRToInfoMutex;
-  llvm::StringMap<std::unique_ptr<doc::Info>> USRToInfo;
-
-  // First reducing phase (reduce all decls into one info per decl).
-  llvm::outs() << "Reducing " << USRToBitcode.size() << " infos...\n";
-  std::atomic<bool> Error;
-  Error = false;
-  llvm::sys::Mutex IndexMutex;
-  // ExecutorConcurrency is a flag exposed by AllTUsExecution.h
-  llvm::DefaultThreadPool 
Pool(llvm::hardware_concurrency(ExecutorConcurrency));
-  for (auto &Group : USRToBitcode) {
-    Pool.async([&]() {
-      std::vector<std::unique_ptr<doc::Info>> Infos;
-
-      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;
+
+    // Mapping phase
+    llvm::outs() << "Mapping decls...\n";
+    auto Err =
+            Executor->get()->execute(doc::newMapperActionFactory(CDCtx), 
ArgAdjuster);
+    if (Err) {
+        if (IgnoreMappingFailures)
+            llvm::errs() << "Error mapping decls in files. Clang-doc will 
ignore "
+                            "these files and continue:\n"
+                         << toString(std::move(Err)) << "\n";
+        else {
+            llvm::errs() << toString(std::move(Err)) << "\n";
+            return 1;
         }
-        std::move(ReadInfos->begin(), ReadInfos->end(),
-                  std::back_inserter(Infos));
-      }
-
-      auto Reduced = doc::mergeInfos(Infos);
-      if (!Reduced) {
-        llvm::errs() << llvm::toString(Reduced.takeError());
-        return;
-      }
-
-      // Add a reference to this Info in the Index
-      {
-        std::lock_guard<llvm::sys::Mutex> Guard(IndexMutex);
-        clang::doc::Generator::addInfoToIndex(CDCtx.Idx, Reduced.get().get());
-      }
-
-      // Save in the result map (needs a lock due to threaded access).
-      {
-        std::lock_guard<llvm::sys::Mutex> Guard(USRToInfoMutex);
-        USRToInfo[Group.getKey()] = std::move(Reduced.get());
-      }
-    });
-  }
-
-  Pool.wait();
-
-  if (Error)
-    return 1;
-
-  // Ensure the root output directory exists.
-  if (std::error_code Err = llvm::sys::fs::create_directories(OutDirectory);
-      Err != std::error_code()) {
-    llvm::errs() << "Failed to create directory '" << OutDirectory << "'\n";
-    return 1;
-  }
-
-  // Run the generator.
-  llvm::outs() << "Generating docs...\n";
-  if (auto Err =
-          G->get()->generateDocs(OutDirectory, std::move(USRToInfo), CDCtx)) {
-    llvm::errs() << toString(std::move(Err)) << "\n";
-    return 1;
-  }
-
-  llvm::outs() << "Generating assets for docs...\n";
-  Err = G->get()->createResources(CDCtx);
-  if (Err) {
-    llvm::errs() << toString(std::move(Err)) << "\n";
-    return 1;
-  }
-
-  return 0;
+    }
+
+    // Collect values into output by key.
+    // 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<std::vector<StringRef>> USRToBitcode;
+    Executor->get()->getToolResults()->forEachResult(
+            [&](StringRef Key, StringRef Value) {
+                auto R = USRToBitcode.try_emplace(Key, 
std::vector<StringRef>());
+                R.first->second.emplace_back(Value);
+            });
+
+    // Collects all Infos according to their unique USR value. This map is 
added
+    // to from the thread pool below and is protected by the USRToInfoMutex.
+    llvm::sys::Mutex USRToInfoMutex;
+    llvm::StringMap<std::unique_ptr<doc::Info>> USRToInfo;
+
+    // First reducing phase (reduce all decls into one info per decl).
+    llvm::outs() << "Reducing " << USRToBitcode.size() << " infos...\n";
+    std::atomic<bool> Error;
+    Error = false;
+    llvm::sys::Mutex IndexMutex;
+    // ExecutorConcurrency is a flag exposed by AllTUsExecution.h
+    llvm::DefaultThreadPool 
Pool(llvm::hardware_concurrency(ExecutorConcurrency));
+    for (auto &Group : USRToBitcode) {
+        Pool.async([&]() {
+            std::vector<std::unique_ptr<doc::Info>> Infos;
+
+            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;
+            }
+
+            // Add a reference to this Info in the Index
+            {
+                std::lock_guard<llvm::sys::Mutex> Guard(IndexMutex);
+                clang::doc::Generator::addInfoToIndex(CDCtx.Idx, 
Reduced.get().get());
+            }
+
+            // Save in the result map (needs a lock due to threaded access).
+            {
+                std::lock_guard<llvm::sys::Mutex> Guard(USRToInfoMutex);
+                USRToInfo[Group.getKey()] = std::move(Reduced.get());
+            }
+        });
+    }
+
+    Pool.wait();
+
+    if (Error)
+        return 1;
+
+    // Ensure the root output directory exists.
+    if (std::error_code Err = llvm::sys::fs::create_directories(OutDirectory);
+            Err != std::error_code()) {
+        llvm::errs() << "Failed to create directory '" << OutDirectory << 
"'\n";
+        return 1;
+    }
+
+    // Run the generator.
+    llvm::outs() << "Generating docs...\n";
+    if (auto Err =
+            G->get()->generateDocs(OutDirectory, std::move(USRToInfo), CDCtx)) 
{
+        llvm::errs() << toString(std::move(Err)) << "\n";
+        return 1;
+    }
+
+    llvm::outs() << "Generating assets for docs...\n";
+    Err = G->get()->createResources(CDCtx);
+    if (Err) {
+        llvm::errs() << toString(std::move(Err)) << "\n";
+        return 1;
+    }
+
+    return 0;
 }

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to