From e94da9ccbc099468df752227716880efef66411b Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov@redhat.com>
Date: Thu, 27 Feb 2025 15:44:27 +0100
Subject: [PATCH] clover: Don't include libclc headers

Per https://github.com/llvm/llvm-project/issues/119967 these
headers are internal implementation details of libclc and were
never supposed to be installed. They are not available anymore
since LLVM 20. Instead opencl-c.h should be used.

There already ise a code path for including opencl-c.h, so always
use it.

This didn't work for me out of the box, because the build system
currently hardcodes the clang resource directory, which is incorrect
for Fedora at least. Fix this by using GetResourcePath +
CLANG_RESOURCE_DIR provided by clang instead. This is basically
the same as what is done in clc_helper.c

I've still retained the old behavior as a fallback just in case
(e.g. if clang is linked statically?)

Upstream-Status: Submitted [https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33805/]
Reviewed-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33805>
Signed-off-by: Khem Raj <raj.khem@gmail.com>
---
 .../frontends/clover/llvm/invocation.cpp      | 53 +++++++++++++------
 src/gallium/frontends/clover/meson.build      |  5 +-
 2 files changed, 39 insertions(+), 19 deletions(-)

diff --git a/src/gallium/frontends/clover/llvm/invocation.cpp b/src/gallium/frontends/clover/llvm/invocation.cpp
index 3cbb05b..ca030b4 100644
--- a/src/gallium/frontends/clover/llvm/invocation.cpp
+++ b/src/gallium/frontends/clover/llvm/invocation.cpp
@@ -24,6 +24,8 @@
 // OTHER DEALINGS IN THE SOFTWARE.
 //
 
+#include <dlfcn.h>
+
 #include <llvm/IR/DiagnosticPrinter.h>
 #include <llvm/IR/DiagnosticInfo.h>
 #include <llvm/IR/LLVMContext.h>
@@ -39,6 +41,8 @@
 #include <clang/Frontend/TextDiagnosticBuffer.h>
 #include <clang/Frontend/TextDiagnosticPrinter.h>
 #include <clang/Basic/TargetInfo.h>
+#include <clang/Config/config.h>
+#include <clang/Driver/Driver.h>
 
 #if LLVM_VERSION_MAJOR >= 20
 #include <llvm/Support/VirtualFileSystem.h>
@@ -323,6 +327,30 @@ namespace {
       return c;
    }
 
+   std::string getResourceDirectory() {
+      Dl_info info;
+      if (dladdr((void *)clang::CompilerInvocation::CreateFromArgs, &info) == 0) {
+         return FALLBACK_CLANG_RESOURCE_DIR;
+      }
+
+      char *libclang_path = realpath(info.dli_fname, NULL);
+      if (libclang_path == nullptr) {
+         return FALLBACK_CLANG_RESOURCE_DIR;
+      }
+
+      // GetResourcePath is a way to retrieve the actual libclang resource dir based on a given
+      // binary or library.
+      std::string clang_resource_dir =
+#if LLVM_VERSION_MAJOR >= 20
+         clang::driver::Driver::GetResourcesPath(std::string(libclang_path));
+#else
+         clang::driver::Driver::GetResourcesPath(std::string(libclang_path), CLANG_RESOURCE_DIR);
+#endif
+      free(libclang_path);
+
+      return clang_resource_dir;
+   }
+
    std::unique_ptr<Module>
    compile(LLVMContext &ctx, clang::CompilerInstance &c,
            const std::string &name, const std::string &source,
@@ -331,25 +359,18 @@ namespace {
       c.getFrontendOpts().ProgramAction = clang::frontend::EmitLLVMOnly;
       c.getHeaderSearchOpts().UseBuiltinIncludes = true;
       c.getHeaderSearchOpts().UseStandardSystemIncludes = true;
-      c.getHeaderSearchOpts().ResourceDir = CLANG_RESOURCE_DIR;
 
-      if (use_libclc) {
-         // Add libclc generic search path
-         c.getHeaderSearchOpts().AddPath(LIBCLC_INCLUDEDIR,
-                                         clang::frontend::Angled,
-                                         false, false);
+      std::string clang_resource_dir = getResourceDirectory();
+      c.getHeaderSearchOpts().ResourceDir = clang_resource_dir;
 
-         // Add libclc include
-         c.getPreprocessorOpts().Includes.push_back("clc/clc.h");
-      } else {
-         // Add opencl-c generic search path
-         c.getHeaderSearchOpts().AddPath(CLANG_RESOURCE_DIR,
-                                         clang::frontend::Angled,
-                                         false, false);
+      // Add opencl-c generic search path
+      std::string clang_include_path = clang_resource_dir + "/include";
+      c.getHeaderSearchOpts().AddPath(clang_include_path,
+                                      clang::frontend::Angled,
+                                      false, false);
 
-         // Add opencl include
-         c.getPreprocessorOpts().Includes.push_back("opencl-c.h");
-      }
+      // Add opencl include
+      c.getPreprocessorOpts().Includes.push_back("opencl-c.h");
 
       // Add definition for the OpenCL version
       const auto dev_version = dev.device_version();
diff --git a/src/gallium/frontends/clover/meson.build b/src/gallium/frontends/clover/meson.build
index e569b86..56a9894 100644
--- a/src/gallium/frontends/clover/meson.build
+++ b/src/gallium/frontends/clover/meson.build
@@ -10,7 +10,6 @@ clover_opencl_cpp_args = [
   '-DCL_USE_DEPRECATED_OPENCL_2_0_APIS',
   '-DCL_USE_DEPRECATED_OPENCL_2_1_APIS',
   '-DCL_USE_DEPRECATED_OPENCL_2_2_APIS',
-  '-DLIBCLC_INCLUDEDIR="@0@/"'.format(dep_clc.get_variable(pkgconfig : 'includedir')),
   '-DLIBCLC_LIBEXECDIR="@0@/"'.format(dep_clc.get_variable(pkgconfig : 'libexecdir'))
 ]
 clover_incs = [inc_include, inc_src, inc_gallium, inc_gallium_aux]
@@ -43,9 +42,9 @@ libclllvm = static_library(
   cpp_args : [
     clover_cpp_args,
     clover_opencl_cpp_args,
-    '-DCLANG_RESOURCE_DIR="@0@"'.format(join_paths(
+    '-DFALLBACK_CLANG_RESOURCE_DIR="@0@"'.format(join_paths(
       dep_llvm.get_variable(cmake : 'LLVM_LIBRARY_DIR', configtool: 'libdir'), 'clang',
-      dep_llvm.version(), 'include',
+      dep_llvm.version()
     )),
   ],
   gnu_symbol_visibility : 'hidden',
