[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