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.
}
Init *DefName = DefProto->getNameInit();
-
StringInit *DefNameString = dyn_cast<StringInit>(DefName);
if (DefNameString) {
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.
// 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");
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
+