[llvm] r326788 - TableGen: Delay instantiating inline anonymous records
Nicolai Hähnle via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 6 12:21:14 PST 2018
On 06.03.2018 19:05, Matt Morehouse wrote:
> One of the commits in this sequence seems to be breaking a couple tests:
> http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/14892.
Yeah, they should all be fixed now.
>
> Testing: 0 .. 10.. 20.. 30.. 40.. 50.. 60.. 70.. FAIL: Clang ::
> TableGen/anonymous-groups.td <http://anonymous-groups.td> (9683 of
> 12091) ******************** TEST 'Clang :: TableGen/anonymous-groups.td
> <http://anonymous-groups.td>' FAILED ******************** Script: --
> clang-tblgen -gen-clang-diag-groups
> -I/b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen
> /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/anonymous-groups.td
> <http://anonymous-groups.td> -o /dev/null 2>&1 |
> /b/sanitizer-x86_64-linux-fast/build/llvm_build_asan/bin/FileCheck
> --strict-whitespace
> /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/anonymous-groups.td
> <http://anonymous-groups.td> -- Exit Code: 1 Command Output (stderr): --
> /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/anonymous-groups.td:10:16:
> error: expected string not found in input // CHECK:
> anonymous-groups.td:[[@LINE-1]]:41: error: group 'name' is referred to
> anonymously ^ <stdin>:1:1: note: scanning from here Included from
> /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/anonymous-groups.td:2
> <http://anonymous-groups.td:2>: ^ <stdin>:1:1: note: with expression
> "@LINE-1" equal to "9" Included from
> /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/anonymous-groups.td:2
> <http://anonymous-groups.td:2>: ^ <stdin>:2:71: note: possible intended
> match here
> /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/DiagnosticBase.inc:15:7:
> error: group 'name' is referred to anonymously ^ -- ********************
> Testing: 0 .. 10.. 20.. 30.. 40.. 50.. 60.. 70.. FAIL: Clang ::
> TableGen/tg-fixits.td <http://tg-fixits.td> (9690 of 12091)
> ******************** TEST 'Clang :: TableGen/tg-fixits.td
> <http://tg-fixits.td>' FAILED ******************** Script: --
> clang-tblgen -gen-clang-diag-groups
> -I/b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen
> /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/tg-fixits.td
> <http://tg-fixits.td> -o /dev/null 2>&1 |
> /b/sanitizer-x86_64-linux-fast/build/llvm_build_asan/bin/FileCheck
> --strict-whitespace
> /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/tg-fixits.td
> <http://tg-fixits.td> -- Exit Code: 1 Command Output (stderr): --
> /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/tg-fixits.td:7:16:
> error: expected string not found in input // CHECK:
> tg-fixits.td:[[@LINE-1]]:41: error: group 'name' is referred to
> anonymously ^ <stdin>:1:1: note: scanning from here Included from
> /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/tg-fixits.td:2
> <http://tg-fixits.td:2>: ^ <stdin>:1:1: note: with expression "@LINE-1"
> equal to "6" Included from
> /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/tg-fixits.td:2
> <http://tg-fixits.td:2>: ^ <stdin>:2:76: note: possible intended match
> here
> /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/TableGen/DiagnosticBase.inc:15:7:
> error: group 'name' is referred to anonymously ^ -- ********************
> Testing: 0 .. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90.. Testing Time:
> 226.63s ******************** Failing Tests (2): Clang ::
> TableGen/anonymous-groups.td <http://anonymous-groups.td> Clang ::
> TableGen/tg-fixits.td <http://tg-fixits.td> Expected Passes : 12019
> Expected Failures : 19 Unsupported Tests : 51 Unexpected Failures: 2
> FAILED: tools/clang/test/CMakeFiles/check-clang
>
>
> Please take a look.
>
> On Tue, Mar 6, 2018 at 5:49 AM, Nicolai Haehnle via llvm-commits
> <llvm-commits at lists.llvm.org <mailto:llvm-commits at lists.llvm.org>> wrote:
>
> Author: nha
> Date: Tue Mar 6 05:49:01 2018
> New Revision: 326788
>
> URL: http://llvm.org/viewvc/llvm-project?rev=326788&view=rev
> <http://llvm.org/viewvc/llvm-project?rev=326788&view=rev>
> Log:
> TableGen: Delay instantiating inline anonymous records
>
> Summary:
> Only instantiate anonymous records once all variable references in
> template
> arguments have been resolved. This allows patterns like the new test
> case,
> which in practice can appear in expressions like:
>
> class IntrinsicTypeProfile<list<LLVMType> ty, int shift> {
> list<LLVMType> types =
> !listconcat(ty, [llvm_any_ty, LLVMMatchType<shift>]);
> }
>
> class FooIntrinsic<IntrinsicTypeProfile P, ...>
> : Intrinsic<..., P.types, ...>;
>
> Without this change, the anonymous LLVMMatchType instantiation would
> never get resolved.
>
> Another consequence of this change is that anonymous inline
> instantiations are uniqued via the folding set of the newly introduced
> VarDefInit.
>
> Change-Id: I7a7041a20e297cf98c9109b28d85e64e176c932a
>
> Reviewers: arsenm, craig.topper, tra, MartinO
>
> Subscribers: wdng, llvm-commits
>
> Differential Revision: https://reviews.llvm.org/D43756
> <https://reviews.llvm.org/D43756>
>
> Modified:
> llvm/trunk/include/llvm/TableGen/Record.h
> llvm/trunk/lib/TableGen/Record.cpp
> llvm/trunk/lib/TableGen/TGParser.cpp
> llvm/trunk/test/TableGen/AnonDefinitionOnDemand.td
>
> Modified: llvm/trunk/include/llvm/TableGen/Record.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/TableGen/Record.h?rev=326788&r1=326787&r2=326788&view=diff
> <http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/TableGen/Record.h?rev=326788&r1=326787&r2=326788&view=diff>
> ==============================================================================
> --- llvm/trunk/include/llvm/TableGen/Record.h (original)
> +++ llvm/trunk/include/llvm/TableGen/Record.h Tue Mar 6 05:49:01 2018
> @@ -320,6 +320,7 @@ protected:
> IK_VarInit,
> IK_VarListElementInit,
> IK_VarBitInit,
> + IK_VarDefInit,
> IK_LastTypedInit,
> IK_UnsetInit
> };
> @@ -1052,6 +1053,58 @@ public:
> }
> };
>
> +/// classname<targs...> - Represent an uninstantiated anonymous class
> +/// instantiation.
> +class VarDefInit final : public TypedInit, public FoldingSetNode,
> + public TrailingObjects<VarDefInit, Init *> {
> + Record *Class;
> + DefInit *Def = nullptr; // after instantiation
> + unsigned NumArgs;
> +
> + explicit VarDefInit(Record *Class, unsigned N)
> + : TypedInit(IK_VarDefInit, RecordRecTy::get(Class)),
> Class(Class), NumArgs(N) {}
> +
> + DefInit *instantiate();
> +
> +public:
> + VarDefInit(const VarDefInit &) = delete;
> + VarDefInit &operator=(const VarDefInit &) = delete;
> +
> + // Do not use sized deallocation due to trailing objects.
> + void operator delete(void *p) { ::operator delete(p); }
> +
> + static bool classof(const Init *I) {
> + return I->getKind() == IK_VarDefInit;
> + }
> + static VarDefInit *get(Record *Class, ArrayRef<Init *> Args);
> +
> + void Profile(FoldingSetNodeID &ID) const;
> +
> + Init *resolveReferences(Resolver &R) const override;
> + Init *Fold() const;
> +
> + std::string getAsString() const override;
> +
> + Init *getArg(unsigned i) const {
> + assert(i < NumArgs && "Argument index out of range!");
> + return getTrailingObjects<Init *>()[i];
> + }
> +
> + using const_iterator = Init *const *;
> +
> + const_iterator args_begin() const { return
> getTrailingObjects<Init *>(); }
> + const_iterator args_end () const { return args_begin() + NumArgs; }
> +
> + size_t args_size () const { return NumArgs; }
> + bool args_empty() const { return NumArgs == 0; }
> +
> + ArrayRef<Init *> args() const { return makeArrayRef(args_begin(),
> NumArgs); }
> +
> + Init *getBit(unsigned Bit) const override {
> + llvm_unreachable("Illegal bit reference off anonymous def");
> + }
> +};
> +
> /// X.Y - Represent a reference to a subfield of a variable
> class FieldInit : public TypedInit {
> Init *Rec; // Record we are referring to
> @@ -1754,6 +1807,21 @@ public:
> }
> };
>
> +/// (Optionally) delegate resolving to a sub-resolver, and keep
> track whether
> +/// there were unresolved references.
> +class TrackUnresolvedResolver final : public Resolver {
> + Resolver *R;
> + bool FoundUnresolved = false;
> +
> +public:
> + explicit TrackUnresolvedResolver(Resolver *R = nullptr)
> + : Resolver(R ? R->getCurrentRecord() : nullptr), R(R) {}
> +
> + bool foundUnresolved() const { return FoundUnresolved; }
> +
> + Init *resolve(Init *VarName) override;
> +};
> +
> } // end namespace llvm
>
> #endif // LLVM_TABLEGEN_RECORD_H
>
> Modified: llvm/trunk/lib/TableGen/Record.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/Record.cpp?rev=326788&r1=326787&r2=326788&view=diff
> <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/Record.cpp?rev=326788&r1=326787&r2=326788&view=diff>
> ==============================================================================
> --- llvm/trunk/lib/TableGen/Record.cpp (original)
> +++ llvm/trunk/lib/TableGen/Record.cpp Tue Mar 6 05:49:01 2018
> @@ -1355,6 +1355,132 @@ std::string DefInit::getAsString() const
> return Def->getName();
> }
>
> +static void ProfileVarDefInit(FoldingSetNodeID &ID,
> + Record *Class,
> + ArrayRef<Init *> Args) {
> + ID.AddInteger(Args.size());
> + ID.AddPointer(Class);
> +
> + for (Init *I : Args)
> + ID.AddPointer(I);
> +}
> +
> +VarDefInit *VarDefInit::get(Record *Class, ArrayRef<Init *> Args) {
> + static FoldingSet<VarDefInit> ThePool;
> +
> + FoldingSetNodeID ID;
> + ProfileVarDefInit(ID, Class, Args);
> +
> + void *IP = nullptr;
> + if (VarDefInit *I = ThePool.FindNodeOrInsertPos(ID, IP))
> + return I;
> +
> + void *Mem = Allocator.Allocate(totalSizeToAlloc<Init *>(Args.size()),
> + alignof(VarDefInit));
> + VarDefInit *I = new(Mem) VarDefInit(Class, Args.size());
> + std::uninitialized_copy(Args.begin(), Args.end(),
> + I->getTrailingObjects<Init *>());
> + ThePool.InsertNode(I, IP);
> + return I;
> +}
> +
> +void VarDefInit::Profile(FoldingSetNodeID &ID) const {
> + ProfileVarDefInit(ID, Class, args());
> +}
> +
> +DefInit *VarDefInit::instantiate() {
> + if (!Def) {
> + RecordKeeper &Records = Class->getRecords();
> + auto NewRecOwner =
> make_unique<Record>(Records.getNewAnonymousName(),
> + Class->getLoc(), Records,
> + /*IsAnonymous=*/true);
> + Record *NewRec = NewRecOwner.get();
> +
> + // Copy values from class to instance
> + for (const RecordVal &Val : Class->getValues()) {
> + if (Val.getName() != "NAME")
> + NewRec->addValue(Val);
> + }
> +
> + // Substitute and resolve template arguments
> + ArrayRef<Init *> TArgs = Class->getTemplateArgs();
> + MapResolver R(NewRec);
> +
> + for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
> + if (i < args_size())
> + R.set(TArgs[i], getArg(i));
> + else
> + R.set(TArgs[i], NewRec->getValue(TArgs[i])->getValue());
> +
> + NewRec->removeValue(TArgs[i]);
> + }
> +
> + NewRec->resolveReferences(R);
> +
> + // Add superclasses.
> + ArrayRef<std::pair<Record *, SMRange>> SCs =
> Class->getSuperClasses();
> + for (const auto &SCPair : SCs)
> + NewRec->addSuperClass(SCPair.first, SCPair.second);
> +
> + NewRec->addSuperClass(Class,
> + SMRange(Class->getLoc().back(),
> + Class->getLoc().back()));
> +
> + // Resolve internal references and store in record keeper
> + NewRec->resolveReferences();
> + Records.addDef(std::move(NewRecOwner));
> +
> + Def = DefInit::get(NewRec);
> + }
> +
> + return Def;
> +}
> +
> +Init *VarDefInit::resolveReferences(Resolver &R) const {
> + TrackUnresolvedResolver UR(&R);
> + bool Changed = false;
> + SmallVector<Init *, 8> NewArgs;
> + NewArgs.reserve(args_size());
> +
> + for (Init *Arg : args()) {
> + Init *NewArg = Arg->resolveReferences(UR);
> + NewArgs.push_back(NewArg);
> + Changed |= NewArg != Arg;
> + }
> +
> + if (Changed) {
> + auto New = VarDefInit::get(Class, NewArgs);
> + if (!UR.foundUnresolved())
> + return New->instantiate();
> + return New;
> + }
> + return const_cast<VarDefInit *>(this);
> +}
> +
> +Init *VarDefInit::Fold() const {
> + if (Def)
> + return Def;
> +
> + TrackUnresolvedResolver R;
> + for (Init *Arg : args())
> + Arg->resolveReferences(R);
> +
> + if (!R.foundUnresolved())
> + return const_cast<VarDefInit *>(this)->instantiate();
> + return const_cast<VarDefInit *>(this);
> +}
> +
> +std::string VarDefInit::getAsString() const {
> + std::string Result = Class->getNameInitAsString() + "<";
> + const char *sep = "";
> + for (Init *Arg : args()) {
> + Result += sep;
> + sep = ", ";
> + Result += Arg->getAsString();
> + }
> + return Result + ">";
> +}
> +
> FieldInit *FieldInit::get(Init *R, StringInit *FN) {
> using Key = std::pair<Init *, StringInit *>;
> static DenseMap<Key, FieldInit*> ThePool;
> @@ -1917,3 +2043,23 @@ Init *RecordResolver::resolve(Init *VarN
> Cache[VarName] = Val;
> return Val;
> }
> +
> +Init *TrackUnresolvedResolver::resolve(Init *VarName) {
> + Init *I = nullptr;
> +
> + if (R) {
> + I = R->resolve(VarName);
> + if (I && !FoundUnresolved) {
> + // Do not recurse into the resolved initializer, as that
> would change
> + // the behavior of the resolver we're delegating, but do
> check to see
> + // if there are unresolved variables remaining.
> + TrackUnresolvedResolver Sub;
> + I->resolveReferences(Sub);
> + FoundUnresolved |= Sub.FoundUnresolved;
> + }
> + }
> +
> + if (!I)
> + FoundUnresolved = true;
> + return I;
> +}
>
> Modified: llvm/trunk/lib/TableGen/TGParser.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGParser.cpp?rev=326788&r1=326787&r2=326788&view=diff
> <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGParser.cpp?rev=326788&r1=326787&r2=326788&view=diff>
> ==============================================================================
> --- llvm/trunk/lib/TableGen/TGParser.cpp (original)
> +++ llvm/trunk/lib/TableGen/TGParser.cpp Tue Mar 6 05:49:01 2018
> @@ -1346,61 +1346,49 @@ Init *TGParser::ParseSimpleValue(Record
> return nullptr;
> }
>
> - SubClassReference SCRef;
> - ParseValueList(SCRef.TemplateArgs, CurRec, Class);
> - if (SCRef.TemplateArgs.empty()) return nullptr;
> + SmallVector<Init *, 8> Args;
> + ParseValueList(Args, CurRec, Class);
> + if (Args.empty()) return nullptr;
>
> if (Lex.getCode() != tgtok::greater) {
> TokError("expected '>' at end of value list");
> return nullptr;
> }
> Lex.Lex(); // eat the '>'
> - SMLoc EndLoc = Lex.getLoc();
>
> - // Create the new record, set it as CurRec temporarily.
> - auto NewRecOwner =
> - make_unique<Record>(Records.getNewAnonymousName(), NameLoc,
> Records,
> - /*IsAnonymous=*/true);
> - Record *NewRec = NewRecOwner.get(); // Keep a copy since we may
> release.
> - SCRef.RefRange = SMRange(NameLoc, EndLoc);
> - SCRef.Rec = Class;
> - // Add info about the subclass to NewRec.
> - if (AddSubClass(NewRec, SCRef))
> + // Typecheck the template arguments list
> + ArrayRef<Init *> ExpectedArgs = Class->getTemplateArgs();
> + if (ExpectedArgs.size() < Args.size()) {
> + Error(NameLoc,
> + "More template args specified than expected");
> return nullptr;
> + }
>
> - if (!CurMultiClass) {
> - NewRec->resolveReferences();
> - Records.addDef(std::move(NewRecOwner));
> - } 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(std::move(NewRecOwner));
> -
> - // Copy the template arguments for the multiclass into the def.
> - for (Init *TArg : CurMultiClass->Rec.getTemplateArgs()) {
> - const RecordVal *RV = CurMultiClass->Rec.getValue(TArg);
> - assert(RV && "Template arg doesn't exist?");
> - NewRec->addValue(*RV);
> - }
> -
> - // We can't return the prototype def here, instead return:
> - // !cast<ItemType>(!strconcat(NAME, AnonName)).
> - const RecordVal *MCNameRV = CurMultiClass->Rec.getValue("NAME");
> - assert(MCNameRV && "multiclass record must have a NAME");
> -
> - return UnOpInit::get(UnOpInit::CAST,
> - BinOpInit::get(BinOpInit::STRCONCAT,
> -
> VarInit::get(MCNameRV->getName(),
> -
> MCNameRV->getType()),
> - NewRec->getNameInit(),
> - StringRecTy::get()),
> - NewRec->getDefInit()->getType());
> + for (unsigned i = 0, e = ExpectedArgs.size(); i != e; ++i) {
> + RecordVal *ExpectedArg = Class->getValue(ExpectedArgs[i]);
> + if (i < Args.size()) {
> + if (TypedInit *TI = dyn_cast<TypedInit>(Args[i])) {
> + RecTy *ExpectedType = ExpectedArg->getType();
> + if (!TI->getType()->typeIsConvertibleTo(ExpectedType)) {
> + Error(NameLoc,
> + "Value specified for template argument #" +
> Twine(i) + " (" +
> + ExpectedArg->getNameInitAsString() + ") is of
> type '" +
> + TI->getType()->getAsString() + "', expected '" +
> + ExpectedType->getAsString() + "': " +
> TI->getAsString());
> + return nullptr;
> + }
> + continue;
> + }
> + } else if (ExpectedArg->getValue()->isComplete())
> + continue;
> +
> + Error(NameLoc,
> + "Value not specified for template argument #" +
> Twine(i) + " (" +
> + ExpectedArgs[i]->getAsUnquotedString() + ")");
> + return nullptr;
> }
>
> - // The result of the expression is a reference to the new record.
> - return DefInit::get(NewRec);
> + return VarDefInit::get(Class, Args)->Fold();
> }
> case tgtok::l_brace: { // Value ::= '{' ValueList '}'
> SMLoc BraceLoc = Lex.getLoc();
>
> Modified: llvm/trunk/test/TableGen/AnonDefinitionOnDemand.td
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/AnonDefinitionOnDemand.td?rev=326788&r1=326787&r2=326788&view=diff
> <http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/AnonDefinitionOnDemand.td?rev=326788&r1=326787&r2=326788&view=diff>
> ==============================================================================
> --- llvm/trunk/test/TableGen/AnonDefinitionOnDemand.td (original)
> +++ llvm/trunk/test/TableGen/AnonDefinitionOnDemand.td Tue Mar 6
> 05:49:01 2018
> @@ -1,6 +1,24 @@
> -// RUN: llvm-tblgen < %s
> +// RUN: llvm-tblgen %s | FileCheck %s
> // XFAIL: vg_leak
>
> +// CHECK: --- Defs ---
> +
> +// CHECK: def X {
> +// CHECK: foo Y = anonymous_0;
> +// CHECK: }
> +
> +// CHECK: def ZD {
> +// CHECK: foo Z = anonymous_1;
> +// CHECK: }
> +
> +// CHECK: def anonymous_0 {
> +// CHECK: int THEVAL = 1;
> +// CHECK: }
> +
> +// CHECK: def anonymous_1 {
> +// CHECK: int THEVAL = 42;
> +// CHECK: }
> +
> class foo<int X> { int THEVAL = X; }
> def foo_imp : foo<1>;
>
> @@ -11,3 +29,9 @@ def x {
> def X {
> foo Y = foo<1>; // This should work too, synthesizing a new
> foo<1>.
> }
> +
> +class Z<int X> {
> + foo Z = foo<X>;
> +}
> +
> +def ZD : Z<42>;
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org <mailto:llvm-commits at lists.llvm.org>
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
> <http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits>
>
>
--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
More information about the llvm-commits
mailing list