[llvm] 49d663d - Revert "[TableGen] Improve algorithms for processing template arguments"

Paul C. Anagnostopoulos via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 18 06:26:50 PST 2021


Author: Paul C. Anagnostopoulos
Date: 2021-02-18T09:26:26-05:00
New Revision: 49d663d5468c144eb7566e81a1a5f598f02a022b

URL: https://github.com/llvm/llvm-project/commit/49d663d5468c144eb7566e81a1a5f598f02a022b
DIFF: https://github.com/llvm/llvm-project/commit/49d663d5468c144eb7566e81a1a5f598f02a022b.diff

LOG: Revert "[TableGen] Improve algorithms for processing template arguments"

This reverts commit e589207d5aaee6cbf1d7c7de8867a17727d14aca.

Added: 
    

Modified: 
    llvm/docs/TableGen/ProgRef.rst
    llvm/include/llvm/TableGen/Record.h
    llvm/lib/TableGen/Record.cpp
    llvm/lib/TableGen/TGParser.cpp
    llvm/lib/TableGen/TGParser.h
    llvm/test/TableGen/self-reference-typeerror.td

Removed: 
    llvm/test/TableGen/template-args.td


################################################################################
diff  --git a/llvm/docs/TableGen/ProgRef.rst b/llvm/docs/TableGen/ProgRef.rst
index b6bd88cb9de5..f5a7760b2885 100644
--- a/llvm/docs/TableGen/ProgRef.rst
+++ b/llvm/docs/TableGen/ProgRef.rst
@@ -299,7 +299,7 @@ wide range of records conveniently and compactly.
 :token:`ClassID`
     Specifying a class name in a type context indicates
     that the type of the defined value must
-    be a subclass of the specified class. This is useful in conjunction with
+    be a subclass of the specified class.  This is useful in conjunction with
     the ``list`` type; for example, to constrain the elements of the list to a
     common base class (e.g., a ``list<Register>`` can only contain definitions
     derived from the ``Register`` class).
@@ -554,22 +554,19 @@ classes and records can inherit.
    TemplateArgDecl: `Type` `TokIdentifier` ["=" `Value`]
 
 A class can be parameterized by a list of "template arguments," whose values
-can be used in the class's record body. These template arguments are
+can be used in the class's record body.  These template arguments are
 specified each time the class is inherited by another class or record.
 
 If a template argument is not assigned a default value with ``=``, it is
 uninitialized (has the "value" ``?``) and must be specified in the template
-argument list when the class is inherited (required argument). If an
-argument is assigned a default value, then it need not be specified in the
-argument list (optional argument). In the declaration, all required template
-arguments must precede any optional arguments. The template argument default
-values are evaluated from left to right.
+argument list when the class is inherited. If an argument is assigned a
+default value, then it need not be specified in the argument list. The
+template argument default values are evaluated from left to right.
 
 The :token:`RecordBody` is defined below. It can include a list of
