https://github.com/srividya-sundaram updated 
https://github.com/llvm/llvm-project/pull/218528

>From 917b404ac322a7abfa93cbf204f8b8043b88efd9 Mon Sep 17 00:00:00 2001
From: srividya sundaram <[email protected]>
Date: Mon, 24 Aug 2026 14:23:25 -0700
Subject: [PATCH 1/8] [Driver][SYCL] Link libclang_rt.builtins.bc for spirv64
 at compile time via getDeviceLibs

---
 .../clang/Basic/DiagnosticDriverKinds.td      |  5 +++
 clang/lib/Driver/ToolChains/SYCL.cpp          | 31 +++++++++++++
 clang/lib/Driver/ToolChains/SYCL.h            |  4 ++
 .../libclang_rt.builtins.bc                   |  0
 clang/test/Driver/sycl-device-lib-spirv64.cpp | 28 ++++++++++++
 .../Driver/sycl-msvc-version-propagation.cpp  |  1 +
 clang/test/Driver/sycl-offload-jit-unix.cpp   |  9 ++--
 clang/test/Driver/sycl-offload-jit-xarch.cpp  |  6 ++-
 clang/test/Driver/sycl-offload-jit.cpp        | 43 +++++++++++++------
 .../Driver/sycl-print-internal-defines.cpp    |  4 +-
 .../Driver/sycl-rtlib-sysroot-mismatch.cpp    |  6 ++-
 clang/test/Driver/sycl-std-default.cpp        |  8 ++--
 clang/test/Driver/sycl-windows.cpp            | 28 ++++++------
 clang/test/Driver/sycl.cpp                    | 30 ++++++-------
 14 files changed, 149 insertions(+), 54 deletions(-)
 create mode 100644 
clang/test/Driver/Inputs/spirv64-sycl/lib/spirv64-unknown-unknown/libclang_rt.builtins.bc
 create mode 100644 clang/test/Driver/sycl-device-lib-spirv64.cpp

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index ae3eecc60fc78..eeefc838bda1d 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -441,6 +441,11 @@ def warn_drv_fraw_string_literals_in_cxx11 : Warning<
 
 def err_drv_libclc_not_found : Error<"no libclc library '%0' found in the 
clang resource directory">;
 
+def err_drv_no_compiler_rt_builtins_bc : Error<
+  "no compiler-rt builtins bitcode library '%0' found in the clang resource "
+  "directory; build compiler-rt with SPIR-V support or pass '--no-offloadlib' "
+  "to compile without it">;
+
 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/lib/Driver/ToolChains/SYCL.cpp 
b/clang/lib/Driver/ToolChains/SYCL.cpp
index 34aa99320473e..2348c179f7aa7 100644
--- a/clang/lib/Driver/ToolChains/SYCL.cpp
+++ b/clang/lib/Driver/ToolChains/SYCL.cpp
@@ -7,6 +7,8 @@
 
//===----------------------------------------------------------------------===//
 #include "SYCL.h"
 #include "clang/Driver/CommonArgs.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/VirtualFileSystem.h"
 
 using namespace clang::driver;
@@ -127,6 +129,14 @@ void SYCLToolChain::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
     BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const {
   HostTC.addClangTargetOptions(DriverArgs, CC1Args, BA, DeviceOffloadingKind);
+
+  // Link device libraries (bitcode) into the device cc1 invocation.
+  for (const auto &BCFile :
+       getDeviceLibs(DriverArgs, BA, DeviceOffloadingKind)) {
+    CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
+                                               : "-mlink-bitcode-file");
+    CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path));
+  }
 }
 
 llvm::opt::DerivedArgList *
@@ -205,3 +215,24 @@ VersionTuple SYCLToolChain::computeMSVCVersion(const 
Driver *D,
                                                const ArgList &Args) const {
   return HostTC.computeMSVCVersion(D, Args);
 }
