[llvm] fef2fc3 - [TableGen] Support non-def operators in !getdagop (#77531)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 10 06:59:42 PST 2024


Author: Visoiu Mistrih Francis
Date: 2024-01-10T06:59:38-08:00
New Revision: fef2fc3400eb5a22a5ccc96bd3862bec0058d305

URL: https://github.com/llvm/llvm-project/commit/fef2fc3400eb5a22a5ccc96bd3862bec0058d305
DIFF: https://github.com/llvm/llvm-project/commit/fef2fc3400eb5a22a5ccc96bd3862bec0058d305.diff

LOG: [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.

Added: 
    

Modified: 
    llvm/lib/TableGen/Record.cpp
    llvm/test/TableGen/getsetop.td

Removed: 
    


################################################################################
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