-superclasses from which the current class inherits, along with field
-definitions and other statements. When a class ``C`` inherits from another
-class ``D``, the fields of ``D`` are effectively merged into the fields of
-``C``.
+superclasses from which the current class inherits, along with field definitions
+and other statements. When a class ``C`` inherits from another class ``D``,
+the fields of ``D`` are effectively merged into the fields of ``C``.
 
 A given class can only be defined once. A ``class`` statement is
 considered to define the class if *any* of the following are true (the
@@ -608,7 +605,7 @@ of the fields of the class or record.
    RecordBody: `ParentClassList` `Body`
    ParentClassList: [":" `ParentClassListNE`]
    ParentClassListNE: `ClassRef` ("," `ClassRef`)*
-   ClassRef: (`ClassID` | `MultiClassID`) ["<" [`ValueList`] ">"]
+   ClassRef: (`ClassID` | `MultiClassID`) ["<" `ValueList` ">"]
 
 A :token:`ParentClassList` containing a :token:`MultiClassID` is valid only
 in the class list of a ``defm`` statement. In that case, the ID must be the

diff  --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h
index ea47d6713026..e75b7f01c868 100644
--- a/llvm/include/llvm/TableGen/Record.h
+++ b/llvm/include/llvm/TableGen/Record.h
@@ -2024,12 +2024,6 @@ class MapResolver final : public Resolver {
 
   void set(Init *Key, Init *Value) { Map[Key] = {Value, false}; }
 
-  bool isComplete(Init *VarName) const {
-    auto It = Map.find(VarName);
-    assert(It != Map.end() && "key must be present in map");
-    return It->second.V->isComplete();
-  }
-
   Init *resolve(Init *VarName) override;
 };
 

diff  --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index 3172d711e7f6..13212098514d 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -2344,13 +2344,13 @@ void Record::resolveReferences(Resolver &R, const RecordVal *SkipVal) {
         if (TypedInit *VRT = dyn_cast<TypedInit>(VR))
           Type =
               (Twine("of type '") + VRT->getType()->getAsString() + "' ").str();
-        PrintFatalError(
-            getLoc(),
-            Twine("Invalid value ") + Type + "found when setting field '" +
-                Value.getNameInitAsString() + "' of type '" +
-                Value.getType()->getAsString() +
-                "' after resolving references: " + VR->getAsUnquotedString() +
-                "\n");
+        PrintFatalError(getLoc(), Twine("Invalid value ") + Type +
+                                      "is found when setting '" +
+                                      Value.getNameInitAsString() +
+                                      "' of type '" +
+                                      Value.getType()->getAsString() +
+                                      "' after resolving references: " +
+                                      VR->getAsUnquotedString() + "\n");
       }
     }
   }

diff  --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 974df42de4c1..87faf77671c6 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -229,33 +229,38 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName,
 /// args as SubClass's template arguments.
 bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
   Record *SC = SubClass.Rec;
+  // Add all of the values in the subclass into the current class.
+  for (const RecordVal &Val : SC->getValues())
+    if (AddValue(CurRec, SubClass.RefRange.Start, Val))
+      return true;
+
+  ArrayRef<Init *> TArgs = SC->getTemplateArgs();
+
+  // Ensure that an appropriate number of template arguments are specified.
+  if (TArgs.size() < SubClass.TemplateArgs.size())
+    return Error(SubClass.RefRange.Start,
+                 "More template args specified than expected");
+
+  // Loop over all of the template arguments, setting them to the specified
+  // value or leaving them as the default if necessary.
   MapResolver R(CurRec);
 
-  // Loop over all the subclass record's fields. Add template arguments
-  // to the resolver map. Add regular fields to the new record.
-  for (const RecordVal &Field : SC->getValues()) {
-    if (Field.isTemplateArg()) {
-      R.set(Field.getNameInit(), Field.getValue());
-    } else {
-      if (AddValue(CurRec, SubClass.RefRange.Start, Field))
+  for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+    if (i < SubClass.TemplateArgs.size()) {
+      // If a value is specified for this template arg, set it now.
+      if (SetValue(CurRec, SubClass.RefRange.Start, TArgs[i],
+                   None, SubClass.TemplateArgs[i]))
         return true;
+    } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
+      return Error(SubClass.RefRange.Start,
+                   "Value not specified for template argument #" +
+                   Twine(i) + " (" + TArgs[i]->getAsUnquotedString() +
+                   ") of subclass '" + SC->getNameInitAsString() + "'!");
     }
-  }
 
-  ArrayRef<Init *> TArgs = SC->getTemplateArgs();
-  assert(SubClass.TemplateArgs.size() <= TArgs.size() &&
-         "Too many template arguments allowed");
-
-  // Loop over the template argument names. If a value was specified,
-  // reset the map value. If not and there was no default, complain.
-  for (unsigned I = 0, E = TArgs.size(); I != E; ++I) {
-    if (I < SubClass.TemplateArgs.size())
-      R.set(TArgs[I], SubClass.TemplateArgs[I]);
-    else if (!R.isComplete(TArgs[I]))
-      return Error(SubClass.RefRange.Start,
-                   "Value not specified for template argument '" +
-                       TArgs[I]->getAsUnquotedString() + "' (#" + Twine(I) +
-                       ") of parent class '" + SC->getNameInitAsString() + "'");
+    R.set(TArgs[i], CurRec->getValue(TArgs[i])->getValue());
+
+    CurRec->removeValue(TArgs[i]);
   }
 
   Init *Name;
