@@ -1190,6 +1190,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
11901190 case tgtok::XNOT:
11911191 case tgtok::XToLower:
11921192 case tgtok::XToUpper:
1193+ case tgtok::XListFlatten:
11931194 case tgtok::XLOG2:
11941195 case tgtok::XHead:
11951196 case tgtok::XTail:
@@ -1235,6 +1236,11 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
12351236 Code = UnOpInit::NOT;
12361237 Type = IntRecTy::get (Records);
12371238 break ;
1239+ case tgtok::XListFlatten:
1240+ Lex.Lex (); // eat the operation.
1241+ Code = UnOpInit::LISTFLATTEN;
1242+ Type = IntRecTy::get (Records); // Bogus type used here.
1243+ break ;
12381244 case tgtok::XLOG2:
12391245 Lex.Lex (); // eat the operation
12401246 Code = UnOpInit::LOG2;
@@ -1309,7 +1315,8 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
13091315 }
13101316 }
13111317
1312- if (Code == UnOpInit::HEAD || Code == UnOpInit::TAIL) {
1318+ if (Code == UnOpInit::HEAD || Code == UnOpInit::TAIL ||
1319+ Code == UnOpInit::LISTFLATTEN) {
13131320 ListInit *LHSl = dyn_cast<ListInit>(LHS);
13141321 TypedInit *LHSt = dyn_cast<TypedInit>(LHS);
13151322 if (!LHSl && !LHSt) {
@@ -1328,19 +1335,34 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
13281335 TokError (" empty list argument in unary operator" );
13291336 return nullptr ;
13301337 }
1338+ bool UseElementType =
1339+ Code == UnOpInit::HEAD || Code == UnOpInit::LISTFLATTEN;
13311340 if (LHSl) {
13321341 Init *Item = LHSl->getElement (0 );
13331342 TypedInit *Itemt = dyn_cast<TypedInit>(Item);
13341343 if (!Itemt) {
13351344 TokError (" untyped list element in unary operator" );
13361345 return nullptr ;
13371346 }
1338- Type = (Code == UnOpInit::HEAD) ? Itemt->getType ()
1339- : ListRecTy::get (Itemt->getType ());
1347+ Type = UseElementType ? Itemt->getType ()
1348+ : ListRecTy::get (Itemt->getType ());
13401349 } else {
13411350 assert (LHSt && " expected list type argument in unary operator" );
13421351 ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType ());
1343- Type = (Code == UnOpInit::HEAD) ? LType->getElementType () : LType;
1352+ Type = UseElementType ? LType->getElementType () : LType;
1353+ }
1354+
1355+ // for !listflatten, we expect a list of lists, but also support a list of
1356+ // non-lists, where !listflatten will be a NOP.
1357+ if (Code == UnOpInit::LISTFLATTEN) {
1358+ ListRecTy *InnerListTy = dyn_cast<ListRecTy>(Type);
1359+ if (InnerListTy) {
1360+ // listflatten will convert list<list<X>> to list<X>.
1361+ Type = ListRecTy::get (InnerListTy->getElementType ());
1362+ } else {
1363+ // If its a list of non-lists, !listflatten will be a NOP.
1364+ Type = ListRecTy::get (Type);
1365+ }
13441366 }
13451367 }
13461368
@@ -1378,7 +1400,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
13781400
13791401 case tgtok::XExists: {
13801402 // Value ::= !exists '<' Type '>' '(' Value ')'
1381- Lex.Lex (); // eat the operation
1403+ Lex.Lex (); // eat the operation.
13821404
13831405 RecTy *Type = ParseOperatorType ();
13841406 if (!Type)
0 commit comments