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
This commit is contained in:
David Greene 2011-08-10 18:27:46 +00:00
parent 0b18d59435
commit 0d886401b3
3 changed files with 58 additions and 9 deletions

View 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

View 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; }

View 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)