Skip to content

Commit fef2fc3

Browse files
authored
[TableGen] Support non-def operators in !getdagop (#77531)
`!getdagop` expects the dag operator to be a def, and errors out if it's not. While that's true in most cases, when multiclasses are involved, the late resolution of the dag operator can result in it not being a def yet, but still have a proper type, wich is required to check against the optional parameter Ty in `!getdagop<Ty>`. e.g, in the following dag: ``` (!cast<TestInstruction>(TestInstructionAndPattern::NAME) foo) ``` the operator is a UnOpInit, but all we need here is to check its type. This fixes a bug where !getdagop is used to query the dag operator that is dependent on the multiclass, which is not yet resolved to a def. Once the folding is performed, the field becomes a record that can be queried.
1 parent 45be680 commit fef2fc3

File tree

2 files changed

+38
-7
lines changed

2 files changed

+38
-7
lines changed

llvm/lib/TableGen/Record.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -923,15 +923,16 @@ Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const {
923923

924924
case GETDAGOP:
925925
if (DagInit *Dag = dyn_cast<DagInit>(LHS)) {
926-
DefInit *DI = DefInit::get(Dag->getOperatorAsDef({}));
927-
if (!DI->getType()->typeIsA(getType())) {
926+
// TI is not necessarily a def due to the late resolution in multiclasses,
927+
// but has to be a TypedInit.
928+
auto *TI = cast<TypedInit>(Dag->getOperator());
929+
if (!TI->getType()->typeIsA(getType())) {
928930
PrintFatalError(CurRec->getLoc(),
929-
Twine("Expected type '") +
930-
getType()->getAsString() + "', got '" +
931-
DI->getType()->getAsString() + "' in: " +
932-
getAsString() + "\n");
931+
Twine("Expected type '") + getType()->getAsString() +
932+
"', got '" + TI->getType()->getAsString() +
933+
"' in: " + getAsString() + "\n");
933934
} else {
934-
return DI;
935+
return Dag->getOperator();
935936
}
936937
}
937938
break;

llvm/test/TableGen/getsetop.td

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// RUN: not llvm-tblgen -DERROR7 %s 2>&1 | FileCheck --check-prefix=ERROR7 %s
99
// RUN: not llvm-tblgen -DERROR8 %s 2>&1 | FileCheck --check-prefix=ERROR8 %s
1010
// RUN: not llvm-tblgen -DERROR9 %s 2>&1 | FileCheck --check-prefix=ERROR9 %s
11+
// RUN: not llvm-tblgen -DERROR10 %s 2>&1 | FileCheck --check-prefix=ERROR10 %s
1112

1213
// !setop and !getop are deprecated in favor of !setdagop and !getdagop.
1314
// Two tests retain the old names just to be sure they are still supported.
@@ -148,3 +149,32 @@ def test {
148149
dag orig_out_of_range = !setdagarg(orig, foo, (foo qux:$a));
149150
#endif
150151
}
152+
153+
// Copy a list (Predicates) that is a field in a dag operator
154+
// (TestInstruction), which is defined in the same multiclass
155+
// (TestInstructionAndPattern) as the destination of the copy
156+
// (TestPattern::Predicates).
157+
class TestInstruction<list<int> _Predicates> {
158+
list<int> Predicates = _Predicates;
159+
}
160+
#ifdef ERROR10
161+
class OtherTestInstruction<list<int> _Predicates> {
162+
list<int> Predicates = _Predicates;
163+
}
164+
// ERROR10: error: Expected type 'OtherTestInstruction', got 'TestInstruction'
165+
class TestPattern<dag D> {
166+
list<int> Predicates = !getdagop<OtherTestInstruction>(D).Predicates;
167+
}
168+
#else
169+
class TestPattern<dag D> {
170+
list<int> Predicates = !getdagop<TestInstruction>(D).Predicates;
171+
}
172+
#endif
173+
174+
multiclass TestInstructionAndPattern<list<int> Predicates> {
175+
def NAME : TestInstruction<Predicates>;
176+
def : TestPattern<(!cast<TestInstruction>(NAME) foo)>;
177+
}
178+
// CHECK: def testInst0 { // TestInstruction
179+
// CHECK-NEXT: list<int> Predicates = [7];
180+
defm testInst0 : TestInstructionAndPattern<[7]>;

0 commit comments

Comments
 (0)