summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorDavid Greene <greened@obbligato.org>2011-08-10 18:27:46 +0000
committerDavid Greene <greened@obbligato.org>2011-08-10 18:27:46 +0000
commit0d886401b3ec09b0c2d267942b07702a2f0740f4 (patch)
treecfd3dca0884b735b192328cd3289acf94a9d906e /utils
parent0b18d59435a7c01a433ac69845e6d8e1ad66ce8b (diff)
downloadllvm-0d886401b3ec09b0c2d267942b07702a2f0740f4.tar.gz
llvm-0d886401b3ec09b0c2d267942b07702a2f0740f4.tar.bz2
llvm-0d886401b3ec09b0c2d267942b07702a2f0740f4.tar.xz
Make Record Name an Init
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
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/Record.cpp52
-rw-r--r--utils/TableGen/Record.h9
-rw-r--r--utils/TableGen/TGParser.cpp6
3 files changed, 58 insertions, 9 deletions
diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp
index 8763ef7152..aabe0254ec 100644
--- a/utils/TableGen/Record.cpp
+++ b/utils/TableGen/Record.cpp
@@ -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
diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h
index 802eaedac0..8e97530637 100644
--- a/utils/TableGen/Record.h
+++ b/utils/TableGen/Record.h
@@ -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; }
diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp
index 2cff3ced57..36e9b82ff3 100644
--- a/utils/TableGen/TGParser.cpp
+++ b/utils/TableGen/TGParser.cpp
@@ -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)