diff --git a/clang/lib/Driver/ToolChains/SYCL.cpp b/clang/lib/Driver/ToolChains/SYCL.cpp index 7b18311c0b98c..6a65ec2e74b94 100644 --- a/clang/lib/Driver/ToolChains/SYCL.cpp +++ b/clang/lib/Driver/ToolChains/SYCL.cpp @@ -95,6 +95,21 @@ void SYCL::constructLLVMForeachCommand(Compilation &C, const JobAction &JA, Foreach, ForeachArgs, None)); } +// The list should match pre-built SYCL device library files located in +// compiler package. Once we add or remove any SYCL device library files, +// the list should be updated accordingly. +static llvm::SmallVector SYCLDeviceLibList{ + "crt", + "cmath", + "cmath-fp64", + "complex", + "complex-fp64", + "fallback-cassert", + "fallback-cmath", + "fallback-cmath-fp64", + "fallback-complex", + "fallback-complex-fp64"}; + const char *SYCL::Linker::constructLLVMLinkCommand( Compilation &C, const JobAction &JA, const InputInfo &Output, const ArgList &Args, StringRef SubArchName, StringRef OutputFilePrefix, @@ -116,16 +131,32 @@ const char *SYCL::Linker::constructLLVMLinkCommand( // an actual object/archive. Take that list and pass those to the linker // instead of the original object. if (JA.isDeviceOffloading(Action::OFK_SYCL)) { - auto SYCLDeviceLibIter = - std::find_if(InputFiles.begin(), InputFiles.end(), [](const auto &II) { - StringRef InputFilename = - llvm::sys::path::filename(StringRef(II.getFilename())); - if (InputFilename.startswith("libsycl-") && - InputFilename.endswith(".o")) - return true; - return false; - }); - bool LinkSYCLDeviceLibs = (SYCLDeviceLibIter != InputFiles.end()); + auto isSYCLDeviceLib = [&C](const InputInfo &II) { + const ToolChain *HostTC = C.getSingleOffloadToolChain(); + StringRef LibPostfix = ".o"; + if (HostTC->getTriple().isWindowsMSVCEnvironment() && + C.getDriver().IsCLMode()) + LibPostfix = ".obj"; + StringRef InputFilename = + llvm::sys::path::filename(StringRef(II.getFilename())); + if (!InputFilename.startswith("libsycl-") || + !InputFilename.endswith(LibPostfix) || (InputFilename.count('-') < 2)) + return false; + size_t PureLibNameLen = InputFilename.find_last_of('-'); + // Skip the prefix "libsycl-" + StringRef PureLibName = InputFilename.substr(8, PureLibNameLen - 8); + for (const auto &L : SYCLDeviceLibList) { + if (PureLibName.compare(L) == 0) + return true; + } + return false; + }; + size_t InputFileNum = InputFiles.size(); + bool LinkSYCLDeviceLibs = (InputFileNum >= 2); + LinkSYCLDeviceLibs = LinkSYCLDeviceLibs && !isSYCLDeviceLib(InputFiles[0]); + for (size_t Idx = 1; Idx < InputFileNum; ++Idx) + LinkSYCLDeviceLibs = + LinkSYCLDeviceLibs && isSYCLDeviceLib(InputFiles[Idx]); // Go through the Inputs to the link. When a listfile is encountered, we // know it is an unbundled generated list. if (LinkSYCLDeviceLibs) diff --git a/clang/test/Driver/sycl-device-lib.cpp b/clang/test/Driver/sycl-device-lib.cpp index 2e34247e315e4..04c57804f2de2 100644 --- a/clang/test/Driver/sycl-device-lib.cpp +++ b/clang/test/Driver/sycl-device-lib.cpp @@ -122,3 +122,11 @@ // SYCL_LLVM_LINK_NO_DEVICE_LIB: clang{{.*}} "-cc1" {{.*}} "-fsycl-is-device" // SYCL_LLVM_LINK_NO_DEVICE_LIB-NOT: llvm-link{{.*}} "-only-needed" // SYCL_LLVM_LINK_NO_DEVICE_LIB: sycl-post-link{{.*}} "-symbols" "-spec-const=rt" "-o" "{{.*}}.table" "{{.*}}.bc" + +/// ########################################################################### +/// test llvm-link behavior for special user input whose filename resembles SYCL device library +// RUN: touch libsycl-crt.o +// RUN: %clangxx -fsycl libsycl-crt.o -### 2>&1 \ +// RUN: | FileCheck %s -check-prefix=SYCL_LLVM_LINK_USER_ONLY_NEEDED +// SYCL_LLVM_LINK_USER_ONLY_NEEDED: llvm-link{{.*}} "{{.*}}.o" "-o" "{{.*}}.bc" "--suppress-warnings" +// SYCL_LLVM_LINK_USER_ONLY_NEEDED: llvm-link{{.*}} "-only-needed" "{{.*}}" "-o" "{{.*}}.bc" "--suppress-warnings"