[llvm] [TableGen] Fix a couple of crashes related to sub-operand dags (PR #156179)

Sergei Barannikov via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 30 06:16:49 PDT 2025


https://github.com/s-barannikov created https://github.com/llvm/llvm-project/pull/156179

The added tests used to crash when attempting to dereference a nullptr MIOpInfo or call MIOpInfo->getArg(0) on an empty MIOpInfo dag.

>From 6e31a7c0b4b4af7144442105f8338fe5c0c1fda0 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sat, 30 Aug 2025 16:15:31 +0300
Subject: [PATCH] [TableGen] Fix a couple of crashes related to sub-operand
 dags

The added tests used to crash when attempting to dereference a nullptr
MIOpInfo or call MIOpInfo->getArg(0) on an empty MIOpInfo dag.
---
 .../sub-arg-dag-error-1.td                    | 28 +++++++++++++++++++
 .../sub-arg-dag-error-2.td                    | 27 ++++++++++++++++++
 .../TableGen/Common/CodeGenInstruction.cpp    | 14 ++++++++--
 3 files changed, 66 insertions(+), 3 deletions(-)
 create mode 100644 llvm/test/TableGen/FixedLenDecoderEmitter/sub-arg-dag-error-1.td
 create mode 100644 llvm/test/TableGen/FixedLenDecoderEmitter/sub-arg-dag-error-2.td

diff --git a/llvm/test/TableGen/FixedLenDecoderEmitter/sub-arg-dag-error-1.td b/llvm/test/TableGen/FixedLenDecoderEmitter/sub-arg-dag-error-1.td
new file mode 100644
index 0000000000000..7090eaf20a9ad
--- /dev/null
+++ b/llvm/test/TableGen/FixedLenDecoderEmitter/sub-arg-dag-error-1.td
@@ -0,0 +1,28 @@
+// RUN: not llvm-tblgen -gen-disassembler -I %p/../../../include %s 2>&1 \
+// RUN:   | FileCheck %s --implicit-check-not=error:
+
+include "llvm/Target/Target.td"
+
+def R0 : Register<"r0">;
+def RC : RegisterClass<"MyTarget", [i32], 32, (add R0)>;
+
+// Used to crash.
+// CHECK: error: In instruction 'I', operand #0 has 1 sub-arg names, but no sub-operands
+
+def I : Instruction {
+  let Size = 1;
+  bits<8> Inst;
+  bits<1> r;
+
+  let Inst{0} = 0;
+  let Inst{1} = r;
+
+  let OutOperandList = (outs);
+  let InOperandList = (ins (RC $r):$op);
+}
+
+def II : InstrInfo;
+
+def MyTarget : Target {
+  let InstructionSet = II;
+}
diff --git a/llvm/test/TableGen/FixedLenDecoderEmitter/sub-arg-dag-error-2.td b/llvm/test/TableGen/FixedLenDecoderEmitter/sub-arg-dag-error-2.td
new file mode 100644
index 0000000000000..65cc0e20350c0
--- /dev/null
+++ b/llvm/test/TableGen/FixedLenDecoderEmitter/sub-arg-dag-error-2.td
@@ -0,0 +1,27 @@
+// RUN: not llvm-tblgen -gen-disassembler -I %p/../../../include %s 2>&1 \
+// RUN:   | FileCheck %s --implicit-check-not=error:
+
+include "llvm/Target/Target.td"
+
+def CustomOp : Operand<i32>;
+
+// Used to crash.
+// CHECK: error: In instruction 'I', operand #0 has 1 sub-arg names, expected 0
+
+def I : Instruction {
+  let Size = 1;
+  bits<8> Inst;
+  bits<1> i;
+
+  let Inst{0} = 0;
+  let Inst{1} = i;
+
+  let OutOperandList = (outs);
+  let InOperandList = (ins (CustomOp $i):$op);
+}
+
+def II : InstrInfo;
+
+def MyTarget : Target {
+  let InstructionSet = II;
+}
diff --git a/llvm/utils/TableGen/Common/CodeGenInstruction.cpp b/llvm/utils/TableGen/Common/CodeGenInstruction.cpp
index da343e5e23177..ff70d50971b89 100644
--- a/llvm/utils/TableGen/Common/CodeGenInstruction.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenInstruction.cpp
@@ -143,12 +143,20 @@ CGIOperandList::CGIOperandList(const Record *R) : TheDef(R) {
         MIOperandNo, NumOps, MIOpInfo);
 
     if (SubArgDag) {
-      if (SubArgDag->getNumArgs() != NumOps) {
+      if (!MIOpInfo) {
         PrintFatalError(R->getLoc(), "In instruction '" + R->getName() +
                                          "', operand #" + Twine(i) + " has " +
                                          Twine(SubArgDag->getNumArgs()) +
-                                         " sub-arg names, expected " +
-                                         Twine(NumOps) + ".");
+                                         " sub-arg names, but no sub-operands");
+      }
+
+      unsigned NumSubArgs = SubArgDag->getNumArgs();
+      unsigned NumSubOps = MIOpInfo->getNumArgs();
+      if (NumSubArgs != NumSubOps) {
+        PrintFatalError(R->getLoc(),
+                        "In instruction '" + R->getName() + "', operand #" +
+                            Twine(i) + " has " + Twine(NumSubArgs) +
+                            " sub-arg names, expected " + Twine(NumSubOps));
       }
 
       for (unsigned j = 0; j < NumOps; ++j) {



More information about the llvm-commits mailing list