@@ -48,6 +48,7 @@ struct SubClassReference {
4848 SubClassReference () = default ;
4949
5050 bool isInvalid () const { return Rec == nullptr ; }
51+ void dump () const ;
5152};
5253
5354struct SubMultiClassReference {
@@ -72,6 +73,19 @@ LLVM_DUMP_METHOD void SubMultiClassReference::dump() const {
7273 for (const Init *TA : TemplateArgs)
7374 TA->dump ();
7475}
76+
77+ LLVM_DUMP_METHOD void SubClassReference::dump () const {
78+ errs () << " Subclass:\n " ;
79+
80+ Rec->dump ();
81+
82+ errs () << " Template args:\n " ;
83+ for (const Init *TA : TemplateArgs) {
84+ TA->dump ();
85+ errs () << " \n " ;
86+ }
87+ errs () << " \n " ;
88+ }
7589#endif
7690
7791static bool checkBitsConcrete (Record &R, const RecordVal &RV) {
@@ -307,6 +321,66 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const Init *ValName,
307321 return false ;
308322}
309323
324+ static std::string getCanonicalRecName (Record *CurRec) {
325+ const Init *Name;
326+ if (CurRec->isClass ())
327+ Name = VarInit::get (QualifiedNameOfImplicitName (*CurRec),
328+ StringRecTy::get (CurRec->getRecords ()));
329+ else
330+ Name = CurRec->getNameInit ();
331+ return Name->getAsUnquotedString ();
332+ }
333+
334+ // https://nimrod.blog/posts/cpp-how-to-access-private-members-validly/
335+ template <typename Tag>
336+ struct Storage {
337+ inline static typename Tag::type ptr;
338+ };
339+
340+ template <typename Tag, typename Tag::type V>
341+ struct PtrTaker {
342+ struct Transferer {
343+ Transferer () { Storage<Tag>::ptr = V; }
344+ };
345+ inline static Transferer tr;
346+ };
347+
348+ struct TemplateArgsTag {
349+ using type = SmallVector<const Init *, 0 > Record::*;
350+ };
351+
352+ template struct PtrTaker <TemplateArgsTag, &Record::TemplateArgs>;
353+
354+ static void
355+ addOrReplaceTemplateArgs (Record *rec,
356+ SmallVector<const ArgumentInit *, 4 > newTemplateArgs) {
357+ SmallVector<const Init *, 0 > *mutableTemplateArgs =
358+ &(*rec.*Storage<TemplateArgsTag>::ptr);
359+ std::string recName = getCanonicalRecName (rec);
360+ for (const ArgumentInit *newTemplateArg : newTemplateArgs) {
361+ const Init **i = llvm::find_if (*mutableTemplateArgs, [&](const Init *tArg) {
362+ const auto *oTArg = llvm::dyn_cast<ArgumentInit>(tArg);
363+ if (oTArg->isNamed ()) {
364+ if (newTemplateArg->isNamed ())
365+ return oTArg->getName () == newTemplateArg->getName ();
366+ return false ;
367+ }
368+ if (newTemplateArg->isPositional ())
369+ return oTArg->getIndex () == newTemplateArg->getIndex ();
370+ return false ;
371+ });
372+ auto newVal = RecordVal (newTemplateArg, RecordRecTy::get (rec),
373+ RecordVal::FK_TemplateArg);
374+ if (i == mutableTemplateArgs->end ()) {
375+ mutableTemplateArgs->push_back (newTemplateArg);
376+ } else {
377+ rec->removeValue (*i);
378+ *i = newTemplateArg;
379+ }
380+ rec->addValue (newVal);
381+ }
382+ }
383+
310384// / AddSubClass - Add SubClass as a subclass to CurRec, resolving its template
311385// / args as SubClass's template arguments.
312386bool TGParser::AddSubClass (Record *CurRec, SubClassReference &SubClass) {
@@ -336,9 +410,15 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
336410 StringRecTy::get (Records));
337411 else
338412 Name = CurRec->getNameInit ();
413+ auto canName = getCanonicalRecName (CurRec);
414+ recordTemplateArgs[canName] = SubClass.TemplateArgs ;
339415 R.set (QualifiedNameOfImplicitName (*SC), Name);
340416
341417 CurRec->resolveReferences (R);
418+ // we only want to keep args for defs not classes which pass
419+ // args to other classes (i think so?)
420+ if (!CurRec->isClass () && !SubClass.TemplateArgs .empty ())
421+ addOrReplaceTemplateArgs (CurRec, SubClass.TemplateArgs );
342422
343423 // Since everything went well, we can now set the "superclass" list for the
344424 // current record.
@@ -531,7 +611,20 @@ bool TGParser::resolve(const std::vector<RecordsEntry> &Source,
531611 MapResolver R (Rec.get ());
532612 for (const auto &S : Substs)
533613 R.set (S.first , S.second );
614+ std::string eName = getCanonicalRecName (E.Rec .get ());
615+ assert (recordTemplateArgs.count (eName));
616+ auto templateArgs = recordTemplateArgs[eName];
534617 Rec->resolveReferences (R);
618+ SmallVector<const ArgumentInit *, 4 > resolvedTemplateArgs;
619+ for (const ArgumentInit *templateArg : templateArgs)
620+ resolvedTemplateArgs.emplace_back (
621+ llvm::cast<ArgumentInit>(templateArg->resolveReferences (R)));
622+ std::string recName = getCanonicalRecName (Rec.get ());
623+ recordTemplateArgs[recName] = resolvedTemplateArgs;
624+ // we only want to keep args for defs not classes which pass
625+ // args to other classes (i think so?)
626+ if (!Rec->isClass () && !resolvedTemplateArgs.empty ())
627+ addOrReplaceTemplateArgs (Rec.get (), resolvedTemplateArgs);
535628
536629 if (Dest)
537630 Dest->push_back (std::move (Rec));
@@ -574,7 +667,7 @@ bool TGParser::addDefOne(std::unique_ptr<Record> Rec) {
574667 Rec->emitRecordDumps ();
575668
576669 // If ObjectBody has template arguments, it's an error.
577- assert (Rec->getTemplateArgs ().empty () && " How'd this get template args?" );
670+ // assert(Rec->getTemplateArgs().empty() && "How'd this get template args?");
578671
579672 for (DefsetRecord *Defset : Defsets) {
580673 DefInit *I = Rec->getDefInit ();
@@ -2872,7 +2965,9 @@ const Init *TGParser::ParseSimpleValue(Record *CurRec, const RecTy *ItemType,
28722965
28732966 if (TrackReferenceLocs)
28742967 Class->appendReferenceLoc (NameLoc);
2875- return VarDefInit::get (NameLoc.Start , Class, Args)->Fold ();
2968+ const VarDefInit *v = VarDefInit::get (NameLoc.Start , Class, Args);
2969+ TheVarDefInitPool.insert (v);
2970+ return v->Fold ();
28762971 }
28772972 case tgtok::l_brace: { // Value ::= '{' ValueList '}'
28782973 SMLoc BraceLoc = Lex.getLoc ();
0 commit comments