Support of using the absolute path profile for LLVM's Context Sensitive FDO

This CL adds the support of using the absolute path profile in LLVM's Context
Sensitive FDO. The newly added option is
    --cs_fdo_absolute_path=<csfdo_profile>
The profile can be of the zip file containing the profile file, a raw or an
indexed LLVM profile file. Unlike --fdo_optimize, it will not accept a profile label.
Profile label should should use option --cs_fdo_profile.

RELNOTES: Add new options --cs_fdo_absolute_path= to support the absolute path
profile for LLVM's context-sensitive FDO.
PiperOrigin-RevId: 251252510
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
index d72b76b..6d7798e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
@@ -147,6 +147,8 @@
   private final PathFragment fdoPath;
   private final Label fdoOptimizeLabel;
 
+  private final PathFragment csFdoAbsolutePath;
+
   private final ImmutableList<String> conlyopts;
 
   private final ImmutableList<String> copts;
@@ -197,6 +199,22 @@
       }
     }
 
+    PathFragment csFdoAbsolutePath = null;
+    if (cppOptions.csFdoAbsolutePathForBuild != null) {
+      csFdoAbsolutePath = PathFragment.create(cppOptions.csFdoAbsolutePathForBuild);
+      if (!csFdoAbsolutePath.isAbsolute()) {
+        throw new InvalidConfigurationException(
+            "Path of '"
+                + csFdoAbsolutePath.getPathString()
+                + "' in --cs_fdo_absolute_path is not an absolute path.");
+      }
+      try {
+        FileSystemUtils.checkBaseName(csFdoAbsolutePath.getBaseName());
+      } catch (IllegalArgumentException e) {
+        throw new InvalidConfigurationException(e);
+      }
+    }
+
     return new CppConfiguration(
         cppOptions.doNotUseCpuTransformer
             ? commonOptions.cpu
@@ -204,6 +222,7 @@
         Preconditions.checkNotNull(commonOptions.cpu),
         fdoPath,
         fdoProfileLabel,
+        csFdoAbsolutePath,
         ImmutableList.copyOf(cppOptions.conlyoptList),
         ImmutableList.copyOf(cppOptions.coptList),
         ImmutableList.copyOf(cppOptions.cxxoptList),
@@ -224,6 +243,7 @@
       String desiredCpu,
       PathFragment fdoPath,
       Label fdoOptimizeLabel,
+      PathFragment csFdoAbsolutePath,
       ImmutableList<String> conlyopts,
       ImmutableList<String> copts,
       ImmutableList<String> cxxopts,
@@ -239,6 +259,7 @@
     this.desiredCpu = desiredCpu;
     this.fdoPath = fdoPath;
     this.fdoOptimizeLabel = fdoOptimizeLabel;
+    this.csFdoAbsolutePath = csFdoAbsolutePath;
     this.conlyopts = conlyopts;
     this.copts = copts;
     this.cxxopts = cxxopts;
@@ -548,6 +569,10 @@
     return cppOptions.csFdoInstrumentForBuild;
   }
 
+  public PathFragment getCSFdoAbsolutePath() {
+    return csFdoAbsolutePath;
+  }
+
   Label getFdoPrefetchHintsLabel() {
     if (isThisHostConfigurationDoNotUseWillBeRemovedFor129045294()) {
       // We don't want FDO in the host configuration
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java
index 52a0619..91641f6 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java
@@ -432,6 +432,17 @@
   public String csFdoInstrumentForBuild;
 
   @Option(
+      name = "cs_fdo_absolute_path",
+      defaultValue = "null",
+      documentationCategory = OptionDocumentationCategory.OUTPUT_PARAMETERS,
+      effectTags = {OptionEffectTag.AFFECTS_OUTPUTS},
+      help =
+          "Use CSFDO profile information to optimize compilation. Specify the absolute path name "
+              + "of the zip file containing the profile file, a raw or an indexed "
+              + "LLVM profile file.")
+  public String csFdoAbsolutePathForBuild;
+
+  @Option(
       name = "xbinary_fdo",
       defaultValue = "null",
       documentationCategory = OptionDocumentationCategory.OUTPUT_PARAMETERS,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoHelper.java
index 687373a..aab809c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoHelper.java
@@ -90,7 +90,10 @@
       }
 
       Pair<FdoInputFile, Artifact> csFdoInputs = null;
-      if (cppConfiguration.getCSFdoProfileLabel() != null) {
+      PathFragment csFdoZip = cppConfiguration.getCSFdoAbsolutePath();
+      if (csFdoZip != null) {
+        csFdoInputFile = FdoInputFile.fromAbsolutePath(csFdoZip);
+      } else if (cppConfiguration.getCSFdoProfileLabel() != null) {
         csFdoInputs = getFdoInputs(ruleContext, attributes.getCSFdoProfileProvider());
       }
       if (csFdoInputs != null) {
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java
index eb32956..dc6120c 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java
@@ -455,6 +455,24 @@
   }
 
   @Test
+  public void testCSFdoRejectRelativePath() throws Exception {
+    reporter.removeHandler(failFastHandler);
+    scratch.file("a/BUILD", "cc_toolchain_alias(name = 'b')");
+    scratch.file("a/profile.profdata", "");
+    scratch.file("a/csprofile.profdata", "");
+    Exception e =
+        assertThrows(
+            Exception.class,
+            () ->
+                useConfiguration(
+                    "-c",
+                    "opt",
+                    "--fdo_optimize=a/profile.profdata",
+                    "--cs_fdo_absolute_path=a/csprofile.profdata"));
+    assertThat(e).hasMessageThat().contains("in --cs_fdo_absolute_path is not an absolute path");
+  }
+
+  @Test
   public void testXFdoOptimizeNotProvider() throws Exception {
     reporter.removeHandler(failFastHandler);
     scratch.file(