+
+llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
+SYCLToolChain::getDeviceLibs(
+    const llvm::opt::ArgList &DriverArgs, BoundArch /*BA*/,
+    const Action::OffloadKind /*DeviceOffloadingKind*/) const {
+  if (!getTriple().isSPIROrSPIRV())
+    return {};
+  if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
+                          true))
+    return {};
+  // compiler-rt always installs the spirv64 .bc file under lib/<triple>/
+  // regardless of LLVM_ENABLE_PER_TARGET_RUNTIME_DIR, so only check that path.
+  SmallString<128> BCPath(getDriver().ResourceDir);
+  llvm::sys::path::append(BCPath, "lib", getTriple().str(),
+                          "libclang_rt.builtins.bc");
+  if (!llvm::sys::fs::exists(BCPath)) {
+    getDriver().Diag(clang::diag::err_drv_no_compiler_rt_builtins_bc) << 
BCPath;
+    return {};
+  }
+  return {{std::string(BCPath), /*ShouldInternalize=*/true}};
+}
diff --git a/clang/lib/Driver/ToolChains/SYCL.h 
b/clang/lib/Driver/ToolChains/SYCL.h
index 48f5d986c3e6e..053f35d6e8660 100644
--- a/clang/lib/Driver/ToolChains/SYCL.h
+++ b/clang/lib/Driver/ToolChains/SYCL.h
@@ -58,6 +58,10 @@ class LLVM_LIBRARY_VISIBILITY SYCLToolChain : public 
ToolChain {
   computeMSVCVersion(const Driver *D,
                      const llvm::opt::ArgList &Args) const override;
 
+  llvm::SmallVector<BitCodeLibraryInfo, 12>
+  getDeviceLibs(const llvm::opt::ArgList &Args, BoundArch BA,
+                const Action::OffloadKind DeviceOffloadingKind) const override;
+
 private:
   const ToolChain &HostTC;
   SYCLInstallationDetector SYCLInstallation;
diff --git 
a/clang/test/Driver/Inputs/spirv64-sycl/lib/spirv64-unknown-unknown/libclang_rt.builtins.bc
 
b/clang/test/Driver/Inputs/spirv64-sycl/lib/spirv64-unknown-unknown/libclang_rt.builtins.bc
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/sycl-device-lib-spirv64.cpp 
b/clang/test/Driver/sycl-device-lib-spirv64.cpp
new file mode 100644
index 0000000000000..467dffa50b1e9
--- /dev/null
+++ b/clang/test/Driver/sycl-device-lib-spirv64.cpp
@@ -0,0 +1,28 @@
+// Tests that the SYCL toolchain links libclang_rt.builtins.bc for spirv64
+// via -mlink-builtin-bitcode, that --no-offloadlib suppresses it, and that
+// -nolibsycl does not suppress it (builtins are target infrastructure, not
+// SYCL runtime).
+
+// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl \
+// RUN:   -resource-dir=%S/Inputs/spirv64-sycl %s 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-BUILTIN-BC
+// CHECK-BUILTIN-BC: "-triple" "spirv64-unknown-unknown"
+// CHECK-BUILTIN-BC: "-mlink-builtin-bitcode" 
"{{.*}}lib{{[/\\]+}}spirv64-unknown-unknown{{[/\\]+}}libclang_rt.builtins.bc"
+
+// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl --no-offloadlib \
+// RUN:   -resource-dir=%S/Inputs/spirv64-sycl %s 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-NO-OFFLOADLIB
+// CHECK-NO-OFFLOADLIB: "-cc1" "-triple" "spirv64-unknown-unknown"
+// CHECK-NO-OFFLOADLIB-NOT: "-mlink-builtin-bitcode"
+
+// -nolibsycl suppresses the SYCL runtime library but NOT compiler-rt builtins.
+// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl -nolibsycl \
+// RUN:   -resource-dir=%S/Inputs/spirv64-sycl %s 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-NOLIBSYCL
+// CHECK-NOLIBSYCL: "-triple" "spirv64-unknown-unknown"
+// CHECK-NOLIBSYCL: "-mlink-builtin-bitcode" 
"{{.*}}lib{{[/\\]+}}spirv64-unknown-unknown{{[/\\]+}}libclang_rt.builtins.bc"
+
+// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -fsycl \
+// RUN:   -resource-dir=%T/nonexistent %s 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-MISSING
+// CHECK-MISSING: error: no compiler-rt builtins bitcode library 
'{{.*}}libclang_rt.builtins.bc' found in the clang resource directory
diff --git a/clang/test/Driver/sycl-msvc-version-propagation.cpp 
b/clang/test/Driver/sycl-msvc-version-propagation.cpp
index c542ceef80ade..1c45a6ff1602a 100644
--- a/clang/test/Driver/sycl-msvc-version-propagation.cpp
+++ b/clang/test/Driver/sycl-msvc-version-propagation.cpp
@@ -2,6 +2,7 @@
 /// SPIR-V device compilation.
 
 // RUN: %clang -### -fsycl --target=x86_64-pc-windows-msvc \
+// RUN:   -resource-dir=%S/Inputs/spirv64-sycl \
 // RUN:   -x c++ %s 2>&1 | FileCheck %s
 
 // CHECK: "-triple" "spirv64-unknown-unknown"
diff --git a/clang/test/Driver/sycl-offload-jit-unix.cpp 
b/clang/test/Driver/sycl-offload-jit-unix.cpp
index 34812576f7874..c6d78a189ac56 100644
--- a/clang/test/Driver/sycl-offload-jit-unix.cpp
+++ b/clang/test/Driver/sycl-offload-jit-unix.cpp
@@ -10,7 +10,8 @@
 // RUN: rm -rf %t && mkdir -p %t/bin %t/lib/x86_64-unknown-linux-gnu
 // RUN: touch %t/lib/x86_64-unknown-linux-gnu/libLLVMSYCL.so
 // RUN: ln -s %clang %t/bin/clang
-// RUN: %t/bin/clang -### -no-canonical-prefixes 
--target=x86_64-unknown-linux-gnu -fsycl %s 2>&1 \
+// RUN: %t/bin/clang -### -no-canonical-prefixes 
--target=x86_64-unknown-linux-gnu -fsycl \
+// RUN:   -resource-dir=%S/Inputs/spirv64-sycl %s 2>&1 \
 // RUN:   | FileCheck 
-check-prefixes=CHECK-LSYCL,CHECK-SYCL-HEADERS-HOST,CHECK-SYCL-HEADERS-DEVICE %s
 // CHECK-SYCL-HEADERS-DEVICE: "-fsycl-is-device"{{.*}} "-internal-isystem" 
"{{.*}}bin{{[/\\]+}}..{{[/\\]+}}include"
 // CHECK-SYCL-HEADERS-HOST: "-fsycl-is-host"{{.*}} "-internal-isystem" 
"{{.*}}bin{{[/\\]+}}..{{[/\\]+}}include"
@@ -20,7 +21,8 @@
 // RUN: rm -rf %t && mkdir -p %t/bin %t/lib
 // RUN: touch %t/lib/libLLVMSYCL.so
 // RUN: ln -s %clang %t/bin/clang
-// RUN: %t/bin/clang -### -no-canonical-prefixes 
--target=x86_64-unknown-linux-gnu -fsycl %s 2>&1 \
+// RUN: %t/bin/clang -### -no-canonical-prefixes 
--target=x86_64-unknown-linux-gnu -fsycl \
+// RUN:   -resource-dir=%S/Inputs/spirv64-sycl %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-LSYCL-FLAT %s
 // CHECK-LSYCL-FLAT: clang-linker-wrapper{{.*}} 
"{{.*}}bin{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}libLLVMSYCL.so"
 
@@ -28,6 +30,7 @@
 // RUN: rm -rf %t && mkdir -p %t/bin %t/lib/x86_64-unknown-linux-gnu
 // RUN: touch %t/lib/x86_64-unknown-linux-gnu/libLLVMSYCL.so
 // RUN: ln -s %clang %t/bin/clang
-// RUN: %t/bin/clang -### -no-canonical-prefixes 
--target=x86_64-unknown-linux-gnu -fsycl -nolibsycl %s 2>&1 \
+// RUN: %t/bin/clang -### -no-canonical-prefixes 
--target=x86_64-unknown-linux-gnu -fsycl -nolibsycl \
+// RUN:   -resource-dir=%S/Inputs/spirv64-sycl %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-NOLIBSYCL %s
 // CHECK-NOLIBSYCL-NOT: libLLVMSYCL.so
diff --git a/clang/test/Driver/sycl-offload-jit-xarch.cpp 
b/clang/test/Driver/sycl-offload-jit-xarch.cpp
index 53af2b16a33f1..6801cb5e6da9b 100644
--- a/clang/test/Driver/sycl-offload-jit-xarch.cpp
+++ b/clang/test/Driver/sycl-offload-jit-xarch.cpp
@@ -2,12 +2,14 @@
 
 // Verify that -Xarch_spirv64 forwards options to the SYCL device compilation
 // and clang-linker-wrapper call.
-// RUN: %clang -fsycl --offload-targets=spirv64-unknown-unknown -Xarch_spirv64 
-O3 -### %s 2>&1 \
+// RUN: %clang -fsycl --no-offloadlib \
+// RUN:   --offload-targets=spirv64-unknown-unknown -Xarch_spirv64 -O3 -### %s 
2>&1 \
 // RUN: | FileCheck -check-prefix=SYCL-DEVICE-O3 %s
 // SYCL-DEVICE-O3: "-triple" "spirv64-unknown-unknown" "-aux-triple" "{{.*}}" 
"-O3"{{.*}} "-fsycl-is-device"
 // SYCL-DEVICE-O3: {{"[^"]*clang-linker-wrapper[^"]*".* 
"--device-compiler=spirv64-unknown-unknown=-O3"}}
 
 // Verify that `-Xarch_spirv64` forwards libraries to the device linker.
-// RUN: %clang -fsycl --offload-targets=spirv64-unknown-unknown -Xarch_spirv64 
-Wl,-lfoo -### %s 2>&1 \
+// RUN: %clang -fsycl --no-offloadlib \
+// RUN:   --offload-targets=spirv64-unknown-unknown -Xarch_spirv64 -Wl,-lfoo 
-### %s 2>&1 \
 // RUN: | FileCheck -check-prefix=DEVICE-LINKER %s
 // DEVICE-LINKER: {{"[^"]*clang-linker-wrapper[^"]*".* 
"--device-linker=spirv64-unknown-unknown=-lfoo"}}
diff --git a/clang/test/Driver/sycl-offload-jit.cpp 
b/clang/test/Driver/sycl-offload-jit.cpp
index c8eff1a4dd28f..991913fe8d771 100644
--- a/clang/test/Driver/sycl-offload-jit.cpp
+++ b/clang/test/Driver/sycl-offload-jit.cpp
@@ -21,7 +21,8 @@
 
 /// Check expected default values for device compilation when using -fsycl as
 /// well as llvm-offload-binary inputs.