@@ -579,8 +584,8 @@ MultiClass *TGParser::ParseMultiClassID() {
   return Result;
 }
 
-/// ParseSubClassReference - Parse a reference to a subclass or a
-/// multiclass. This returns a SubClassRefTy with a null Record* on error.
+/// ParseSubClassReference - Parse a reference to a subclass or to a templated
+/// subclass.  This returns a SubClassRefTy with a null Record* on error.
 ///
 ///  SubClassRef ::= ClassID
 ///  SubClassRef ::= ClassID '<' ValueList '>'
@@ -604,18 +609,25 @@ ParseSubClassReference(Record *CurRec, bool isDefm) {
     return Result;
   }
 
-  if (ParseTemplateArgValueList(Result.TemplateArgs, CurRec, Result.Rec)) {
-    Result.Rec = nullptr; // Error parsing value list.
+  if (Lex.getCode() == tgtok::greater) {
+    TokError("subclass reference requires a non-empty list of template values");
+    Result.Rec = nullptr;
     return Result;
   }
 
-  if (CheckTemplateArgValues(Result.TemplateArgs, Result.RefRange.Start,
-                             Result.Rec)) {
-    Result.Rec = nullptr; // Error checking value list.
+  ParseValueList(Result.TemplateArgs, CurRec, Result.Rec);
+  if (Result.TemplateArgs.empty()) {
+    Result.Rec = nullptr;   // Error parsing value list.
     return Result;
   }
 
+  if (!consume(tgtok::greater)) {
+    TokError("expected '>' in template value list");
+    Result.Rec = nullptr;
+    return Result;
+  }
   Result.RefRange.End = Lex.getLoc();
+
   return Result;
 }
 
@@ -640,12 +652,23 @@ ParseSubMultiClassReference(MultiClass *CurMC) {
     return Result;
   }
 
-  if (ParseTemplateArgValueList(Result.TemplateArgs, &CurMC->Rec,
-                                &Result.MC->Rec)) {
-    Result.MC = nullptr; // Error parsing value list.
+  if (Lex.getCode() == tgtok::greater) {
+    TokError("subclass reference requires a non-empty list of template values");
+    Result.MC = nullptr;
     return Result;
   }
 
+  ParseValueList(Result.TemplateArgs, &CurMC->Rec, &Result.MC->Rec);
+  if (Result.TemplateArgs.empty()) {
+    Result.MC = nullptr;   // Error parsing value list.
+    return Result;
+  }
+
+  if (!consume(tgtok::greater)) {
+    TokError("expected '>' in template value list");
+    Result.MC = nullptr;
+    return Result;
+  }
   Result.RefRange.End = Lex.getLoc();
 
   return Result;
@@ -2009,9 +2032,15 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
     if (Lex.Lex() != tgtok::less)  // consume the Id.
       return ParseIDValue(CurRec, Name, NameLoc, Mode);    // Value ::= IDValue
 
-    // Value ::= CLASSID '<' ValueListNE '>' (CLASSID has been consumed)
-    // This is supposed to synthesize a new anonymous definition, deriving
-    // from the class with the template arguments, but no body.
+    // Value ::= ID '<' ValueListNE '>'
+    if (Lex.Lex() == tgtok::greater) {
+      TokError("expected non-empty value list");
+      return nullptr;
+    }
+
+    // This is a CLASS<initvalslist> expression.  This is supposed to synthesize
+    // a new anonymous definition, deriving from CLASS<initvalslist> with no
+    // body.
     Record *Class = Records.getClass(Name->getValue());
     if (!Class) {
       Error(NameLoc, "Expected a class name, got '" + Name->getValue() + "'");
@@ -2019,26 +2048,44 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
     }
 
     SmallVector<Init *, 8> Args;
-    Lex.Lex(); // consume the <
-    if (ParseTemplateArgValueList(Args, CurRec, Class))
-      return nullptr; // Error parsing value list.
-
-    if (CheckTemplateArgValues(Args, NameLoc, Class))
-      return nullptr; // Error checking template argument values.
-
-    // Loop through the arguments that were not specified and make sure
-    // they have a complete value.
-    // TODO: If we just keep a required argument count, we can do away
-    //       with this checking.
-    ArrayRef<Init *> TArgs = Class->getTemplateArgs();
-    for (unsigned I = Args.size(), E = TArgs.size(); I < E; ++I) {
-      RecordVal *Arg = Class->getValue(TArgs[I]);
-      if (!Arg->getValue()->isComplete()) 
-        Error(NameLoc, "Value not specified for template argument '" +
-                           TArgs[I]->getAsUnquotedString() + "' (#" + Twine(I) +
-                           ") of parent class '" +
-                           Class->getNameInitAsString() + "'");
-              
+    ParseValueList(Args, CurRec, Class);
+    if (Args.empty()) return nullptr;
+
+    if (!consume(tgtok::greater)) {
+      TokError("expected '>' at end of value list");
+      return nullptr;
+    }
+
+    // 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;
+    }
+
+    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;
     }
 
     return VarDefInit::get(Class, Args)->Fold();
@@ -2111,7 +2158,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
     }
 
     if (Lex.getCode() != tgtok::r_square) {
-      ParseValueList(Vals, CurRec,
+      ParseValueList(Vals, CurRec, nullptr,
                      GivenListTy ? GivenListTy->getElementType() : nullptr);
       if (Vals.empty()) return nullptr;
     }
@@ -2475,15 +2522,32 @@ void TGParser::ParseDagArgList(
   }
 }
 
