forked from OSchip/llvm-project
[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 llvm-svn: 208183
This commit is contained in:
parent
a2125140ae
commit
314e80e5f8
|
@ -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
|
||||
|
|
|
@ -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
|
||||
======
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() + ")";
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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"]>;
|
Loading…
Reference in New Issue