diff --git a/llvm/test/TableGen/InsufficientPositionalOperands.td b/llvm/test/TableGen/InsufficientPositionalOperands.td new file mode 100644 --- /dev/null +++ b/llvm/test/TableGen/InsufficientPositionalOperands.td @@ -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); +} diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp --- a/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -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 @@ -118,16 +119,16 @@ (!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++;