aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/TableGen/Record.cpp29
-rw-r--r--llvm/lib/TableGen/TGLexer.cpp1
-rw-r--r--llvm/lib/TableGen/TGLexer.h1
-rw-r--r--llvm/lib/TableGen/TGParser.cpp32
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)