summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Sanders <daniel.sanders@imgtec.com>2014-05-07 10:13:19 +0000
committerDaniel Sanders <daniel.sanders@imgtec.com>2014-05-07 10:13:19 +0000
commitd80222a48b11d5ec35a2e3502d014bdbd9f137c0 (patch)
treeac9c2b281c9f3e3cfc599fc0abf75c080af9293b
parent0c9ea21554e976b23e494ca8bda48bd1691ac8a4 (diff)
downloadllvm-d80222a48b11d5ec35a2e3502d014bdbd9f137c0.tar.gz
llvm-d80222a48b11d5ec35a2e3502d014bdbd9f137c0.tar.bz2
llvm-d80222a48b11d5ec35a2e3502d014bdbd9f137c0.tar.xz
[tablegen] Add !listconcat operator with the similar semantics as !strconcat
Summary: It concatenates two or more lists. In addition to the !strconcat semantics the lists must have the same element type. My overall aim is to make it easy to append to Instruction.Predicates rather than override it. This can be done by concatenating lists passed as arguments, or by concatenating lists passed in additional fields. Reviewers: dsanders Reviewed By: dsanders Subscribers: hfinkel, llvm-commits Differential Revision: http://reviews.llvm.org/D3506 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208183 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--docs/TableGen/LangIntro.rst6
-rw-r--r--docs/TableGen/LangRef.rst2
-rw-r--r--include/llvm/TableGen/Record.h3
-rw-r--r--lib/TableGen/Record.cpp13
-rw-r--r--lib/TableGen/TGLexer.cpp1
-rw-r--r--lib/TableGen/TGLexer.h2
-rw-r--r--lib/TableGen/TGParser.cpp22
-rw-r--r--test/TableGen/listconcat.td18
8 files changed, 63 insertions, 4 deletions
diff --git a/docs/TableGen/LangIntro.rst b/docs/TableGen/LangIntro.rst
index 5b6094fa91..3e74dffb00 100644
--- a/docs/TableGen/LangIntro.rst
+++ b/docs/TableGen/LangIntro.rst
@@ -160,6 +160,12 @@ supported include:
remaining elements in the list may be arbitrary other values, including
nested ```dag``' values.
+``!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.
+ More than two arguments are accepted with the result being the concatenation
+ of all the lists given.
+
``!strconcat(a, b, ...)``
A string value that is the result of concatenating the 'a' and 'b' strings.
More than two arguments are accepted with the result being the concatenation
diff --git a/docs/TableGen/LangRef.rst b/docs/TableGen/LangRef.rst
index 781f789faa..9b074be38d 100644
--- a/docs/TableGen/LangRef.rst
+++ b/docs/TableGen/LangRef.rst
@@ -93,7 +93,7 @@ wide variety of meanings:
BangOperator: one of
:!eq !if !head !tail !con
:!add !shl !sra !srl
- :!cast !empty !subst !foreach !strconcat
+ :!cast !empty !subst !foreach !listconcat !strconcat
Syntax
======
diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h
index 5b2a706ae1..e74a8f2d8a 100644
--- a/include/llvm/TableGen/Record.h
+++ b/include/llvm/TableGen/Record.h
@@ -929,7 +929,8 @@ public:
///
class BinOpInit : public OpInit {
public:
- enum BinaryOp { ADD, SHL, SRA, SRL, STRCONCAT, CONCAT, EQ };
+ enum BinaryOp { ADD, SHL, SRA, SRL, LISTCONCAT, STRCONCAT, CONCAT, EQ };
+
private:
BinaryOp Opc;
Init *LHS, *RHS;
diff --git a/lib/TableGen/Record.cpp b/lib/TableGen/Record.cpp
index 57d2703b82..c17aea99f8 100644
--- a/lib/TableGen/Record.cpp
+++ b/lib/TableGen/Record.cpp
@@ -918,6 +918,18 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {
}
break;
}
+ case LISTCONCAT: {
+ ListInit *LHSs = dyn_cast<ListInit>(LHS);
+ ListInit *RHSs = dyn_cast<ListInit>(RHS);
+ if (LHSs && RHSs) {
+ std::vector<Init *> Args;
+ Args.insert(Args.end(), LHSs->begin(), LHSs->end());
+ Args.insert(Args.end(), RHSs->begin(), RHSs->end());
+ return ListInit::get(
+ Args, static_cast<ListRecTy *>(LHSs->getType())->getElementType());
+ }
+ break;
+ }
case STRCONCAT: {
StringInit *LHSs = dyn_cast<StringInit>(LHS);
StringInit *RHSs = dyn_cast<StringInit>(RHS);
@@ -987,6 +999,7 @@ std::string BinOpInit::getAsString() const {
case SRA: Result = "!sra"; break;
case SRL: Result = "!srl"; break;
case EQ: Result = "!eq"; break;
+ case LISTCONCAT: Result = "!listconcat"; break;
case STRCONCAT: Result = "!strconcat"; break;
}
return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")";
diff --git a/lib/TableGen/TGLexer.cpp b/lib/TableGen/TGLexer.cpp
index 57f603183b..1ec2eea67d 100644
--- a/lib/TableGen/TGLexer.cpp
+++ b/lib/TableGen/TGLexer.cpp
@@ -478,6 +478,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
.Case("empty", tgtok::XEmpty)
.Case("subst", tgtok::XSubst)
.Case("foreach", tgtok::XForEach)
+ .Case("listconcat", tgtok::XListConcat)
.Case("strconcat", tgtok::XStrConcat)
.Default(tgtok::Error);
diff --git a/lib/TableGen/TGLexer.h b/lib/TableGen/TGLexer.h
index d1bd70d2ec..1e599f84b0 100644
--- a/lib/TableGen/TGLexer.h
+++ b/lib/TableGen/TGLexer.h
@@ -47,7 +47,7 @@ namespace tgtok {
MultiClass, String,
// !keywords.
- XConcat, XADD, XSRA, XSRL, XSHL, XStrConcat, XCast, XSubst,
+ XConcat, XADD, XSRA, XSRL, XSHL, XListConcat, XStrConcat, XCast, XSubst,
XForEach, XHead, XTail, XEmpty, XIf, XEq,
// Integer value.
diff --git a/lib/TableGen/TGParser.cpp b/lib/TableGen/TGParser.cpp
index dd3a0967d1..038e0180fb 100644
--- a/lib/TableGen/TGParser.cpp
+++ b/lib/TableGen/TGParser.cpp
@@ -903,6 +903,7 @@ Init *TGParser::ParseOperation(Record *CurRec) {
case tgtok::XSRL:
case tgtok::XSHL:
case tgtok::XEq:
+ case tgtok::XListConcat:
case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')'
tgtok::TokKind OpTok = Lex.getCode();
SMLoc OpLoc = Lex.getLoc();
@@ -919,6 +920,10 @@ Init *TGParser::ParseOperation(Record *CurRec) {
case tgtok::XSRL: Code = BinOpInit::SRL; Type = IntRecTy::get(); break;
case tgtok::XSHL: Code = BinOpInit::SHL; Type = IntRecTy::get(); break;
case tgtok::XEq: Code = BinOpInit::EQ; Type = BitRecTy::get(); break;
+ case tgtok::XListConcat:
+ Code = BinOpInit::LISTCONCAT;
+ // We don't know the list type until we parse the first argument
+ break;
case tgtok::XStrConcat:
Code = BinOpInit::STRCONCAT;
Type = StringRecTy::get();
@@ -949,9 +954,22 @@ Init *TGParser::ParseOperation(Record *CurRec) {
}
Lex.Lex(); // eat the ')'
+ // If we are doing !listconcat, we should know the type by now
+ if (OpTok == tgtok::XListConcat) {
+ if (VarInit *Arg0 = dyn_cast<VarInit>(InitList[0]))
+ Type = Arg0->getType();
+ else if (ListInit *Arg0 = dyn_cast<ListInit>(InitList[0]))
+ Type = Arg0->getType();
+ else {
+ InitList[0]->dump();
+ Error(OpLoc, "expected a list");
+ return nullptr;
+ }
+ }
+
// We allow multiple operands to associative operators like !strconcat as
// shorthand for nesting them.
- if (Code == BinOpInit::STRCONCAT) {
+ if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT) {
while (InitList.size() > 2) {
Init *RHS = InitList.pop_back_val();
RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type))
@@ -1134,6 +1152,7 @@ RecTy *TGParser::ParseOperatorType() {
/// SimpleValue ::= SHLTOK '(' Value ',' Value ')'
/// SimpleValue ::= SRATOK '(' Value ',' Value ')'
/// SimpleValue ::= SRLTOK '(' Value ',' Value ')'
+/// SimpleValue ::= LISTCONCATTOK '(' Value ',' Value ')'
/// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')'
///
Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
@@ -1417,6 +1436,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
case tgtok::XSRL:
case tgtok::XSHL:
case tgtok::XEq:
+ case tgtok::XListConcat:
case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')'
case tgtok::XIf:
case tgtok::XForEach:
diff --git a/test/TableGen/listconcat.td b/test/TableGen/listconcat.td
new file mode 100644
index 0000000000..870e649d41
--- /dev/null
+++ b/test/TableGen/listconcat.td
@@ -0,0 +1,18 @@
+// RUN: llvm-tblgen %s | FileCheck %s
+
+// CHECK: class Y<list<string> Y:S = ?> {
+// CHECK: list<string> T1 = !listconcat(Y:S, ["foo"]);
+// CHECK: list<string> T2 = !listconcat(Y:S, !listconcat(["foo"], !listconcat(Y:S, ["bar", "baz"])));
+// CHECK: }
+
+// CHECK: def Z {
+// CHECK: list<string> T1 = ["fu", "foo"];
+// CHECK: list<string> T2 = ["fu", "foo", "fu", "bar", "baz"];
+// CHECK: }
+
+class Y<list<string> S> {
+ list<string> T1 = !listconcat(S, ["foo"]);
+ list<string> T2 = !listconcat(S, ["foo"], S, ["bar", "baz"]);
+}
+
+def Z : Y<["fu"]>;