[TableGen][CodeEmitterGen] Do not crash on insufficient positional instruction operands.
authorIvan Kosarev <ivan.kosarev@amd.com>
Fri, 10 Jun 2022 13:18:29 +0000 (14:18 +0100)
committerIvan Kosarev <ivan.kosarev@amd.com>
Fri, 10 Jun 2022 13:38:54 +0000 (14:38 +0100)
Reviewed By: foad

Differential Revision: https://reviews.llvm.org/D126288

llvm/test/TableGen/InsufficientPositionalOperands.td [new file with mode: 0644]
llvm/utils/TableGen/CodeEmitterGen.cpp

diff --git a/llvm/test/TableGen/InsufficientPositionalOperands.td b/llvm/test/TableGen/InsufficientPositionalOperands.td
new file mode 100644 (file)
index 0000000..5927bf9
--- /dev/null
@@ -0,0 +1,30 @@
+// RUN: not llvm-tblgen -gen-emitter -I %p/../../include %s 2>&1 | FileCheck %s
+
+// Check that TableGen doesn't crash on insufficient positional
+// instruction operands.
+
+include "llvm/Target/Target.td"
+
+def ArchInstrInfo : InstrInfo { }
+
+def Arch : Target {
+  let InstructionSet = ArchInstrInfo;
+}
+
+def Reg : Register<"reg">;
+
+def Regs : RegisterClass<"foo", [i32], 0, (add Reg)>;
+
+def foo : Instruction {
+  bits<3> rd;
+  bits<3> rs;
+
+  bits<8> Inst;
+  let Inst{1-0} = 0;
+  let Inst{4-2} = rd;
+  let Inst{7-5} = rs;
+
+// CHECK: Too few operands in record foo (no match for variable rs)
+  let OutOperandList = (outs Regs:$xd);
+  let InOperandList = (ins);
+}
index 8f96b7f..2b9931b 100644 (file)
@@ -22,6 +22,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Error.h"
 #include "llvm/TableGen/Record.h"
 #include "llvm/TableGen/TableGenBackend.h"
 #include <cassert>
@@ -118,16 +119,16 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
               (!NamedOpIndices.empty() && NamedOpIndices.count(
                 CGI.Operands.getSubOperandNumber(NumberedOp).first)))) {
       ++NumberedOp;
+    }
 
-      if (NumberedOp >= CGI.Operands.back().MIOperandNo +
-                        CGI.Operands.back().MINumOperands) {
-        errs() << "Too few operands in record " << R->getName() <<
-                  " (no match for variable " << VarName << "):\n";
-        errs() << *R;
-        errs() << '\n';
-
-        return;
-      }
+    if (NumberedOp >=
+        CGI.Operands.back().MIOperandNo + CGI.Operands.back().MINumOperands) {
+      std::string E;
+      raw_string_ostream S(E);
+      S << "Too few operands in record " << R->getName()
+        << " (no match for variable " << VarName << "):\n";
+      S << *R;
+      PrintFatalError(R, E);
     }
 
     OpIdx = NumberedOp++;