1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +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:
Javed Absar 2019-03-05 17:16:07 +00:00
parent dcde6a778e
commit d19970f650
4 changed files with 78 additions and 4 deletions

View File

@ -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;

View File

@ -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: {

View File

@ -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())

View 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] # []>;