-/// ParseValueList - Parse a comma separated list of values, returning them
-/// in a vector. Note that this always expects to be able to parse at least one
-/// value. It returns an empty list if this is not possible.
+/// ParseValueList - Parse a comma separated list of values, returning them as a
+/// vector.  Note that this always expects to be able to parse at least one
+/// value.  It returns an empty list if this is not possible.
 ///
 ///   ValueList ::= Value (',' Value)
 ///
-void TGParser::ParseValueList(SmallVectorImpl<Init *> &Result, Record *CurRec,
-                              RecTy *ItemType) {
-
+void TGParser::ParseValueList(SmallVectorImpl<Init*> &Result, Record *CurRec,
+                              Record *ArgsRec, RecTy *EltTy) {
+  RecTy *ItemType = EltTy;
+  unsigned int ArgN = 0;
+  if (ArgsRec && !EltTy) {
+    ArrayRef<Init *> TArgs = ArgsRec->getTemplateArgs();
+    if (TArgs.empty()) {
+      TokError("template argument provided to non-template class");
+      Result.clear();
+      return;
+    }
+    const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]);
+    if (!RV) {
+      errs() << "Cannot find template arg " << ArgN << " (" << TArgs[ArgN]
+        << ")\n";
+    }
+    assert(RV && "Template argument record not found??");
+    ItemType = RV->getType();
+    ++ArgN;
+  }
   Result.push_back(ParseValue(CurRec, ItemType));
   if (!Result.back()) {
     Result.clear();
@@ -2494,6 +2558,19 @@ void TGParser::ParseValueList(SmallVectorImpl<Init *> &Result, Record *CurRec,
     // ignore trailing comma for lists
     if (Lex.getCode() == tgtok::r_square)
       return;
+
+    if (ArgsRec && !EltTy) {
+      ArrayRef<Init *> TArgs = ArgsRec->getTemplateArgs();
+      if (ArgN >= TArgs.size()) {
+        TokError("too many template arguments");
+        Result.clear();
+        return;
+      }
+      const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]);
+      assert(RV && "Template argument record not found??");
+      ItemType = RV->getType();
+      ++ArgN;
+    }
     Result.push_back(ParseValue(CurRec, ItemType));
     if (!Result.back()) {
       Result.clear();
@@ -2502,48 +2579,9 @@ void TGParser::ParseValueList(SmallVectorImpl<Init *> &Result, Record *CurRec,
   }
 }
 
