[llvm] [TableGen] Support non-def operators in !getdagop (PR #77531)
Visoiu Mistrih Francis via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 9 14:12:01 PST 2024
https://github.com/francisvm created https://github.com/llvm/llvm-project/pull/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.
>From e87a0a45cebbbe508e76ba3f35d90394125269cc Mon Sep 17 00:00:00 2001
From: Francis Visoiu Mistrih <francisvm at apple.com>
Date: Tue, 9 Jan 2024 13:31:29 -0800
Subject: [PATCH] [TableGen] Support non-def operators in !getdagop
`!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.
---
llvm/lib/TableGen/Record.cpp | 15 ++++++++-------
llvm/test/TableGen/getsetop.td | 30 ++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index aa981fdab4b3e6..2b3e8a0c7f848a 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -923,15 +923,16 @@ Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const {
case GETDAGOP:
if (DagInit *Dag = dyn_cast<DagInit>(LHS)) {
- DefInit *DI = DefInit::get(Dag->getOperatorAsDef({}));
- if (!DI->getType()->typeIsA(getType())) {
+ // TI is not necessarily a def due to the late resolution in multiclasses,
+ // but has to be a TypedInit.
+ auto *TI = cast<TypedInit>(Dag->getOperator());
+ if (!TI->getType()->typeIsA(getType())) {
PrintFatalError(CurRec->getLoc(),
- Twine("Expected type '") +
- getType()->getAsString() + "', got '" +
- DI->getType()->getAsString() + "' in: " +
- getAsString() + "\n");
+ Twine("Expected type '") + getType()->getAsString() +
+ "', got '" + TI->getType()->getAsString() +
+ "' in: " + getAsString() + "\n");
} else {
- return DI;
+ return Dag->getOperator();
}
}
break;
diff --git a/llvm/test/TableGen/getsetop.td b/llvm/test/TableGen/getsetop.td
index 0a91e1b2a583f3..aac644fe34cb28 100644
--- a/llvm/test/TableGen/getsetop.td
+++ b/llvm/test/TableGen/getsetop.td
@@ -8,6 +8,7 @@
// RUN: not llvm-tblgen -DERROR7 %s 2>&1 | FileCheck --check-prefix=ERROR7 %s
// RUN: not llvm-tblgen -DERROR8 %s 2>&1 | FileCheck --check-prefix=ERROR8 %s
// RUN: not llvm-tblgen -DERROR9 %s 2>&1 | FileCheck --check-prefix=ERROR9 %s
+// RUN: not llvm-tblgen -DERROR10 %s 2>&1 | FileCheck --check-prefix=ERROR10 %s
// !setop and !getop are deprecated in favor of !setdagop and !getdagop.
// Two tests retain the old names just to be sure they are still supported.
@@ -148,3 +149,32 @@ def test {
dag orig_out_of_range = !setdagarg(orig, foo, (foo qux:$a));
#endif
}
+
+// Copy a list (Predicates) that is a field in a dag operator
+// (TestInstruction), which is defined in the same multiclass
+// (TestInstructionAndPattern) as the destination of the copy
+// (TestPattern::Predicates).
+class TestInstruction<list<int> _Predicates> {
+ list<int> Predicates = _Predicates;
+}
+#ifdef ERROR10
+class OtherTestInstruction<list<int> _Predicates> {
+ list<int> Predicates = _Predicates;
+}
+// ERROR10: error: Expected type 'OtherTestInstruction', got 'TestInstruction'
+class TestPattern<dag D> {
+ list<int> Predicates = !getdagop<OtherTestInstruction>(D).Predicates;
+}
+#else
+class TestPattern<dag D> {
+ list<int> Predicates = !getdagop<TestInstruction>(D).Predicates;
+}
+#endif
+
+multiclass TestInstructionAndPattern<list<int> Predicates> {
+ def NAME : TestInstruction<Predicates>;
+ def : TestPattern<(!cast<TestInstruction>(NAME) foo)>;
+}
+// CHECK: def testInst0 { // TestInstruction
+// CHECK-NEXT: list<int> Predicates = [7];
+defm testInst0 : TestInstructionAndPattern<[7]>;
More information about the llvm-commits
mailing list