[llvm] [SPIRV] Error in backend for vararg functions (PR #169111)
Nick Sarnie via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 21 14:24:52 PST 2025
https://github.com/sarnex created https://github.com/llvm/llvm-project/pull/169111
SPIR-V doesn't support variadic functions besides `printf`, and `printf` is already handled at this point.
If we don't do this, we generate invalid SPIR-V because the backend has no idea how to codegen vararg functions. We get asm like this:
```
%27 = OpFunction %6 None %7
%28 = OpFunctionParameter %4
; -- End function
```
The above is totally invalid and causes crashes in downstream tools like `spirv-as` and `spirv-link`.
We already have many `printf` tests locking down that this doesn't break `printf`.
Note the SPIR-V Translator does the same thing, see [here](https://github.com/KhronosGroup/SPIRV-LLVM-Translator/pull/2703).
>From fdd15b241bde3f4d0b742160330172cd1eefeae8 Mon Sep 17 00:00:00 2001
From: Nick Sarnie <nick.sarnie at intel.com>
Date: Fri, 21 Nov 2025 14:19:38 -0800
Subject: [PATCH] [SPIRV] Error in backend for vararg functions
Signed-off-by: Nick Sarnie <nick.sarnie at intel.com>
---
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 10 +++++++---
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h | 2 +-
llvm/test/CodeGen/SPIRV/function/vararg.ll | 17 +++++++++++++++++
3 files changed, 25 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/CodeGen/SPIRV/function/vararg.ll
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index 76fd834fd7219..b3f0478ecb8bf 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -970,8 +970,11 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeForwardPointer(
}
SPIRVType *SPIRVGlobalRegistry::getOpTypeFunction(
- SPIRVType *RetType, const SmallVectorImpl<SPIRVType *> &ArgTypes,
+ const FunctionType *Ty, SPIRVType *RetType,
+ const SmallVectorImpl<SPIRVType *> &ArgTypes,
MachineIRBuilder &MIRBuilder) {
+ if (Ty->isVarArg())
+ reportFatalUsageError("SPIR-V does not support variadic functions");
return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)
.addDef(createTypeVReg(MIRBuilder))
@@ -988,7 +991,8 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeFunctionWithArgs(
MachineIRBuilder &MIRBuilder) {
if (const MachineInstr *MI = findMI(Ty, false, &MIRBuilder.getMF()))
return MI;
- const MachineInstr *NewMI = getOpTypeFunction(RetType, ArgTypes, MIRBuilder);
+ const MachineInstr *NewMI =
+ getOpTypeFunction(cast<FunctionType>(Ty), RetType, ArgTypes, MIRBuilder);
add(Ty, false, NewMI);
return finishCreatingSPIRVType(Ty, NewMI);
}
@@ -1097,7 +1101,7 @@ SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
for (const auto &ParamTy : FType->params())
ParamTypes.push_back(findSPIRVType(ParamTy, MIRBuilder, AccQual,
ExplicitLayoutRequired, EmitIR));
- return getOpTypeFunction(RetTy, ParamTypes, MIRBuilder);
+ return getOpTypeFunction(FType, RetTy, ParamTypes, MIRBuilder);
}
unsigned AddrSpace = typeToAddressSpace(Ty);
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index c230e62e795e8..09c77f0cfd4f5 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -464,7 +464,7 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping {
SPIRVType *getOpTypeForwardPointer(SPIRV::StorageClass::StorageClass SC,
MachineIRBuilder &MIRBuilder);
- SPIRVType *getOpTypeFunction(SPIRVType *RetType,
+ SPIRVType *getOpTypeFunction(const FunctionType *Ty, SPIRVType *RetType,
const SmallVectorImpl<SPIRVType *> &ArgTypes,
MachineIRBuilder &MIRBuilder);
diff --git a/llvm/test/CodeGen/SPIRV/function/vararg.ll b/llvm/test/CodeGen/SPIRV/function/vararg.ll
new file mode 100644
index 0000000000000..a32b6fc541ad3
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/function/vararg.ll
@@ -0,0 +1,17 @@
+; RUN: not llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - 2>&1 | FileCheck %s
+
+ at glob = addrspace(1) global ptr null, align 8
+
+; Function Attrs: mustprogress noinline norecurse optnone
+define noundef i32 @main() #0 {
+entry:
+ %retval = alloca i32, align 4
+ %retval.ascast = addrspacecast ptr %retval to ptr addrspace(4)
+ store i32 0, ptr addrspace(4) %retval.ascast, align 4
+ store ptr @_Z3fooiz, ptr addrspace(4) addrspacecast (ptr addrspace(1) @glob to ptr addrspace(4)), align 8
+ call spir_func void (i32, ...) @_Z3fooiz(i32 noundef 5, i32 noundef 3)
+ ret i32 0
+}
+
+; CHECK: SPIR-V does not support variadic functions
+declare spir_func void @_Z3fooiz(i32 noundef, ...) #1
More information about the llvm-commits
mailing list