[llvm] 031d998 - [SPIRV] Error in backend for vararg functions (#169111)

via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 25 07:17:08 PST 2025


Author: Nick Sarnie
Date: 2025-11-25T15:17:04Z
New Revision: 031d99836de51f2d6dfeb4f539e2d1af85f4f263

URL: https://github.com/llvm/llvm-project/commit/031d99836de51f2d6dfeb4f539e2d1af85f4f263
DIFF: https://github.com/llvm/llvm-project/commit/031d99836de51f2d6dfeb4f539e2d1af85f4f263.diff

LOG: [SPIRV] Error in backend for vararg functions (#169111)

SPIR-V doesn't support variadic functions, though we make an exception
for `printf`.

If we don't error, we generate invalid SPIR-V because the backend has no
idea how to codegen vararg functions as it is not described in the spec.
We get asm like this:

```
%27 = OpFunction %6 None %7
%28 = OpFunctionParameter %4
                                        ; -- End function
```

The above asm is totally invalid, there's no `OpFunctionEnd` and it
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`, it was already handled elsewhere at the time the error check
runs.

Note the SPIR-V Translator does the same thing, see
[here](https://github.com/KhronosGroup/SPIRV-LLVM-Translator/pull/2703).

---------

Signed-off-by: Nick Sarnie <nick.sarnie at intel.com>

Added: 
    llvm/test/CodeGen/SPIRV/function/vararg.ll

Modified: 
    llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
    llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index 76fd834fd7219..bd0c7d15afd12 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -21,6 +21,7 @@
 #include "SPIRVUtils.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/IntrinsicsSPIRV.h"
@@ -970,8 +971,15 @@ 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()) {
+    Function &Fn = MIRBuilder.getMF().getFunction();
+    Ty->getContext().diagnose(DiagnosticInfoUnsupported(
+        Fn, "SPIR-V does not support variadic functions",
+        MIRBuilder.getDebugLoc()));
+  }
   return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
     auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)
                    .addDef(createTypeVReg(MIRBuilder))
@@ -988,7 +996,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 +1106,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..7f734834ccf51
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/function/vararg.ll
@@ -0,0 +1,10 @@
+; RUN: not llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers < %s 2>&1 | FileCheck %s
+
+define void @bar() {
+entry:
+  call spir_func void (i32, ...) @_Z3fooiz(i32 5, i32 3)
+  ret void
+}
+
+; CHECK:error: {{.*}} in function bar void (): SPIR-V does not support variadic functions
+declare spir_func void @_Z3fooiz(i32, ...)


        


More information about the llvm-commits mailing list