diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/TableGen/Record.cpp | 29 | ||||
| -rw-r--r-- | llvm/lib/TableGen/TGLexer.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/TableGen/TGLexer.h | 1 | ||||
| -rw-r--r-- | llvm/lib/TableGen/TGParser.cpp | 32 |
4 files changed, 58 insertions, 5 deletions
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp index a72a0799..0f99b4a 100644 --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -986,6 +986,32 @@ Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const { } } break; + + case LISTFLATTEN: + if (ListInit *LHSList = dyn_cast<ListInit>(LHS)) { + ListRecTy *InnerListTy = dyn_cast<ListRecTy>(LHSList->getElementType()); + // list of non-lists, !listflatten() is a NOP. + if (!InnerListTy) + return LHS; + + auto Flatten = [](ListInit *List) -> std::optional<std::vector<Init *>> { + std::vector<Init *> Flattened; + // Concatenate elements of all the inner lists. + for (Init *InnerInit : List->getValues()) { + ListInit *InnerList = dyn_cast<ListInit>(InnerInit); + if (!InnerList) + return std::nullopt; + for (Init *InnerElem : InnerList->getValues()) + Flattened.push_back(InnerElem); + }; + return Flattened; + }; + + auto Flattened = Flatten(LHSList); + if (Flattened) + return ListInit::get(*Flattened, InnerListTy->getElementType()); + } + break; } return const_cast<UnOpInit *>(this); } @@ -1010,6 +1036,9 @@ std::string UnOpInit::getAsString() const { case EMPTY: Result = "!empty"; break; case GETDAGOP: Result = "!getdagop"; break; case LOG2 : Result = "!logtwo"; break; + case LISTFLATTEN: + Result = "!listflatten"; + break; case REPR: Result = "!repr"; break; diff --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp index 62a884e..8fe7f69 100644 --- a/llvm/lib/TableGen/TGLexer.cpp +++ b/llvm/lib/TableGen/TGLexer.cpp @@ -628,6 +628,7 @@ tgtok::TokKind TGLexer::LexExclaim() { .Case("foreach", tgtok::XForEach) .Case("filter", tgtok::XFilter) .Case("listconcat", tgtok::XListConcat) + .Case("listflatten", tgtok::XListFlatten) .Case("listsplat", tgtok::XListSplat) .Case("listremove", tgtok::XListRemove) .Case("range", tgtok::XRange) diff --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h index 9adc03c..4fa4d84 100644 --- a/llvm/lib/TableGen/TGLexer.h +++ b/llvm/lib/TableGen/TGLexer.h @@ -122,6 +122,7 @@ enum TokKind { XSRL, XSHL, XListConcat, + XListFlatten, XListSplat, XStrConcat, XInterleave, diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp index 1a60c2a..54c9a90 100644 --- a/llvm/lib/TableGen/TGParser.cpp +++ b/llvm/lib/TableGen/TGParser.cpp @@ -1190,6 +1190,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { case tgtok::XNOT: case tgtok::XToLower: case tgtok::XToUpper: + case tgtok::XListFlatten: case tgtok::XLOG2: case tgtok::XHead: case tgtok::XTail: @@ -1235,6 +1236,11 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { Code = UnOpInit::NOT; Type = IntRecTy::get(Records); break; + case tgtok::XListFlatten: + Lex.Lex(); // eat the operation. + Code = UnOpInit::LISTFLATTEN; + Type = IntRecTy::get(Records); // Bogus type used here. + break; case tgtok::XLOG2: Lex.Lex(); // eat the operation Code = UnOpInit::LOG2; @@ -1309,7 +1315,8 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { } } - if (Code == UnOpInit::HEAD || Code == UnOpInit::TAIL) { + if (Code == UnOpInit::HEAD || Code == UnOpInit::TAIL || + Code == UnOpInit::LISTFLATTEN) { ListInit *LHSl = dyn_cast<ListInit>(LHS); TypedInit *LHSt = dyn_cast<TypedInit>(LHS); if (!LHSl && !LHSt) { @@ -1328,6 +1335,8 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { TokError("empty list argument in unary operator"); return nullptr; } + bool UseElementType = + Code == UnOpInit::HEAD || Code == UnOpInit::LISTFLATTEN; if (LHSl) { Init *Item = LHSl->getElement(0); TypedInit *Itemt = dyn_cast<TypedInit>(Item); @@ -1335,12 +1344,25 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { TokError("untyped list element in unary operator"); return nullptr; } - Type = (Code == UnOpInit::HEAD) ? Itemt->getType() - : ListRecTy::get(Itemt->getType()); + Type = UseElementType ? Itemt->getType() + : ListRecTy::get(Itemt->getType()); } else { assert(LHSt && "expected list type argument in unary operator"); ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType()); - Type = (Code == UnOpInit::HEAD) ? LType->getElementType() : LType; + Type = UseElementType ? LType->getElementType() : LType; + } + + // for !listflatten, we expect a list of lists, but also support a list of + // non-lists, where !listflatten will be a NOP. + if (Code == UnOpInit::LISTFLATTEN) { + ListRecTy *InnerListTy = dyn_cast<ListRecTy>(Type); + if (InnerListTy) { + // listflatten will convert list<list<X>> to list<X>. + Type = ListRecTy::get(InnerListTy->getElementType()); + } else { + // If its a list of non-lists, !listflatten will be a NOP. + Type = ListRecTy::get(Type); + } } } @@ -1378,7 +1400,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { case tgtok::XExists: { // Value ::= !exists '<' Type '>' '(' Value ')' - Lex.Lex(); // eat the operation + Lex.Lex(); // eat the operation. RecTy *Type = ParseOperatorType(); if (!Type) |
