summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/docs/TableGen/LangRef.rst8
-rw-r--r--llvm/include/llvm/TableGen/Record.h1
-rw-r--r--llvm/lib/TableGen/Record.cpp15
-rw-r--r--llvm/lib/TableGen/TGParser.cpp37
-rw-r--r--llvm/test/TableGen/ForeachList.td19
5 files changed, 51 insertions, 29 deletions
diff --git a/llvm/docs/TableGen/LangRef.rst b/llvm/docs/TableGen/LangRef.rst
index 89996f35822..702b40c9011 100644
--- a/llvm/docs/TableGen/LangRef.rst
+++ b/llvm/docs/TableGen/LangRef.rst
@@ -360,13 +360,17 @@ precede any ``class``'s that appear.
-----------
.. 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``
-----------------
diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h
index d23167ac5bf..cf955662463 100644
--- a/llvm/include/llvm/TableGen/Record.h
+++ b/llvm/include/llvm/TableGen/Record.h
@@ -1203,6 +1203,7 @@ public:
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();
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index 9fd8b94e4af..2fbe4cc493f 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -1633,16 +1633,17 @@ Init *FieldInit::getBit(unsigned Bit) const {
Init *FieldInit::resolveReferences(Resolver &R) const {
Init *NewRec = Rec->resolveReferences(R);
+ if (NewRec != Rec)
+ return FieldInit::get(NewRec, FieldName)->Fold();
+ return const_cast<FieldInit *>(this);
+}
- if (DefInit *DI = dyn_cast<DefInit>(NewRec)) {
+Init *FieldInit::Fold() const {
+ if (DefInit *DI = dyn_cast<DefInit>(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<FieldInit *>(this);
}
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 59f5e6e5866..a60fa90c190 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -1819,7 +1819,7 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
Result->getAsString() + "'");
return nullptr;
}
- Result = FieldInit::get(Result, FieldName);
+ Result = FieldInit::get(Result, FieldName)->Fold();
Lex.Lex(); // eat field name
break;
}
@@ -2038,9 +2038,9 @@ Init *TGParser::ParseDeclaration(Record *CurRec,
/// 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) {
@@ -2062,24 +2062,6 @@ VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) {
SmallVector<unsigned, 16> 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<ListInit>(List);
- if (!ForeachListValue) {
- TokError("Expected a Value list");
- return nullptr;
- }
- RecTy *ValueType = ForeachListValue->getType();
- ListRecTy *ListType = dyn_cast<ListRecTy>(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;
@@ -2096,6 +2078,21 @@ VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) {
Lex.Lex();
break;
}
+
+ default: {
+ SMLoc ValueLoc = Lex.getLoc();
+ Init *I = ParseValue(nullptr);
+ if (!isa<ListInit>(I)) {
+ std::string Type;
+ if (TypedInit *TI = dyn_cast<TypedInit>(I))
+ Type = (Twine("' of type '") + TI->getType()->getAsString()).str();
+ Error(ValueLoc, "expected a list, got '" + I->getAsString() + Type + "'");
+ return nullptr;
+ }
+ ForeachListValue = dyn_cast<ListInit>(I);
+ IterType = ForeachListValue->getElementType();
+ break;
+ }
}
if (!Ranges.empty()) {
diff --git a/llvm/test/TableGen/ForeachList.td b/llvm/test/TableGen/ForeachList.td
index 9bc76e0f0cf..2ac2b8254ef 100644
--- a/llvm/test/TableGen/ForeachList.td
+++ b/llvm/test/TableGen/ForeachList.td
@@ -10,6 +10,18 @@ foreach i = [0, 1, 2, 3, 4, 5, 6, 7] in {
def F#i : Register<"F"#i, i>;
}
+def Defs {
+ list<int> a = [0, 1];
+ list<int> 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 @@ foreach i = [0, 1, 2, 3, 4, 5, 6, 7] in {
// 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
OpenPOWER on IntegriCloud