diff --git a/llvm/test/TableGen/invalid_typecast_assert.td b/llvm/test/TableGen/invalid_typecast_assert.td new file mode 100644 index 0000000000000..4bf23b2258b88 --- /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: {{.*}} type cast should not have zero arguments! +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 8076ce2486f56..68a2a17c4acbd 100644 --- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp @@ -3010,7 +3010,13 @@ TreePatternNodePtr TreePattern::ParseTreePattern(const Init *TheInit, return nullptr; } - auto ParseCastOperand = [this](const DagInit *Dag, StringRef OpName) { + auto ParseCastOperand = [this](const DagInit *Dag, + StringRef OpName) -> TreePatternNodePtr { + if (Dag->getNumArgs() == 0) { + error("type cast should not have zero arguments!"); + return nullptr; + } + if (Dag->getNumArgs() != 1) error("Type cast only takes one operand!"); @@ -3024,6 +3030,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) @@ -3049,6 +3057,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!"); @@ -3606,10 +3616,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