-// ParseTemplateArgValueList - Parse a template argument list with the syntax
-// shown, filling in the Result vector. The open angle has been consumed.
-// An empty argument list is allowed. Return false if okay, true if an 
-// error was detected.
-//
-//   TemplateArgList ::= '<' [Value {',' Value}*] '>'
-bool TGParser::ParseTemplateArgValueList(SmallVectorImpl<Init *> &Result,
-                                         Record *CurRec, Record *ArgsRec) {
-
-  assert(Result.empty() && "Result vector is not empty");
-  ArrayRef<Init *> TArgs = ArgsRec->getTemplateArgs();
-  unsigned ArgIndex = 0;
-  RecTy *ItemType;
-
-  if (consume(tgtok::greater)) // empty value list
-    return false;
-
-  while (true) {
-    if (ArgIndex >= TArgs.size()) {
-      TokError("Too many template arguments: " + utostr(ArgIndex + 1));
-      return true;
-    }
-    const RecordVal *Arg = ArgsRec->getValue(TArgs[ArgIndex]);
-    assert(Arg && "Template argument record not found");
-
-    ItemType = Arg->getType();
-    Init *Value = ParseValue(CurRec, ItemType);
-    if (!Value)
-      return true;
-    Result.push_back(Value);
-
-    if (consume(tgtok::greater)) // end of argument list?
-      return false;
-    if (!consume(tgtok::comma)) // must be comma
-      return true;
-    ++ArgIndex; 
-  }
-}
-
 /// ParseDeclaration - Read a declaration, returning the name of field ID, or an
-/// empty string on error.  This can happen in a number of 
diff erent contexts,
-/// including within a def or in the template args for a class (in which case
+/// empty string on error.  This can happen in a number of 
diff erent context's,
+/// including within a def or in the template args for a def (which which case
 /// CurRec will be non-null) and within the template args for a multiclass (in
 /// which case CurRec will be null, but CurMultiClass will be set).  This can
 /// also happen within a def that is within a multiclass, which will set both
