diff options
| author | Javed Absar <javed.absar@arm.com> | 2019-03-05 17:16:07 +0000 |
|---|---|---|
| committer | Javed Absar <javed.absar@arm.com> | 2019-03-05 17:16:07 +0000 |
| commit | 34d3b80dbab7f89f5f59d506b8447af6cfe3379d (patch) | |
| tree | e8eac091dd213f1f34d65dc2356866b308f03c60 /llvm/lib | |
| parent | 05812b65db6dedaa6fa36926dd6a1d4793362f30 (diff) | |
| download | bcm5719-llvm-34d3b80dbab7f89f5f59d506b8447af6cfe3379d.tar.gz bcm5719-llvm-34d3b80dbab7f89f5f59d506b8447af6cfe3379d.zip | |
TableGen: Allow lists to be concatenated through '#'
Currently one can concatenate strings using hash(#),
but not lists, although that would be a natural thing to do.
This patch allows one to write something like:
def : A<!listconcat([1,2], [3,4])>;
simply as :
def : A<[1,2] # [3,4]>;
This was missing feature was highlighted by Nicolai
at FOSDEM talk.
Reviewed by: nhaehnle, hfinkel
Differential Revision: https://reviews.llvm.org/D58895
llvm-svn: 355414
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/TableGen/Record.cpp | 18 | ||||
| -rw-r--r-- | llvm/lib/TableGen/TGParser.cpp | 23 |
2 files changed, 37 insertions, 4 deletions
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp index 480a002b64a..4222a0b57fb 100644 --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -856,6 +856,24 @@ Init *BinOpInit::getStrConcat(Init *I0, Init *I1) { return BinOpInit::get(BinOpInit::STRCONCAT, I0, I1, StringRecTy::get()); } +static ListInit *ConcatListInits(const ListInit *LHS, + const ListInit *RHS) { + SmallVector<Init *, 8> Args; + Args.insert(Args.end(), LHS->begin(), LHS->end()); + Args.insert(Args.end(), RHS->begin(), RHS->end()); + return ListInit::get(Args, LHS->getElementType()); +} + +Init *BinOpInit::getListConcat(TypedInit *LHS, Init *RHS) { + assert(isa<ListRecTy>(LHS->getType()) && "First arg must be a list"); + + // Shortcut for the common case of concatenating two lists. + if (const ListInit *LHSList = dyn_cast<ListInit>(LHS)) + if (const ListInit *RHSList = dyn_cast<ListInit>(RHS)) + return ConcatListInits(LHSList, RHSList); + return BinOpInit::get(BinOpInit::LISTCONCAT, LHS, RHS, LHS->getType()); +} + Init *BinOpInit::Fold(Record *CurRec) const { switch (getOpcode()) { case CONCAT: { diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp index 58343bda275..90c9b390e10 100644 --- a/llvm/lib/TableGen/TGParser.cpp +++ b/llvm/lib/TableGen/TGParser.cpp @@ -2119,16 +2119,31 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) { case tgtok::paste: SMLoc PasteLoc = Lex.getLoc(); - - // Create a !strconcat() operation, first casting each operand to - // a string if necessary. - TypedInit *LHS = dyn_cast<TypedInit>(Result); if (!LHS) { Error(PasteLoc, "LHS of paste is not typed!"); return nullptr; } + // Check if it's a 'listA # listB' + if (isa<ListRecTy>(LHS->getType())) { + Lex.Lex(); // Eat the '#'. + + switch (Lex.getCode()) { + case tgtok::colon: + case tgtok::semi: + case tgtok::l_brace: + Result = LHS; // trailing paste, ignore. + break; + default: + Init *RHSResult = ParseValue(CurRec, ItemType, ParseNameMode); + Result = BinOpInit::getListConcat(LHS, RHSResult); + } + break; + } + + // Create a !strconcat() operation, first casting each operand to + // a string if necessary. if (LHS->getType() != StringRecTy::get()) { LHS = dyn_cast<TypedInit>( UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get()) |

