[llvm] 8f1427d - [TableGen] Gracefully error out in ParseTreePattern when DAG has zero operands so that llvm-tblgen doesn't crash (#161417)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 21 09:32:03 PST 2026
Author: Prerona Chaudhuri
Date: 2026-01-21T17:31:59Z
New Revision: 8f1427d26929bdec364f46a9043303e6b1ed4200
URL: https://github.com/llvm/llvm-project/commit/8f1427d26929bdec364f46a9043303e6b1ed4200
DIFF: https://github.com/llvm/llvm-project/commit/8f1427d26929bdec364f46a9043303e6b1ed4200.diff
LOG: [TableGen] Gracefully error out in ParseTreePattern when DAG has zero operands so that llvm-tblgen doesn't crash (#161417)
Also handle the case when Pat->Child(i) is null in
CodeGenDAGPatterns::FindPatternInputsAndOutputs().
Fixes issue #157619 : TableGen asserts on invalid cast
Added:
llvm/test/TableGen/invalid_typecast_assert.td
Modified:
llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
Removed:
################################################################################
diff --git a/llvm/test/TableGen/invalid_typecast_assert.td b/llvm/test/TableGen/invalid_typecast_assert.td
new file mode 100644
index 0000000000000..d0e8706ebfe5a
--- /dev/null
+++ b/llvm/test/TableGen/invalid_typecast_assert.td
@@ -0,0 +1,51 @@
+// The test incorrectly classifies the pattern as a typecast and it ends up with a
+// 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+2]]:1: error: {{.*}} Type cast only takes one operand!
+// CHECK: [[@LINE+1]]:1: error: {{.*}} cannot update node type from unknown 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 6ff726dfc7e2a..5827497488943 100644
--- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
@@ -1851,7 +1851,11 @@ bool TreePatternNode::UpdateNodeTypeFromInst(unsigned ResNo,
else if (Operand->isSubClassOf("RegisterOperand"))
RC = Operand->getValueAsDef("RegClass");
- assert(RC && "Unknown operand type");
+ if (!RC) {
+ TP.error("cannot update node type from unknown operand!");
+ return false;
+ }
+
CodeGenTarget &Tgt = TP.getDAGPatterns().getTargetInfo();
if (RC->isSubClassOf("RegClassByHwMode"))
return UpdateNodeType(
@@ -2918,15 +2922,22 @@ TreePattern::TreePattern(const Record *TheRec, const ListInit *RawPat,
bool isInput, CodeGenDAGPatterns &cdp)
: TheRecord(TheRec), CDP(cdp), isInputPattern(isInput), HasError(false),
Infer(*this) {
- for (const Init *I : RawPat->getElements())
- Trees.push_back(ParseTreePattern(I, ""));
+ for (const Init *I : RawPat->getElements()) {
+ TreePatternNodePtr Node = ParseTreePattern(I, "");
+ if (!Node)
+ return;
+ Trees.push_back(Node);
+ }
}
TreePattern::TreePattern(const Record *TheRec, const DagInit *Pat, bool isInput,
CodeGenDAGPatterns &cdp)
: TheRecord(TheRec), CDP(cdp), isInputPattern(isInput), HasError(false),
Infer(*this) {
- Trees.push_back(ParseTreePattern(Pat, ""));
+ TreePatternNodePtr Node = ParseTreePattern(Pat, "");
+ if (!Node)
+ return;
+ Trees.push_back(Node);
}
TreePattern::TreePattern(const Record *TheRec, ArrayRef<const Init *> Args,
@@ -3037,12 +3048,17 @@ 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));
};
@@ -3051,6 +3067,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)
@@ -3076,6 +3094,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!");
@@ -3121,8 +3141,13 @@ TreePatternNodePtr TreePattern::ParseTreePattern(const Init *TheInit,
std::vector<TreePatternNodePtr> Children;
// Parse all the operands.
- for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i)
- Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgNameStr(i)));
+ for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
+ TreePatternNodePtr Child =
+ ParseTreePattern(Dag->getArg(i), Dag->getArgNameStr(i));
+ if (!Child)
+ return nullptr;
+ Children.push_back(Child);
+ }
// Get the actual number of results before Operator is converted to an
// intrinsic node (which is hard-coded to have either zero or one result).
More information about the llvm-commits
mailing list