-// RUN: %clang -### -fsycl -c --target=x86_64-unknown-linux-gnu %s 2>&1 \
+// RUN: %clang -### -fsycl --no-offloadlib \
+// RUN:   -c --target=x86_64-unknown-linux-gnu %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHK-DEVICE-TRIPLE %s
 // CHK-DEVICE-TRIPLE: "-cc1"{{.*}} "-triple" "spirv64-unknown-unknown"
 // CHK-DEVICE-TRIPLE-SAME: "-aux-triple" "x86_64-unknown-linux-gnu"
@@ -36,42 +37,59 @@
 
 /// Check -fsycl-is-device is passed when compiling for the device.
 /// Check -fsycl-is-host is passed when compiling for host.
-// RUN: %clang -### -fsycl -c %s 2>&1 \
+// RUN: %clang -### -fsycl --no-offloadlib -c %s 2>&1 \
 // RUN:   | FileCheck -check-prefixes=CHK-FSYCL-IS-DEVICE,CHK-FSYCL-IS-HOST %s
-// RUN: %clang -### -fsycl -fsycl-device-only %s 2>&1 \
+// RUN: %clang -### -fsycl --no-offloadlib -fsycl-device-only %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHK-FSYCL-IS-DEVICE %s
-// RUN: %clang_cl -### -fsycl -c -- %s 2>&1 \
+// RUN: %clang_cl -### -fsycl --no-offloadlib -c -- %s 2>&1 \
 // RUN:   | FileCheck -check-prefixes=CHK-FSYCL-IS-DEVICE,CHK-FSYCL-IS-HOST %s
-// RUN: %clang -### -fsycl -fsycl-host-only %s 2>&1 \
+// RUN: %clang -### -fsycl --no-offloadlib -fsycl-host-only %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHK-FSYCL-IS-HOST %s
 // CHK-FSYCL-IS-DEVICE: "-cc1"{{.*}} "-fsycl-is-device" {{.*}} "-emit-llvm-bc"
 // CHK-FSYCL-IS-HOST: "-cc1"{{.*}} "-fsycl-is-host"
 
+/// Check that SYCL compilation defaults to relocatable device code (-fgpu-rdc
+/// is passed to both the device and the host -cc1 invocation) and that
+/// -fno-gpu-rdc disables it.
+// RUN: %clang -### -fsycl --no-offloadlib -c %s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=CHK-SYCL-RDC,CHK-SYCL-RDC-HOST %s
+// RUN: %clang -### -fsycl --no-offloadlib -fgpu-rdc -c %s 2>&1 \
+// RUN:   | FileCheck -check-prefixes=CHK-SYCL-RDC,CHK-SYCL-RDC-HOST %s
+// RUN: %clang -### -fsycl --no-offloadlib -fno-gpu-rdc -c %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHK-SYCL-NORDC %s
+// CHK-SYCL-RDC: "-cc1"{{.*}} "-fsycl-is-device" {{.*}} "-fgpu-rdc"
+// CHK-SYCL-RDC-HOST: "-cc1"{{.*}} "-fsycl-is-host" {{.*}} "-fgpu-rdc"
+// CHK-SYCL-NORDC-NOT: "-fgpu-rdc"
+
 // Check that --allow-partial-linkage and --create-library are not passed to
 // clang-linker-wrapper for SYCL (they are spirv-link flags, not 
clang-sycl-linker flags).
-// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl %s 2>&1 \
+// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl --no-offloadlib 
%s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-NO-SPIRVLINK-FLAGS %s
 // CHECK-NO-SPIRVLINK-FLAGS-NOT: 
--device-linker=spirv64-unknown-unknown=--allow-partial-linkage
 // CHECK-NO-SPIRVLINK-FLAGS-NOT: 
--device-linker=spirv64-unknown-unknown=--create-library
 
 /// Check -fsycl-device-image-split= is forwarded to clang-sycl-linker as the
 /// corresponding --module-split-mode= value.
-// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl 
-fsycl-device-image-split=kernel %s 2>&1 \
+// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl --no-offloadlib \
+// RUN:   -fsycl-device-image-split=kernel %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHK-SPLIT-KERNEL %s
 // CHK-SPLIT-KERNEL: 
clang-linker-wrapper{{.*}}"--device-linker=spirv64-unknown-unknown=--module-split-mode=kernel"
-// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl 
-fsycl-device-image-split=translation_unit %s 2>&1 \
+// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl --no-offloadlib \
+// RUN:   -fsycl-device-image-split=translation_unit %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHK-SPLIT-TU %s
 // CHK-SPLIT-TU: 
clang-linker-wrapper{{.*}}"--device-linker=spirv64-unknown-unknown=--module-split-mode=translation_unit"
-// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl 
-fsycl-device-image-split=link_unit %s 2>&1 \
+// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl --no-offloadlib \
+// RUN:   -fsycl-device-image-split=link_unit %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHK-SPLIT-LU %s
 // CHK-SPLIT-LU: 
clang-linker-wrapper{{.*}}"--device-linker=spirv64-unknown-unknown=--module-split-mode=link_unit"
 
 /// Check the bare -fsycl-device-image-split flag aliases to 
'translation_unit'.
-// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl 
-fsycl-device-image-split %s 2>&1 \
+// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl --no-offloadlib \
+// RUN:   -fsycl-device-image-split %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHK-SPLIT-TU %s
 
 /// Check that without -fsycl-device-image-split, no --module-split-mode= is 
passed.
-// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl %s 2>&1 \
+// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl --no-offloadlib 
%s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHK-NO-SPLIT %s
 // CHK-NO-SPLIT-NOT: --module-split-mode=
 
@@ -81,7 +99,8 @@
 // CHK-SPLIT-INVALID: error: invalid value 'bogus' in 
'-fsycl-device-image-split='
 
 /// Check -fsycl-device-image-split is unused when not linking (e.g. -c).
-// RUN: %clang -### -c --target=x86_64-unknown-linux-gnu -fsycl 
-fsycl-device-image-split=kernel %s 2>&1 \
+// RUN: %clang -### -c --target=x86_64-unknown-linux-gnu -fsycl 
--no-offloadlib \
+// RUN:   -fsycl-device-image-split=kernel %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHK-SPLIT-UNUSED %s
 // CHK-SPLIT-UNUSED: warning: argument unused during compilation: 
'-fsycl-device-image-split=kernel'
 
diff --git a/clang/test/Driver/sycl-print-internal-defines.cpp 
b/clang/test/Driver/sycl-print-internal-defines.cpp
index 389aaf25608c6..b0efa278a5660 100644
--- a/clang/test/Driver/sycl-print-internal-defines.cpp
+++ b/clang/test/Driver/sycl-print-internal-defines.cpp
@@ -1,8 +1,8 @@
 // Test that clang can print defines in SYCL mode.
 
-// RUN: %clangxx -fsycl -dM -E %s 2>&1 | FileCheck --check-prefix 
CHECK-PRINT-INTERNAL-DEFINES %s
+// RUN: %clangxx -fsycl --no-offloadlib -dM -E %s 2>&1 | FileCheck 
--check-prefix CHECK-PRINT-INTERNAL-DEFINES %s
 // CHECK-PRINT-INTERNAL-DEFINES: #define
 
 // Printing defines also works when input is stdin.
-// RUN: %clangxx -fsycl -dM -E - < /dev/null 2>&1 | FileCheck 
--check-prefixes=CHECK-PRINT-INTERNAL-DEFINES,CHECK-NO-ERROR %s
+// RUN: %clangxx -fsycl --no-offloadlib -dM -E - < /dev/null 2>&1 | FileCheck 
--check-prefixes=CHECK-PRINT-INTERNAL-DEFINES,CHECK-NO-ERROR %s
 // CHECK-NO-ERROR-NOT: error:
