Process Multidefs
authorDavid Greene <greened@obbligato.org>
Wed, 5 Oct 2011 22:42:45 +0000 (22:42 +0000)
committerDavid Greene <greened@obbligato.org>
Wed, 5 Oct 2011 22:42:45 +0000 (22:42 +0000)
Process each multidef declared in a multiclass.  Iterate through the
list and instantiate a def in the multiclass for each item, resolving
the list item to the temporary iterator (possibly) used in the
multidef ObjectBody.  We then process each generated def in the normal
way.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141233 91177308-0d34-0410-b5e6-96231b3b80d8

lib/TableGen/TGParser.cpp

index fafac0c29d7d241412ae5442d5021d39d63b0a24..ed51977c3d011ab14d5cdfe876370b27812e8b5c 100644 (file)
@@ -2174,6 +2174,92 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
       NewRecDefs.push_back(CurRec);
     }
 
+    // Loop over multidefs, instantiating them.
+    for (unsigned i = 0, e = MC->MultiDefPrototypes.size(); i != e; ++i) {
+      // Each multidef generates a set of defs, one per item in the
+      // given list.
+
+      // Resolve the list now.  This record serves as a base class for
+      // the individual records created below.
+      Record *DefProto = MC->MultiDefPrototypes[i].Rec;
+      TypedInit *List = MC->MultiDefPrototypes[i].List;
+      IntInit *Start = MC->MultiDefPrototypes[i].Start;
+
+      // This is the name of the second item in the multidef <> list.
+      // It is a temporary iterator that holds the current value of
+      // the list element being processed.
+      std::string &ItemName = MC->MultiDefPrototypes[i].ItemName;
+      Record *BaseRec = InstantiateMulticlassDef(*MC, DefProto, DefmPrefix,
+                                                 DefmPrefixLoc);
+      // Make the list a member of the base record.
+      RecordVal ListV("__MDListInit__", List->getType(), 0);
+      ListV.setValue(List);
+      BaseRec->addValue(ListV);
+      // Resolve the base multidef record to template args.  This
+      // should resolve the list.  We don't delete the arguments
+      // values because we want the created defs to inherit them.
+      // Each list item needs to be resolved against these values.
+      // They will be deleted when we do final processing of the
+      // instantiated def.
+      if (ResolveMulticlassDefArgs(*MC, BaseRec, DefmPrefixLoc,
+                                   SubClassLoc, TArgs, TemplateVals,
+                                   false/*Do not delete args*/))
+        return Error(SubClassLoc, "could not instantiate def");
+      RecordVal *ListVP = BaseRec->getValue("__MDListInit__");
+      ListInit *ListIn = dynamic_cast<ListInit *>(ListVP->getValue());
+      if (ListIn == 0)
+        return Error(SubClassLoc, "multidef init must be of list type");
+      // Remove the temporary list since we've resolve it and don't
+      // need it to be part of the defs.
+      BaseRec->removeValue("__MDListInit__");
+
+      // For each item in the list, create a def.
+      for(int64_t it = Start->getValue(); it < ListIn->getSize(); ++it) {
+        std::stringstream id;
+        id << it;
+
+        // Create a record prefixed with MD<n>., where <n> is an
+        // incrementing value.  This guarantees that defs created via
+        // multidefs are named uniquely.
+        Record *CurRec = InstantiateMulticlassDef(*MC, BaseRec,
+                                                  "MD" + id.str() + ".",
+                                                  DefmPrefixLoc);
+        // Get the list item and resolve it.
+        Init *ItemVal = ListIn->resolveListElementReference(*CurRec, 0, it);
+        if (!ItemVal)
+          return Error(SubClassLoc, "invalid list item");
+        // Set the temporary item (iterator) value now.
+        if (SetValue(CurRec, SubClassLoc, ItemName, std::vector<unsigned>(), ItemVal)) {
+          Error(DefmPrefixLoc, "when instantiating this defm");
+          return true;
+        }
+  
+        // Resolve it next.
+        CurRec->resolveReferencesTo(CurRec->getValue(ItemName));
+
+        // Remove it.
+        CurRec->removeValue(ItemName);
+
+        // Now instantiate the def as if it had been declared directly
+        // as part of the multicass.
+        if (ResolveMulticlassDefArgs(*MC, CurRec, DefmPrefixLoc,
+                                     SubClassLoc, TArgs, TemplateVals,
+                                     true/*Delete args*/))
+          return Error(SubClassLoc, "could not instantiate def");
+         
+        if (ResolveMulticlassDef(*MC, CurRec, DefProto, DefmPrefixLoc))
+          return Error(SubClassLoc, "could not instantiate def");
+      }
+    }
 
     if (Lex.getCode() != tgtok::comma) break;
     Lex.Lex(); // eat ','.