Index: lib/TableGen/TGParser.h =================================================================== --- lib/TableGen/TGParser.h +++ lib/TableGen/TGParser.h @@ -138,7 +138,9 @@ Record *InstantiateMulticlassDef(MultiClass &MC, Record *DefProto, Init *&DefmPrefix, - SMRange DefmPrefixRange); + SMRange DefmPrefixRange, + const std::vector &TArgs, + std::vector &TemplateVals); bool ResolveMulticlassDefArgs(MultiClass &MC, Record *DefProto, SMLoc DefmPrefixLoc, Index: lib/TableGen/TGParser.cpp =================================================================== --- lib/TableGen/TGParser.cpp +++ lib/TableGen/TGParser.cpp @@ -2322,7 +2322,9 @@ InstantiateMulticlassDef(MultiClass &MC, Record *DefProto, Init *&DefmPrefix, - SMRange DefmPrefixRange) { + SMRange DefmPrefixRange, + const std::vector &TArgs, + std::vector &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 @@ } Init *DefName = DefProto->getNameInit(); - StringInit *DefNameString = dyn_cast(DefName); if (DefNameString) { @@ -2386,12 +2387,40 @@ 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(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(DefName); + + if (!DefNameString) + DefName = DefName->convertInitializerTo(StringRecTy::get()); + + // We ran out of options here... + DefNameString = dyn_cast(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 @@ // Loop over all the def's in the multiclass, instantiating each one. for (const std::unique_ptr &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: test/TableGen/MultiClassDefName.td =================================================================== --- test/TableGen/MultiClassDefName.td +++ test/TableGen/MultiClassDefName.td @@ -39,3 +39,45 @@ defm : MC2<"bar">; +multiclass MC3 { + def ZFizz#s : C; +} + +defm : MC3<"Buzz">; + +// CHECK: def ZFizzBuzz +// CHECK: string name = "Buzz"; +// CHECK-NOT: MC3::s + +multiclass MC4 { + def NAME#s : C; +} + +defm ZTagazok : MC4<"AToi">; + +// CHECK: def ZTagazokAToi +// CHECK: string name = "AToi"; +// CHECK-NOT: MC4::s + +multiclass MC5 { + def NAME#c.name : C; +} + +def CTiger : C<"Tiger">; +defm Zebra : MC5; + +// CHECK: def ZebraTiger +// CHECK: string name = "Tiger"; +// CHECK-NOT: MC5::c + +multiclass MC6 { + def NAME#Tiger#c.name : C; +} + +def CAligator : C<"Aligator">; +defm Zebra : MC6; + +// CHECK: def ZebraTigerAligator +// CHECK: string name = "Aligator"; +// CHECK-NOT: MC6::c +