Supply the C++ toolchain files to genrules using them directly using the
middleman.

RELNOTES: None.
PiperOrigin-RevId: 213451420
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/CommandHelper.java b/src/main/java/com/google/devtools/build/lib/analysis/CommandHelper.java
index 08cebe5..07d5e00 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/CommandHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/CommandHelper.java
@@ -165,11 +165,24 @@
     for (Iterable<? extends TransitiveInfoCollection> tools : toolsList) {
       for (TransitiveInfoCollection dep : tools) { // (Note: host configuration)
         Label label = AliasProvider.getDependencyLabel(dep);
+        MiddlemanProvider toolMiddleman = dep.getProvider(MiddlemanProvider.class);
+        if (toolMiddleman != null) {
+          resolvedToolsBuilder.addAll(toolMiddleman.getMiddlemanArtifact());
+          // It is not obviously correct to skip potentially adding getFilesToRun of the
+          // FilesToRunProvider. However, for all tools that we know of that provide a middleman,
+          // the middleman is equivalent to the list of files coming out of getFilesToRun().
+          // Just adding all the files creates a substantial performance bottleneck. E.g. a C++
+          // toolchain might consist of thousands of files and tracking them one by one for each
+          // action that uses them is inefficient.
+          continue;
+        }
+
         FilesToRunProvider tool = dep.getProvider(FilesToRunProvider.class);
         if (tool == null) {
           continue;
         }
 
+        // TODO(djasper): This is flattening the NestedSet coming out of getFilesToRun(). Don't.
         Iterable<Artifact> files = tool.getFilesToRun();
         resolvedToolsBuilder.addAll(files);
         Artifact executableArtifact = tool.getExecutable();