From efea1845a276b9e56b2ae442560756138afb069a Mon Sep 17 00:00:00 2001 From: "Balaji V. Iyer" Date: Fri, 23 Oct 2026 15:25:14 -0700 Subject: [PATCH 1/3] Init commit --- .../ClangLinkerWrapper.cpp | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index 8260d7f379d17..509c56e4daff5 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -2447,12 +2447,14 @@ Expected linkDevice(ArrayRef InputFiles, } Error containerizeRawImage(std::unique_ptr &Img, OffloadKind Kind, - const ArgList &Args) { + const ArgList &Args, StringRef CompileOpts = "", + StringRef LinkOpts = "") { llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ)); if (Kind == OFK_OpenMP && Triple.isSPIRV() && Triple.getVendor() == llvm::Triple::Intel && !Args.hasArg(OPT_embed_bitcode)) - return offloading::intel::containerizeOpenMPSPIRVImage(Img, Triple); + return offloading::intel::containerizeOpenMPSPIRVImage( + Img, Triple, CompileOpts, LinkOpts); return Error::success(); } @@ -2914,11 +2916,12 @@ Error handleOverrideImages( return Error::success(); } -/// Function looks for compile/link options encoded in SYCL images. If they are -/// found, then they are returned. If it is found that images have different -/// compile options or different link options, then an error is returned. +/// Function looks for compile/link options encoded in offload images. If they +/// are found, then they are returned. If it is found that images have +/// different compile options or different link options, then an error is +/// returned. Expected> -extractSYCLCompileLinkOptions(ArrayRef OffloadFiles) { +extractCompileLinkOptions(ArrayRef OffloadFiles) { if (OffloadFiles.size() == 0) return std::pair{}; @@ -3007,7 +3010,7 @@ linkAndWrapDeviceFiles(ArrayRef> LinkerInputFiles, if (HasSYCLOffloadKind) { auto LinkerArgs = getLinkerArgs(Input, BaseArgs, OFK_SYCL); Expected> CompileLinkOptionsOrErr = - extractSYCLCompileLinkOptions(Input); + extractCompileLinkOptions(Input); if (!CompileLinkOptionsOrErr) return CompileLinkOptionsOrErr.takeError(); @@ -3136,6 +3139,17 @@ linkAndWrapDeviceFiles(ArrayRef> LinkerInputFiles, InputFiles.emplace_back(*FileNameOrErr); } + // Recover the compile/link options the driver recorded in each input's + // offload metadata; the device linker invocation below does not + // preserve them in its output, so they must be forwarded explicitly + // when containerizing below. + Expected> CompileLinkOptionsOrErr = + extractCompileLinkOptions(Input); + if (!CompileLinkOptionsOrErr) + return CompileLinkOptionsOrErr.takeError(); + std::pair &CompileLinkOptions = + *CompileLinkOptionsOrErr; + // Link the remaining device files using the device linker. auto OutputOrErr = linkDevice(InputFiles, LinkerArgs, ActiveOffloadKindMask); @@ -3157,7 +3171,9 @@ linkAndWrapDeviceFiles(ArrayRef> LinkerInputFiles, } // Manually containerize offloading images not in ELF format. - if (Error E = containerizeRawImage(*FileOrErr, Kind, LinkerArgs)) + if (Error E = containerizeRawImage(*FileOrErr, Kind, LinkerArgs, + CompileLinkOptions.first, + CompileLinkOptions.second)) return E; std::scoped_lock Guard(ImageMtx); From 6db373d80e0d69adbbd2d37ef4d6fcc2583b4db1 Mon Sep 17 00:00:00 2001 From: "Balaji V. Iyer" Date: Fri, 23 Oct 2026 15:30:12 -0700 Subject: [PATCH 2/3] Added test case. --- .../openmp-compile-opts.cpp | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 clang/test/OffloadTools/clang-linker-wrapper/openmp-compile-opts.cpp diff --git a/clang/test/OffloadTools/clang-linker-wrapper/openmp-compile-opts.cpp b/clang/test/OffloadTools/clang-linker-wrapper/openmp-compile-opts.cpp new file mode 100644 index 0000000000000..879f1d50bfc85 --- /dev/null +++ b/clang/test/OffloadTools/clang-linker-wrapper/openmp-compile-opts.cpp @@ -0,0 +1,27 @@ +// Verify that compile-opts recorded in an OpenMP SPIR-V device image's +// offload metadata survive clang-linker-wrapper instead of being silently +// dropped when the image is re-containerized for the OpenMP JIT runtime. +// REQUIRES: system-linux +// REQUIRES: spirv-registered-target +// REQUIRES: x86-registered-target + +// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o %t.bc +// RUN: %clang_cc1 %s -triple spirv64-intel -fopenmp-is-target-device -emit-obj -o %t.device.o +// RUN: llvm-offload-binary -o %t.bundle "--image=file=%t.device.o,triple=spirv64-intel,arch=generic,kind=openmp,compile-opts=-cl-opt-disable" +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-obj -fembed-offload-object=%t.bundle -x ir %t.bc -o %t.host.o +// RUN: clang-linker-wrapper --dry-run --print-wrapped-module -host-triple=x86_64-unknown-linux-gnu %t.host.o -o %t.out --linker-path="/usr/bin/ld" > %t.ir 2>&1 +// RUN: FileCheck %s --input-file=%t.ir + +// CHECK: @.omp_offloading.device_image = {{.*}}compile-opts{{.*}}-cl-opt-disable + +// Stub symbols required by the OpenMP offload descriptor registration code +// emitted by clang-linker-wrapper; avoids linking -lomp/-lomptarget/-lc. +extern "C" { +void __tgt_register_lib(void *) {} +void __tgt_unregister_lib(void *) {} +int atexit(void (*)(void)) { return 0; } +} + +int main(int argc, char** argv) { + return 0; +} From 5fbc0dea536b9a233952754e1f0ac483ea9e6bf6 Mon Sep 17 00:00:00 2001 From: "Balaji V. Iyer" Date: Fri, 23 Oct 2026 17:00:39 -0700 Subject: [PATCH 3/3] Added changes requested by Mike --- .../openmp-compile-opts.cpp | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/clang/test/OffloadTools/clang-linker-wrapper/openmp-compile-opts.cpp b/clang/test/OffloadTools/clang-linker-wrapper/openmp-compile-opts.cpp index 879f1d50bfc85..619c1ae16189d 100644 --- a/clang/test/OffloadTools/clang-linker-wrapper/openmp-compile-opts.cpp +++ b/clang/test/OffloadTools/clang-linker-wrapper/openmp-compile-opts.cpp @@ -1,27 +1,22 @@ -// Verify that compile-opts recorded in an OpenMP SPIR-V device image's -// offload metadata survive clang-linker-wrapper instead of being silently -// dropped when the image is re-containerized for the OpenMP JIT runtime. +// Verify that compile-opts/link-opts recorded in an OpenMP SPIR-V device +// image's offload metadata survive clang-linker-wrapper instead of being +// silently dropped when the image is re-containerized for the OpenMP JIT +// runtime. // REQUIRES: system-linux // REQUIRES: spirv-registered-target // REQUIRES: x86-registered-target // RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o %t.bc // RUN: %clang_cc1 %s -triple spirv64-intel -fopenmp-is-target-device -emit-obj -o %t.device.o -// RUN: llvm-offload-binary -o %t.bundle "--image=file=%t.device.o,triple=spirv64-intel,arch=generic,kind=openmp,compile-opts=-cl-opt-disable" +// RUN: llvm-offload-binary -o %t.bundle "--image=file=%t.device.o,triple=spirv64-intel,arch=generic,kind=openmp,compile-opts=-cl-opt-disable,link-opts=-cl-take-global-address" // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-obj -fembed-offload-object=%t.bundle -x ir %t.bc -o %t.host.o // RUN: clang-linker-wrapper --dry-run --print-wrapped-module -host-triple=x86_64-unknown-linux-gnu %t.host.o -o %t.out --linker-path="/usr/bin/ld" > %t.ir 2>&1 -// RUN: FileCheck %s --input-file=%t.ir +// +// The embedded strings are serialized through a string-table builder that +// may reorder them relative to each other, so each is checked with a +// separate FileCheck run rather than relying on their relative order. +// RUN: FileCheck %s --input-file=%t.ir --check-prefix=COMPILE-OPTS +// RUN: FileCheck %s --input-file=%t.ir --check-prefix=LINK-OPTS -// CHECK: @.omp_offloading.device_image = {{.*}}compile-opts{{.*}}-cl-opt-disable - -// Stub symbols required by the OpenMP offload descriptor registration code -// emitted by clang-linker-wrapper; avoids linking -lomp/-lomptarget/-lc. -extern "C" { -void __tgt_register_lib(void *) {} -void __tgt_unregister_lib(void *) {} -int atexit(void (*)(void)) { return 0; } -} - -int main(int argc, char** argv) { - return 0; -} +// COMPILE-OPTS: @.omp_offloading.device_image = {{.*}}compile-opts{{.*}}-cl-opt-disable +// LINK-OPTS: @.omp_offloading.device_image = {{.*}}link-opts{{.*}}-cl-take-global-address