[llvm] [TableGen] Gracefully error out in ParseTreePattern when DAG has zero operands so that llvm-tblgen doesn't crash (PR #161417)

Prerona Chaudhuri via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 7 08:46:21 PST 2025


https://github.com/pchaudhuri-nv updated https://github.com/llvm/llvm-project/pull/161417

>From b0d675206dc96b55166388f3e6b1cc638db73a73 Mon Sep 17 00:00:00 2001
From: pchaudhuri-nv <prerona.chaudhuri16 at vit.edu>
Date: Tue, 30 Sep 2025 18:30:56 +0000
Subject: [PATCH] fic

---
 llvm/test/TableGen/invalid_typecast_assert.td | 50 +++++++++++++++++++
 .../TableGen/Common/CodeGenDAGPatterns.cpp    | 30 ++++++++---
 2 files changed, 73 insertions(+), 7 deletions(-)
 create mode 100644 llvm/test/TableGen/invalid_typecast_assert.td

diff --git a/llvm/test/TableGen/invalid_typecast_assert.td b/llvm/test/TableGen/invalid_typecast_assert.td
new file mode 100644
index 0000000000000..67019f6abb677
--- /dev/null
+++ b/llvm/test/TableGen/invalid_typecast_assert.td
@@ -0,0 +1,50 @@
+// The test incorrect classifies the pattern as a typecast and it ends up with
+// typecast DAG with zero arguements, leading to llvm-tblgen crash.
+// This test will check if the error is gracefully handled without any crash.
+ 
+// RUN: not llvm-tblgen -gen-dag-isel -I %p/../../include %s 2>&1 | FileCheck %s
+
+include "llvm/Target/Target.td"
+
+class MyReg<string n>
+  : Register<n> {
+  let Namespace = "MyTarget";
+}
+
+def X0 : MyReg<"x0">;
+def X1 : MyReg<"x1">;
+
+def XRegs : RegisterClass<"MyTarget", [i64], 64, (add X0, X1)>;
+
+class TestInstruction : Instruction {
+  let Size = 2;
+  let Namespace = "MyTarget";
+  let hasSideEffects = false;
+  let hasExtraSrcRegAllocReq = false;
+  let hasExtraDefRegAllocReq = false;
+
+  field bits<16> Inst;
+  bits<3> dst;
+  bits<3> src;
+  bits<3> opcode;
+
+  let Inst{2-0} = dst;
+  let Inst{5-3} = src;
+  let Inst{7-5} = opcode;
+}
+
+def MY_LOAD : TestInstruction {
+  let OutOperandList = (outs XRegs:$dst);
+  let InOperandList = (ins ptr_rc:$ptr);
+  let AsmString = "my_load $dst, $ptr";
+  let opcode = 0;
+}
+
+// CHECK: [[@LINE+1]]:1: error: {{.*}} Type cast only takes one operand!
+def : Pat<
+  (i64 (load (iPTR:$src))),
+  (MY_LOAD $val, $src)
+>;
+
+def MyTargetISA : InstrInfo;
+def MyTarget : Target { let InstructionSet = MyTargetISA; }
diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
index 364817fa6d030..fbedca39ad36a 100644
--- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
@@ -1820,7 +1820,8 @@ bool TreePatternNode::UpdateNodeTypeFromInst(unsigned ResNo,
                                              TreePattern &TP) {
   // The 'unknown' operand indicates that types should be inferred from the
   // context.
-  if (Operand->isSubClassOf("unknown_class"))
+  if (Operand->isSubClassOf("unknown_class") ||
+      Operand->isSubClassOf("PointerLikeRegClass"))
     return false;
 
   // The Operand class specifies a type directly.
@@ -3020,12 +3021,18 @@ TreePatternNodePtr TreePattern::ParseTreePattern(const Init *TheInit,
     return nullptr;
   }
 
-  auto ParseCastOperand = [this](const DagInit *Dag, StringRef OpName) {
-    if (Dag->getNumArgs() != 1)
+  auto ParseCastOperand = [this](const DagInit *Dag,
+                                 StringRef OpName) -> TreePatternNodePtr {
+
+    if (Dag->getNumArgs() != 1) {
       error("Type cast only takes one operand!");
+      return nullptr;
+    }
 
-    if (!OpName.empty())
+    if (!OpName.empty()) {
       error("Type cast should not have a name!");
+      return nullptr;
+    }
 
     return ParseTreePattern(Dag->getArg(0), Dag->getArgNameStr(0));
   };
@@ -3034,6 +3041,8 @@ TreePatternNodePtr TreePattern::ParseTreePattern(const Init *TheInit,
     // If the operator is a list (of value types), then this must be "type cast"
     // of a leaf node with multiple results.
     TreePatternNodePtr New = ParseCastOperand(Dag, OpName);
+    if (!New)
+      return nullptr;
 
     size_t NumTypes = New->getNumTypes();
     if (LI->empty() || LI->size() != NumTypes)
@@ -3059,6 +3068,8 @@ TreePatternNodePtr TreePattern::ParseTreePattern(const Init *TheInit,
     // If the operator is a ValueType, then this must be "type cast" of a leaf
     // node.
     TreePatternNodePtr New = ParseCastOperand(Dag, OpName);
+    if (!New)
+      return nullptr;
 
     if (New->getNumTypes() != 1)
       error("ValueType cast can only have one type!");
@@ -3608,10 +3619,15 @@ void CodeGenDAGPatterns::FindPatternInputsAndOutputs(
     // If this is not a set, verify that the children nodes are not void typed,
     // and recurse.
     for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {
-      if (Pat->getChild(i).getNumTypes() == 0)
+      TreePatternNodePtr Child = Pat->getChildShared(i);
+      if (!Child) {
+        I.error("child node at index " + Twine(i) + " is null!");
+        continue;
+      }
+      if (Child->getNumTypes() == 0)
         I.error("Cannot have void nodes inside of patterns!");
-      FindPatternInputsAndOutputs(I, Pat->getChildShared(i), InstInputs,
-                                  InstResults, InstImpResults);
+      FindPatternInputsAndOutputs(I, Child, InstInputs, InstResults,
+                                  InstImpResults);
     }
 
     // If this is a non-leaf node with no children, treat it basically as if



More information about the llvm-commits mailing list