diff --git a/clang/test/Driver/sycl-rtlib-sysroot-mismatch.cpp 
b/clang/test/Driver/sycl-rtlib-sysroot-mismatch.cpp
index 87ed4ba1f9ff7..8a339edaeeeca 100644
--- a/clang/test/Driver/sycl-rtlib-sysroot-mismatch.cpp
+++ b/clang/test/Driver/sycl-rtlib-sysroot-mismatch.cpp
@@ -5,13 +5,15 @@
 // RUN: rm -rf %t && mkdir -p %t/bin %t/lib
 // RUN: touch %t/lib/libLLVMSYCL.so
 // RUN: ln -s %clang %t/bin/clang
-// RUN: %t/bin/clang -### -no-canonical-prefixes 
--target=x86_64-unknown-linux-gnu -fsycl --sysroot=/nonexistent-prefix %s 2>&1 \
+// RUN: %t/bin/clang -### -no-canonical-prefixes 
--target=x86_64-unknown-linux-gnu -fsycl \
+// RUN:   -resource-dir=%S/Inputs/spirv64-sycl --sysroot=/nonexistent-prefix 
%s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-FLAT %s
 
 // RUN: rm -rf %t && mkdir -p %t/bin %t/lib/x86_64-unknown-linux-gnu
 // RUN: touch %t/lib/x86_64-unknown-linux-gnu/libLLVMSYCL.so
 // RUN: ln -s %clang %t/bin/clang
-// RUN: %t/bin/clang -### -no-canonical-prefixes 
--target=x86_64-unknown-linux-gnu -fsycl --sysroot=/nonexistent-prefix %s 2>&1 \
+// RUN: %t/bin/clang -### -no-canonical-prefixes 
--target=x86_64-unknown-linux-gnu -fsycl \
+// RUN:   -resource-dir=%S/Inputs/spirv64-sycl --sysroot=/nonexistent-prefix 
%s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-PER-TARGET %s
 
 // CHECK-FLAT: "{{.*}}/bin/../lib/libLLVMSYCL.so"
diff --git a/clang/test/Driver/sycl-std-default.cpp 
b/clang/test/Driver/sycl-std-default.cpp
index df377169a3944..ad73522bed1c6 100644
--- a/clang/test/Driver/sycl-std-default.cpp
+++ b/clang/test/Driver/sycl-std-default.cpp
@@ -1,6 +1,6 @@
 // Tests that SYCL defaults to C++17 when no -std= is specified
 
-// RUN: %clangxx -### -fsycl -c %s 2>&1 | FileCheck %s 
--check-prefixes=CHECK-DEVICE,CHECK-HOST
+// RUN: %clangxx -### -fsycl --no-offloadlib -c %s 2>&1 | FileCheck %s 
--check-prefixes=CHECK-DEVICE,CHECK-HOST
 
 // CHECK-DEVICE: "-cc1"{{.*}} "-fsycl-is-device"
 // CHECK-DEVICE-SAME: "-std=c++17"
@@ -8,7 +8,7 @@
 // CHECK-HOST-SAME: "-std=c++17"
 
 // Test that explicit -std= overrides the default
-// RUN: %clangxx -### -fsycl -std=c++20 -c %s 2>&1 | FileCheck %s 
--check-prefixes=CHECK-OVERRIDE-DEVICE,CHECK-OVERRIDE-HOST
+// RUN: %clangxx -### -fsycl --no-offloadlib -std=c++20 -c %s 2>&1 | FileCheck 
%s --check-prefixes=CHECK-OVERRIDE-DEVICE,CHECK-OVERRIDE-HOST
 
 // CHECK-OVERRIDE-DEVICE: "-cc1"{{.*}} "-fsycl-is-device"
 // CHECK-OVERRIDE-DEVICE-SAME: "-std=c++20"
@@ -34,7 +34,7 @@
 // CHECK-C99-ERROR: error: invalid argument '-std=c99' not allowed with 
'-fsycl'
 
 // Test on Windows with clang-cl (MSVC mode)
-// RUN: %clang_cl --target=x86_64-pc-windows-msvc -### -fsycl -- %s 2>&1 | 
FileCheck %s --check-prefixes=CHECK-MSVC-DEVICE,CHECK-MSVC-HOST
+// RUN: %clang_cl --target=x86_64-pc-windows-msvc -### -fsycl --no-offloadlib 
-- %s 2>&1 | FileCheck %s --check-prefixes=CHECK-MSVC-DEVICE,CHECK-MSVC-HOST
 
 // CHECK-MSVC-DEVICE: "-cc1"{{.*}} "-fsycl-is-device"
 // CHECK-MSVC-DEVICE-SAME: "-std=c++17"
@@ -42,7 +42,7 @@
 // CHECK-MSVC-HOST-SAME: "-std=c++17"
 
 // Test that /std: override works on Windows
-// RUN: %clang_cl --target=x86_64-pc-windows-msvc -### -fsycl /std:c++20 -- %s 
2>&1 | FileCheck %s 
--check-prefixes=CHECK-MSVC-OVERRIDE-DEVICE,CHECK-MSVC-OVERRIDE-HOST
+// RUN: %clang_cl --target=x86_64-pc-windows-msvc -### -fsycl --no-offloadlib 
/std:c++20 -- %s 2>&1 | FileCheck %s 
--check-prefixes=CHECK-MSVC-OVERRIDE-DEVICE,CHECK-MSVC-OVERRIDE-HOST
 
 // CHECK-MSVC-OVERRIDE-DEVICE: "-cc1"{{.*}} "-fsycl-is-device"
 // CHECK-MSVC-OVERRIDE-DEVICE-SAME: "-std=c++20"
diff --git a/clang/test/Driver/sycl-windows.cpp 
b/clang/test/Driver/sycl-windows.cpp
index f07c05e74c3c7..e4b26feaa9292 100644
--- a/clang/test/Driver/sycl-windows.cpp
+++ b/clang/test/Driver/sycl-windows.cpp
@@ -6,7 +6,7 @@
 // -libpath: in linker output.
 
 /// Test 1: /MD (explicit) and release library dependency
-// RUN: %clang_cl -### -fsycl /MD --target=x86_64-pc-windows-msvc -- %s 2>&1 \
+// RUN: %clang_cl -### -fsycl --no-offloadlib /MD 
--target=x86_64-pc-windows-msvc -- %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-MD %s
 // CHECK-MD: "-cc1"
 // CHECK-MD: "--dependent-lib=LLVMSYCL"
@@ -24,14 +24,14 @@
 // CHECK-MTD-ERROR: error: SYCL requires dynamic C++ runtime
 
 /// Test 4: /MD uses release library
-// RUN: %clang_cl -### -fsycl /MD --target=x86_64-pc-windows-msvc -- %s 2>&1 \
+// RUN: %clang_cl -### -fsycl --no-offloadlib /MD 
--target=x86_64-pc-windows-msvc -- %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-RELEASE %s
 // CHECK-RELEASE: "-cc1"
 // CHECK-RELEASE: "--dependent-lib=LLVMSYCL"
 // CHECK-RELEASE-NOT: LLVMSYCLd
 
 /// Test 5: /MDd uses debug library
-// RUN: %clang_cl -### -fsycl /MDd --target=x86_64-pc-windows-msvc -- %s 2>&1 \
+// RUN: %clang_cl -### -fsycl --no-offloadlib /MDd 
--target=x86_64-pc-windows-msvc -- %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-DEBUG %s
 // CHECK-DEBUG: "-cc1"
 // CHECK-DEBUG: "--dependent-lib=LLVMSYCLd"
