diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index d4bc5572482..8c5452e511c 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -1401,6 +1401,18 @@ class Record { DefInit *TheInit; bool IsAnonymous; + // Class-instance values can be used by other defs. For example, Struct + // is used here as a template argument to another class: + // + // multiclass MultiClass { + // def Def : Class>; + // + // These need to get fully resolved before instantiating any other + // definitions that usie them (e.g. Def). However, inside a multiclass they + // can't be immediately resolved so we mark them ResolveFirst to fully + // resolve them later as soon as the multiclass is instantiated. + bool ResolveFirst; + void init(); void checkName(); @@ -1409,13 +1421,15 @@ public: explicit Record(const std::string &N, ArrayRef locs, RecordKeeper &records, bool Anonymous = false) : ID(LastID++), Name(StringInit::get(N)), Locs(locs.begin(), locs.end()), - TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous) { + TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous), + ResolveFirst(false) { init(); } explicit Record(Init *N, ArrayRef locs, RecordKeeper &records, bool Anonymous = false) : ID(LastID++), Name(N), Locs(locs.begin(), locs.end()), - TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous) { + TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous), + ResolveFirst(false) { init(); } @@ -1425,7 +1439,8 @@ public: ID(LastID++), Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs), Values(O.Values), SuperClasses(O.SuperClasses), SuperClassRanges(O.SuperClassRanges), TrackedRecords(O.TrackedRecords), - TheInit(O.TheInit), IsAnonymous(O.IsAnonymous) { } + TheInit(O.TheInit), IsAnonymous(O.IsAnonymous), + ResolveFirst(O.ResolveFirst) { } ~Record() {} @@ -1553,6 +1568,14 @@ public: return IsAnonymous; } + bool isResolveFirst() const { + return ResolveFirst; + } + + void setResolveFirst(bool b) { + ResolveFirst = b; + } + void dump() const; //===--------------------------------------------------------------------===// diff --git a/lib/TableGen/TGParser.cpp b/lib/TableGen/TGParser.cpp index 15039792042..f2910019ed9 100644 --- a/lib/TableGen/TGParser.cpp +++ b/lib/TableGen/TGParser.cpp @@ -1264,6 +1264,9 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, NewRec->resolveReferences(); Records.addDef(NewRec); } else { + // This needs to get resolved once the multiclass template arguments are + // known before any use. + NewRec->setResolveFirst(true); // Otherwise, we're inside a multiclass, add it to the multiclass. CurMultiClass->DefPrototypes.push_back(NewRec); @@ -2602,6 +2605,12 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { if (ResolveMulticlassDef(*MC, CurRec, DefProto, DefmLoc)) return Error(SubClassLoc, "could not instantiate def"); + // Defs that can be used by other definitions should be fully resolved + // before any use. + if (DefProto->isResolveFirst() && !CurMultiClass) { + CurRec->resolveReferences(); + CurRec->setResolveFirst(false); + } NewRecDefs.push_back(CurRec); } diff --git a/test/TableGen/ClassInstanceValue.td b/test/TableGen/ClassInstanceValue.td new file mode 100644 index 00000000000..b6c4c93cb09 --- /dev/null +++ b/test/TableGen/ClassInstanceValue.td @@ -0,0 +1,19 @@ +// RUN: llvm-tblgen %s | FileCheck %s +// XFAIL: vg_leak + +class Struct { + int I = !shl(i, 1); + int J = !shl(I, 1); +} + +class Class { + int Class_J = s.J; +} + +multiclass MultiClass { + def Def : Class>; +// CHECK: Class_J = 8 +// CHECK-NOT: Class_J = !shl(I, 1) +} + +defm Defm : MultiClass<2>;