+/// ProcessForeachDefs - Given a record, apply all of the variable
+/// values in all surrounding foreach loops, creating new records for
+/// each combination of values.
+bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc) {
+ if (Loops.empty())
+ return false;
+
+ // We want to instantiate a new copy of CurRec for each combination
+ // of nested loop iterator values. We don't want top instantiate
+ // any copies until we have values for each loop iterator.
+ IterSet IterVals;
+ return ProcessForeachDefs(CurRec, Loc, IterVals);
+}
+
+/// ProcessForeachDefs - Given a record, a loop and a loop iterator,
+/// apply each of the variable values in this loop and then process
+/// subloops.
+bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc, IterSet &IterVals){
+ // Recursively build a tuple of iterator values.
+ if (IterVals.size() != Loops.size()) {
+ assert(IterVals.size() < Loops.size());
+ ForeachLoop &CurLoop = Loops[IterVals.size()];
+ ListInit *List = dyn_cast<ListInit>(CurLoop.ListValue);
+ if (!List) {
+ Error(Loc, "Loop list is not a list");
+ return true;
+ }
+
+ // Process each value.
+ for (unsigned i = 0; i < List->size(); ++i) {
+ Init *ItemVal = List->resolveListElementReference(*CurRec, nullptr, i);
+ IterVals.push_back(IterRecord(CurLoop.IterVar, ItemVal));
+ if (ProcessForeachDefs(CurRec, Loc, IterVals))
+ return true;
+ IterVals.pop_back();
+ }
+ return false;
+ }
+
+ // This is the bottom of the recursion. We have all of the iterator values
+ // for this point in the iteration space. Instantiate a new record to
+ // reflect this combination of values.
+ auto IterRec = make_unique<Record>(*CurRec);
+
+ // Set the iterator values now.
+ for (IterRecord &IR : IterVals) {
+ VarInit *IterVar = IR.IterVar;
+ TypedInit *IVal = dyn_cast<TypedInit>(IR.IterValue);
+ if (!IVal)
+ return Error(Loc, "foreach iterator value is untyped");
+
+ IterRec->addValue(RecordVal(IterVar->getName(), IVal->getType(), false));
+
+ if (SetValue(IterRec.get(), Loc, IterVar->getName(), None, IVal))
+ return Error(Loc, "when instantiating this def");
+
+ // Resolve it next.
+ IterRec->resolveReferencesTo(IterRec->getValue(IterVar->getName()));
+
+ // Remove it.
+ IterRec->removeValue(IterVar->getName());
+ }
+
+ if (Records.getDef(IterRec->getNameInitAsString())) {
+ // If this record is anonymous, it's no problem, just generate a new name
+ if (!IterRec->isAnonymous())
+ return Error(Loc, "def already exists: " +IterRec->getNameInitAsString());
+
+ IterRec->setName(GetNewAnonymousName());
+ }
+
+ Record *IterRecSave = IterRec.get(); // Keep a copy before release.
+ Records.addDef(std::move(IterRec));
+ IterRecSave->resolveReferences();
+ return false;
+}
+