diff --git a/llvm/test/TableGen/invalid_typecast_assert.td b/llvm/test/TableGen/invalid_typecast_assert.td new file mode 100644 index 0000000000000..22591851f224e --- /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 -check-prefix=ERROR-CHK %s + +include "llvm/Target/Target.td" + +class MyReg + : Register { + 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; +} + +// ERROR-CHK: [[@LINE+1]]:1: error: {{.*}} This type cast has zero arguments. It takes only 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 75bea77faba42..e30e459ca919d 100644 --- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp @@ -3012,7 +3012,14 @@ TreePatternNodePtr TreePattern::ParseTreePattern(const Init *TheInit, return nullptr; } - auto ParseCastOperand = [this](const DagInit *Dag, StringRef OpName) { + auto ParseCastOperand = + [this](const DagInit *Dag, + StringRef OpName) -> std::optional { + if (Dag->getNumArgs() == 0) { + error("This type cast has zero arguments. It takes only one operand!"); + return std::nullopt; + } + if (Dag->getNumArgs() != 1) error("Type cast only takes one operand!"); @@ -3025,7 +3032,10 @@ TreePatternNodePtr TreePattern::ParseTreePattern(const Init *TheInit, if (const ListInit *LI = dyn_cast(Dag->getOperator())) { // 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); + auto MaybeNew = ParseCastOperand(Dag, OpName); + if (!MaybeNew) + return nullptr; + TreePatternNodePtr New = *MaybeNew; size_t NumTypes = New->getNumTypes(); if (LI->empty() || LI->size() != NumTypes) @@ -3050,7 +3060,10 @@ TreePatternNodePtr TreePattern::ParseTreePattern(const Init *TheInit, if (Operator->isSubClassOf("ValueType")) { // If the operator is a ValueType, then this must be "type cast" of a leaf // node. - TreePatternNodePtr New = ParseCastOperand(Dag, OpName); + auto MaybeNew = ParseCastOperand(Dag, OpName); + if (!MaybeNew) + return nullptr; + TreePatternNodePtr New = *MaybeNew; if (New->getNumTypes() != 1) error("ValueType cast can only have one type!"); @@ -3608,10 +3621,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