[llvm] [LLVM][Intrinsic] Move overload index validation to C++ (PR #195297)
Rahul Joshi via llvm-commits
llvm-commits at lists.llvm.org
Fri May 1 10:21:40 PDT 2026
https://github.com/jurahul updated https://github.com/llvm/llvm-project/pull/195297
>From 74756cc50b53aae37656a0e95581e2672e099474 Mon Sep 17 00:00:00 2001
From: Rahul Joshi <rjoshi at nvidia.com>
Date: Fri, 1 May 2026 06:46:06 -0700
Subject: [PATCH] [LLVM][Intrinsic] Move overload index validation to C++
---
llvm/include/llvm/IR/Intrinsics.td | 21 ---------
llvm/test/TableGen/intrinsic-arginfo-error.td | 9 ----
...nsic-overload-dependent-type-validation.td | 31 +++++++++----
.../TableGen/Basic/CodeGenIntrinsics.cpp | 43 ++++++++++++++++---
4 files changed, 59 insertions(+), 45 deletions(-)
delete mode 100644 llvm/test/TableGen/intrinsic-arginfo-error.td
diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index 2028d232084f9..d7c05641ff70c 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -705,27 +705,6 @@ class TypeInfoGen<list<LLVMType> RetTypes, list<LLVMType> ParamTypes> {
bit isOverloaded = !not(!empty(OverloadTypes));
- // Validate that the overload index referenced by dependent types always
- // references an LLVMAnyType type.
- list<int> InvalidOverload = !foreach(ty, AllTypes,
- // an entry in the list will be 1 if its a dependent type and it
- // references another overload type that is not `Any`.
- !and(
- !isa<LLVMDependentType>(ty),
- !if(!ge(!cast<LLVMDependentType>(ty).OverloadIndex, !size(OverloadTypes)),
- 1,
- !not(!isa<LLVMAnyType>(OverloadTypes[!cast<LLVMDependentType>(ty).OverloadIndex]))
- )
- )
- );
- assert !eq(!foldl(0, InvalidOverload, a, x, !add(a, x)), 0),
- "dependent types must reference an overload index of an \'llvm_any\' type";
-
- list<LLVMType> Types = !foreach(ty, AllTypes,
- !if(!isa<LLVMDependentType>(ty),
- OverloadTypes[!cast<LLVMDependentType>(ty).OverloadIndex],
- ty));
-
list<int> TypeSig = !listflatten(!listconcat(
[!cond(
!eq(!size(RetTypes), 0): [IIT_Done.Number],
diff --git a/llvm/test/TableGen/intrinsic-arginfo-error.td b/llvm/test/TableGen/intrinsic-arginfo-error.td
deleted file mode 100644
index 0a49e73bf5529..0000000000000
--- a/llvm/test/TableGen/intrinsic-arginfo-error.td
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: not llvm-tblgen -gen-intrinsic-enums -I %p/../../include %s 2>&1 | FileCheck %s
-
-include "llvm/IR/Intrinsics.td"
-
-// CHECK: error: assertion failed: dependent types must reference an overload index of an 'llvm_any' type
-def int_test : DefaultAttrsIntrinsic<
- [llvm_anyint_ty],
- [llvm_anyint_ty, LLVMMatchType<2>],
- [IntrNoMem]>;
diff --git a/llvm/test/TableGen/intrinsic-overload-dependent-type-validation.td b/llvm/test/TableGen/intrinsic-overload-dependent-type-validation.td
index b7da7f6c0bf87..274f31ddb9027 100644
--- a/llvm/test/TableGen/intrinsic-overload-dependent-type-validation.td
+++ b/llvm/test/TableGen/intrinsic-overload-dependent-type-validation.td
@@ -1,7 +1,8 @@
-// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST0 2>&1 | FileCheck %s --check-prefix=CHECK-TEST0
-// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST1 2>&1 | FileCheck %s --check-prefix=CHECK-TEST1
-// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST2 2>&1 | FileCheck %s --check-prefix=CHECK-TEST2
-// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST3 2>&1 | FileCheck %s --check-prefix=CHECK-TEST3
+// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST0 2>&1 | FileCheck %s -DFILE=%s --check-prefix=CHECK-TEST0
+// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST1 2>&1 | FileCheck %s -DFILE=%s --check-prefix=CHECK-TEST1
+// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST2 2>&1 | FileCheck %s -DFILE=%s --check-prefix=CHECK-TEST2
+// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST3 2>&1 | FileCheck %s -DFILE=%s --check-prefix=CHECK-TEST3
+// RUN: not llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s -DTEST4 2>&1 | FileCheck %s -DFILE=%s --check-prefix=CHECK-TEST4
// This unit test tests various overloaded intrinsics that use dependent
// types to validate that if they reference an overload type is not one of the
@@ -12,12 +13,12 @@ include "llvm/IR/Intrinsics.td"
#ifdef TEST0
-// CHECK-TEST0: error: assertion failed: dependent types must reference an overload index of an 'llvm_any' type
def int_test: DefaultAttrsIntrinsic<
[ llvm_anyvector_ty], // overload index 0.
[ LLVMVectorOfAnyPointersToElt<0>, // overload index 1.
llvm_anyvector_ty, // overload index 2.
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>,
+// CHECK-TEST0: [[FILE]]:[[@LINE+3]]:7: error: for intrinsic int_test overload index 1 is invalid, dependent types must reference an overload index of an 'llvm_any' type
// Error: Fully dependent type references overload index 1,
// which is not one of the llvm_any-types.
LLVMMatchType<1>,
@@ -28,13 +29,13 @@ def int_test: DefaultAttrsIntrinsic<
#ifdef TEST1
-// CHECK-TEST1: error: assertion failed: dependent types must reference an overload index of an 'llvm_any' type
def int_test: DefaultAttrsIntrinsic<
[ llvm_anyvector_ty], // overload index 0.
[ LLVMVectorOfAnyPointersToElt<0>, // overload index 1.
llvm_anyvector_ty, // overload index 2.
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>,
LLVMMatchType<0>,
+// CHECK-TEST1: [[FILE]]:[[@LINE+3]]:7: error: for intrinsic int_test overload index 1 is invalid, dependent types must reference an overload index of an 'llvm_any' type
// Error: Fully dependent type references overload index 1,
// which is not one of the llvm_any-types.
LLVMScalarOrSameVectorWidth<1, llvm_i1_ty>,
@@ -44,7 +45,6 @@ def int_test: DefaultAttrsIntrinsic<
#ifdef TEST2
-// CHECK-TEST2: error: assertion failed: dependent types must reference an overload index of an 'llvm_any' type
def int_test: DefaultAttrsIntrinsic<
[ llvm_anyvector_ty], // overload index 0.
[ LLVMVectorOfAnyPointersToElt<0>, // overload index 1.
@@ -52,6 +52,7 @@ def int_test: DefaultAttrsIntrinsic<
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>,
LLVMMatchType<0>,
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>,
+// CHECK-TEST2: [[FILE]]:[[@LINE+3]]:7: error: for intrinsic int_test overload index 1 is invalid, dependent types must reference an overload index of an 'llvm_any' type
// Error: Partially dependent type references overload index 1,
// which is not one of the llvm_any-types.
LLVMVectorOfAnyPointersToElt<1>, // overload index 3.
@@ -60,7 +61,6 @@ def int_test: DefaultAttrsIntrinsic<
#ifdef TEST3
-// CHECK-TEST3: error: assertion failed: dependent types must reference an overload index of an 'llvm_any' type
def int_test: DefaultAttrsIntrinsic<
[ llvm_anyvector_ty], // overload index 0.
[ LLVMVectorOfAnyPointersToElt<0>, // overload index 1.
@@ -68,7 +68,22 @@ def int_test: DefaultAttrsIntrinsic<
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>,
LLVMMatchType<0>,
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>,
+// CHECK-TEST3: [[FILE]]:[[@LINE+2]]:7: error: for intrinsic int_test overload index 3 is invalid, dependent types must reference an overload index of an 'llvm_any' type
// Error: Partially dependent type references overload index 3 (itself).
LLVMVectorOfAnyPointersToElt<3>, // overload index 3.
llvm_i32_ty]>;
#endif // TEST3
+
+#ifdef TEST4
+
+def int_test: DefaultAttrsIntrinsic<
+ [ llvm_anyvector_ty], // overload index 0.
+ [ LLVMVectorOfAnyPointersToElt<0>, // overload index 1.
+ llvm_anyvector_ty, // overload index 2.
+// CHECK-TEST4: [[FILE]]:[[@LINE+2]]:7: error: for intrinsic int_test overload index 10 is invalid, intrinsic only has 3 overloaded types
+ // Error: Overload index out of bounds.
+ LLVMScalarOrSameVectorWidth<10, llvm_i1_ty>,
+ LLVMMatchType<0>,
+ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>,
+ llvm_i32_ty]>;
+#endif // TEST4
diff --git a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
index af70f216d538a..05ce7f22468c3 100644
--- a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
+++ b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
@@ -16,6 +16,7 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include <algorithm>
@@ -307,6 +308,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(const Record *R,
}
unsigned NumRet = R->getValueAsListInit("RetTypes")->size();
+ unsigned NumParam = R->getValueAsListInit("ParamTypes")->size();
+
if (NumRet > MaxNumReturn)
PrintFatalError(DefLoc, "intrinsics can only return upto " +
Twine(MaxNumReturn) + " values, '" + DefName +
@@ -318,20 +321,46 @@ CodeGenIntrinsic::CodeGenIntrinsic(const Record *R,
" should be of subclass of TypeInfoGen!");
isOverloaded = TypeInfo->getValueAsBit("isOverloaded");
- const ListInit *TypeList = TypeInfo->getValueAsListInit("Types");
+ std::vector<const Record *> AllTypes =
+ TypeInfo->getValueAsListOfDefs("AllTypes");
+
+ // Validate overload index values in dependent types.
+ if (isOverloaded) {
+ const ListInit *OverloadedTypes =
+ TypeInfo->getValueAsListInit("OverloadTypes");
+ unsigned NumOverloadedTypes = OverloadedTypes->size();
+ for (const auto &[Idx, Ty] : enumerate(AllTypes)) {
+ if (!Ty->isSubClassOf("LLVMDependentType"))
+ continue;
+ unsigned OverloadIndex = Ty->getValueAsInt("OverloadIndex");
+ if (OverloadIndex >= NumOverloadedTypes)
+ PrintFatalError(
+ Ty, formatv("for intrinsic {} overload index {} is invalid, "
+ "intrinsic only has {} overloaded types",
+ DefName, OverloadIndex, NumOverloadedTypes));
+ const Record *OTy = OverloadedTypes->getElementAsRecord(OverloadIndex);
+ if (!OTy->isSubClassOf("LLVMAnyType"))
+ PrintFatalError(Ty, formatv("for intrinsic {} overload index {} is "
+ "invalid, dependent types must reference "
+ "an overload index of an \'llvm_any\' type",
+ DefName, OverloadIndex));
+
+ // Replace the dependent type with the overloaded type it references.
+ AllTypes[Idx] = OTy;
+ }
+ }
+
+ ArrayRef<const Record *> AllTypesRef = AllTypes;
// Types field is a concatenation of Return types followed by Param types.
- unsigned Idx = 0;
- for (; Idx < NumRet; ++Idx) {
- const Record *RetTy = TypeList->getElementAsRecord(Idx);
+ for (const Record *RetTy : AllTypesRef.take_front(NumRet)) {
if (RetTy->getName() == "llvm_vararg_ty")
PrintFatalError(DefLoc, "cannot use llvm_vararg_ty as a return type");
IS.RetTys.push_back(RetTy);
}
- for (unsigned E = TypeList->size(); Idx < E; ++Idx) {
- const Record *ParamTy = TypeList->getElementAsRecord(Idx);
- if (Idx != E - 1 && ParamTy->getName() == "llvm_vararg_ty")
+ for (const auto &[Idx, ParamTy] : enumerate(AllTypesRef.drop_front(NumRet))) {
+ if (Idx != NumParam - 1 && ParamTy->getName() == "llvm_vararg_ty")
PrintFatalError(DefLoc,
"llvm_vararg_ty can only be the last parameter type");
IS.ParamTys.push_back(ParamTy);
More information about the llvm-commits
mailing list