Index: docs/TableGen/LangRef.rst =================================================================== --- docs/TableGen/LangRef.rst +++ docs/TableGen/LangRef.rst @@ -360,13 +360,17 @@ ----------- .. productionlist:: - Foreach: "foreach" `Declaration` "in" "{" `Object`* "}" - :| "foreach" `Declaration` "in" `Object` + Foreach: "foreach" `ForeachDeclaration` "in" "{" `Object`* "}" + :| "foreach" `ForeachDeclaration` "in" `Object` + ForeachDeclaration: ID "=" ( "{" `RangeList` "}" | `RangePiece` | `Value` ) The value assigned to the variable in the declaration is iterated over and the object or object list is reevaluated with the variable set at each iterated value. +Note that the productions involving RangeList and RangePiece have precedence +over the more generic value parsing based on the first token. + Top-Level ``let`` ----------------- Index: include/llvm/TableGen/Record.h =================================================================== --- include/llvm/TableGen/Record.h +++ include/llvm/TableGen/Record.h @@ -1201,6 +1201,7 @@ Init *getBit(unsigned Bit) const override; Init *resolveReferences(Resolver &R) const override; + Init *Fold() const; std::string getAsString() const override { return Rec->getAsString() + "." + FieldName->getValue().str(); Index: lib/TableGen/Record.cpp =================================================================== --- lib/TableGen/Record.cpp +++ lib/TableGen/Record.cpp @@ -1620,16 +1620,17 @@ Init *FieldInit::resolveReferences(Resolver &R) const { Init *NewRec = Rec->resolveReferences(R); + if (NewRec != Rec) + return FieldInit::get(NewRec, FieldName)->Fold(); + return const_cast(this); +} - if (DefInit *DI = dyn_cast(NewRec)) { +Init *FieldInit::Fold() const { + if (DefInit *DI = dyn_cast(Rec)) { Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue(); - Init *BVR = FieldVal->resolveReferences(R); - if (BVR->isComplete()) - return BVR; + if (FieldVal->isComplete()) + return FieldVal; } - - if (NewRec != Rec) - return FieldInit::get(NewRec, FieldName); return const_cast(this); } Index: lib/TableGen/TGParser.cpp =================================================================== --- lib/TableGen/TGParser.cpp +++ lib/TableGen/TGParser.cpp @@ -1817,7 +1817,7 @@ Result->getAsString() + "'"); return nullptr; } - Result = FieldInit::get(Result, FieldName); + Result = FieldInit::get(Result, FieldName)->Fold(); Lex.Lex(); // eat field name break; } @@ -2036,9 +2036,9 @@ /// the name of the declared object or a NULL Init on error. Return /// the name of the parsed initializer list through ForeachListName. /// -/// ForeachDeclaration ::= ID '=' '[' ValueList ']' /// ForeachDeclaration ::= ID '=' '{' RangeList '}' /// ForeachDeclaration ::= ID '=' RangePiece +/// ForeachDeclaration ::= ID '=' Value /// VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) { if (Lex.getCode() != tgtok::Id) { @@ -2060,24 +2060,6 @@ SmallVector Ranges; switch (Lex.getCode()) { - default: TokError("Unknown token when expecting a range list"); return nullptr; - case tgtok::l_square: { // '[' ValueList ']' - Init *List = ParseSimpleValue(nullptr); - ForeachListValue = dyn_cast(List); - if (!ForeachListValue) { - TokError("Expected a Value list"); - return nullptr; - } - RecTy *ValueType = ForeachListValue->getType(); - ListRecTy *ListType = dyn_cast(ValueType); - if (!ListType) { - TokError("Value list is not of list type"); - return nullptr; - } - IterType = ListType->getElementType(); - break; - } - case tgtok::IntVal: { // RangePiece. if (ParseRangePiece(Ranges)) return nullptr; @@ -2094,6 +2076,21 @@ Lex.Lex(); break; } + + default: { + SMLoc ValueLoc = Lex.getLoc(); + Init *I = ParseValue(nullptr); + if (!isa(I)) { + std::string Type; + if (TypedInit *TI = dyn_cast(I)) + Type = (Twine("' of type '") + TI->getType()->getAsString()).str(); + Error(ValueLoc, "expected a list, got '" + I->getAsString() + Type + "'"); + return nullptr; + } + ForeachListValue = dyn_cast(I); + IterType = ForeachListValue->getElementType(); + break; + } } if (!Ranges.empty()) { Index: test/TableGen/ForeachList.td =================================================================== --- test/TableGen/ForeachList.td +++ test/TableGen/ForeachList.td @@ -10,6 +10,18 @@ def F#i : Register<"F"#i, i>; } +def Defs { + list a = [0, 1]; + list b = [2, 3]; +} + +foreach i = Defs.a in { + def X#i; +} + +foreach i = !listconcat(Defs.a, Defs.b) in +def Y#i; + // CHECK: def F0 // CHECK: string Name = "F0"; // CHECK: int Index = 0; @@ -73,3 +85,10 @@ // CHECK: def R7 // CHECK: string Name = "R7"; // CHECK: int Index = 7; + +// CHECK: def X0 +// CHECK: def X1 +// CHECK: def Y0 +// CHECK: def Y1 +// CHECK: def Y2 +// CHECK: def Y3