Skip to content

Commit df74736

Browse files
authored
[clang] Add the ability to link libclc OpenCL libraries (llvm#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.
1 parent 6de745b commit df74736

File tree

9 files changed

+79
-3
lines changed

9 files changed

+79
-3
lines changed

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,8 @@ def warn_drv_fraw_string_literals_in_cxx11 : Warning<
394394
"ignoring '-f%select{no-|}0raw-string-literals', which is only valid for C and C++ standards before C++11">,
395395
InGroup<UnusedCommandLineArgument>;
396396

397+
def err_drv_libclc_not_found : Error<"no libclc library '%0' found in the clang resource directory">;
398+
397399
def err_drv_invalid_malign_branch_EQ : Error<
398400
"invalid argument '%0' to -malign-branch=; each element must be one of: %1">;
399401

clang/include/clang/Driver/CommonArgs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ void addOpenMPDeviceRTL(const Driver &D, const llvm::opt::ArgList &DriverArgs,
215215
StringRef BitcodeSuffix, const llvm::Triple &Triple,
216216
const ToolChain &HostTC);
217217

218+
void addOpenCLBuiltinsLib(const Driver &D, const llvm::opt::ArgList &DriverArgs,
219+
llvm::opt::ArgStringList &CC1Args);
220+
218221
void addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC,
219222
const llvm::opt::ArgList &Args,
220223
llvm::opt::ArgStringList &CmdArgs,

clang/include/clang/Driver/Options.td

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,21 @@ def fno_hip_emit_relocatable : Flag<["-"], "fno-hip-emit-relocatable">,
14221422
HelpText<"Do not override toolchain to compile HIP source to relocatable">;
14231423
}
14241424

1425+
// Clang specific/exclusive options for OpenACC.
1426+
def openacc_macro_override
1427+
: Separate<["-"], "fexperimental-openacc-macro-override">,
1428+
Visibility<[ClangOption, CC1Option]>,
1429+
Group<f_Group>,
1430+
HelpText<"Overrides the _OPENACC macro value for experimental testing "
1431+
"during OpenACC support development">;
1432+
def openacc_macro_override_EQ
1433+
: Joined<["-"], "fexperimental-openacc-macro-override=">,
1434+
Alias<openacc_macro_override>;
1435+
1436+
// End Clang specific/exclusive options for OpenACC.
1437+
1438+
def libclc_lib_EQ : Joined<["--"], "libclc-lib=">, Group<opencl_Group>,
1439+
HelpText<"Namespec of libclc OpenCL bitcode library to link">;
14251440
def libomptarget_amdgpu_bc_path_EQ : Joined<["--"], "libomptarget-amdgpu-bc-path=">, Group<i_Group>,
14261441
HelpText<"Path to libomptarget-amdgcn bitcode library">;
14271442
def libomptarget_amdgcn_bc_path_EQ : Joined<["--"], "libomptarget-amdgcn-bc-path=">, Group<i_Group>,

clang/lib/Driver/ToolChains/AMDGPU.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,9 @@ void AMDGPUToolChain::addClangTargetOptions(
857857
CC1Args.push_back("-fvisibility=hidden");
858858
CC1Args.push_back("-fapply-global-visibility-to-externs");
859859
}
860+
861+
if (DeviceOffloadingKind == Action::OFK_None)
862+
addOpenCLBuiltinsLib(getDriver(), DriverArgs, CC1Args);
860863
}
861864

862865
void AMDGPUToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {

clang/lib/Driver/ToolChains/CommonArgs.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2985,6 +2985,43 @@ void tools::addHIPRuntimeLibArgs(const ToolChain &TC, Compilation &C,
29852985
}
29862986
}
29872987

