[llvm] 9ba969c - [SPIR-V] Reject builtin calls if mangled argument types do not match the IR (#208152)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 29 00:47:42 PDT 2026
Author: Arseniy Obolenskiy
Date: 2026-07-29T09:47:36+02:00
New Revision: 9ba969c46204e4723cf4b5720a34fc537ce2d458
URL: https://github.com/llvm/llvm-project/commit/9ba969c46204e4723cf4b5720a34fc537ce2d458
DIFF: https://github.com/llvm/llvm-project/commit/9ba969c46204e4723cf4b5720a34fc537ce2d458.diff
LOG: [SPIR-V] Reject builtin calls if mangled argument types do not match the IR (#208152)
Added:
llvm/test/CodeGen/SPIRV/get-global-id-non-integer-dim.ll
Modified:
llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_tensor_float32_conversion/tf32-conv.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index 7167e3f69e0af..c482807c02ec6 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -3463,6 +3463,79 @@ mapBuiltinToOpcode(StringRef DemangledCall,
return std::make_tuple(-1, 0, 0);
}
+/// Checks that scalar/vector numeric arguments of \p Call match the types
+/// implied by their mangling in \p DemangledCall. Pointers and opaque
+/// builtin types (images, samplers, pipes, etc.) are not validated here, as
+/// mangling does not enforce their exact spelling.
+///
+/// \returns false if a numeric argument's SPIR-V type disagrees with the
+/// type implied by the mangled name, true otherwise.
+static bool demangledArgTypesMatchIR(const SPIRV::IncomingCall *Call,
+ StringRef DemangledCall,
+ SPIRVGlobalRegistry *GR, LLVMContext &Ctx,
+ const CallBase &CB) {
+ if (Call->isSpirvOp())
+ return true;
+
+ SmallVector<StringRef, 10> ArgTypeStrs;
+ if (!SPIRV::parseBuiltinTypeStr(ArgTypeStrs, DemangledCall, Ctx))
+ return true;
+
+ unsigned ArgBase = CB.hasStructRetAttr() ? 1 : 0;
+ if (Call->Arguments.size() < ArgBase)
+ return true;
+ unsigned NumMangledArgs = Call->Arguments.size() - ArgBase;
+ unsigned NumArgsToCheck =
+ std::min<unsigned>(NumMangledArgs, ArgTypeStrs.size());
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgsToCheck; ++ArgIdx) {
+ StringRef ArgTypeStr = ArgTypeStrs[ArgIdx].trim();
+ // Opaque/builtin OpenCL and SPIR-V types (images, samplers, pipes,
+ // reserve_id, etc.) are not validated here, as mangling does not enforce
+ // their exact spelling, and some builtin type names have no TableGen
+ // record and would otherwise abort compilation when parsed.
+ if (hasBuiltinTypePrefix(ArgTypeStr))
+ continue;
+
+ Type *ExpectedType = SPIRV::parseBuiltinCallArgumentType(ArgTypeStr, Ctx);
+ if (!ExpectedType || ExpectedType->isVoidTy() ||
+ ExpectedType->isPointerTy() || ExpectedType->isTargetExtTy())
+ continue;
+
+ SPIRVTypeInst ArgType =
+ GR->getSPIRVTypeForVReg(Call->Arguments[ArgIdx + ArgBase]);
+ if (!ArgType)
+ continue;
+ unsigned ArgTypeOpcode = ArgType->getOpcode();
+ if (ArgTypeOpcode != SPIRV::OpTypeInt &&
+ ArgTypeOpcode != SPIRV::OpTypeFloat &&
+ ArgTypeOpcode != SPIRV::OpTypeBool &&
+ ArgTypeOpcode != SPIRV::OpTypeVector)
+ continue;
+
+ auto *ExpectedVecType = dyn_cast<VectorType>(ExpectedType);
+ Type *ExpectedScalarType =
+ ExpectedVecType ? ExpectedVecType->getElementType() : ExpectedType;
+ SPIRVTypeInst ArgScalarType = GR->getScalarOrVectorComponentType(ArgType);
+ if (!ArgScalarType)
+ continue;
+
+ bool ExpectedIsInt = ExpectedScalarType->isIntegerTy();
+ unsigned ArgOpcode = ArgScalarType->getOpcode();
+ bool ArgIsInt =
+ ArgOpcode == SPIRV::OpTypeInt || ArgOpcode == SPIRV::OpTypeBool;
+
+ if (ExpectedIsInt != ArgIsInt)
+ return false;
+
+ unsigned ExpectedElts =
+ ExpectedVecType ? ExpectedVecType->getElementCount().getFixedValue()
+ : 1;
+ if (ExpectedElts != GR->getScalarOrVectorComponentCount(ArgType))
+ return false;
+ }
+ return true;
+}
+
std::optional<bool> lowerBuiltin(StringRef DemangledCall,
SPIRV::InstructionSet::InstructionSet Set,
MachineIRBuilder &MIRBuilder,
@@ -3499,6 +3572,17 @@ std::optional<bool> lowerBuiltin(StringRef DemangledCall,
return std::nullopt;
}
+ // Check that argument types match what the mangling implies. If not
+ // (e.g. broken mangling), treat the call as a regular function call
+ // rather than crashing.
+ if (!demangledArgTypesMatchIR(Call.get(), DemangledCall, GR,
+ MIRBuilder.getContext(), CB)) {
+ LLVM_DEBUG(dbgs() << "Argument types do not match mangled types for "
+ << "builtin " << DemangledCall
+ << "; treating as a normal function\n");
+ return std::nullopt;
+ }
+
// Match the builtin with implementation based on the grouping.
switch (Call->Builtin->Group) {
case SPIRV::Extended:
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_tensor_float32_conversion/tf32-conv.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_tensor_float32_conversion/tf32-conv.ll
index dcad78d17bff7..62481c1e876dd 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_tensor_float32_conversion/tf32-conv.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_tensor_float32_conversion/tf32-conv.ll
@@ -45,18 +45,18 @@ declare spir_func <8 x float> @_Z25__spirv_RoundFToTF32INTELDv8_f(<8 x float>)
define dso_local spir_kernel void @test_ocl(float %a) {
entry:
- %res4 = call spir_func float @_Z35intel_round_as_tensor_float32_floatt(float 0.000000e+00)
- %res5 = call spir_func <2 x float> @_Z37intel_round_as_tensor_float322_float2Dv2_t(<2 x float> zeroinitializer)
- %res6 = call spir_func <3 x float> @_Z37intel_round_as_tensor_float323_float3Dv3_t(<3 x float> zeroinitializer)
- %res7 = call spir_func <4 x float> @_Z37intel_round_as_tensor_float324_float4Dv4_t(<4 x float> zeroinitializer)
- %res8 = call spir_func <8 x float> @_Z37intel_round_as_tensor_float328_float8Dv8_t(<8 x float> zeroinitializer)
- %res9 = call spir_func <16 x float> @_Z39intel_round_as_tensor_float3216_float16Dv16_t(<16 x float> zeroinitializer)
+ %res4 = call spir_func float @_Z35intel_round_as_tensor_float32_floatf(float 0.000000e+00)
+ %res5 = call spir_func <2 x float> @_Z37intel_round_as_tensor_float322_float2Dv2_f(<2 x float> zeroinitializer)
+ %res6 = call spir_func <3 x float> @_Z37intel_round_as_tensor_float323_float3Dv3_f(<3 x float> zeroinitializer)
+ %res7 = call spir_func <4 x float> @_Z37intel_round_as_tensor_float324_float4Dv4_f(<4 x float> zeroinitializer)
+ %res8 = call spir_func <8 x float> @_Z37intel_round_as_tensor_float328_float8Dv8_f(<8 x float> zeroinitializer)
+ %res9 = call spir_func <16 x float> @_Z39intel_round_as_tensor_float3216_float16Dv16_f(<16 x float> zeroinitializer)
ret void
}
-declare spir_func float @_Z35intel_round_as_tensor_float32_floatt(float)
-declare spir_func <2 x float> @_Z37intel_round_as_tensor_float322_float2Dv2_t(<2 x float>)
-declare spir_func <3 x float> @_Z37intel_round_as_tensor_float323_float3Dv3_t(<3 x float>)
-declare spir_func <4 x float> @_Z37intel_round_as_tensor_float324_float4Dv4_t(<4 x float>)
-declare spir_func <8 x float> @_Z37intel_round_as_tensor_float328_float8Dv8_t(<8 x float>)
-declare spir_func <16 x float> @_Z39intel_round_as_tensor_float3216_float16Dv16_t(<16 x float>)
+declare spir_func float @_Z35intel_round_as_tensor_float32_floatf(float)
+declare spir_func <2 x float> @_Z37intel_round_as_tensor_float322_float2Dv2_f(<2 x float>)
+declare spir_func <3 x float> @_Z37intel_round_as_tensor_float323_float3Dv3_f(<3 x float>)
+declare spir_func <4 x float> @_Z37intel_round_as_tensor_float324_float4Dv4_f(<4 x float>)
+declare spir_func <8 x float> @_Z37intel_round_as_tensor_float328_float8Dv8_f(<8 x float>)
+declare spir_func <16 x float> @_Z39intel_round_as_tensor_float3216_float16Dv16_f(<16 x float>)
diff --git a/llvm/test/CodeGen/SPIRV/get-global-id-non-integer-dim.ll b/llvm/test/CodeGen/SPIRV/get-global-id-non-integer-dim.ll
new file mode 100644
index 0000000000000..a9c19df446eaa
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/get-global-id-non-integer-dim.ll
@@ -0,0 +1,18 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown -spirv-ext=+SPV_KHR_bfloat16 %s -o - | FileCheck %s
+; RUN: llc -O2 -mtriple=spirv64-unknown-unknown -spirv-ext=+SPV_KHR_bfloat16 %s -o - | FileCheck %s
+
+; get_global_id and its sibling workgroup-query builtins take an integer
+; dimension index.
+
+; CHECK: %[[#Func:]] = OpFunction %[[#]] None %[[#]]
+; CHECK: OpFunctionParameter
+; CHECK: OpFunctionEnd
+; CHECK: OpFunctionCall %[[#]] %[[#Func]]
+
+declare spir_func i64 @_Z13get_global_idj(bfloat)
+
+define spir_kernel void @fuzz_kernel(ptr addrspace(1) %out, bfloat %dim) {
+ %id = call spir_func i64 @_Z13get_global_idj(bfloat %dim)
+ store i64 %id, ptr addrspace(1) %out
+ ret void
+}
More information about the llvm-commits
mailing list