summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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"]>;