@@ -2574,28 +2612,23 @@ Init *TGParser::ParseDeclaration(Record *CurRec,
   Init *DeclName = StringInit::get(Str);
   Lex.Lex();
 
-  bool BadField;
-  if (!ParsingTemplateArgs) { // def, possibly in a multiclass
-    BadField = AddValue(CurRec, IdLoc,
-                        RecordVal(DeclName, IdLoc, Type,
-                                  HasField ? RecordVal::FK_NonconcreteOK
-                                           : RecordVal::FK_Normal));
-
-  } else if (CurRec) { // class template argument
-    DeclName = QualifyName(*CurRec, CurMultiClass, DeclName, ":");
-    BadField = AddValue(CurRec, IdLoc, RecordVal(DeclName, IdLoc, Type,
-                                                 RecordVal::FK_TemplateArg));
-
-  } else { // multiclass template argument
-    assert(CurMultiClass && "invalid context for template argument");
-    DeclName = QualifyName(CurMultiClass->Rec, CurMultiClass, DeclName, "::");
-    BadField = AddValue(CurRec, IdLoc, RecordVal(DeclName, IdLoc, Type,
-                                                 RecordVal::FK_TemplateArg));
-  }
-  if (BadField)
+  if (ParsingTemplateArgs) {
+    if (CurRec)
+      DeclName = QualifyName(*CurRec, CurMultiClass, DeclName, ":");
+    else
+      assert(CurMultiClass);
+    if (CurMultiClass)
+      DeclName = QualifyName(CurMultiClass->Rec, CurMultiClass, DeclName,
+                             "::");
+  }
+
+  // Add the field to the record.
+  if (AddValue(CurRec, IdLoc, RecordVal(DeclName, IdLoc, Type,
+                                        HasField ? RecordVal::FK_NonconcreteOK
+                                                 : RecordVal::FK_Normal)))
     return nullptr;
 
-  // If a value is present, parse it and set new field's value.
+  // If a value is present, parse it.
   if (consume(tgtok::equal)) {
     SMLoc ValLoc = Lex.getLoc();
     Init *Val = ParseValue(CurRec, Type);
@@ -2682,7 +2715,7 @@ VarInit *TGParser::ParseForeachDeclaration(Init *&ForeachListValue) {
   if (!Ranges.empty()) {
     assert(!IterType && "Type already initialized?");
     IterType = IntRecTy::get();
-    std::vector<Init *> Values;
+    std::vector<Init*> Values;
     for (unsigned R : Ranges)
       Values.push_back(IntInit::get(R));
     ForeachListValue = ListInit::get(Values, IterType);
@@ -2696,7 +2729,7 @@ VarInit *TGParser::ParseForeachDeclaration(Init *&ForeachListValue) {
 
 /// ParseTemplateArgList - Read a template argument list, which is a non-empty
 /// sequence of template-declarations in <>'s.  If CurRec is non-null, these are
-/// template args for a class, which may or may not be in a multiclass. If null,
+/// template args for a def, which may or may not be in a multiclass.  If null,
 /// these are the template args for a multiclass.
 ///
 ///    TemplateArgList ::= '<' Declaration (',' Declaration)* '>'
@@ -3460,28 +3493,32 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
   while (true) {
     if (!Ref.Rec) return true;
 
-    // To instantiate a multiclass, we get the multiclass and then loop
-    // through its template argument names. Substs contains a substitution
-    // value for each argument, either the value specified or the default.
-    // Then we can resolve the template arguments.
+    // To instantiate a multiclass, we need to first get the multiclass, then
+    // instantiate each def contained in the multiclass with the SubClassRef
+    // template parameters.
     MultiClass *MC = MultiClasses[std::string(Ref.Rec->getName())].get();
     assert(MC && "Didn't lookup multiclass correctly?");
+    ArrayRef<Init*> TemplateVals = Ref.TemplateArgs;
 
-    ArrayRef<Init *> TemplateVals = Ref.TemplateArgs;
+    // Verify that the correct number of template arguments were specified.
     ArrayRef<Init *> TArgs = MC->Rec.getTemplateArgs();
-    SubstStack Substs;
+    if (TArgs.size() < TemplateVals.size())
+      return Error(SubClassLoc,
+                   "more template args specified than multiclass expects");
 
+    SubstStack Substs;
     for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
       if (i < TemplateVals.size()) {
         Substs.emplace_back(TArgs[i], TemplateVals[i]);
       } else {
         Init *Default = MC->Rec.getValue(TArgs[i])->getValue();
-        if (!Default->isComplete())
+        if (!Default->isComplete()) {
           return Error(SubClassLoc,
-                       "value not specified for template argument '" +
-                           TArgs[i]->getAsUnquotedString() + "' (#" +
-                           Twine(i) + ") of multiclass '" +
-                           MC->Rec.getNameInitAsString() + "'");
+                       "value not specified for template argument #" +
+                           Twine(i) + " (" + TArgs[i]->getAsUnquotedString() +
+                           ") of multiclass '" + MC->Rec.getNameInitAsString() +
+                           "'");
+        }
         Substs.emplace_back(TArgs[i], Default);
       }
     }
@@ -3500,7 +3537,7 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
 
     SubClassLoc = Lex.getLoc();
 
-    // A defm can inherit from regular classes (non-multiclasses) as
+    // A defm can inherit from regular classes (non-multiclass) as
     // long as they come in the end of the inheritance list.
     InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != nullptr);
 
@@ -3605,41 +3642,6 @@ bool TGParser::ParseFile() {
   return TokError("Unexpected token at top level");
 }
 
-// Check the types of the template argument values for a class
-// inheritance, multiclass invocation, or anonymous class invocation.
-// If necessary, replace an argument with a cast to the required type.
-// The argument count has already been checked.
-bool TGParser::CheckTemplateArgValues(SmallVectorImpl<llvm::Init *> &Values,
-                                      SMLoc Loc, Record *ArgsRec) {
-
-  ArrayRef<Init *> TArgs = ArgsRec->getTemplateArgs();
-
-  for (unsigned I = 0, E = Values.size(); I < E; ++I) {
-    RecordVal *Arg = ArgsRec->getValue(TArgs[I]);
-    RecTy *ArgType = Arg->getType();
-    auto *Value = Values[I];
-
-    if (TypedInit *ArgValue = dyn_cast<TypedInit>(Value)) { 
-      auto *CastValue = ArgValue->getCastTo(ArgType);
-      if (CastValue) {
-        assert((!isa<TypedInit>(CastValue) ||
-                cast<TypedInit>(CastValue)->getType()->typeIsA(ArgType)) &&
-               "result of template arg value cast has wrong type");
-        Values[I] = CastValue;
-      } else {
-        PrintFatalError(Loc,
-                        "Value specified for template argument '" +
-                            Arg->getNameInitAsString() + "' (#" + Twine(I) +
-                            ") is of type " + ArgValue->getType()->getAsString() +
-                            "; expected type " + ArgType->getAsString() + ": " +
-                            ArgValue->getAsString());
-      }
-    }
-  }
-
-  return false;
-}
-
 // Check an assertion: Obtain the condition value and be sure it is true.
 // If not, print a nonfatal error along with the message.
 void TGParser::CheckAssert(SMLoc Loc, Init *Condition, Init *Message) {

diff  --git a/llvm/lib/TableGen/TGParser.h b/llvm/lib/TableGen/TGParser.h
index 5b847ab7344f..578a56c9d01c 100644
--- a/llvm/lib/TableGen/TGParser.h
+++ b/llvm/lib/TableGen/TGParser.h
@@ -243,10 +243,8 @@ class TGParser {
                          IDParseMode Mode = ParseValueMode);
   Init *ParseValue(Record *CurRec, RecTy *ItemType = nullptr,
                    IDParseMode Mode = ParseValueMode);
-  void ParseValueList(SmallVectorImpl<llvm::Init*> &Result,
-                      Record *CurRec, RecTy *ItemType = nullptr);
-  bool ParseTemplateArgValueList(SmallVectorImpl<llvm::Init *> &Result,
-                                 Record *CurRec, Record *ArgsRec);
+  void ParseValueList(SmallVectorImpl<llvm::Init*> &Result, Record *CurRec,
+                      Record *ArgsRec = nullptr, RecTy *EltTy = nullptr);
   void ParseDagArgList(
       SmallVectorImpl<std::pair<llvm::Init*, StringInit*>> &Result,
       Record *CurRec);
@@ -266,8 +264,6 @@ class TGParser {
   MultiClass *ParseMultiClassID();
   bool ApplyLetStack(Record *CurRec);
   bool ApplyLetStack(RecordsEntry &Entry);
-  bool CheckTemplateArgValues(SmallVectorImpl<llvm::Init *> &Values,
-                              SMLoc Loc, Record *ArgsRec);
   void CheckAssert(SMLoc Loc, Init *Condition, Init *Message);
   void CheckRecordAsserts(Record &Rec);
 };

diff  --git a/llvm/test/TableGen/self-reference-typeerror.td b/llvm/test/TableGen/self-reference-typeerror.td
index 6f8da4dae135..35c6131fa2c9 100644
--- a/llvm/test/TableGen/self-reference-typeerror.td
+++ b/llvm/test/TableGen/self-reference-typeerror.td
@@ -1,14 +1,13 @@
 // RUN: not llvm-tblgen %s 2>&1 | FileCheck %s
 // XFAIL: vg_leak
 
-class Cl<Cl rec> {
-  Cl Arec = rec;
+class A<A x> {
+  A a = x;
 }
 
 // At the time A0 is referenced, A has not yet been established as a superclass.
 // This kind of self-reference is discourage, but if you *really* want it, you
 // can force it with !cast.
 //
-// CHECK: alue specified for template argument 'Cl:rec'
-
-def Rec0 : Cl<Rec0>;
+// CHECK: Field 'A:x' of type 'A' is incompatible with value
+def A0 : A<A0>;

diff  --git a/llvm/test/TableGen/template-args.td b/llvm/test/TableGen/template-args.td
deleted file mode 100644
index 2a931adffe9a..000000000000
--- a/llvm/test/TableGen/template-args.td
+++ /dev/null
@@ -1,142 +0,0 @@
-// RUN: llvm-tblgen %s | FileCheck %s
-// RUN: not llvm-tblgen -DERROR1 %s 2>&1 | FileCheck --check-prefix=ERROR1 %s
-// RUN: not llvm-tblgen -DERROR2 %s 2>&1 | FileCheck --check-prefix=ERROR2 %s
-// RUN: not llvm-tblgen -DERROR3 %s 2>&1 | FileCheck --check-prefix=ERROR3 %s
-// RUN: not llvm-tblgen -DERROR4 %s 2>&1 | FileCheck --check-prefix=ERROR4 %s
-// RUN: not llvm-tblgen -DERROR5 %s 2>&1 | FileCheck --check-prefix=ERROR5 %s
-// RUN: not llvm-tblgen -DERROR6 %s 2>&1 | FileCheck --check-prefix=ERROR6 %s
-
-// This file tests that template arguments are type-checked and cast
-// if necessary.
-
-// Class template arguments.
-
-class Class1<string nm> {
-  string Name = nm;
-}
-
-// CHECK: def Rec1
-// CHECK:   string Name = "Alice"
-// CHECK:   string NameName = "AliceAlice"
-
-def Rec1 : Class1<"Alice"> {
-  string NameName = Name # Name;
-}
-
-#ifdef ERROR1
-// ERROR1: Value specified for template argument 'Class1:nm' (#0) is of type int
-
-def Rec2 : Class1<42> {
-}
-#endif
-
-class Class2<bits<8> cd> {
-  int Code = cd;
-}
-
-// CHECK: def Rec3
-// CHECK:   int Code = 42
-// CHECK:   list<int> CodeList = [42]
-
-def Rec3 : Class2<0b00101010> {
-  list<int> CodeList = [Code];
-}
-
-// CHECK: def Rec4
-// CHECK:   int Code = 42
-// CHECK:   list<int> CodeList = [42]
-
-def Rec4 : Class2<42> {
-  list<int> CodeList = [Code];
-}
-
-#ifdef ERROR2
-// ERROR2: Value specified for template argument 'Class2:cd' (#0) is of type string
-
-def Rec5 : Class2<"oops"> {
-  list<int> CodeList = [Code];
-}
-#endif
-
-// Anonymous class instantiation template arguments.
-
-// CHECK: def Rec6
-// CHECK:   string Name = "Ted"
-
-def Rec6 {
-  string Name = Class1<"Ted">.Name;
-}
-
-#ifdef ERROR3
-// ERROR3: Value specified for template argument 'Class1:nm' (#0) is of type int
-
-def Rec7 {
-  string Name = Class1<42>.Name;
-}
-#endif
-
-// CHECK: def Rec8
-// CHECK:   list<int> CodeList = [42]
-
-def Rec8 {
-  list<int> CodeList = [Class2<42>.Code];
-}
-
-#ifdef ERROR4
-// ERROR4: Value specified for template argument 'Class2:cd' (#0) is of type string
-
-def Rec9 {
-  list<int> CodeList = [Class2<"huh?">.Code];
-}
-#endif
-
-// Multiclass template arguments.
-
-multiclass MC1<string nm> {
-  def _1 {
-    string Name = nm;
-  }
-  def _2 {
-    string NameNmae = nm # nm;
-  }
-}
-
-// CHECK: def RecMC1_1
-// CHECK:   string Name = "Carol"
-// CHECK: def RecMC1_2
-// CHECK:   string NameNmae = "CarolCarol"
-
-defm RecMC1 : MC1<"Carol">;
-
-#ifdef ERROR5
-// ERROR5: Value specified for template argument 'MC1::nm' (#0) is of type int
-
-defm RecMC2 : MC1<42>;
-#endif
-
-multiclass MC2<bits<8> cd> {
-  def _1 {
-    bits<8> Code = cd;
-  }
-  def _2 {
-    int Code = cd;
-  }
-  def _3 {
-    list<int> CodeList = [cd];
-  }
-}
-
-// CHECK: def RecMC3_1
-// CHECK:   bits<8> Code = { 0, 0, 1, 0, 1, 0, 1, 0 }
-// CHECK: def RecMC3_2
-// CHECK:   int Code = 42
-// CHECK: def RecMC3_3
-// CHECK:   list<int> CodeList = [42]
-
-defm RecMC3 : MC2<42>;
-
-#ifdef ERROR6
-// ERROR6: Value specified for template argument 'MC2::cd' (#0) is of type string
-
-defm RecMC4 : MC2<"Bob">;
-#endif


        


More information about the llvm-commits mailing list