diff options
author | David Greene <greened@obbligato.org> | 2011-08-10 18:27:46 +0000 |
---|---|---|
committer | David Greene <greened@obbligato.org> | 2011-08-10 18:27:46 +0000 |
commit | 0d886401b3ec09b0c2d267942b07702a2f0740f4 (patch) | |
tree | cfd3dca0884b735b192328cd3289acf94a9d906e /utils/TableGen/Record.cpp | |
parent | 0b18d59435a7c01a433ac69845e6d8e1ad66ce8b (diff) | |
download | llvm-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/TableGen/Record.cpp')
-rw-r--r-- | utils/TableGen/Record.cpp | 52 |
1 files changed, 46 insertions, 6 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 |