[llvm] r326788 - TableGen: Delay instantiating inline anonymous records
Matt Morehouse via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 6 10:05:44 PST 2018
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.
Testing: 0 .. 10.. 20.. 30.. 40.. 50.. 60.. 70..
FAIL: Clang :: TableGen/anonymous-groups.td (9683 of 12091)
******************** TEST 'Clang :: TableGen/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
-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
--
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:
^
<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:
^
<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 (9690 of 12091)
******************** TEST 'Clang :: TableGen/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
-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
--
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:
^
<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:
^
<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
Clang :: TableGen/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> 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
> 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
>
> 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
> ============================================================
> ==================
> --- 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
> ============================================================
> ==================
> --- 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
> ============================================================
> ==================
> --- 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
> ============================================================
> ==================
> --- 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
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180306/9be10205/attachment.html>
More information about the llvm-commits
mailing list