[clang] [clang][Driver][SPIR-V] Allow linking IR using llvm-link (PR #169572)
Nick Sarnie via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 9 12:55:02 PST 2025
https://github.com/sarnex updated https://github.com/llvm/llvm-project/pull/169572
>From 89b0fe0a8cc57d27c69d18927c1ae10833d82a29 Mon Sep 17 00:00:00 2001
From: Nick Sarnie <nick.sarnie at intel.com>
Date: Tue, 25 Nov 2025 13:23:36 -0800
Subject: [PATCH 1/4] [clang][Driver][SPIR-V] Allow linking IR using llvm-link
Signed-off-by: Nick Sarnie <nick.sarnie at intel.com>
---
clang/lib/Driver/Driver.cpp | 16 +++++++++++---
clang/lib/Driver/ToolChains/SPIRV.cpp | 26 ++++++++++++++++++++++
clang/lib/Driver/ToolChains/SPIRV.h | 5 +++++
clang/test/Driver/spirv-llvm-link.c | 31 +++++++++++++++++++++++++++
4 files changed, 75 insertions(+), 3 deletions(-)
create mode 100644 clang/test/Driver/spirv-llvm-link.c
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index de8d4601210ae..27d5bcd4290c6 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -4265,8 +4265,11 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
Args.AddFlagArg(nullptr,
getOpts().getOption(options::OPT_frtlib_add_rpath));
}
- // Emitting LLVM while linking disabled except in HIPAMD Toolchain
- if (Args.hasArg(options::OPT_emit_llvm) && !Args.hasArg(options::OPT_hip_link))
+ // Emitting LLVM while linking disabled except in the HIPAMD or SPIR-V
+ // Toolchains
+ if (Args.hasArg(options::OPT_emit_llvm) &&
+ !Args.hasArg(options::OPT_hip_link) &&
+ !C.getDefaultToolChain().getTriple().isSPIRV())
Diag(clang::diag::err_drv_emit_llvm_link);
if (C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() &&
LTOMode != LTOK_None &&
@@ -4595,7 +4598,14 @@ void Driver::BuildDefaultActions(Compilation &C, DerivedArgList &Args,
LA->propagateHostOffloadInfo(C.getActiveOffloadKinds(),
/*BoundArch=*/nullptr);
} else {
- LA = C.MakeAction<LinkJobAction>(LinkerInputs, types::TY_Image);
+ // If we are linking but were passed -emit-llvm, we will be calling
+ // llvm-link, so set the output type accordingly. This is only allowed in
+ // rare cases, so make sure we aren't going to error about it.
+ types::ID LT =
+ Args.hasArg(options::OPT_emit_llvm) && !Diags.hasErrorOccurred()
+ ? types::TY_LLVM_BC
+ : types::TY_Image;
+ LA = C.MakeAction<LinkJobAction>(LinkerInputs, LT);
}
if (!UseNewOffloadingDriver)
LA = OffloadBuilder->processHostLinkAction(LA);
diff --git a/clang/lib/Driver/ToolChains/SPIRV.cpp b/clang/lib/Driver/ToolChains/SPIRV.cpp
index 27de55cfebfc1..ddb2a0bbb5058 100644
--- a/clang/lib/Driver/ToolChains/SPIRV.cpp
+++ b/clang/lib/Driver/ToolChains/SPIRV.cpp
@@ -70,6 +70,28 @@ void SPIRV::constructAssembleCommand(Compilation &C, const Tool &T,
Exec, CmdArgs, Input, Output));
}
+void SPIRV::constructLLVMLinkCommand(Compilation &C, const Tool &T,
+ const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgStringList &Args) {
+ // Construct llvm-link command.
+ // The output from llvm-link is a bitcode file.
+ ArgStringList LlvmLinkArgs;
+
+ assert(!Inputs.empty() && "Must have at least one input.");
+
+ LlvmLinkArgs.append({"-o", Output.getFilename()});
+ for (auto Input : Inputs)
+ LlvmLinkArgs.push_back(Input.getFilename());
+
+ const char *LlvmLink =
+ C.getArgs().MakeArgString(T.getToolChain().GetProgramPath("llvm-link"));
+ C.addCommand(std::make_unique<Command>(JA, T, ResponseFileSupport::None(),
+ LlvmLink, LlvmLinkArgs, Inputs,
+ Output));
+}
+
void SPIRV::Translator::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -121,6 +143,10 @@ void SPIRV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ if (JA.getType() == types::TY_LLVM_BC) {
+ constructLLVMLinkCommand(C, *this, JA, Output, Inputs, {});
+ return;
+ }
const ToolChain &ToolChain = getToolChain();
std::string Linker = ToolChain.GetProgramPath(getShortName());
ArgStringList CmdArgs;
diff --git a/clang/lib/Driver/ToolChains/SPIRV.h b/clang/lib/Driver/ToolChains/SPIRV.h
index 924eb01adcbbf..249053c23b792 100644
--- a/clang/lib/Driver/ToolChains/SPIRV.h
+++ b/clang/lib/Driver/ToolChains/SPIRV.h
@@ -27,6 +27,11 @@ void constructAssembleCommand(Compilation &C, const Tool &T,
const InputInfo &Input,
const llvm::opt::ArgStringList &Args);
+void constructLLVMLinkCommand(Compilation &C, const Tool &T,
+ const JobAction &JA, const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgStringList &Args);
+
class LLVM_LIBRARY_VISIBILITY Translator : public Tool {
public:
Translator(const ToolChain &TC)
diff --git a/clang/test/Driver/spirv-llvm-link.c b/clang/test/Driver/spirv-llvm-link.c
new file mode 100644
index 0000000000000..9c30654707016
--- /dev/null
+++ b/clang/test/Driver/spirv-llvm-link.c
@@ -0,0 +1,31 @@
+// Check BC input
+// RUN: mkdir -p %t
+// RUN: touch %t/a.bc
+// RUN: touch %t/b.bc
+// RUN: %clang -### --target=spirv64 -emit-llvm %t/a.bc %t/b.bc 2>&1 | FileCheck --check-prefix=CHECK-TOOL-BC %s
+
+// CHECK-TOOL-BC: "-cc1" {{.*}} "-o" "[[TMP1_BC:.+]]" "-x" "ir" "{{.*}}.bc"
+// CHECK-TOOL-BC: "-cc1" {{.*}} "-o" "[[TMP2_BC:.+]]" "-x" "ir" "{{.*}}.bc"
+// CHECK-TOOL-BC: llvm-link{{.*}} "-o" {{.*}} "[[TMP1_BC]]" "[[TMP2_BC]]"
+
+// RUN: %clang -ccc-print-bindings --target=spirv64 -emit-llvm %t/a.bc %t/b.bc 2>&1 | FileCheck -check-prefix=CHECK-BINDINGS-BC %s
+
+// CHECK-BINDINGS-BC: "spirv64" - "clang", inputs: ["{{.*}}.bc"], output: "[[TMP1_BINDINGS_BC:.+]]"
+// CHECK-BINDINGS-BC: "spirv64" - "clang", inputs: ["{{.*}}.bc"], output: "[[TMP2_BINDINGS_BC:.+]]"
+// CHECK-BINDINGS-BC: "spirv64" - "SPIR-V::Linker", inputs: ["[[TMP1_BINDINGS_BC]]", "[[TMP2_BINDINGS_BC]]"], output: "{{.*}}.bc"
+
+// Check source input
+// RUN: touch %t/foo.c
+// RUN: touch %t/bar.c
+
+// RUN: %clang -### --target=spirv64 -emit-llvm %t/foo.c %t/bar.c 2>&1 | FileCheck --check-prefix=CHECK-TOOL-SRC %s
+
+// CHECK-TOOL-SRC: "-cc1" {{.*}} "-o" "[[TMP1_SRC_BC:.+]]" "-x" "c" "{{.*}}foo.c"
+// CHECK-TOOL-SRC: "-cc1" {{.*}} "-o" "[[TMP2_SRC_BC:.+]]" "-x" "c" "{{.*}}bar.c"
+// CHECK-TOOL-SRC: llvm-link{{.*}} "-o" {{.*}} "[[TMP1_SRC_BC]]" "[[TMP2_SRC_BC]]"
+
+// RUN: %clang -ccc-print-bindings --target=spirv64 -emit-llvm %t/foo.c %t/bar.c 2>&1 | FileCheck -check-prefix=CHECK-BINDINGS-SRC %s
+
+// CHECK-BINDINGS-SRC: "spirv64" - "clang", inputs: ["{{.*}}foo.c"], output: "[[TMP1_BINDINGS_SRC_BC:.+]]"
+// CHECK-BINDINGS-SRC: "spirv64" - "clang", inputs: ["{{.*}}bar.c"], output: "[[TMP2_BINDINGS_SRC_BC:.+]]"
+// CHECK-BINDINGS-SRC: "spirv64" - "SPIR-V::Linker", inputs: ["[[TMP1_BINDINGS_SRC_BC]]", "[[TMP2_BINDINGS_SRC_BC]]"], output: "{{.*}}.bc"
>From 4af3b7e2503f0500c588f96b69c697ce282ffa60 Mon Sep 17 00:00:00 2001
From: Nick Sarnie <nick.sarnie at intel.com>
Date: Tue, 2 Dec 2025 14:21:21 -0800
Subject: [PATCH 2/4] add utility
Signed-off-by: Nick Sarnie <nick.sarnie at intel.com>
---
clang/include/clang/Driver/CommonArgs.h | 8 ++++++
clang/lib/Driver/ToolChains/CommonArgs.cpp | 25 ++++++++++++++++++
clang/lib/Driver/ToolChains/HIPAMD.cpp | 26 ++++++-------------
clang/lib/Driver/ToolChains/HIPSPV.cpp | 7 ++---
clang/lib/Driver/ToolChains/SPIRV.cpp | 12 ++++-----
clang/lib/Driver/ToolChains/SPIRV.h | 2 +-
.../Driver/hipspv-link-static-library.hip | 4 +--
clang/test/Driver/hipspv-toolchain-rdc.hip | 2 +-
clang/test/Driver/hipspv-toolchain.hip | 2 +-
9 files changed, 53 insertions(+), 35 deletions(-)
diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h
index ac17d6211d882..f86ad4b758436 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -312,6 +312,14 @@ void setComplexRange(const Driver &D, StringRef NewOpt,
LangOptions::ComplexRangeKind NewRange, StringRef &LastOpt,
LangOptions::ComplexRangeKind &Range);
+void constructLlvmLinkCommand(Compilation &C, const Tool &T,
+ const JobAction &JA,
+ const InputInfoList &JobInputs,
+ const llvm::opt::ArgStringList &LinkerInputs,
+ const InputInfo &Output,
+ const llvm::opt::ArgList &Args,
+ const char *OutputFilename = nullptr);
+
} // end namespace tools
} // end namespace driver
} // end namespace clang
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 4c036f0f8dee3..8c922f47eeb8d 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -3637,3 +3637,28 @@ void tools::setComplexRange(const Driver &D, StringRef NewOpt,
LastOpt = NewOpt;
Range = NewRange;
}
+
+void tools::constructLlvmLinkCommand(Compilation &C, const Tool &T,
+ const JobAction &JA,
+ const InputInfoList &JobInputs,
+ const ArgStringList &LinkerInputs,
+ const InputInfo &Output,
+ const llvm::opt::ArgList &Args,
+ const char *OutputFilename) {
+ // Construct llvm-link command.
+ // The output from llvm-link is a bitcode file.
+
+ assert(!LinkerInputs.empty() && !JobInputs.empty() &&
+ "Must have at least one input.");
+
+ ArgStringList LlvmLinkArgs(
+ {"-o", OutputFilename ? OutputFilename : Output.getFilename()});
+
+ LlvmLinkArgs.append(LinkerInputs);
+
+ const ToolChain &TC = T.getToolChain();
+ const char *LlvmLink = Args.MakeArgString(TC.GetProgramPath("llvm-link"));
+ C.addCommand(std::make_unique<Command>(JA, T, ResponseFileSupport::None(),
+ LlvmLink, LlvmLinkArgs, JobInputs,
+ Output));
+}
diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp
index 231a38c2d3717..d51a4c86cd7c2 100644
--- a/clang/lib/Driver/ToolChains/HIPAMD.cpp
+++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp
@@ -33,32 +33,22 @@ using namespace llvm::opt;
#define NULL_FILE "/dev/null"
#endif
-void AMDGCN::Linker::constructLlvmLinkCommand(Compilation &C,
- const JobAction &JA,
- const InputInfoList &Inputs,
- const InputInfo &Output,
- const llvm::opt::ArgList &Args) const {
- // Construct llvm-link command.
- // The output from llvm-link is a bitcode file.
- ArgStringList LlvmLinkArgs;
+void AMDGCN::Linker::constructLlvmLinkCommand(
+ Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
+ const InputInfo &Output, const llvm::opt::ArgList &Args) const {
- assert(!Inputs.empty() && "Must have at least one input.");
+ ArgStringList LinkerInputs;
- LlvmLinkArgs.append({"-o", Output.getFilename()});
for (auto Input : Inputs)
- LlvmLinkArgs.push_back(Input.getFilename());
+ LinkerInputs.push_back(Input.getFilename());
// Look for archive of bundled bitcode in arguments, and add temporary files
// for the extracted archive of bitcode to inputs.
auto TargetID = Args.getLastArgValue(options::OPT_mcpu_EQ);
- AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, LlvmLinkArgs, "amdgcn",
+ AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, LinkerInputs, "amdgcn",
TargetID, /*IsBitCodeSDL=*/true);
-
- const char *LlvmLink =
- Args.MakeArgString(getToolChain().GetProgramPath("llvm-link"));
- C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
- LlvmLink, LlvmLinkArgs, Inputs,
- Output));
+ tools::constructLlvmLinkCommand(C, *this, JA, Inputs, LinkerInputs, Output,
+ Args);
}
void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA,
diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp
index be0f49d8e1497..18d7636c37a6d 100644
--- a/clang/lib/Driver/ToolChains/HIPSPV.cpp
+++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp
@@ -69,11 +69,8 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand(
"generic"; // SPIR-V is generic, no specific target ID like -mcpu
tools::AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, LinkArgs, Arch,
Target, /*IsBitCodeSDL=*/true);
- LinkArgs.append({"-o", TempFile});
- const char *LlvmLink =
- Args.MakeArgString(getToolChain().GetProgramPath("llvm-link"));
- C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
- LlvmLink, LinkArgs, Inputs, Output));
+ tools::constructLlvmLinkCommand(C, *this, JA, Inputs, LinkArgs, Output, Args,
+ TempFile);
// Post-link HIP lowering.
diff --git a/clang/lib/Driver/ToolChains/SPIRV.cpp b/clang/lib/Driver/ToolChains/SPIRV.cpp
index ddb2a0bbb5058..44f7a917aa84a 100644
--- a/clang/lib/Driver/ToolChains/SPIRV.cpp
+++ b/clang/lib/Driver/ToolChains/SPIRV.cpp
@@ -74,17 +74,15 @@ void SPIRV::constructLLVMLinkCommand(Compilation &C, const Tool &T,
const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const llvm::opt::ArgStringList &Args) {
- // Construct llvm-link command.
- // The output from llvm-link is a bitcode file.
- ArgStringList LlvmLinkArgs;
+ const llvm::opt::ArgList &Args) {
- assert(!Inputs.empty() && "Must have at least one input.");
+ ArgStringList LlvmLinkArgs;
- LlvmLinkArgs.append({"-o", Output.getFilename()});
for (auto Input : Inputs)
LlvmLinkArgs.push_back(Input.getFilename());
+ tools::constructLlvmLinkCommand(C, T, JA, Inputs, LlvmLinkArgs, Output, Args);
+
const char *LlvmLink =
C.getArgs().MakeArgString(T.getToolChain().GetProgramPath("llvm-link"));
C.addCommand(std::make_unique<Command>(JA, T, ResponseFileSupport::None(),
@@ -144,7 +142,7 @@ void SPIRV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const ArgList &Args,
const char *LinkingOutput) const {
if (JA.getType() == types::TY_LLVM_BC) {
- constructLLVMLinkCommand(C, *this, JA, Output, Inputs, {});
+ constructLLVMLinkCommand(C, *this, JA, Output, Inputs, Args);
return;
}
const ToolChain &ToolChain = getToolChain();
diff --git a/clang/lib/Driver/ToolChains/SPIRV.h b/clang/lib/Driver/ToolChains/SPIRV.h
index 249053c23b792..018e9fa99607c 100644
--- a/clang/lib/Driver/ToolChains/SPIRV.h
+++ b/clang/lib/Driver/ToolChains/SPIRV.h
@@ -30,7 +30,7 @@ void constructAssembleCommand(Compilation &C, const Tool &T,
void constructLLVMLinkCommand(Compilation &C, const Tool &T,
const JobAction &JA, const InputInfo &Output,
const InputInfoList &Inputs,
- const llvm::opt::ArgStringList &Args);
+ const llvm::opt::ArgList &Args);
class LLVM_LIBRARY_VISIBILITY Translator : public Tool {
public:
diff --git a/clang/test/Driver/hipspv-link-static-library.hip b/clang/test/Driver/hipspv-link-static-library.hip
index 03126ae589a09..cf16236738c12 100644
--- a/clang/test/Driver/hipspv-link-static-library.hip
+++ b/clang/test/Driver/hipspv-link-static-library.hip
@@ -22,7 +22,7 @@
// Verify that the input files are added before the SDL files in llvm-link command
// This tests the ordering fix to match HIPAMD behavior
// SDL-LINK: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}libSDL.a" "-targets=hip-spirv64-unknown-unknown-unknown-generic" "-output=[[SDL_A:.*\.a]]" "-allow-missing-bundles"
-// SDL-LINK: "{{.*}}llvm-link" "{{.*}}.bc" "[[SDL_A]]" "-o"
+// SDL-LINK: "{{.*}}llvm-link" "-o" "{{.*}}.bc" "{{.*}}.bc" "[[SDL_A]]"
// SDL-ARCHIVE: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}libSDL.a" "-targets=hip-spirv64-unknown-unknown-unknown-generic" "-output=[[SDL_A:.*\.a]]" "-allow-missing-bundles"
-// SDL-ARCHIVE: "{{.*}}llvm-link" "{{.*}}.bc" "[[SDL_A]]" "-o"
+// SDL-ARCHIVE: "{{.*}}llvm-link" "-o" "{{.*}}.bc" "{{.*}}.bc" "[[SDL_A]]"
diff --git a/clang/test/Driver/hipspv-toolchain-rdc.hip b/clang/test/Driver/hipspv-toolchain-rdc.hip
index acdadacc49064..05d9079f8dc18 100644
--- a/clang/test/Driver/hipspv-toolchain-rdc.hip
+++ b/clang/test/Driver/hipspv-toolchain-rdc.hip
@@ -41,7 +41,7 @@
// CHECK-SAME: {{.*}} [[B_SRC]]
// Link device code, lower it with HIPSPV passes and emit SPIR-V binary.
-// CHECK: {{".*llvm-link.*"}} [[A_BC1]] [[B_BC1]] "-o" [[AB_LINK:".*bc"]]
+// CHECK: {{".*llvm-link.*"}} "-o" [[AB_LINK:".*bc"]] [[A_BC1]] [[B_BC1]]
// CHECK: {{".*opt.*"}} [[AB_LINK]] "-load-pass-plugin"
// CHECK-SAME: "{{.*}}/Inputs/hipspv/lib/libLLVMHipSpvPasses.so"
// CHECK-SAME: "-o" [[AB_LOWER:".*bc"]]
diff --git a/clang/test/Driver/hipspv-toolchain.hip b/clang/test/Driver/hipspv-toolchain.hip
index 3c175ebf433cc..85c4333e877f2 100644
--- a/clang/test/Driver/hipspv-toolchain.hip
+++ b/clang/test/Driver/hipspv-toolchain.hip
@@ -14,7 +14,7 @@
// CHECK-SAME: "-o" [[DEV_BC:".*bc"]]
// CHECK-SAME: "-x" "hip"
-// CHECK: {{".*llvm-link"}} [[DEV_BC]] "-o" [[LINK_BC:".*bc"]]
+// CHECK: {{".*llvm-link"}} "-o" [[LINK_BC:".*bc"]] [[DEV_BC]]
// CHECK: {{".*opt"}} [[LINK_BC]] "-load-pass-plugin"
// CHECK-SAME: {{".*/hipspv/lib/libLLVMHipSpvPasses.so"}}
>From a19f7299f8df61710d260fa2cde288a487f590b4 Mon Sep 17 00:00:00 2001
From: Nick Sarnie <nick.sarnie at intel.com>
Date: Mon, 8 Dec 2025 12:01:50 -0800
Subject: [PATCH 3/4] add -S test and comment
Signed-off-by: Nick Sarnie <nick.sarnie at intel.com>
---
clang/include/clang/Driver/CommonArgs.h | 3 ++
clang/test/Driver/spirv-llvm-link-emit-asm.c | 31 ++++++++++++++++++++
2 files changed, 34 insertions(+)
create mode 100644 clang/test/Driver/spirv-llvm-link-emit-asm.c
diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h
index f86ad4b758436..c5e84c1a97574 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -312,6 +312,9 @@ void setComplexRange(const Driver &D, StringRef NewOpt,
LangOptions::ComplexRangeKind NewRange, StringRef &LastOpt,
LangOptions::ComplexRangeKind &Range);
+// This function expects that the inputs to llvm-link will be specified by the
+// caller, but the output is handled by this function, with the optional ability
+// to set the output filename.
void constructLlvmLinkCommand(Compilation &C, const Tool &T,
const JobAction &JA,
const InputInfoList &JobInputs,
diff --git a/clang/test/Driver/spirv-llvm-link-emit-asm.c b/clang/test/Driver/spirv-llvm-link-emit-asm.c
new file mode 100644
index 0000000000000..86d3c1c9a6ba5
--- /dev/null
+++ b/clang/test/Driver/spirv-llvm-link-emit-asm.c
@@ -0,0 +1,31 @@
+// Check BC input with -S
+// RUN: mkdir -p %t
+// RUN: touch %t/a.bc
+// RUN: touch %t/b.bc
+// RUN: %clang -### --target=spirv64 -emit-llvm -S %t/a.bc %t/b.bc 2>&1 | FileCheck --check-prefix=CHECK-TOOL-BC %s
+
+// CHECK-TOOL-BC: "-cc1" {{.*}} "-o" "{{.*}}.ll" "-x" "ir" "{{.*}}.bc"
+// CHECK-TOOL-BC: "-cc1" {{.*}} "-o" "{{.*}}.ll" "-x" "ir" "{{.*}}.bc"
+// CHECK-TOOL-BC-NOT: llvm-link
+
+// RUN: %clang -ccc-print-bindings --target=spirv64 -emit-llvm -S %t/a.bc %t/b.bc 2>&1 | FileCheck -check-prefix=CHECK-BINDINGS-BC %s
+
+// CHECK-BINDINGS-BC: "spirv64" - "clang", inputs: ["{{.*}}.bc"], output: "[[TMP1_BINDINGS_BC:.+]]"
+// CHECK-BINDINGS-BC: "spirv64" - "clang", inputs: ["{{.*}}.bc"], output: "[[TMP2_BINDINGS_BC:.+]]"
+// CHECK-BINDINGS-BC-NOT: SPIR-V::Linker
+
+// Check source input with -S
+// RUN: touch %t/foo.c
+// RUN: touch %t/bar.c
+
+// RUN: %clang -### --target=spirv64 -emit-llvm -S %t/foo.c %t/bar.c 2>&1 | FileCheck --check-prefix=CHECK-TOOL-SRC %s
+
+// CHECK-TOOL-SRC: "-cc1" {{.*}} "-o" "{{.*}}.ll" "-x" "c" "{{.*}}foo.c"
+// CHECK-TOOL-SRC: "-cc1" {{.*}} "-o" "{{.*}}.ll" "-x" "c" "{{.*}}bar.c"
+// CHECK-TOOL-SRC-NOT: llvm-link
+
+// RUN: %clang -ccc-print-bindings --target=spirv64 -emit-llvm -S %t/foo.c %t/bar.c 2>&1 | FileCheck -check-prefix=CHECK-BINDINGS-SRC %s
+
+// CHECK-BINDINGS-SRC: "spirv64" - "clang", inputs: ["{{.*}}foo.c"], output: "{{.*}}.ll"
+// CHECK-BINDINGS-SRC: "spirv64" - "clang", inputs: ["{{.*}}bar.c"], output: "{{.*}}.ll"
+// CHECK-BINDINGS-SRC-NOT: SPIR-V::Linker
>From 6eca6298243ba8985268ab0d081d8b71269d56f0 Mon Sep 17 00:00:00 2001
From: Nick Sarnie <nick.sarnie at intel.com>
Date: Tue, 9 Dec 2025 09:29:31 -0800
Subject: [PATCH 4/4] Llvm->LLVM
Signed-off-by: Nick Sarnie <nick.sarnie at intel.com>
---
clang/include/clang/Driver/CommonArgs.h | 2 +-
clang/lib/Driver/ToolChains/CommonArgs.cpp | 2 +-
clang/lib/Driver/ToolChains/HIPAMD.cpp | 8 ++++----
clang/lib/Driver/ToolChains/HIPAMD.h | 2 +-
clang/lib/Driver/ToolChains/HIPSPV.cpp | 2 +-
clang/lib/Driver/ToolChains/SPIRV.cpp | 2 +-
6 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h
index c5e84c1a97574..94498ea7f5381 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -315,7 +315,7 @@ void setComplexRange(const Driver &D, StringRef NewOpt,
// This function expects that the inputs to llvm-link will be specified by the
// caller, but the output is handled by this function, with the optional ability
// to set the output filename.
-void constructLlvmLinkCommand(Compilation &C, const Tool &T,
+void constructLLVMLinkCommand(Compilation &C, const Tool &T,
const JobAction &JA,
const InputInfoList &JobInputs,
const llvm::opt::ArgStringList &LinkerInputs,
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 8c922f47eeb8d..0abd41e6e1a27 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -3638,7 +3638,7 @@ void tools::setComplexRange(const Driver &D, StringRef NewOpt,
Range = NewRange;
}
-void tools::constructLlvmLinkCommand(Compilation &C, const Tool &T,
+void tools::constructLLVMLinkCommand(Compilation &C, const Tool &T,
const JobAction &JA,
const InputInfoList &JobInputs,
const ArgStringList &LinkerInputs,
diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp
index d51a4c86cd7c2..1e393daef390a 100644
--- a/clang/lib/Driver/ToolChains/HIPAMD.cpp
+++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp
@@ -33,7 +33,7 @@ using namespace llvm::opt;
#define NULL_FILE "/dev/null"
#endif
-void AMDGCN::Linker::constructLlvmLinkCommand(
+void AMDGCN::Linker::constructLLVMLinkCommand(
Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
const InputInfo &Output, const llvm::opt::ArgList &Args) const {
@@ -47,7 +47,7 @@ void AMDGCN::Linker::constructLlvmLinkCommand(
auto TargetID = Args.getLastArgValue(options::OPT_mcpu_EQ);
AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, LinkerInputs, "amdgcn",
TargetID, /*IsBitCodeSDL=*/true);
- tools::constructLlvmLinkCommand(C, *this, JA, Inputs, LinkerInputs, Output,
+ tools::constructLLVMLinkCommand(C, *this, JA, Inputs, LinkerInputs, Output,
Args);
}
@@ -163,7 +163,7 @@ void AMDGCN::Linker::constructLinkAndEmitSpirvCommand(
const char *LinkedBCFilePath = HIP::getTempFile(C, LinkedBCFilePrefix, "bc");
InputInfo LinkedBCFile(&JA, LinkedBCFilePath, Output.getBaseInput());
- constructLlvmLinkCommand(C, JA, Inputs, LinkedBCFile, Args);
+ constructLLVMLinkCommand(C, JA, Inputs, LinkedBCFile, Args);
// Emit SPIR-V binary.
llvm::opt::ArgStringList TrArgs{
@@ -195,7 +195,7 @@ void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args, *this);
if (JA.getType() == types::TY_LLVM_BC)
- return constructLlvmLinkCommand(C, JA, Inputs, Output, Args);
+ return constructLLVMLinkCommand(C, JA, Inputs, Output, Args);
if (getToolChain().getEffectiveTriple().isSPIRV())
return constructLinkAndEmitSpirvCommand(C, JA, Inputs, Output, Args);
diff --git a/clang/lib/Driver/ToolChains/HIPAMD.h b/clang/lib/Driver/ToolChains/HIPAMD.h
index 30fc01a2f8e40..7c6540fff235a 100644
--- a/clang/lib/Driver/ToolChains/HIPAMD.h
+++ b/clang/lib/Driver/ToolChains/HIPAMD.h
@@ -37,7 +37,7 @@ class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
void constructLldCommand(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs, const InputInfo &Output,
const llvm::opt::ArgList &Args) const;
- void constructLlvmLinkCommand(Compilation &C, const JobAction &JA,
+ void constructLLVMLinkCommand(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const InputInfo &Output,
const llvm::opt::ArgList &Args) const;
diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp
index 18d7636c37a6d..f797573a5725d 100644
--- a/clang/lib/Driver/ToolChains/HIPSPV.cpp
+++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp
@@ -69,7 +69,7 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand(
"generic"; // SPIR-V is generic, no specific target ID like -mcpu
tools::AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, LinkArgs, Arch,
Target, /*IsBitCodeSDL=*/true);
- tools::constructLlvmLinkCommand(C, *this, JA, Inputs, LinkArgs, Output, Args,
+ tools::constructLLVMLinkCommand(C, *this, JA, Inputs, LinkArgs, Output, Args,
TempFile);
// Post-link HIP lowering.
diff --git a/clang/lib/Driver/ToolChains/SPIRV.cpp b/clang/lib/Driver/ToolChains/SPIRV.cpp
index 44f7a917aa84a..2877aae3e6d78 100644
--- a/clang/lib/Driver/ToolChains/SPIRV.cpp
+++ b/clang/lib/Driver/ToolChains/SPIRV.cpp
@@ -81,7 +81,7 @@ void SPIRV::constructLLVMLinkCommand(Compilation &C, const Tool &T,
for (auto Input : Inputs)
LlvmLinkArgs.push_back(Input.getFilename());
- tools::constructLlvmLinkCommand(C, T, JA, Inputs, LlvmLinkArgs, Output, Args);
+ tools::constructLLVMLinkCommand(C, T, JA, Inputs, LlvmLinkArgs, Output, Args);
const char *LlvmLink =
C.getArgs().MakeArgString(T.getToolChain().GetProgramPath("llvm-link"));
More information about the cfe-commits
mailing list