================
@@ -123,6 +156,107 @@ class IndexActionFactory : public 
tooling::FrontendActionFactory {
   RelationSlab::Builder Relations;
 };
 
+// Action factory that writes per-file shards (for sharded index format).
+// Each TU's index data is sharded independently — no merging across TUs.
+// Header shards are deduplicated: if a header's content hasn't changed since
+// the last time we wrote its shard, we skip writing it again.
+class ShardedIndexActionFactory : public tooling::FrontendActionFactory {
+public:
+  ShardedIndexActionFactory(BackgroundIndexStorage &Storage)
+      : Storage(Storage) {}
+
+  std::unique_ptr<FrontendAction> create() override {
+    // Snapshot the current shard versions so the callback can check staleness
+    // without holding the lock during indexing.
+    llvm::StringMap<ShardVersion> Snapshot;
+    {
+      std::lock_guard<std::mutex> Lock(ShardVersionsMu);
+      Snapshot = ShardVersions;
+    }
+
+    SymbolCollector::Options Opts;
+    Opts.CountReferences = true;
+
+    return createStaticIndexingAction(
+        Opts, [this, Snapshot](IndexFileIn Index) {
+          writeShards(std::move(Index), Snapshot);
+        });
+  }
+
+  bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
+                     FileManager *Files,
+                     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+                     DiagnosticConsumer *DiagConsumer) override {
+    disableUnsupportedOptions(*Invocation);
+    return tooling::FrontendActionFactory::runInvocation(
+        std::move(Invocation), Files, std::move(PCHContainerOps), 
DiagConsumer);
+  }
+
+private:
+  void writeShards(IndexFileIn Index,
+                   const llvm::StringMap<ShardVersion> &Snapshot) {
+    if (!Index.Sources)
+      return;
+
+    // Find the URI of the main file (the TU root). Store as owned string
+    // because we move Index below, which would invalidate any StringRef into 
it.
+    std::string MainUri;
+    for (const auto &[Uri, Node] : *Index.Sources) {
+      if (Node.Flags & IncludeGraphNode::SourceFlag::IsTU) {
+        MainUri = Uri.str();
+        break;
+      }
+    }
+
+    // Collect files that need updated shards, based on content digest.
+    // Files whose shard was already written with the same digest are skipped.
+    llvm::StringMap<std::pair<Path, FileDigest>> FilesToUpdate;
+    for (const auto &[Uri, Node] : *Index.Sources) {
+      auto AbsPath = URI::resolve(Uri, MainUri);
+      if (!AbsPath) {
+        elog("Failed to resolve URI {0}: {1}", Uri, AbsPath.takeError());
+        continue;
+      }
+      auto DigestIt = Snapshot.find(*AbsPath);
+      if (DigestIt == Snapshot.end() || DigestIt->second.Digest != Node.Digest)
+        FilesToUpdate[Uri] = {std::move(*AbsPath), Node.Digest};
+    }
+
+    // Shard the index data by file.
+    FileShardedIndex ShardedIndex(std::move(Index));
+
+    unsigned Written = 0;
+    for (const auto &[Uri, PathAndDigest] : FilesToUpdate) {
+      auto Shard = ShardedIndex.getShard(Uri);
+      if (!Shard) {
+        elog("Failed to get shard for {0}", Uri);
+        continue;
+      }
+      PathRef Path = PathAndDigest.first;
+
+      // Command line is only meaningful for the TU's main file.
+      if (Uri != MainUri)
+        Shard->Cmd.reset();
+
+      IndexFileOut Out(*Shard);
+      Out.Format = IndexFileFormat::RIFF;
----------------
HighCommander4 wrote:

Since we're hardcoding `RIFF` here, we should error out if 
`--index-type=sharded` is used with `--format=yaml`, rather than silently 
succeeding and writing RIFF anyways.

https://github.com/llvm/llvm-project/pull/175209
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to