[TableGen] Resolve complex def names inside multiclasses
authorHal Finkel <hfinkel@anl.gov>
Thu, 21 May 2015 04:32:56 +0000 (04:32 +0000)
committerHal Finkel <hfinkel@anl.gov>
Thu, 21 May 2015 04:32:56 +0000 (04:32 +0000)
We had not been trying hard enough to resolve def names inside multiclasses
that had complex concatenations, etc. Now we'll try harder.

Patch by Amaury Sechet!

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

lib/TableGen/TGParser.cpp
lib/TableGen/TGParser.h
test/TableGen/MultiClassDefName.td

index 23ef5354fca46eda6ea1226ffc8156278d1e7a35..0e654f982410a939b1dfc6921a15c1ea615b85ab 100644 (file)
@@ -2322,7 +2322,9 @@ Record *TGParser::
 InstantiateMulticlassDef(MultiClass &MC,
                          Record *DefProto,
                          Init *&DefmPrefix,
-                         SMRange DefmPrefixRange) {
+                         SMRange DefmPrefixRange,
+                         const std::vector<Init *> &TArgs,
+                         std::vector<Init *> &TemplateVals) {
   // We need to preserve DefProto so it can be reused for later
   // instantiations, so create a new Record to inherit from it.
 
@@ -2338,7 +2340,6 @@ InstantiateMulticlassDef(MultiClass &MC,
   }
 
   Init *DefName = DefProto->getNameInit();
-
   StringInit *DefNameString = dyn_cast<StringInit>(DefName);
 
   if (DefNameString) {
@@ -2386,12 +2387,40 @@ InstantiateMulticlassDef(MultiClass &MC,
     RecordVal *DefNameRV = CurRec->getValue("NAME");
     CurRec->resolveReferencesTo(DefNameRV);
 
+    // Check if the name is a complex pattern.
+    // If so, resolve it.
+    DefName = CurRec->getNameInit();
+    DefNameString = dyn_cast<StringInit>(DefName);
+
+    // OK the pattern is more complex than simply using NAME.
+    // Let's use the heavy weaponery.
+    if (!DefNameString) {
+      ResolveMulticlassDefArgs(MC, CurRec.get(), DefmPrefixRange.Start,
+                               Lex.getLoc(), TArgs, TemplateVals,
+                               false/*Delete args*/);
+      DefName = CurRec->getNameInit();
+      DefNameString = dyn_cast<StringInit>(DefName);
+
+      if (!DefNameString)
+        DefName = DefName->convertInitializerTo(StringRecTy::get());
+
+      // We ran out of options here...
+      DefNameString = dyn_cast<StringInit>(DefName);
+      if (!DefNameString) {
+        PrintFatalError(CurRec->getLoc()[CurRec->getLoc().size() - 1],
+                        DefName->getAsUnquotedString() + " is not a string.");
+        return nullptr;
+      }
+
+      CurRec->setName(DefName);
+    }
+
     // Now that NAME references are resolved and we're at the top level of
     // any multiclass expansions, add the record to the RecordKeeper. If we are
     // currently in a multiclass, it means this defm appears inside a
     // multiclass and its name won't be fully resolvable until we see
-    // the top-level defm.  Therefore, we don't add this to the
-    // RecordKeeper at this point.  If we did we could get duplicate
+    // the top-level defm. Therefore, we don't add this to the
+    // RecordKeeper at this point. If we did we could get duplicate
     // defs as more than one probably refers to NAME or some other
     // common internal placeholder.
 
@@ -2523,12 +2552,19 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
 
     // Loop over all the def's in the multiclass, instantiating each one.
     for (const std::unique_ptr<Record> &DefProto : MC->DefPrototypes) {
+      // The record name construction goes as follow:
+      //  - If the def name is a string, prepend the prefix.
+      //  - If the def name is a more complex pattern, use that pattern.
+      // As a result, the record is instanciated before resolving
+      // arguments, as it would make its name a string.
       Record *CurRec = InstantiateMulticlassDef(*MC, DefProto.get(), DefmPrefix,
                                                 SMRange(DefmLoc,
-                                                        DefmPrefixEndLoc));
+                                                        DefmPrefixEndLoc),
+                                                TArgs, TemplateVals);
       if (!CurRec)
         return true;
 
+      // Now that the record is instanciated, we can resolve arguments.
       if (ResolveMulticlassDefArgs(*MC, CurRec, DefmLoc, SubClassLoc,
                                    TArgs, TemplateVals, true/*Delete args*/))
         return Error(SubClassLoc, "could not instantiate def");
index 22a00e5919512609369c4c937d4a32db4acd1610..d69d1f4572f907af46001f3f191e77a57cf51bc7 100644 (file)
@@ -138,7 +138,9 @@ private:  // Parser methods.
   Record *InstantiateMulticlassDef(MultiClass &MC,
                                    Record *DefProto,
                                    Init *&DefmPrefix,
-                                   SMRange DefmPrefixRange);
+                                   SMRange DefmPrefixRange,
+                                   const std::vector<Init *> &TArgs,
+                                   std::vector<Init *> &TemplateVals);
   bool ResolveMulticlassDefArgs(MultiClass &MC,
                                 Record *DefProto,
                                 SMLoc DefmPrefixLoc,
index 811d92667eb2be17c534ffdb8aea67ee8dfc38a2..fafa1ad3081bcf7eec35843358749031c67d5a44 100644 (file)
@@ -39,3 +39,45 @@ multiclass MC2<string name> {
 
 defm : MC2<"bar">;
 
+multiclass MC3<string s> {
+  def ZFizz#s : C<s>;
+}
+
+defm : MC3<"Buzz">;
+
+// CHECK: def ZFizzBuzz
+// CHECK: string name = "Buzz";
+// CHECK-NOT: MC3::s
+
+multiclass MC4<string s> {
+  def NAME#s : C<s>;
+}
+
+defm ZTagazok : MC4<"AToi">;
+
+// CHECK: def ZTagazokAToi
+// CHECK: string name = "AToi";
+// CHECK-NOT: MC4::s
+
+multiclass MC5<C c> {
+  def NAME#c.name : C<c.name>;
+}
+
+def CTiger : C<"Tiger">;
+defm Zebra : MC5<CTiger>;
+
+// CHECK: def ZebraTiger
+// CHECK: string name = "Tiger";
+// CHECK-NOT: MC5::c
+
+multiclass MC6<C c> {
+  def NAME#Tiger#c.name : C<c.name>;
+}
+
+def CAligator : C<"Aligator">;
+defm Zebra : MC6<CAligator>;
+
+// CHECK: def ZebraTigerAligator
+// CHECK: string name = "Aligator";
+// CHECK-NOT: MC6::c
+