diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h --- a/llvm/include/llvm/TableGen/Record.h +++ b/llvm/include/llvm/TableGen/Record.h @@ -301,6 +301,7 @@ IK_CondOpInit, IK_FoldOpInit, IK_IsAOpInit, + IK_AnonymousNameInit, IK_StringInit, IK_VarInit, IK_VarListElementInit, @@ -576,6 +577,36 @@ } }; +/// "anonymous_n" - Represent an anonymous record name +class AnonymousNameInit : public TypedInit { + unsigned Value; + + explicit AnonymousNameInit(unsigned V) + : TypedInit(IK_AnonymousNameInit, StringRecTy::get()), Value(V) {} + +public: + AnonymousNameInit(const AnonymousNameInit &) = delete; + AnonymousNameInit &operator=(const AnonymousNameInit &) = delete; + + static bool classof(const Init *I) { + return I->getKind() == IK_AnonymousNameInit; + } + + static AnonymousNameInit *get(unsigned); + + unsigned getValue() const { return Value; } + + StringInit *getNameInit() const; + + std::string getAsString() const override; + + Init *resolveReferences(Resolver &R) const override; + + Init *getBit(unsigned Bit) const override { + llvm_unreachable("Illegal bit reference off string"); + } +}; + /// "foo" - Represent an initialization by a string value. class StringInit : public TypedInit { public: diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -503,6 +503,26 @@ return BitsInit::get(NewBits); } +AnonymousNameInit *AnonymousNameInit::get(unsigned V) { + return new (Allocator) AnonymousNameInit(V); +} + +StringInit *AnonymousNameInit::getNameInit() const { + return StringInit::get(getAsString()); +} + +std::string AnonymousNameInit::getAsString() const { + return "anonymous_" + utostr(Value); +} + +Init *AnonymousNameInit::resolveReferences(Resolver &R) const { + if (R.isFinal()) + return getNameInit(); + auto *Old = const_cast(static_cast(this)); + auto *New = R.resolve(Old); + return New ? New : Old; +} + StringInit *StringInit::get(StringRef V, StringFormat Fmt) { static StringMap StringPool(Allocator); static StringMap CodePool(Allocator); @@ -702,7 +722,9 @@ // Self-references are allowed, but their resolution is delayed until // the final resolve to ensure that we get the correct type for them. - if (Name == CurRec->getNameInit()) { + auto *Anonymous = dyn_cast(CurRec->getNameInit()); + if (Name == CurRec->getNameInit() || + (Anonymous && Name == Anonymous->getNameInit())) { if (!IsFinal) break; D = CurRec; @@ -2589,7 +2611,7 @@ /// GetNewAnonymousName - Generate a unique anonymous name that can be used as /// an identifier. Init *RecordKeeper::getNewAnonymousName() { - return StringInit::get("anonymous_" + utostr(AnonCounter++)); + return AnonymousNameInit::get(AnonCounter++); } // These functions implement the phase timing facility. Starting a timer diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp --- a/llvm/lib/TableGen/TGParser.cpp +++ b/llvm/lib/TableGen/TGParser.cpp @@ -446,7 +446,12 @@ PrintNote(Prev->getLoc(), "location of previous definition"); return true; } - Rec->setName(Records.getNewAnonymousName()); + auto *OldName = Rec->getNameInit(); + auto *NewName = Records.getNewAnonymousName(); + + MapResolver R(Rec.get()); + R.set(OldName, NewName); + Rec->resolveReferences(R); } Rec->resolveReferences(); diff --git a/llvm/test/TableGen/self-reference.td b/llvm/test/TableGen/self-reference.td --- a/llvm/test/TableGen/self-reference.td +++ b/llvm/test/TableGen/self-reference.td @@ -32,6 +32,19 @@ // CHECK: Fc as_c = F0; // CHECK: } +// CHECK: def anonymous_0 { +// CHECK: G g = anonymous_0; +// CHECK: } +// CHECK: def anonymous_1 { +// CHECK: G g = anonymous_1; +// CHECK: } +// CHECK: def anonymous_2 { +// CHECK: G g = anonymous_2; +// CHECK: } +// CHECK: def anonymous_5 { +// CHECK: G g = anonymous_5; +// CHECK: } + def ops; class A { @@ -96,3 +109,18 @@ def F0x { Fc as_c = F0; } + +// anonymous record self-reference in foreach and multiclass +class G { + G g = !cast(NAME); +} + +foreach _ = [1, 2] in + def : G; + +multiclass H { + def : G; +} + +defm : H; +defm : H;