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 @@ -2359,7 +2359,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. @@ -2375,7 +2377,6 @@ } Init *DefName = DefProto->getNameInit(); - StringInit *DefNameString = dyn_cast(DefName); if (DefNameString) { @@ -2423,12 +2424,40 @@ RecordVal *DefNameRV = CurRec->getValue("NAME"); CurRec->resolveReferencesTo(DefNameRV); + // Check if the name is a complex pattern. + // If yes, resolve ! + 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 option 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. @@ -2567,12 +2596,19 @@ for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) { Record *DefProto = MC->DefPrototypes[i].get(); + // 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, 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,13 @@ defm : MC2<"bar">; +multiclass MC3 { + def ZFizz#s : C; +} + +defm : MC3<"Buzz">; + +// CHECK: def ZFizzBuzz +// CHECK: string name = "Buzz"; +// CHECK-NOT: MC3::s +