mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
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
This commit is contained in:
parent
dcde6a778e
commit
d19970f650
@ -820,6 +820,7 @@ public:
|
||||
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;
|
||||
|
||||
|
@ -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: {
|
||||
|
@ -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())
|
||||
|
40
test/TableGen/listpaste.td
Normal file
40
test/TableGen/listpaste.td
Normal file
@ -0,0 +1,40 @@
|
||||
// RUN: llvm-tblgen %s | FileCheck %s
|
||||
|
||||
// CHECK: class A<bit A:x = ?> {
|
||||
// CHECK: list<int> lst = !listconcat([], !if(A:x, [], [4]));
|
||||
// CHECK: }
|
||||
class A<bit x> {
|
||||
list<int> lst = [] # !if(x, [], [4]);
|
||||
}
|
||||
|
||||
// CHECK: class A1<list<int> A1:l = ?> {
|
||||
// CHECK: list<int> A1List = A1:l;
|
||||
// CHECK: }
|
||||
class A1<list<int> l> {
|
||||
list<int> A1List = l;
|
||||
}
|
||||
|
||||
// CHECK: def A0 {
|
||||
// CHECK: list<int> lst = [4];
|
||||
// CHECK: }
|
||||
def A0 : A<0>;
|
||||
|
||||
// CHECK: def A1 {
|
||||
// CHECK: list<int> lst = [];
|
||||
// CHECK: }
|
||||
def A1 : A<1>;
|
||||
|
||||
// CHECK: def A1_0 {
|
||||
// CHECK: list<int> A1List = [1, 2, 3, 4];
|
||||
// CHECK: }
|
||||
def A1_0 : A1<[1,2] # [3,4]>;
|
||||
|
||||
// CHECK: def A1_1 {
|
||||
// CHECK: list<int> A1List = [1, 2];
|
||||
// CHECK: }
|
||||
def A1_1 : A1<[] # [1,2]>;
|
||||
|
||||
// CHECK: def A1_2 { // A1
|
||||
// CHECK: list<int> A1List = [1, 2];
|
||||
// CHECK: }
|
||||
def A1_2 : A1<[1,2] # []>;
|
Loading…
x
Reference in New Issue
Block a user