Author: Fraser Cormack Date: 2025-08-04T15:37:22+01:00 New Revision: df7473673214b063f7ca5d726263c5089f193ffd
URL: https://github.com/llvm/llvm-project/commit/df7473673214b063f7ca5d726263c5089f193ffd DIFF: https://github.com/llvm/llvm-project/commit/df7473673214b063f7ca5d726263c5089f193ffd.diff LOG: [clang] Add the ability to link libclc OpenCL libraries (#146503) This commit adds driver support for linking libclc OpenCL libraries. It takes the form of a new optional flag: --libclc-lib=namespec. Nothing is linked unless this flag is specified. Not all libclc targets have corresponding clang targets. For this reason it is desirable for users to be able to specify a libclc library name. We support this by taking both a library name (without the .bc suffix) or a filename. Both of these are searched for in the clang resource directory. Filenames are also checked themselves so that absolute paths can be provided. The syntax for specifying filenames (as opposed to library names) uses a leading colon (:), inspired by the -l option. To accommodate this option, libclc libraries are now placed into clang's resource directory in an in-tree configuration. The libraries are all placed in <resource-dir>/lib/libclc and are not grouped under host-specific directories as some other runtime libraries are; it is not expected that OpenCL libraries will differ depending on the host toolchain. Currently only the AMDGPU toolchain supports this option as a proof of concept. Other targets such as NVPTX or SPIR/SPIR-V could support it too. We could optionally let target toolchains search for libclc libraries themselves, possibly when passed an empty --libclc-lib. Added: clang/test/Driver/Inputs/libclc/libclc.bc clang/test/Driver/Inputs/libclc/subdir/libclc.bc clang/test/Driver/opencl-libclc.cl Modified: clang/include/clang/Basic/DiagnosticDriverKinds.td clang/include/clang/Driver/CommonArgs.h clang/include/clang/Driver/Options.td clang/lib/Driver/ToolChains/AMDGPU.cpp clang/lib/Driver/ToolChains/CommonArgs.cpp libclc/CMakeLists.txt Removed: ################################################################################ diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 759ba0419bd45..0f17f4aa761ea 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -394,6 +394,8 @@ def warn_drv_fraw_string_literals_in_cxx11 : Warning< "ignoring '-f%select{no-|}0raw-string-literals', which is only valid for C and C++ standards before C++11">, InGroup<UnusedCommandLineArgument>; +def err_drv_libclc_not_found : Error<"no libclc library '%0' found in the clang resource directory">; + def err_drv_invalid_malign_branch_EQ : Error< "invalid argument '%0' to -malign-branch=; each element must be one of: %1">; diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h index 49c7149380fba..9802962d107c9 100644 --- a/clang/include/clang/Driver/CommonArgs.h +++ b/clang/include/clang/Driver/CommonArgs.h @@ -215,6 +215,9 @@ void addOpenMPDeviceRTL(const Driver &D, const llvm::opt::ArgList &DriverArgs, StringRef BitcodeSuffix, const llvm::Triple &Triple, const ToolChain &HostTC); +void addOpenCLBuiltinsLib(const Driver &D, const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args); + void addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 3c04aeb5af59c..6aab43c9ed57f 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1422,6 +1422,21 @@ def fno_hip_emit_relocatable : Flag<["-"], "fno-hip-emit-relocatable">, HelpText<"Do not override toolchain to compile HIP source to relocatable">; } +// Clang specific/exclusive options for OpenACC. +def openacc_macro_override + : Separate<["-"], "fexperimental-openacc-macro-override">, + Visibility<[ClangOption, CC1Option]>, + Group<f_Group>, + HelpText<"Overrides the _OPENACC macro value for experimental testing " + "during OpenACC support development">; +def openacc_macro_override_EQ + : Joined<["-"], "fexperimental-openacc-macro-override=">, + Alias<openacc_macro_override>; + +// End Clang specific/exclusive options for OpenACC. + +def libclc_lib_EQ : Joined<["--"], "libclc-lib=">, Group<opencl_Group>, + HelpText<"Namespec of libclc OpenCL bitcode library to link">; def libomptarget_amdgpu_bc_path_EQ : Joined<["--"], "libomptarget-amdgpu-bc-path=">, Group<i_Group>, HelpText<"Path to libomptarget-amdgcn bitcode library">; def libomptarget_amdgcn_bc_path_EQ : Joined<["--"], "libomptarget-amdgcn-bc-path=">, Group<i_Group>, diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp index 07816830f8e3d..5e463b9c98687 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -857,6 +857,9 @@ void AMDGPUToolChain::addClangTargetOptions( CC1Args.push_back("-fvisibility=hidden"); CC1Args.push_back("-fapply-global-visibility-to-externs"); } + + if (DeviceOffloadingKind == Action::OFK_None) + addOpenCLBuiltinsLib(getDriver(), DriverArgs, CC1Args); } void AMDGPUToolChain::addClangWarningOptions(ArgStringList &CC1Args) const { diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 334fcbb5b1eb2..53fd525e941e3 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -2985,6 +2985,43 @@ void tools::addHIPRuntimeLibArgs(const ToolChain &TC, Compilation &C, } } +void tools::addOpenCLBuiltinsLib(const Driver &D, + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) { + // Check whether user specifies a libclc bytecode library + const Arg *A = DriverArgs.getLastArg(options::OPT_libclc_lib_EQ); + if (!A) + return; + + // Find device libraries in <LLVM_DIR>/lib/clang/<ver>/lib/libclc/ + SmallString<128> LibclcPath(D.ResourceDir); + llvm::sys::path::append(LibclcPath, "lib", "libclc"); + + // If the namespec is of the form :filename, search for that file. + StringRef LibclcNamespec(A->getValue()); + bool FilenameSearch = LibclcNamespec.consume_front(":"); + SmallString<128> LibclcTargetFile(LibclcNamespec); + + if (FilenameSearch && llvm::sys::fs::exists(LibclcTargetFile)) { + CC1Args.push_back("-mlink-builtin-bitcode"); + CC1Args.push_back(DriverArgs.MakeArgString(LibclcTargetFile)); + } else { + // Search the library paths for the file + if (!FilenameSearch) + LibclcTargetFile += ".bc"; + + llvm::sys::path::append(LibclcPath, LibclcTargetFile); + if (llvm::sys::fs::exists(LibclcPath)) { + CC1Args.push_back("-mlink-builtin-bitcode"); + CC1Args.push_back(DriverArgs.MakeArgString(LibclcPath)); + } else { + // Since the user requested a library, if we haven't one then report an + // error. + D.Diag(diag::err_drv_libclc_not_found) << LibclcTargetFile; + } + } +} + void tools::addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, diff --git a/clang/test/Driver/Inputs/libclc/libclc.bc b/clang/test/Driver/Inputs/libclc/libclc.bc new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/Inputs/libclc/subdir/libclc.bc b/clang/test/Driver/Inputs/libclc/subdir/libclc.bc new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/opencl-libclc.cl b/clang/test/Driver/opencl-libclc.cl new file mode 100644 index 0000000000000..185690768c75b --- /dev/null +++ b/clang/test/Driver/opencl-libclc.cl @@ -0,0 +1,9 @@ +// RUN: %clang -### -target amdgcn-amd-amdhsa --no-offloadlib --libclc-lib=:%S/Inputs/libclc/libclc.bc %s 2>&1 | FileCheck %s +// RUN: %clang -### -target amdgcn-amd-amdhsa --no-offloadlib --libclc-lib=:%S/Inputs/libclc/subdir/libclc.bc %s 2>&1 | FileCheck %s --check-prefix CHECK-SUBDIR + +// RUN: not %clang -### -target amdgcn-amd-amdhsa --no-offloadlib --libclc-lib=:%S/Inputs/libclc/subdir/not-here.bc %s 2>&1 | FileCheck %s --check-prefix CHECK-ERROR + +// CHECK: -mlink-builtin-bitcode{{.*}}Inputs{{/|\\\\}}libclc{{/|\\\\}}libclc.bc +// CHECK-SUBDIR: -mlink-builtin-bitcode{{.*}}Inputs{{/|\\\\}}libclc{{/|\\\\}}subdir{{/|\\\\}}libclc.bc + +// CHECK-ERROR: no libclc library{{.*}}not-here.bc' found in the clang resource directory diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt index 5b95edc75bcdf..adfabf48297af 100644 --- a/libclc/CMakeLists.txt +++ b/libclc/CMakeLists.txt @@ -73,6 +73,9 @@ if( LIBCLC_STANDALONE_BUILD OR CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DI set( ${tool}_target ) endforeach() endif() + + # Setup the paths where libclc runtimes should be stored. + set( LIBCLC_OUTPUT_LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR} ) else() # In-tree configuration set( LIBCLC_STANDALONE_BUILD FALSE ) @@ -92,10 +95,14 @@ else() get_host_tool_path( llvm-link LLVM_LINK llvm-link_exe llvm-link_target ) get_host_tool_path( opt OPT opt_exe opt_target ) endif() -endif() -# Setup the paths where libclc runtimes should be stored. -set( LIBCLC_OUTPUT_LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR} ) + # Setup the paths where libclc runtimes should be stored. By default, in an + # in-tree build we place the libraries in clang's resource driectory. + get_clang_resource_dir( LIBCLC_OUTPUT_DIR PREFIX ${LLVM_LIBRARY_OUTPUT_INTDIR}/.. ) + + # Note we do not adhere to LLVM_ENABLE_PER_TARGET_RUNTIME_DIR. + set( LIBCLC_OUTPUT_LIBRARY_DIR ${LIBCLC_OUTPUT_DIR}/lib/libclc ) +endif() if( EXISTS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} ) message( WARNING "Using custom LLVM tools to build libclc: " _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits