Make Record Name an Init
authorDavid Greene <greened@obbligato.org>
Wed, 10 Aug 2011 18:27:46 +0000 (18:27 +0000)
committerDavid Greene <greened@obbligato.org>
Wed, 10 Aug 2011 18:27:46 +0000 (18:27 +0000)
Use an Init (ultimately a StringInit) to represent the Record name.
This allows the name to be composed by standard TableGen operators.
This will enable us to get rid of the ugly #NAME# hack processing and
naturally replace it with operators.  It also increases flexibility
and power of the TableGen language by allowing record identifiers to
be computed dynamically.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137232 91177308-0d34-0410-b5e6-96231b3b80d8

utils/TableGen/Record.cpp
utils/TableGen/Record.h
utils/TableGen/TGParser.cpp

index 8763ef7152c95a15119622a49267787aebea4c64..aabe0254ecf1682deb4705da5bb54a3f1d8ea028 100644 (file)
@@ -14,6 +14,7 @@
 #include "Record.h"
 #include "Error.h"
 #include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Format.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
@@ -1638,22 +1639,61 @@ void RecordVal::print(raw_ostream &OS, bool PrintSem) const {
 
 unsigned Record::LastID = 0;
 
+void Record::checkName() {
+  // Ensure the record name has string type.
+  const TypedInit *TypedName = dynamic_cast<const TypedInit *>(Name);
+  assert(TypedName && "Record name is not typed!");
+  RecTy *Type = TypedName->getType();
+  if (dynamic_cast<StringRecTy *>(Type) == 0) {
+    llvm_unreachable("Record name is not a string!");
+  }
+}
+
 DefInit *Record::getDefInit() {
   if (!TheInit)
     TheInit = new DefInit(this, new RecordRecTy(this));
   return TheInit;
 }
 
-void Record::setName(const std::string &Name) {
-  if (TrackedRecords.getDef(getName()) == this) {
-    TrackedRecords.removeDef(getName());
-    this->Name = Name;
+const std::string &Record::getName() const {
+  const StringInit *NameString =
+    dynamic_cast<const StringInit *>(Name);
+  assert(NameString && "Record name is not a string!");
+  return NameString->getValue();
+}
+
+void Record::setName(Init *NewName) {
+  if (TrackedRecords.getDef(Name->getAsUnquotedString()) == this) {
+    TrackedRecords.removeDef(Name->getAsUnquotedString());
+    Name = NewName;
     TrackedRecords.addDef(this);
   } else {
-    TrackedRecords.removeClass(getName());
-    this->Name = Name;
+    TrackedRecords.removeClass(Name->getAsUnquotedString());
+    Name = NewName;
     TrackedRecords.addClass(this);
   }
+  checkName();
+  // Since the Init for the name was changed, see if we can resolve
+  // any of it using members of the Record.
+  Init *ComputedName = Name->resolveReferences(*this, 0);
+  if (ComputedName != Name) {
+    setName(ComputedName);
+  }
+  // DO NOT resolve record values to the name at this point because
+  // there might be default values for arguments of this def.  Those
+  // arguments might not have been resolved yet so we don't want to
+  // prematurely assume values for those arguments were not passed to
+  // this def.
+  //
+  // Nonetheless, it may be that some of this Record's values
+  // reference the record name.  Indeed, the reason for having the
+  // record name be an Init is to provide this flexibility.  The extra
+  // resolve steps after completely instantiating defs takes care of
+  // this.  See TGParser::ParseDef and TGParser::ParseDefm.
+}
+
+void Record::setName(const std::string &Name) {
+  setName(StringInit::get(Name));
 }
 
 /// resolveReferencesTo - If anything in this record refers to RV, replace the
index 802eaedac0c7b08cf2cd6f887012c95851272afe..8e975306378caaba73308be62abbb269df2cba3e 100644 (file)
@@ -1373,7 +1373,7 @@ class Record {
 
   // Unique record ID.
   unsigned ID;
-  std::string Name;
+  Init *Name;
   SMLoc Loc;
   std::vector<std::string> TemplateArgs;
   std::vector<RecordVal> Values;
@@ -1384,11 +1384,13 @@ class Record {
 
   DefInit *TheInit;
 
+  void checkName();
+
 public:
 
   // Constructs a record.
   explicit Record(const std::string &N, SMLoc loc, RecordKeeper &records) :
-    ID(LastID++), Name(N), Loc(loc), TrackedRecords(records), TheInit(0) {}
+    ID(LastID++), Name(StringInit::get(N)), Loc(loc), TrackedRecords(records), TheInit(0) {}
   ~Record() {}
 
 
@@ -1397,7 +1399,8 @@ public:
 
   unsigned getID() const { return ID; }
 
-  const std::string &getName() const { return Name; }
+  const std::string &getName() const;
+  void setName(Init *Name);               // Also updates RecordKeeper.
   void setName(const std::string &Name);  // Also updates RecordKeeper.
 
   SMLoc getLoc() const { return Loc; }
index 2cff3ced57e6da6883d4a611a97f849b2d0d73be..36e9b82ff3f5c546dc676d9c8c75588a68b29c17 100644 (file)
@@ -1690,6 +1690,9 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) {
     return true;
 
   if (CurMultiClass == 0)  // Def's in multiclasses aren't really defs.
+    // See Record::setName().  This resolve step will see any new name
+    // for the def that might have been created when resolving
+    // inheritance, values and arguments above.
     CurRec->resolveReferences();
 
   // If ObjectBody has template arguments, it's an error.
@@ -2102,6 +2105,9 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
 
   if (!CurMultiClass)
     for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i)
+      // See Record::setName().  This resolve step will see any new
+      // name for the def that might have been created when resolving
+      // inheritance, values and arguments above.
       NewRecDefs[i]->resolveReferences();
 
   if (Lex.getCode() != tgtok::semi)