[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