From 0d886401b3ec09b0c2d267942b07702a2f0740f4 Mon Sep 17 00:00:00 2001 From: David Greene Date: Wed, 10 Aug 2011 18:27:46 +0000 Subject: 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 --- utils/TableGen/Record.cpp | 52 +++++++++++++++++++++++++++++++++++++++------ utils/TableGen/Record.h | 9 +++++--- utils/TableGen/TGParser.cpp | 6 ++++++ 3 files changed, 58 insertions(+), 9 deletions(-) (limited to 'utils') 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(Name); + assert(TypedName && "Record name is not typed!"); + RecTy *Type = TypedName->getType(); + if (dynamic_cast(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(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 TemplateArgs; std::vector 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) -- cgit v1.2.3