2988+
void tools::addOpenCLBuiltinsLib(const Driver &D,
2989+
const llvm::opt::ArgList &DriverArgs,
2990+
llvm::opt::ArgStringList &CC1Args) {
2991+
// Check whether user specifies a libclc bytecode library
2992+
const Arg *A = DriverArgs.getLastArg(options::OPT_libclc_lib_EQ);
2993+
if (!A)
2994+
return;
2995+
2996+
// Find device libraries in <LLVM_DIR>/lib/clang/<ver>/lib/libclc/
2997+
SmallString<128> LibclcPath(D.ResourceDir);
2998+
llvm::sys::path::append(LibclcPath, "lib", "libclc");
2999+
3000+
// If the namespec is of the form :filename, search for that file.
3001+
StringRef LibclcNamespec(A->getValue());
3002+
bool FilenameSearch = LibclcNamespec.consume_front(":");
3003+
SmallString<128> LibclcTargetFile(LibclcNamespec);
3004+
3005+
if (FilenameSearch && llvm::sys::fs::exists(LibclcTargetFile)) {
3006+
CC1Args.push_back("-mlink-builtin-bitcode");
3007+
CC1Args.push_back(DriverArgs.MakeArgString(LibclcTargetFile));
3008+
} else {
3009+
// Search the library paths for the file
3010+
if (!FilenameSearch)
3011+
LibclcTargetFile += ".bc";
3012+
3013+
llvm::sys::path::append(LibclcPath, LibclcTargetFile);
3014+
if (llvm::sys::fs::exists(LibclcPath)) {
3015+
CC1Args.push_back("-mlink-builtin-bitcode");
3016+
CC1Args.push_back(DriverArgs.MakeArgString(LibclcPath));
3017+
} else {
3018+
// Since the user requested a library, if we haven't one then report an
3019+
// error.
3020+
D.Diag(diag::err_drv_libclc_not_found) << LibclcTargetFile;
3021+
}
3022+
}
3023+
}
3024+
29883025
void tools::addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC,
29893026
const llvm::opt::ArgList &Args,
29903027
llvm::opt::ArgStringList &CmdArgs,

clang/test/Driver/Inputs/libclc/libclc.bc

Whitespace-only changes.

clang/test/Driver/Inputs/libclc/subdir/libclc.bc

Whitespace-only changes.

clang/test/Driver/opencl-libclc.cl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %clang -### -target amdgcn-amd-amdhsa --no-offloadlib --libclc-lib=:%S/Inputs/libclc/libclc.bc %s 2>&1 | FileCheck %s
2+
// 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
3+
4+
// 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
5+
6+
// CHECK: -mlink-builtin-bitcode{{.*}}Inputs{{/|\\\\}}libclc{{/|\\\\}}libclc.bc
7+
// CHECK-SUBDIR: -mlink-builtin-bitcode{{.*}}Inputs{{/|\\\\}}libclc{{/|\\\\}}subdir{{/|\\\\}}libclc.bc
8+
9+
// CHECK-ERROR: no libclc library{{.*}}not-here.bc' found in the clang resource directory

libclc/CMakeLists.txt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ if( LIBCLC_STANDALONE_BUILD OR CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DI
7373
set( ${tool}_target )
7474
endforeach()
7575
endif()
76+
77+
# Setup the paths where libclc runtimes should be stored.
78+
set( LIBCLC_OUTPUT_LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR} )
7679
else()
7780
# In-tree configuration
7881
set( LIBCLC_STANDALONE_BUILD FALSE )
@@ -92,10 +95,14 @@ else()
9295
get_host_tool_path( llvm-link LLVM_LINK llvm-link_exe llvm-link_target )
9396
get_host_tool_path( opt OPT opt_exe opt_target )
9497
endif()
95-
endif()
9698

97-
# Setup the paths where libclc runtimes should be stored.
98-
set( LIBCLC_OUTPUT_LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR} )
99+
# Setup the paths where libclc runtimes should be stored. By default, in an
100+
# in-tree build we place the libraries in clang's resource driectory.
101+
get_clang_resource_dir( LIBCLC_OUTPUT_DIR PREFIX ${LLVM_LIBRARY_OUTPUT_INTDIR}/.. )
102+
103+
# Note we do not adhere to LLVM_ENABLE_PER_TARGET_RUNTIME_DIR.
104+
set( LIBCLC_OUTPUT_LIBRARY_DIR ${LIBCLC_OUTPUT_DIR}/lib/libclc )
105+
endif()
99106

100107
if( EXISTS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} )
101108
message( WARNING "Using custom LLVM tools to build libclc: "

0 commit comments

Comments
 (0)