[llvm] r327492 - TableGen: Add !dag function for construction

Nicolai Haehnle via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 14 04:00:27 PDT 2018


Author: nha
Date: Wed Mar 14 04:00:26 2018
New Revision: 327492

URL: http://llvm.org/viewvc/llvm-project?rev=327492&view=rev
Log:
TableGen: Add !dag function for construction

This allows constructing DAG nodes with programmatically determined
names, and can simplify constructing DAG nodes in other cases as
well.

Also, add documentation and some very simple tests for the already
existing !con.

Change-Id: Ida61cd82e99752548d7109ce8da34d29da56a5f7

Differential revision: https://reviews.llvm.org/D44110

Added:
    llvm/trunk/test/TableGen/dag-functional.td
Modified:
    llvm/trunk/docs/TableGen/LangIntro.rst
    llvm/trunk/docs/TableGen/LangRef.rst
    llvm/trunk/include/llvm/TableGen/Record.h
    llvm/trunk/lib/TableGen/Record.cpp
    llvm/trunk/lib/TableGen/TGLexer.cpp
    llvm/trunk/lib/TableGen/TGLexer.h
    llvm/trunk/lib/TableGen/TGParser.cpp

Modified: llvm/trunk/docs/TableGen/LangIntro.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/TableGen/LangIntro.rst?rev=327492&r1=327491&r2=327492&view=diff
==============================================================================
--- llvm/trunk/docs/TableGen/LangIntro.rst (original)
+++ llvm/trunk/docs/TableGen/LangIntro.rst Wed Mar 14 04:00:26 2018
@@ -165,6 +165,24 @@ supported include:
     remaining elements in the list may be arbitrary other values, including
     nested ```dag``' values.
 
+``!con(a, b, ...)``
+    Concatenate two or more DAG nodes. Their operations must equal.
+
+    Example: !con((op a1:$name1, a2:$name2), (op b1:$name3)) results in
+    the DAG node (op a1:$name1, a2:$name2, b1:$name3).
+
+``!dag(op, children, names)``
+    Generate a DAG node programmatically. 'children' and 'names' must be lists
+    of equal length or unset ('?'). 'names' must be a 'list<string>'.
+
+    Due to limitations of the type system, 'children' must be a list of items
+    of a common type. In practice, this means that they should either have the
+    same type or be records with a common superclass. Mixing dag and non-dag
+    items is not possible.
+
+    Example: !dag(op, [a1, a2], ["name1", "name2"]) results in
+    (op a1:$name1, a2:$name2).
+
 ``!listconcat(a, b, ...)``
     A list value that is the result of concatenating the 'a' and 'b' lists.
     The lists must have the same element type.

Modified: llvm/trunk/docs/TableGen/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/TableGen/LangRef.rst?rev=327492&r1=327491&r2=327492&view=diff
==============================================================================
--- llvm/trunk/docs/TableGen/LangRef.rst (original)
+++ llvm/trunk/docs/TableGen/LangRef.rst Wed Mar 14 04:00:26 2018
@@ -99,7 +99,7 @@ wide variety of meanings:
                :!add    !shl     !sra     !srl       !and
                :!or     !empty   !subst   !foreach   !strconcat
                :!cast   !listconcat       !size      !foldl
-               :!isa
+               :!isa    !dag
 
 
 Syntax

Modified: llvm/trunk/include/llvm/TableGen/Record.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/TableGen/Record.h?rev=327492&r1=327491&r2=327492&view=diff
==============================================================================
--- llvm/trunk/include/llvm/TableGen/Record.h (original)
+++ llvm/trunk/include/llvm/TableGen/Record.h Wed Mar 14 04:00:26 2018
@@ -856,7 +856,7 @@ public:
 /// !op (X, Y, Z) - Combine two inits.
 class TernOpInit : public OpInit, public FoldingSetNode {
 public:
-  enum TernaryOp : uint8_t { SUBST, FOREACH, IF };
+  enum TernaryOp : uint8_t { SUBST, FOREACH, IF, DAG };
 
 private:
   Init *LHS, *MHS, *RHS;

Modified: llvm/trunk/lib/TableGen/Record.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/Record.cpp?rev=327492&r1=327491&r2=327492&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/Record.cpp (original)
+++ llvm/trunk/lib/TableGen/Record.cpp Wed Mar 14 04:00:26 2018
@@ -1114,6 +1114,30 @@ Init *TernOpInit::Fold(Record *CurRec, M
     }
     break;
   }
+
+  case DAG: {
+    ListInit *MHSl = dyn_cast<ListInit>(MHS);
+    ListInit *RHSl = dyn_cast<ListInit>(RHS);
+    bool MHSok = MHSl || isa<UnsetInit>(MHS);
+    bool RHSok = RHSl || isa<UnsetInit>(RHS);
+
+    if (isa<UnsetInit>(MHS) && isa<UnsetInit>(RHS))
+      break; // Typically prevented by the parser, but might happen with template args
+
+    if (MHSok && RHSok && (!MHSl || !RHSl || MHSl->size() == RHSl->size())) {
+      SmallVector<std::pair<Init *, StringInit *>, 8> Children;
+      unsigned Size = MHSl ? MHSl->size() : RHSl->size();
+      for (unsigned i = 0; i != Size; ++i) {
+        Init *Node = MHSl ? MHSl->getElement(i) : UnsetInit::get();
+        Init *Name = RHSl ? RHSl->getElement(i) : UnsetInit::get();
+        if (!isa<StringInit>(Name) && !isa<UnsetInit>(Name))
+          return const_cast<TernOpInit *>(this);
+        Children.emplace_back(Node, dyn_cast<StringInit>(Name));
+      }
+      return DagInit::get(LHS, nullptr, Children);
+    }
+    break;
+  }
   }
 
   return const_cast<TernOpInit *>(this);
@@ -1155,6 +1179,7 @@ std::string TernOpInit::getAsString() co
   case SUBST: Result = "!subst"; break;
   case FOREACH: Result = "!foreach"; break;
   case IF: Result = "!if"; break;
+  case DAG: Result = "!dag"; break;
   }
   return Result + "(" + LHS->getAsString() + ", " + MHS->getAsString() + ", " +
          RHS->getAsString() + ")";

Modified: llvm/trunk/lib/TableGen/TGLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGLexer.cpp?rev=327492&r1=327491&r2=327492&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGLexer.cpp (original)
+++ llvm/trunk/lib/TableGen/TGLexer.cpp Wed Mar 14 04:00:26 2018
@@ -473,6 +473,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
     .Case("tail", tgtok::XTail)
     .Case("size", tgtok::XSize)
     .Case("con", tgtok::XConcat)
+    .Case("dag", tgtok::XDag)
     .Case("add", tgtok::XADD)
     .Case("and", tgtok::XAND)
     .Case("or", tgtok::XOR)

Modified: llvm/trunk/lib/TableGen/TGLexer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGLexer.h?rev=327492&r1=327491&r2=327492&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGLexer.h (original)
+++ llvm/trunk/lib/TableGen/TGLexer.h Wed Mar 14 04:00:26 2018
@@ -48,7 +48,7 @@ namespace tgtok {
 
     // !keywords.
     XConcat, XADD, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XStrConcat, XCast,
-    XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XEq, XIsA,
+    XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XEq, XIsA, XDag,
 
     // Integer value.
     IntVal,

Modified: llvm/trunk/lib/TableGen/TGParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGParser.cpp?rev=327492&r1=327491&r2=327492&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGParser.cpp (original)
+++ llvm/trunk/lib/TableGen/TGParser.cpp Wed Mar 14 04:00:26 2018
@@ -1159,6 +1159,7 @@ Init *TGParser::ParseOperation(Record *C
                ->Fold(CurRec, CurMultiClass);
   }
 
+  case tgtok::XDag:
   case tgtok::XIf:
   case tgtok::XSubst: {  // Value ::= !ternop '(' Value ',' Value ',' Value ')'
     TernOpInit::TernaryOp Code;
@@ -1168,6 +1169,11 @@ Init *TGParser::ParseOperation(Record *C
     Lex.Lex();  // eat the operation
     switch (LexCode) {
     default: llvm_unreachable("Unhandled code!");
+    case tgtok::XDag:
+      Code = TernOpInit::DAG;
+      Type = DagRecTy::get();
+      ItemType = nullptr;
+      break;
     case tgtok::XIf:
       Code = TernOpInit::IF;
       break;
@@ -1190,6 +1196,7 @@ Init *TGParser::ParseOperation(Record *C
     }
     Lex.Lex();  // eat the ','
 
+    SMLoc MHSLoc = Lex.getLoc();
     Init *MHS = ParseValue(CurRec, ItemType);
     if (!MHS)
       return nullptr;
@@ -1200,6 +1207,7 @@ Init *TGParser::ParseOperation(Record *C
     }
     Lex.Lex();  // eat the ','
 
+    SMLoc RHSLoc = Lex.getLoc();
     Init *RHS = ParseValue(CurRec, ItemType);
     if (!RHS)
       return nullptr;
@@ -1212,6 +1220,36 @@ Init *TGParser::ParseOperation(Record *C
 
     switch (LexCode) {
     default: llvm_unreachable("Unhandled code!");
+    case tgtok::XDag: {
+      TypedInit *MHSt = dyn_cast<TypedInit>(MHS);
+      if (!MHSt && !isa<UnsetInit>(MHS)) {
+        Error(MHSLoc, "could not determine type of the child list in !dag");
+        return nullptr;
+      }
+      if (MHSt && !isa<ListRecTy>(MHSt->getType())) {
+        Error(MHSLoc, Twine("expected list of children, got type '") +
+                          MHSt->getType()->getAsString() + "'");
+        return nullptr;
+      }
+
+      TypedInit *RHSt = dyn_cast<TypedInit>(RHS);
+      if (!RHSt && !isa<UnsetInit>(RHS)) {
+        Error(RHSLoc, "could not determine type of the name list in !dag");
+        return nullptr;
+      }
+      if (RHSt && StringRecTy::get()->getListTy() != RHSt->getType()) {
+        Error(RHSLoc, Twine("expected list<string>, got type '") +
+                          RHSt->getType()->getAsString() + "'");
+        return nullptr;
+      }
+
+      if (!MHSt && !RHSt) {
+        Error(MHSLoc,
+              "cannot have both unset children and unset names in !dag");
+        return nullptr;
+      }
+      break;
+    }
     case tgtok::XIf: {
       RecTy *MHSTy = nullptr;
       RecTy *RHSTy = nullptr;
@@ -1728,6 +1766,7 @@ Init *TGParser::ParseSimpleValue(Record
   case tgtok::XCast:  // Value ::= !unop '(' Value ')'
   case tgtok::XIsA:
   case tgtok::XConcat:
+  case tgtok::XDag:
   case tgtok::XADD:
   case tgtok::XAND:
   case tgtok::XOR:

Added: llvm/trunk/test/TableGen/dag-functional.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/dag-functional.td?rev=327492&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/dag-functional.td (added)
+++ llvm/trunk/test/TableGen/dag-functional.td Wed Mar 14 04:00:26 2018
@@ -0,0 +1,95 @@
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+
+// CHECK: --- Defs ---
+
+// CHECK: def A0 {
+// CHECK:   dag ret = (ops);
+// CHECK: }
+
+// CHECK: def A1 {
+// CHECK:   dag ret = (ops 1:$a, 2:$b);
+// CHECK: }
+
+// CHECK: def A2 {
+// CHECK:   dag ret = (ops (ops ?:$name):$a, (ops 1):$b, (ops "foo"):$c);
+// CHECK: }
+
+// CHECK: def A3 {
+// CHECK:   dag ret = (ops NodeA0:$a, NodeB0:$b);
+// CHECK: }
+
+// CHECK: def A4 {
+// CHECK:   dag ret = (ops NodeA0, NodeB0);
+// CHECK: }
+
+// CHECK: def B0 {
+// CHECK:   dag ret = (ops);
+// CHECK: }
+
+// CHECK: def B1 {
+// CHECK:   dag ret = (ops 1:$a, 2:$b);
+// CHECK: }
+
+// CHECK: def C0 {
+// CHECK:   dag ret1 = (ops ?:$a, ?:$b);
+// CHECK:   dag ret2 = (ops 1, 2);
+// CHECK: }
+
+def ops;
+
+class Node<int val, string name> {
+  int Val = val;
+  string Name = name;
+}
+
+class Aint<list<int> nodes, list<string> names> {
+  dag ret = !dag(ops, nodes, names);
+}
+
+class Adag<list<dag> nodes, list<string> names> {
+  dag ret = !dag(ops, nodes, names);
+}
+
+class NodeBase;
+
+class NodeA<int val> : NodeBase {
+  int x = val;
+}
+
+class NodeB<int val> : NodeBase {
+  int y = val;
+}
+
+class Anode<list<NodeBase> nodes, list<string> names> {
+  dag ret = !dag(ops, nodes, names);
+}
+
+class B<list<Node> nodes> {
+  dag ret = !foldl((ops), nodes, lhs, rhs, !con(lhs, !dag(ops, [rhs.Val], [rhs.Name])));
+}
+
+def A0 : Aint<[], []>;
+def A1 : Aint<[1, 2], ["a", "b"]>;
+
+def A2 : Adag<[(ops $name), (ops 1), (ops "foo")], ["a", "b", "c"]>;
+
+def NodeA0 : NodeA<0>;
+def NodeB0 : NodeB<0>;
+
+def A3 : Anode<[NodeA0, NodeB0], ["a", "b"]>;
+
+def A4 {
+  // Like A3, but with a literal list directly in the !dag.
+  dag ret = !dag(ops, [NodeA0, NodeB0], ?);
+}
+
+def B0 : B<[]>;
+def B1 : B<[Node<1, "a">, Node<2, "b">]>;
+
+class C<list<int> nodes, list<string> names> {
+  dag ret1 = !dag(ops, ?, names);
+  dag ret2 = !dag(ops, nodes, ?);
+}
+
+def C0 : C<[1, 2], ["a", "b"]>;




More information about the llvm-commits mailing list