Index: llvm/trunk/include/llvm/TableGen/Record.h =================================================================== --- llvm/trunk/include/llvm/TableGen/Record.h +++ llvm/trunk/include/llvm/TableGen/Record.h @@ -820,6 +820,7 @@ static BinOpInit *get(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type); static Init *getStrConcat(Init *lhs, Init *rhs); + static Init *getListConcat(TypedInit *lhs, Init *rhs); void Profile(FoldingSetNodeID &ID) const; Index: llvm/trunk/lib/TableGen/Record.cpp =================================================================== --- llvm/trunk/lib/TableGen/Record.cpp +++ llvm/trunk/lib/TableGen/Record.cpp @@ -856,6 +856,24 @@ return BinOpInit::get(BinOpInit::STRCONCAT, I0, I1, StringRecTy::get()); } +static ListInit *ConcatListInits(const ListInit *LHS, + const ListInit *RHS) { + SmallVector 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(LHS->getType()) && "First arg must be a list"); + + // Shortcut for the common case of concatenating two lists. + if (const ListInit *LHSList = dyn_cast(LHS)) + if (const ListInit *RHSList = dyn_cast(RHS)) + return ConcatListInits(LHSList, RHSList); + return BinOpInit::get(BinOpInit::LISTCONCAT, LHS, RHS, LHS->getType()); +} + Init *BinOpInit::Fold(Record *CurRec) const { switch (getOpcode()) { case CONCAT: { Index: llvm/trunk/lib/TableGen/TGParser.cpp =================================================================== --- llvm/trunk/lib/TableGen/TGParser.cpp +++ llvm/trunk/lib/TableGen/TGParser.cpp @@ -2119,16 +2119,31 @@ case tgtok::paste: SMLoc PasteLoc = Lex.getLoc(); - - // Create a !strconcat() operation, first casting each operand to - // a string if necessary. - TypedInit *LHS = dyn_cast(Result); if (!LHS) { Error(PasteLoc, "LHS of paste is not typed!"); return nullptr; } + // Check if it's a 'listA # listB' + if (isa(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( UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get()) Index: llvm/trunk/test/TableGen/listpaste.td =================================================================== --- llvm/trunk/test/TableGen/listpaste.td +++ llvm/trunk/test/TableGen/listpaste.td @@ -0,0 +1,40 @@ +// RUN: llvm-tblgen %s | FileCheck %s + +// CHECK: class A { +// CHECK: list lst = !listconcat([], !if(A:x, [], [4])); +// CHECK: } +class A { + list lst = [] # !if(x, [], [4]); +} + +// CHECK: class A1 A1:l = ?> { +// CHECK: list A1List = A1:l; +// CHECK: } +class A1 l> { + list A1List = l; +} + +// CHECK: def A0 { +// CHECK: list lst = [4]; +// CHECK: } +def A0 : A<0>; + +// CHECK: def A1 { +// CHECK: list lst = []; +// CHECK: } +def A1 : A<1>; + +// CHECK: def A1_0 { +// CHECK: list A1List = [1, 2, 3, 4]; +// CHECK: } +def A1_0 : A1<[1,2] # [3,4]>; + +// CHECK: def A1_1 { +// CHECK: list A1List = [1, 2]; +// CHECK: } +def A1_1 : A1<[] # [1,2]>; + +// CHECK: def A1_2 { // A1 +// CHECK: list A1List = [1, 2]; +// CHECK: } +def A1_2 : A1<[1,2] # []>;