@@ -44,70 +44,70 @@
 // CHECK-STATIC-ERROR: error: SYCL requires dynamic C++ runtime
 
 /// Test 7: -fms-runtime-lib=dll_dbg uses debug library
-// RUN: %clang_cl -### -fsycl -fms-runtime-lib=dll_dbg \
+// RUN: %clang_cl -### -fsycl --no-offloadlib -fms-runtime-lib=dll_dbg \
 // RUN:   --target=x86_64-pc-windows-msvc -- %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-FLAG-DEBUG %s
 // CHECK-FLAG-DEBUG: "-cc1"
 // CHECK-FLAG-DEBUG: "--dependent-lib=LLVMSYCLd"
 
 /// Test 8: LNK4078 warning is suppressed
-// RUN: %clang_cl -### -fsycl --target=x86_64-pc-windows-msvc -- %s 2>&1 \
+// RUN: %clang_cl -### -fsycl --no-offloadlib --target=x86_64-pc-windows-msvc 
-- %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-IGNORE %s
 // CHECK-IGNORE: clang-linker-wrapper"
 // CHECK-IGNORE: "/IGNORE:4078"
 
 /// Test 9: -nolibsycl skips library dependency and CRT check
-// RUN: %clang_cl -### -fsycl -nolibsycl /MT \
+// RUN: %clang_cl -### -fsycl -nolibsycl --no-offloadlib /MT \
 // RUN:   --target=x86_64-pc-windows-msvc -- %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-NOLIBSYCL %s
 // CHECK-NOLIBSYCL-NOT: error:
 // CHECK-NOLIBSYCL-NOT: "--dependent-lib=LLVMSYCL"
 
 /// Test 10: Explicit /MD results in correct library
-// RUN: %clang_cl -### -fsycl /MD --target=x86_64-pc-windows-msvc -- %s 2>&1 \
+// RUN: %clang_cl -### -fsycl --no-offloadlib /MD 
--target=x86_64-pc-windows-msvc -- %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-EXPLICIT-MD %s
 // CHECK-EXPLICIT-MD: "-cc1"
 // CHECK-EXPLICIT-MD: "--dependent-lib=LLVMSYCL"
 
 /// Test 11: Library search path is added at linker stage
-// RUN: %clang_cl -### -fsycl /MD --target=x86_64-pc-windows-msvc -- %s 2>&1 \
+// RUN: %clang_cl -### -fsycl --no-offloadlib /MD 
--target=x86_64-pc-windows-msvc -- %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-LIBPATH %s
 // CHECK-LIBPATH: clang-linker-wrapper"
 // CHECK-LIBPATH: "-libpath:{{.*}}{{[/\\]+}}lib"
 
 /// Test 12: clang (non-clang-cl) with MSVC target uses -defaultlib:
-// RUN: %clang -### -fsycl -fms-runtime-lib=dll 
--target=x86_64-pc-windows-msvc -- %s 2>&1 \
+// RUN: %clang -### -fsycl --no-offloadlib -fms-runtime-lib=dll 
--target=x86_64-pc-windows-msvc -- %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-CLANG-DEFAULTLIB %s
 // CHECK-CLANG-DEFAULTLIB: clang-linker-wrapper"
 // CHECK-CLANG-DEFAULTLIB: "-libpath:{{.*}}{{[/\\]+}}lib"
 // CHECK-CLANG-DEFAULTLIB: "-defaultlib:LLVMSYCL"
 
 /// Test 13: clang with -fms-runtime-lib=dll_dbg uses debug library via 
-defaultlib:
-// RUN: %clang -### -fsycl -fms-runtime-lib=dll_dbg 
--target=x86_64-pc-windows-msvc -- %s 2>&1 \
+// RUN: %clang -### -fsycl --no-offloadlib -fms-runtime-lib=dll_dbg 
--target=x86_64-pc-windows-msvc -- %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-CLANG-DEBUG %s
 // CHECK-CLANG-DEBUG: clang-linker-wrapper"
 // CHECK-CLANG-DEBUG: "-defaultlib:LLVMSYCLd"
 
 /// Test 14: Default CRT behavior - release library when no CRT flag specified
-// RUN: %clang -### -fsycl -fms-runtime-lib=dll 
--target=x86_64-pc-windows-msvc -- %s 2>&1 \
+// RUN: %clang -### -fsycl --no-offloadlib -fms-runtime-lib=dll 
--target=x86_64-pc-windows-msvc -- %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-DEFAULT-CRT %s
 // CHECK-DEFAULT-CRT: "-cc1"
 // CHECK-DEFAULT-CRT: "--dependent-lib=LLVMSYCL"
 // CHECK-DEFAULT-CRT-NOT: LLVMSYCLd
 
 /// Test 15: Separate compilation - compile step embeds --dependent-lib in 
object
-// RUN: %clang -### -fsycl -c -fms-runtime-lib=dll 
--target=x86_64-pc-windows-msvc -- %s 2>&1 \
+// RUN: %clang -### -fsycl --no-offloadlib -c -fms-runtime-lib=dll 
--target=x86_64-pc-windows-msvc -- %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-SEP-COMPILE %s
 // CHECK-SEP-COMPILE: "--dependent-lib=LLVMSYCL"
 
 /// Test 16: Separate compilation - link step adds -libpath: and -defaultlib: 
for pre-compiled object
 // RUN: touch %t.obj
-// RUN: %clang -### -fsycl -fms-runtime-lib=dll 
--target=x86_64-pc-windows-msvc -- %t.obj 2>&1 \
+// RUN: %clang -### -fsycl --no-offloadlib -fms-runtime-lib=dll 
--target=x86_64-pc-windows-msvc -- %t.obj 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-SEP-LINK %s
 // CHECK-SEP-LINK: "-libpath:{{.*}}{{[/\\]+}}lib"
 // CHECK-SEP-LINK: "-defaultlib:LLVMSYCL"
 
 /// Test 17: clang (non-clang-cl) with -nolibsycl suppresses 
-defaultlib:LLVMSYCL
-// RUN: %clang -### -fsycl -nolibsycl -fms-runtime-lib=dll 
--target=x86_64-pc-windows-msvc -- %s 2>&1 \
+// RUN: %clang -### -fsycl -nolibsycl --no-offloadlib -fms-runtime-lib=dll 
--target=x86_64-pc-windows-msvc -- %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-CLANG-NOLIBSYCL %s
 // CHECK-CLANG-NOLIBSYCL-NOT: "-defaultlib:LLVMSYCL"
