From d07251d18a9a81d81d54e324388f4a057b7b7afb Mon Sep 17 00:00:00 2001 From: "Plyakhin, Yury" Date: Mon, 29 Sep 2025 23:54:53 +0200 Subject: [PATCH 1/2] [clang-sycl-linker] Generate SymbolTable for each image This PR adds extraction of kernel names for each image and stores them to the Image's StringData field. --- .../clang-sycl-linker/ClangSYCLLinker.cpp | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index fde6b55165868..8b186e6e28618 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -466,6 +466,12 @@ static Error runAOTCompile(StringRef InputFile, StringRef OutputFile, return createStringError(inconvertibleErrorCode(), "Unsupported arch"); } +bool isKernel(const Function &F) { + const CallingConv::ID CC = F.getCallingConv(); + return CC == CallingConv::SPIR_KERNEL || CC == CallingConv::AMDGPU_KERNEL || + CC == CallingConv::PTX_Kernel; +} + /// Performs the following steps: /// 1. Link input device code (user code and SYCL device library code). /// 2. Run SPIR-V code generation. @@ -486,6 +492,22 @@ Error runSYCLLink(ArrayRef Files, const ArgList &Args) { SmallVector SplitModules; SplitModules.emplace_back(*LinkedFile); + // Generate symbol table. + SmallVector SymbolTable; + for (size_t I = 0, E = SplitModules.size(); I != E; ++I) { + Expected> ModOrErr = + getBitcodeModule(SplitModules[I], C); + if (!ModOrErr) + return ModOrErr.takeError(); + + SmallVector Symbols; + for (Function &F : **ModOrErr) { + if (isKernel(F)) + Symbols.push_back(F.getName()); + } + SymbolTable.emplace_back(llvm::join(Symbols.begin(), Symbols.end(), "\n")); + } + bool IsAOTCompileNeeded = IsIntelOffloadArch( StringToOffloadArch(Args.getLastArgValue(OPT_arch_EQ))); @@ -523,12 +545,13 @@ Error runSYCLLink(ArrayRef Files, const ArgList &Args) { return createFileError(File, EC); } OffloadingImage TheImage{}; - TheImage.TheImageKind = IMG_Object; + TheImage.TheImageKind = IMG_None; TheImage.TheOffloadKind = OFK_SYCL; TheImage.StringData["triple"] = Args.MakeArgString(Args.getLastArgValue(OPT_triple_EQ)); TheImage.StringData["arch"] = Args.MakeArgString(Args.getLastArgValue(OPT_arch_EQ)); + TheImage.StringData["symbols"] = SymbolTable[I]; TheImage.Image = std::move(*FileOrErr); llvm::SmallString<0> Buffer = OffloadBinary::write(TheImage); From c383c6b5655d4b1d40c9c2dfac33e2cc56f5a815 Mon Sep 17 00:00:00 2001 From: "Plyakhin, Yury" Date: Tue, 30 Sep 2025 19:26:54 +0200 Subject: [PATCH 2/2] added TODO comments --- clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 8b186e6e28618..8dd993fb04362 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -466,6 +466,7 @@ static Error runAOTCompile(StringRef InputFile, StringRef OutputFile, return createStringError(inconvertibleErrorCode(), "Unsupported arch"); } +// TODO: Consider using LLVM-IR metadata to identify globals of interest bool isKernel(const Function &F) { const CallingConv::ID CC = F.getCallingConv(); return CC == CallingConv::SPIR_KERNEL || CC == CallingConv::AMDGPU_KERNEL || @@ -545,6 +546,12 @@ Error runSYCLLink(ArrayRef Files, const ArgList &Args) { return createFileError(File, EC); } OffloadingImage TheImage{}; + // TODO: TheImageKind should be + // `IsAOTCompileNeeded ? IMG_Object : IMG_SPIRV;` + // For that we need to update SYCL Runtime to align with the ImageKind enum. + // Temporarily it is initalized to IMG_None, because in that case, SYCL + // Runtime has a heuristic to understand what the Image Kind is, so at least + // it works. TheImage.TheImageKind = IMG_None; TheImage.TheOffloadKind = OFK_SYCL; TheImage.StringData["triple"] =