diff --git a/clang/test/Driver/sycl.cpp b/clang/test/Driver/sycl.cpp
index e78b2a7593323..fdd397579af0f 100644
--- a/clang/test/Driver/sycl.cpp
+++ b/clang/test/Driver/sycl.cpp
@@ -1,18 +1,18 @@
-// RUN: %clang -### -fsycl -c %s 2>&1 | FileCheck %s --check-prefix=ENABLED
-// RUN: %clang -### -fsycl %s 2>&1 | FileCheck %s --check-prefix=ENABLED
-// RUN: %clang -### -fsycl -sycl-std=1.2.1 %s 2>&1 | FileCheck %s 
--check-prefix=ENABLED
-// RUN: %clang -### -fsycl -sycl-std=121 %s 2>&1 | FileCheck %s 
--check-prefix=ENABLED
-// RUN: %clang -### -fsycl -sycl-std=2017 %s 2>&1 | FileCheck %s 
--check-prefix=ENABLED
-// RUN: %clang -### -fsycl -sycl-std=2020 %s 2>&1 | FileCheck %s 
--check-prefix=ENABLED
-// RUN: %clang -### -fsycl -sycl-std=sycl-1.2.1 %s 2>&1 | FileCheck %s 
--check-prefix=ENABLED
-// RUN: %clang -### -fno-sycl -fsycl %s 2>&1 | FileCheck %s 
--check-prefix=ENABLED
+// RUN: %clang -### -fsycl --no-offloadlib -c %s 2>&1 | FileCheck %s 
--check-prefix=ENABLED
+// RUN: %clang -### -fsycl --no-offloadlib %s 2>&1 | FileCheck %s 
--check-prefix=ENABLED
+// RUN: %clang -### -fsycl --no-offloadlib -sycl-std=1.2.1 %s 2>&1 | FileCheck 
%s --check-prefix=ENABLED
+// RUN: %clang -### -fsycl --no-offloadlib -sycl-std=121 %s 2>&1 | FileCheck 
%s --check-prefix=ENABLED
+// RUN: %clang -### -fsycl --no-offloadlib -sycl-std=2017 %s 2>&1 | FileCheck 
%s --check-prefix=ENABLED
+// RUN: %clang -### -fsycl --no-offloadlib -sycl-std=2020 %s 2>&1 | FileCheck 
%s --check-prefix=ENABLED
+// RUN: %clang -### -fsycl --no-offloadlib -sycl-std=sycl-1.2.1 %s 2>&1 | 
FileCheck %s --check-prefix=ENABLED
+// RUN: %clang -### -fno-sycl -fsycl --no-offloadlib %s 2>&1 | FileCheck %s 
--check-prefix=ENABLED
 // RUN: %clang -### -sycl-std=2017 %s 2>&1 | FileCheck %s 
--check-prefix=DISABLED
-// RUN: %clangxx -### -fsycl %s 2>&1 | FileCheck %s --check-prefix=ENABLED
+// RUN: %clangxx -### -fsycl --no-offloadlib %s 2>&1 | FileCheck %s 
--check-prefix=ENABLED
 // RUN: %clangxx -### -fno-sycl %s 2>&1 | FileCheck %s --check-prefix=DISABLED
 // RUN: %clangxx -### -fsycl -fno-sycl %s 2>&1 | FileCheck %s 
--check-prefix=DISABLED
 // RUN: %clangxx -### %s 2>&1 | FileCheck %s --check-prefix=DISABLED
-// RUN: %clang_cl -### -fsycl -sycl-std=2017 -- %s 2>&1 | FileCheck %s 
--check-prefix=ENABLED
-// RUN: %clang_cl -### -fsycl -- %s 2>&1 | FileCheck %s --check-prefix=ENABLED
+// RUN: %clang_cl -### -fsycl --no-offloadlib -sycl-std=2017 -- %s 2>&1 | 
FileCheck %s --check-prefix=ENABLED
+// RUN: %clang_cl -### -fsycl --no-offloadlib -- %s 2>&1 | FileCheck %s 
--check-prefix=ENABLED
 // RUN: %clang_cl -### -- %s 2>&1 | FileCheck %s --check-prefix=DISABLED
 
 // ENABLED: "-cc1"{{.*}} "-fsycl-is-device"
@@ -20,9 +20,9 @@
 // DISABLED-NOT: "-fsycl-is-device"
 // DISABLED-NOT: "-sycl-std="
 
-// RUN: %clang -### -fsycl  %s 2>&1 | FileCheck %s --check-prefix=DEFAULT
-// RUN: %clangxx -### -fsycl %s 2>&1 | FileCheck %s --check-prefix=DEFAULT
-// RUN: %clang_cl -### -fsycl -- %s 2>&1 | FileCheck %s --check-prefix=DEFAULT
+// RUN: %clang -### -fsycl --no-offloadlib %s 2>&1 | FileCheck %s 
--check-prefix=DEFAULT
+// RUN: %clangxx -### -fsycl --no-offloadlib %s 2>&1 | FileCheck %s 
--check-prefix=DEFAULT
+// RUN: %clang_cl -### -fsycl --no-offloadlib -- %s 2>&1 | FileCheck %s 
--check-prefix=DEFAULT
 
 // DEFAULT: "-sycl-std=2020"
 
@@ -32,5 +32,5 @@
 // CHECK-NO-OFFLOADLIB-NOT: warning: unknown argument ignored in clang-cl: 
'--no-offloadlib'
 
 // Verify that -fsycl with a C input is an error (enforced in the frontend).
-// RUN: not %clang -fsycl -x c %s 2>&1 | FileCheck %s 
--check-prefix=CHECK-C-INPUT
+// RUN: not %clang -fsycl --no-offloadlib -x c %s 2>&1 | FileCheck %s 
--check-prefix=CHECK-C-INPUT
 // CHECK-C-INPUT: error: invalid argument 'C' not allowed with '-fsycl'

>From 6ff12869e1e5511bbdf686ab6e58d8e9efcb68ca Mon Sep 17 00:00:00 2001
From: srividya sundaram <[email protected]>
Date: Mon, 24 Aug 2026 18:22:02 -0700
Subject: [PATCH 2/8] [Driver][SYCL] Fix spirv64 builtins lookup: restrict to
 spirv64, use VFS, support legacy layout

- Replace isSPIROrSPIRV() with isSPIRV() && isArch64Bit() to avoid
  false fatal diagnostics for spir/spir64/spirv32 targets that have
  no compiler-rt builtins library.
- Use getDriver().getVFS().exists() instead of llvm::sys::fs::exists()
  so VFS overlays are respected, consistent with the rest of the driver.
- Add fallback for LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF builds where
  the .bc is installed as lib/<os>/libclang_rt.builtins-spirv64.bc
  rather than lib/<triple>/libclang_rt.builtins.bc.
- Add test and fixture for the legacy layout fallback.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
---
 clang/lib/Driver/ToolChains/SYCL.cpp               | 14 +++++++++-----
 .../lib/linux/libclang_rt.builtins-spirv64.bc      |  0
 clang/test/Driver/sycl-device-lib-spirv64.cpp      | 10 +++++++++-
 3 files changed, 18 insertions(+), 6 deletions(-)
 create mode 100644 
clang/test/Driver/Inputs/spirv64-sycl-legacy/lib/linux/libclang_rt.builtins-spirv64.bc

diff --git a/clang/lib/Driver/ToolChains/SYCL.cpp 
b/clang/lib/Driver/ToolChains/SYCL.cpp
index 2348c179f7aa7..5d33aac328d7c 100644
--- a/clang/lib/Driver/ToolChains/SYCL.cpp
+++ b/clang/lib/Driver/ToolChains/SYCL.cpp
@@ -7,7 +7,6 @@
 
//===----------------------------------------------------------------------===//
 #include "SYCL.h"
 #include "clang/Driver/CommonArgs.h"
-#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/VirtualFileSystem.h"
 
@@ -220,17 +219,22 @@ llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
 SYCLToolChain::getDeviceLibs(
     const llvm::opt::ArgList &DriverArgs, BoundArch /*BA*/,
     const Action::OffloadKind /*DeviceOffloadingKind*/) const {
-  if (!getTriple().isSPIROrSPIRV())
+  if (!getTriple().isSPIRV() || !getTriple().isArch64Bit())
     return {};
   if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
                           true))
     return {};
-  // compiler-rt always installs the spirv64 .bc file under lib/<triple>/
-  // regardless of LLVM_ENABLE_PER_TARGET_RUNTIME_DIR, so only check that path.
+  // LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON: 
lib/<triple>/libclang_rt.builtins.bc
   SmallString<128> BCPath(getDriver().ResourceDir);
   llvm::sys::path::append(BCPath, "lib", getTriple().str(),
                           "libclang_rt.builtins.bc");
-  if (!llvm::sys::fs::exists(BCPath)) {
+  if (!getDriver().getVFS().exists(BCPath)) {
+    // LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF: 
lib/<os>/libclang_rt.builtins-spirv64.bc
+    BCPath = getDriver().ResourceDir;
+    llvm::sys::path::append(BCPath, "lib", getOSLibName(),
+                            "libclang_rt.builtins-spirv64.bc");
+  }
+  if (!getDriver().getVFS().exists(BCPath)) {
     getDriver().Diag(clang::diag::err_drv_no_compiler_rt_builtins_bc) << 
BCPath;
     return {};
   }
diff --git 
a/clang/test/Driver/Inputs/spirv64-sycl-legacy/lib/linux/libclang_rt.builtins-spirv64.bc
 
b/clang/test/Driver/Inputs/spirv64-sycl-legacy/lib/linux/libclang_rt.builtins-spirv64.bc
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/sycl-device-lib-spirv64.cpp 
b/clang/test/Driver/sycl-device-lib-spirv64.cpp
index 467dffa50b1e9..f090d2dbb34dc 100644
--- a/clang/test/Driver/sycl-device-lib-spirv64.cpp
+++ b/clang/test/Driver/sycl-device-lib-spirv64.cpp
@@ -22,7 +22,15 @@
 // CHECK-NOLIBSYCL: "-triple" "spirv64-unknown-unknown"
 // CHECK-NOLIBSYCL: "-mlink-builtin-bitcode" 
"{{.*}}lib{{[/\\]+}}spirv64-unknown-unknown{{[/\\]+}}libclang_rt.builtins.bc"
 
+// Test fallback to LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF layout:
+// lib/<os>/libclang_rt.builtins-spirv64.bc
+// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fsycl \
+// RUN:   -resource-dir=%S/Inputs/spirv64-sycl-legacy %s 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-LEGACY-BC
+// CHECK-LEGACY-BC: "-triple" "spirv64-unknown-unknown"
+// CHECK-LEGACY-BC: "-mlink-builtin-bitcode" 
"{{.*}}lib{{[/\\]+}}linux{{[/\\]+}}libclang_rt.builtins-spirv64.bc"
+
 // RUN: not %clang -### --target=x86_64-unknown-linux-gnu -fsycl \
 // RUN:   -resource-dir=%T/nonexistent %s 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=CHECK-MISSING
-// CHECK-MISSING: error: no compiler-rt builtins bitcode library 
'{{.*}}libclang_rt.builtins.bc' found in the clang resource directory
+// CHECK-MISSING: error: no compiler-rt builtins bitcode library 
'{{.*}}libclang_rt.builtins{{.*}}.bc' found in the clang resource directory

>From f6de24dcdfb1a662ac4620c2a7b10857cf720068 Mon Sep 17 00:00:00 2001
From: srividya sundaram <[email protected]>
Date: Mon, 24 Aug 2026 18:24:53 -0700
Subject: [PATCH 3/8] [Driver][SYCL] clang-format: wrap long comment line

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
---
 clang/lib/Driver/ToolChains/SYCL.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Driver/ToolChains/SYCL.cpp 
b/clang/lib/Driver/ToolChains/SYCL.cpp
index 5d33aac328d7c..a31338257ea01 100644
--- a/clang/lib/Driver/ToolChains/SYCL.cpp
+++ b/clang/lib/Driver/ToolChains/SYCL.cpp
@@ -229,7 +229,8 @@ SYCLToolChain::getDeviceLibs(
   llvm::sys::path::append(BCPath, "lib", getTriple().str(),
                           "libclang_rt.builtins.bc");
   if (!getDriver().getVFS().exists(BCPath)) {
-    // LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF: 
lib/<os>/libclang_rt.builtins-spirv64.bc
+    // LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF:
+    // lib/<os>/libclang_rt.builtins-spirv64.bc
     BCPath = getDriver().ResourceDir;
     llvm::sys::path::append(BCPath, "lib", getOSLibName(),
                             "libclang_rt.builtins-spirv64.bc");

>From a3d1eaac531ab2d6b404f907dddb39d1518d0b24 Mon Sep 17 00:00:00 2001
From: srividya sundaram <[email protected]>
Date: Mon, 24 Aug 2026 20:39:13 -0700
Subject: [PATCH 4/8] [Driver][SYCL] Fix legacy builtins path to use host OS
 name

For LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF, compiler-rt installs under
lib/<host-os>/, not lib/<device-os>/. Since the spirv64 device triple
has OS=unknown, getOSLibName() returned "unknown" instead of "linux".
Use HostTC.getOSLibName() to get the correct host OS directory.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
---
 clang/lib/Driver/ToolChains/SYCL.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Driver/ToolChains/SYCL.cpp 
b/clang/lib/Driver/ToolChains/SYCL.cpp
index a31338257ea01..e6d3c0ecdf133 100644
--- a/clang/lib/Driver/ToolChains/SYCL.cpp
+++ b/clang/lib/Driver/ToolChains/SYCL.cpp
@@ -232,7 +232,7 @@ SYCLToolChain::getDeviceLibs(
     // LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF:
     // lib/<os>/libclang_rt.builtins-spirv64.bc
     BCPath = getDriver().ResourceDir;
-    llvm::sys::path::append(BCPath, "lib", getOSLibName(),
+    llvm::sys::path::append(BCPath, "lib", HostTC.getOSLibName(),
                             "libclang_rt.builtins-spirv64.bc");
   }
   if (!getDriver().getVFS().exists(BCPath)) {

>From 257c7ee857d256d8a69bd979bfec3cc3e38cf7c3 Mon Sep 17 00:00:00 2001
From: srividya sundaram <[email protected]>
Date: Mon, 24 Aug 2026 20:51:30 -0700
Subject: [PATCH 5/8] [Driver][SYCL] Use MakeArgStringRef instead of
 MakeArgString for BC path

Avoids an unnecessary copy; consistent with the AMDGPU toolchain pattern.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
---
 clang/lib/Driver/ToolChains/SYCL.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Driver/ToolChains/SYCL.cpp 
b/clang/lib/Driver/ToolChains/SYCL.cpp
index e6d3c0ecdf133..8934c8d45e5b0 100644
--- a/clang/lib/Driver/ToolChains/SYCL.cpp
+++ b/clang/lib/Driver/ToolChains/SYCL.cpp
@@ -134,7 +134,7 @@ void SYCLToolChain::addClangTargetOptions(
        getDeviceLibs(DriverArgs, BA, DeviceOffloadingKind)) {
     CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
                                                : "-mlink-bitcode-file");
-    CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path));
+    CC1Args.push_back(DriverArgs.MakeArgStringRef(BCFile.Path));
   }
 }
 

>From 4f0e3f4600ae05499919c626d2dd1defc6ba313a Mon Sep 17 00:00:00 2001
From: srividya sundaram <[email protected]>
Date: Mon, 24 Aug 2026 21:08:06 -0700
Subject: [PATCH 6/8] [Driver][SYCL] Gate builtins linking on OFK_SYCL to fix
 preprocessing regression

addClangTargetOptions is called for all cc1 action types including
preprocessing (-E) and syntax-only. Without a guard, getDeviceLibs()
would run for -dM -E and emit a fatal error when libclang_rt.builtins.bc
is absent, even though no device IR is produced. Gate the getDeviceLibs
loop on DeviceOffloadingKind == OFK_SYCL so preprocessing and other
non-IR actions bypass the builtins lookup entirely.

Also revert the --no-offloadlib workaround from sycl-print-internal-defines.cpp
which was masking this regression.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
---
 clang/lib/Driver/ToolChains/SYCL.cpp             | 16 ++++++++++------
 .../test/Driver/sycl-print-internal-defines.cpp  |  4 ++--
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/SYCL.cpp 
b/clang/lib/Driver/ToolChains/SYCL.cpp
index 8934c8d45e5b0..da4bd32c1da7a 100644
--- a/clang/lib/Driver/ToolChains/SYCL.cpp
+++ b/clang/lib/Driver/ToolChains/SYCL.cpp
@@ -129,12 +129,16 @@ void SYCLToolChain::addClangTargetOptions(
     BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const {
   HostTC.addClangTargetOptions(DriverArgs, CC1Args, BA, DeviceOffloadingKind);
 
-  // Link device libraries (bitcode) into the device cc1 invocation.
-  for (const auto &BCFile :
-       getDeviceLibs(DriverArgs, BA, DeviceOffloadingKind)) {
-    CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
-                                               : "-mlink-bitcode-file");
-    CC1Args.push_back(DriverArgs.MakeArgStringRef(BCFile.Path));
+  // Only link device libraries for actual SYCL device IR compilation.
+  // Preprocessing and syntax-only actions do not produce device IR, so
+  // requiring the builtins bitcode there would be a spurious fatal error.
+  if (DeviceOffloadingKind == Action::OFK_SYCL) {
+    for (const auto &BCFile :
+         getDeviceLibs(DriverArgs, BA, DeviceOffloadingKind)) {
+      CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
+                                                 : "-mlink-bitcode-file");
+      CC1Args.push_back(DriverArgs.MakeArgStringRef(BCFile.Path));
+    }
   }
 }
 
diff --git a/clang/test/Driver/sycl-print-internal-defines.cpp 
b/clang/test/Driver/sycl-print-internal-defines.cpp
index b0efa278a5660..389aaf25608c6 100644
--- a/clang/test/Driver/sycl-print-internal-defines.cpp
+++ b/clang/test/Driver/sycl-print-internal-defines.cpp
@@ -1,8 +1,8 @@
 // Test that clang can print defines in SYCL mode.
 
-// RUN: %clangxx -fsycl --no-offloadlib -dM -E %s 2>&1 | FileCheck 
--check-prefix CHECK-PRINT-INTERNAL-DEFINES %s
+// RUN: %clangxx -fsycl -dM -E %s 2>&1 | FileCheck --check-prefix 
CHECK-PRINT-INTERNAL-DEFINES %s
 // CHECK-PRINT-INTERNAL-DEFINES: #define
 
 // Printing defines also works when input is stdin.
-// RUN: %clangxx -fsycl --no-offloadlib -dM -E - < /dev/null 2>&1 | FileCheck 
--check-prefixes=CHECK-PRINT-INTERNAL-DEFINES,CHECK-NO-ERROR %s
+// RUN: %clangxx -fsycl -dM -E - < /dev/null 2>&1 | FileCheck 
--check-prefixes=CHECK-PRINT-INTERNAL-DEFINES,CHECK-NO-ERROR %s
 // CHECK-NO-ERROR-NOT: error:

>From 85fd212f7f98eb15bb85fca2afc3634a2c679704 Mon Sep 17 00:00:00 2001
From: srividya sundaram <[email protected]>
Date: Mon, 24 Aug 2026 21:12:14 -0700
Subject: [PATCH 7/8] [Driver][SYCL] Use exact spirv64 arch check instead of
 isSPIRV()+isArch64Bit()

The logical 'spirv' arch also returns 64 from getArchPointerBitWidth(),
so isSPIRV() && isArch64Bit() incorrectly matches it. compiler-rt only
builds builtins for the concrete spirv64 arch, so restrict the check to
getArch() == spirv64 directly.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
---
 clang/lib/Driver/ToolChains/SYCL.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Driver/ToolChains/SYCL.cpp 
b/clang/lib/Driver/ToolChains/SYCL.cpp
index da4bd32c1da7a..8287dabdbab9a 100644
--- a/clang/lib/Driver/ToolChains/SYCL.cpp
+++ b/clang/lib/Driver/ToolChains/SYCL.cpp
@@ -223,7 +223,7 @@ llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
 SYCLToolChain::getDeviceLibs(
     const llvm::opt::ArgList &DriverArgs, BoundArch /*BA*/,
     const Action::OffloadKind /*DeviceOffloadingKind*/) const {
-  if (!getTriple().isSPIRV() || !getTriple().isArch64Bit())
+  if (getTriple().getArch() != llvm::Triple::spirv64)
     return {};
   if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
                           true))

>From 4163b8a53cd3cbc500be15b8f0859d4afb7697da Mon Sep 17 00:00:00 2001
From: srividya sundaram <[email protected]>
Date: Tue, 25 Aug 2026 06:06:44 -0700
Subject: [PATCH 8/8] [Driver][SYCL] Gate builtins linking on OFK_SYCL to fix
 preprocessing regression

The DeviceOffloadingKind passed to addClangTargetOptions is always
OFK_SYCL for the SYCL device toolchain regardless of the action type,
so an OFK_SYCL guard is ineffective. Instead, check whether -E or
-fsyntax-only has already been pushed into CC1Args (both are set before
addClangTargetOptions is called) to detect non-IR actions and skip the
getDeviceLibs lookup, avoiding a spurious fatal error on preprocessing
and syntax-only invocations that have no builtins installed.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
---
 clang/lib/Driver/ToolChains/SYCL.cpp | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/SYCL.cpp 
b/clang/lib/Driver/ToolChains/SYCL.cpp
index 8287dabdbab9a..342a0305647cc 100644
--- a/clang/lib/Driver/ToolChains/SYCL.cpp
+++ b/clang/lib/Driver/ToolChains/SYCL.cpp
@@ -129,10 +129,17 @@ void SYCLToolChain::addClangTargetOptions(
     BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const {
   HostTC.addClangTargetOptions(DriverArgs, CC1Args, BA, DeviceOffloadingKind);
 
-  // Only link device libraries for actual SYCL device IR compilation.
-  // Preprocessing and syntax-only actions do not produce device IR, so
-  // requiring the builtins bitcode there would be a spurious fatal error.
-  if (DeviceOffloadingKind == Action::OFK_SYCL) {
+  // Only link device libraries when actually emitting device IR.
+  // Preprocessing (-E) and syntax-only (-fsyntax-only) actions do not produce
+  // IR so -mlink-builtin-bitcode would be unused, and requiring the builtins
+  // bitcode to exist would be a spurious fatal error on those code paths.
+  auto IsNonIRAction = [](const llvm::opt::ArgStringList &Args) {
+    for (const char *A : Args)
+      if (llvm::StringRef(A) == "-E" || llvm::StringRef(A) == "-fsyntax-only")
+        return true;
+    return false;
+  };
+  if (!IsNonIRAction(CC1Args)) {
     for (const auto &BCFile :
          getDeviceLibs(DriverArgs, BA, DeviceOffloadingKind)) {
       CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to